Skip to main content
Glama
ssv445

Lorem Ipsum MCP Server

by ssv445
Arbitrary.js26.9 kB
/** * @since 3.10.0 */ import * as Arr from "./Array.js"; import * as FastCheck from "./FastCheck.js"; import { globalValue } from "./GlobalValue.js"; import * as errors_ from "./internal/schema/errors.js"; import * as schemaId_ from "./internal/schema/schemaId.js"; import * as util_ from "./internal/schema/util.js"; import * as Option from "./Option.js"; import * as Predicate from "./Predicate.js"; import * as SchemaAST from "./SchemaAST.js"; /** * Returns a LazyArbitrary for the `A` type of the provided schema. * * @category arbitrary * @since 3.10.0 */ export const makeLazy = schema => { const description = getDescription(schema.ast, []); return go(description, { maxDepth: 2 }); }; /** * Returns a fast-check Arbitrary for the `A` type of the provided schema. * * @category arbitrary * @since 3.10.0 */ export const make = schema => makeLazy(schema)(FastCheck); /** @internal */ export const makeStringConstraints = options => { const out = { _tag: "StringConstraints", constraints: {} }; if (Predicate.isNumber(options.minLength)) { out.constraints.minLength = options.minLength; } if (Predicate.isNumber(options.maxLength)) { out.constraints.maxLength = options.maxLength; } if (Predicate.isString(options.pattern)) { out.pattern = options.pattern; } return out; }; /** @internal */ export const makeNumberConstraints = options => { const out = { _tag: "NumberConstraints", constraints: {}, isInteger: options.isInteger ?? false }; if (Predicate.isNumber(options.min)) { out.constraints.min = Math.fround(options.min); } if (Predicate.isBoolean(options.minExcluded)) { out.constraints.minExcluded = options.minExcluded; } if (Predicate.isNumber(options.max)) { out.constraints.max = Math.fround(options.max); } if (Predicate.isBoolean(options.maxExcluded)) { out.constraints.maxExcluded = options.maxExcluded; } if (Predicate.isBoolean(options.noNaN)) { out.constraints.noNaN = options.noNaN; } if (Predicate.isBoolean(options.noDefaultInfinity)) { out.constraints.noDefaultInfinity = options.noDefaultInfinity; } return out; }; /** @internal */ export const makeBigIntConstraints = options => { const out = { _tag: "BigIntConstraints", constraints: {} }; if (Predicate.isBigInt(options.min)) { out.constraints.min = options.min; } if (Predicate.isBigInt(options.max)) { out.constraints.max = options.max; } return out; }; /** @internal */ export const makeArrayConstraints = options => { const out = { _tag: "ArrayConstraints", constraints: {} }; if (Predicate.isNumber(options.minLength)) { out.constraints.minLength = options.minLength; } if (Predicate.isNumber(options.maxLength)) { out.constraints.maxLength = options.maxLength; } return out; }; /** @internal */ export const makeDateConstraints = options => { const out = { _tag: "DateConstraints", constraints: {} }; if (Predicate.isDate(options.min)) { out.constraints.min = options.min; } if (Predicate.isDate(options.max)) { out.constraints.max = options.max; } if (Predicate.isBoolean(options.noInvalidDate)) { out.constraints.noInvalidDate = options.noInvalidDate; } return out; }; const getArbitraryAnnotation = /*#__PURE__*/SchemaAST.getAnnotation(SchemaAST.ArbitraryAnnotationId); const getASTConstraints = ast => { const TypeAnnotationId = ast.annotations[SchemaAST.SchemaIdAnnotationId]; if (Predicate.isPropertyKey(TypeAnnotationId)) { const out = ast.annotations[TypeAnnotationId]; if (Predicate.isReadonlyRecord(out)) { return out; } } }; const idMemoMap = /*#__PURE__*/globalValue(/*#__PURE__*/Symbol.for("effect/Arbitrary/IdMemoMap"), () => new Map()); let counter = 0; function wrapGetDescription(f, g) { return (ast, path) => f(ast, g(ast, path)); } function parseMeta(ast) { const jsonSchema = SchemaAST.getJSONSchemaAnnotation(ast).pipe(Option.filter(Predicate.isReadonlyRecord), Option.getOrUndefined); const schemaId = Option.getOrElse(SchemaAST.getSchemaIdAnnotation(ast), () => undefined); const schemaParams = Option.fromNullable(schemaId).pipe(Option.map(id => ast.annotations[id]), Option.filter(Predicate.isReadonlyRecord), Option.getOrUndefined); return [schemaId, { ...schemaParams, ...jsonSchema }]; } /** @internal */ export const getDescription = /*#__PURE__*/wrapGetDescription((ast, description) => { const annotation = getArbitraryAnnotation(ast); if (Option.isSome(annotation)) { return { ...description, annotations: [...description.annotations, annotation.value] }; } return description; }, (ast, path) => { const [schemaId, meta] = parseMeta(ast); switch (ast._tag) { case "Refinement": { const from = getDescription(ast.from, path); switch (from._tag) { case "StringKeyword": return { ...from, constraints: [...from.constraints, makeStringConstraints(meta)], refinements: [...from.refinements, ast] }; case "NumberKeyword": { const c = schemaId === schemaId_.NonNaNSchemaId ? makeNumberConstraints({ noNaN: true }) : makeNumberConstraints({ isInteger: "type" in meta && meta.type === "integer", noNaN: "type" in meta && meta.type === "number" ? true : undefined, noDefaultInfinity: "type" in meta && meta.type === "number" ? true : undefined, min: meta.exclusiveMinimum ?? meta.minimum, minExcluded: "exclusiveMinimum" in meta ? true : undefined, max: meta.exclusiveMaximum ?? meta.maximum, maxExcluded: "exclusiveMaximum" in meta ? true : undefined }); return { ...from, constraints: [...from.constraints, c], refinements: [...from.refinements, ast] }; } case "BigIntKeyword": { const c = getASTConstraints(ast); return { ...from, constraints: c !== undefined ? [...from.constraints, makeBigIntConstraints(c)] : from.constraints, refinements: [...from.refinements, ast] }; } case "TupleType": return { ...from, constraints: [...from.constraints, makeArrayConstraints({ minLength: meta.minItems, maxLength: meta.maxItems })], refinements: [...from.refinements, ast] }; case "DateFromSelf": return { ...from, constraints: [...from.constraints, makeDateConstraints(meta)], refinements: [...from.refinements, ast] }; default: return { ...from, refinements: [...from.refinements, ast] }; } } case "Declaration": { if (schemaId === schemaId_.DateFromSelfSchemaId) { return { _tag: "DateFromSelf", constraints: [makeDateConstraints(meta)], path, refinements: [], annotations: [] }; } return { _tag: "Declaration", typeParameters: ast.typeParameters.map(ast => getDescription(ast, path)), path, refinements: [], annotations: [], ast }; } case "Literal": { return { _tag: "Literal", literal: ast.literal, path, refinements: [], annotations: [] }; } case "UniqueSymbol": { return { _tag: "UniqueSymbol", symbol: ast.symbol, path, refinements: [], annotations: [] }; } case "Enums": { return { _tag: "Enums", enums: ast.enums, path, refinements: [], annotations: [], ast }; } case "TemplateLiteral": { return { _tag: "TemplateLiteral", head: ast.head, spans: ast.spans.map(span => ({ description: getDescription(span.type, path), literal: span.literal })), path, refinements: [], annotations: [] }; } case "StringKeyword": return { _tag: "StringKeyword", constraints: [], path, refinements: [], annotations: [] }; case "NumberKeyword": return { _tag: "NumberKeyword", constraints: [], path, refinements: [], annotations: [] }; case "BigIntKeyword": return { _tag: "BigIntKeyword", constraints: [], path, refinements: [], annotations: [] }; case "TupleType": return { _tag: "TupleType", constraints: [], elements: ast.elements.map((element, i) => ({ isOptional: element.isOptional, description: getDescription(element.type, [...path, i]) })), rest: ast.rest.map((element, i) => getDescription(element.type, [...path, i])), path, refinements: [], annotations: [] }; case "TypeLiteral": return { _tag: "TypeLiteral", propertySignatures: ast.propertySignatures.map(ps => ({ isOptional: ps.isOptional, name: ps.name, value: getDescription(ps.type, [...path, ps.name]) })), indexSignatures: ast.indexSignatures.map(is => ({ parameter: getDescription(is.parameter, path), value: getDescription(is.type, path) })), path, refinements: [], annotations: [] }; case "Union": return { _tag: "Union", members: ast.types.map((member, i) => getDescription(member, [...path, i])), path, refinements: [], annotations: [] }; case "Suspend": { const memoId = idMemoMap.get(ast); if (memoId !== undefined) { return { _tag: "Ref", id: memoId, ast, path, refinements: [], annotations: [] }; } counter++; const id = `__id-${counter}__`; idMemoMap.set(ast, id); return { _tag: "Suspend", id, ast, description: () => getDescription(ast.f(), path), path, refinements: [], annotations: [] }; } case "Transformation": return getDescription(ast.to, path); case "NeverKeyword": return { _tag: "NeverKeyword", path, refinements: [], annotations: [], ast }; default: { return { _tag: "Keyword", value: ast._tag, path, refinements: [], annotations: [] }; } } }); function getMax(n1, n2) { return n1 === undefined ? n2 : n2 === undefined ? n1 : n1 <= n2 ? n2 : n1; } function getMin(n1, n2) { return n1 === undefined ? n2 : n2 === undefined ? n1 : n1 <= n2 ? n1 : n2; } const getOr = (a, b) => { return a === undefined ? b : b === undefined ? a : a || b; }; function mergePattern(pattern1, pattern2) { if (pattern1 === undefined) { return pattern2; } if (pattern2 === undefined) { return pattern1; } return `(?:${pattern1})|(?:${pattern2})`; } function mergeStringConstraints(c1, c2) { return makeStringConstraints({ minLength: getMax(c1.constraints.minLength, c2.constraints.minLength), maxLength: getMin(c1.constraints.maxLength, c2.constraints.maxLength), pattern: mergePattern(c1.pattern, c2.pattern) }); } function buildStringConstraints(description) { return description.constraints.length === 0 ? undefined : description.constraints.reduce(mergeStringConstraints); } function mergeNumberConstraints(c1, c2) { return makeNumberConstraints({ isInteger: c1.isInteger || c2.isInteger, min: getMax(c1.constraints.min, c2.constraints.min), minExcluded: getOr(c1.constraints.minExcluded, c2.constraints.minExcluded), max: getMin(c1.constraints.max, c2.constraints.max), maxExcluded: getOr(c1.constraints.maxExcluded, c2.constraints.maxExcluded), noNaN: getOr(c1.constraints.noNaN, c2.constraints.noNaN), noDefaultInfinity: getOr(c1.constraints.noDefaultInfinity, c2.constraints.noDefaultInfinity) }); } function buildNumberConstraints(description) { return description.constraints.length === 0 ? undefined : description.constraints.reduce(mergeNumberConstraints); } function mergeBigIntConstraints(c1, c2) { return makeBigIntConstraints({ min: getMax(c1.constraints.min, c2.constraints.min), max: getMin(c1.constraints.max, c2.constraints.max) }); } function buildBigIntConstraints(description) { return description.constraints.length === 0 ? undefined : description.constraints.reduce(mergeBigIntConstraints); } function mergeDateConstraints(c1, c2) { return makeDateConstraints({ min: getMax(c1.constraints.min, c2.constraints.min), max: getMin(c1.constraints.max, c2.constraints.max), noInvalidDate: getOr(c1.constraints.noInvalidDate, c2.constraints.noInvalidDate) }); } function buildDateConstraints(description) { return description.constraints.length === 0 ? undefined : description.constraints.reduce(mergeDateConstraints); } const constArrayConstraints = /*#__PURE__*/makeArrayConstraints({}); function mergeArrayConstraints(c1, c2) { return makeArrayConstraints({ minLength: getMax(c1.constraints.minLength, c2.constraints.minLength), maxLength: getMin(c1.constraints.maxLength, c2.constraints.maxLength) }); } function buildArrayConstraints(description) { return description.constraints.length === 0 ? undefined : description.constraints.reduce(mergeArrayConstraints); } const arbitraryMemoMap = /*#__PURE__*/globalValue(/*#__PURE__*/Symbol.for("effect/Arbitrary/arbitraryMemoMap"), () => new WeakMap()); function applyFilters(filters, arb) { return fc => filters.reduce((arb, filter) => arb.filter(filter), arb(fc)); } function absurd(message) { return () => { throw new Error(message); }; } function getContextConstraints(description) { switch (description._tag) { case "StringKeyword": return buildStringConstraints(description); case "NumberKeyword": return buildNumberConstraints(description); case "BigIntKeyword": return buildBigIntConstraints(description); case "DateFromSelf": return buildDateConstraints(description); case "TupleType": return buildArrayConstraints(description); } } function wrapGo(f, g) { return (description, ctx) => f(description, ctx, g(description, ctx)); } const go = /*#__PURE__*/wrapGo((description, ctx, lazyArb) => { const annotation = description.annotations[description.annotations.length - 1]; // error handling if (annotation === undefined) { switch (description._tag) { case "Declaration": case "NeverKeyword": throw new Error(errors_.getArbitraryMissingAnnotationErrorMessage(description.path, description.ast)); case "Enums": if (description.enums.length === 0) { throw new Error(errors_.getArbitraryEmptyEnumErrorMessage(description.path)); } } } const filters = description.refinements.map(ast => a => Option.isNone(ast.filter(a, SchemaAST.defaultParseOption, ast))); if (annotation === undefined) { return applyFilters(filters, lazyArb); } const constraints = getContextConstraints(description); if (constraints !== undefined) { ctx = { ...ctx, constraints }; } if (description._tag === "Declaration") { return applyFilters(filters, annotation(...description.typeParameters.map(p => go(p, ctx)), ctx)); } if (description.refinements.length > 0) { // TODO(4.0): remove the `lazyArb` parameter return applyFilters(filters, annotation(lazyArb, ctx)); } return annotation(ctx); }, (description, ctx) => { switch (description._tag) { case "DateFromSelf": { const constraints = buildDateConstraints(description); return fc => fc.date(constraints?.constraints); } case "Declaration": case "NeverKeyword": return absurd(`BUG: cannot generate an arbitrary for ${description._tag}`); case "Literal": return fc => fc.constant(description.literal); case "UniqueSymbol": return fc => fc.constant(description.symbol); case "Keyword": { switch (description.value) { case "UndefinedKeyword": return fc => fc.constant(undefined); case "VoidKeyword": case "UnknownKeyword": case "AnyKeyword": return fc => fc.anything(); case "BooleanKeyword": return fc => fc.boolean(); case "SymbolKeyword": return fc => fc.string().map(s => Symbol.for(s)); case "ObjectKeyword": return fc => fc.oneof(fc.object(), fc.array(fc.anything())); } } case "Enums": return fc => fc.oneof(...description.enums.map(([_, value]) => fc.constant(value))); case "TemplateLiteral": { return fc => { const string = fc.string({ maxLength: 5 }); const number = fc.float({ noDefaultInfinity: true, noNaN: true }); const getTemplateLiteralArb = description => { const components = description.head !== "" ? [fc.constant(description.head)] : []; const getTemplateLiteralSpanTypeArb = description => { switch (description._tag) { case "StringKeyword": return string; case "NumberKeyword": return number; case "Literal": return fc.constant(String(description.literal)); case "Union": return fc.oneof(...description.members.map(getTemplateLiteralSpanTypeArb)); case "TemplateLiteral": return getTemplateLiteralArb(description); default: return fc.constant(""); } }; description.spans.forEach(span => { components.push(getTemplateLiteralSpanTypeArb(span.description)); if (span.literal !== "") { components.push(fc.constant(span.literal)); } }); return fc.tuple(...components).map(spans => spans.join("")); }; return getTemplateLiteralArb(description); }; } case "StringKeyword": { const constraints = buildStringConstraints(description); const pattern = constraints?.pattern; return pattern !== undefined ? fc => fc.stringMatching(new RegExp(pattern)) : fc => fc.string(constraints?.constraints); } case "NumberKeyword": { const constraints = buildNumberConstraints(description); return constraints?.isInteger ? fc => fc.integer(constraints.constraints) : fc => fc.float(constraints?.constraints); } case "BigIntKeyword": { const constraints = buildBigIntConstraints(description); return fc => fc.bigInt(constraints?.constraints ?? {}); } case "TupleType": { const elements = []; let hasOptionals = false; for (const element of description.elements) { elements.push(go(element.description, ctx)); if (element.isOptional) { hasOptionals = true; } } const rest = description.rest.map(d => go(d, ctx)); return fc => { // --------------------------------------------- // handle elements // --------------------------------------------- let output = fc.tuple(...elements.map(arb => arb(fc))); if (hasOptionals) { const indexes = fc.tuple(...description.elements.map(element => element.isOptional ? fc.boolean() : fc.constant(true))); output = output.chain(tuple => indexes.map(booleans => { for (const [i, b] of booleans.reverse().entries()) { if (!b) { tuple.splice(booleans.length - i, 1); } } return tuple; })); } // --------------------------------------------- // handle rest element // --------------------------------------------- if (Arr.isNonEmptyReadonlyArray(rest)) { const constraints = buildArrayConstraints(description) ?? constArrayConstraints; const [head, ...tail] = rest; const item = head(fc); output = output.chain(as => { const len = as.length; // We must adjust the constraints for the rest element // because the elements might have generated some values const restArrayConstraints = subtractElementsLength(constraints.constraints, len); if (restArrayConstraints.maxLength === 0) { return fc.constant(as); } /* `getSuspendedArray` is used to generate less values in the context of a recursive schema. Without it, the following schema would generate an big amount of values possibly leading to a stack overflow: ```ts type A = ReadonlyArray<A | null> const schema = S.Array( S.NullOr(S.suspend((): S.Schema<A> => schema)) ) ``` */ const arr = ctx.depthIdentifier !== undefined ? getSuspendedArray(fc, ctx.depthIdentifier, ctx.maxDepth, item, restArrayConstraints) : fc.array(item, restArrayConstraints); if (len === 0) { return arr; } return arr.map(rest => [...as, ...rest]); }); // --------------------------------------------- // handle post rest elements // --------------------------------------------- for (let j = 0; j < tail.length; j++) { output = output.chain(as => tail[j](fc).map(a => [...as, a])); } } return output; }; } case "TypeLiteral": { const propertySignatures = []; const requiredKeys = []; for (const ps of description.propertySignatures) { if (!ps.isOptional) { requiredKeys.push(ps.name); } propertySignatures.push(go(ps.value, ctx)); } const indexSignatures = description.indexSignatures.map(is => [go(is.parameter, ctx), go(is.value, ctx)]); return fc => { const pps = {}; for (let i = 0; i < propertySignatures.length; i++) { const ps = description.propertySignatures[i]; pps[ps.name] = propertySignatures[i](fc); } let output = fc.record(pps, { requiredKeys }); // --------------------------------------------- // handle index signatures // --------------------------------------------- for (let i = 0; i < indexSignatures.length; i++) { const key = indexSignatures[i][0](fc); const value = indexSignatures[i][1](fc); output = output.chain(o => { const item = fc.tuple(key, value); /* `getSuspendedArray` is used to generate less key/value pairs in the context of a recursive schema. Without it, the following schema would generate an big amount of values possibly leading to a stack overflow: ```ts type A = { [_: string]: A } const schema = S.Record({ key: S.String, value: S.suspend((): S.Schema<A> => schema) }) ``` */ const arr = ctx.depthIdentifier !== undefined ? getSuspendedArray(fc, ctx.depthIdentifier, ctx.maxDepth, item, { maxLength: 2 }) : fc.array(item); return arr.map(tuples => ({ ...Object.fromEntries(tuples), ...o })); }); } return output; }; } case "Union": { const members = description.members.map(member => go(member, ctx)); return fc => fc.oneof(...members.map(arb => arb(fc))); } case "Suspend": { const memo = arbitraryMemoMap.get(description.ast); if (memo) { return memo; } if (ctx.depthIdentifier === undefined) { ctx = { ...ctx, depthIdentifier: description.id }; } const get = util_.memoizeThunk(() => { return go(description.description(), ctx); }); const out = fc => fc.constant(null).chain(() => get()(fc)); arbitraryMemoMap.set(description.ast, out); return out; } case "Ref": { const memo = arbitraryMemoMap.get(description.ast); if (memo) { return memo; } throw new Error(`BUG: Ref ${JSON.stringify(description.id)} not found`); } } }); function subtractElementsLength(constraints, len) { if (len === 0 || constraints.minLength === undefined && constraints.maxLength === undefined) { return constraints; } const out = { ...constraints }; if (out.minLength !== undefined) { out.minLength = Math.max(out.minLength - len, 0); } if (out.maxLength !== undefined) { out.maxLength = Math.max(out.maxLength - len, 0); } return out; } const getSuspendedArray = (fc, depthIdentifier, maxDepth, item, constraints) => { // In the context of a recursive schema, we don't want a `maxLength` greater than 2. // The only exception is when `minLength` is also set, in which case we set // `maxLength` to the minimum value, which is `minLength`. const maxLengthLimit = Math.max(2, constraints.minLength ?? 0); if (constraints.maxLength !== undefined && constraints.maxLength > maxLengthLimit) { constraints = { ...constraints, maxLength: maxLengthLimit }; } return fc.oneof({ maxDepth, depthIdentifier }, fc.constant([]), fc.array(item, constraints)); }; //# sourceMappingURL=Arbitrary.js.map

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ssv445/lorem-ipsum-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server