Skip to main content
Glama
ssv445

Lorem Ipsum MCP Server

by ssv445
JSONSchema.js24.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.make = exports.fromAST = void 0; var Arr = _interopRequireWildcard(require("./Array.js")); var errors_ = _interopRequireWildcard(require("./internal/schema/errors.js")); var Option = _interopRequireWildcard(require("./Option.js")); var ParseResult = _interopRequireWildcard(require("./ParseResult.js")); var Predicate = _interopRequireWildcard(require("./Predicate.js")); var Record = _interopRequireWildcard(require("./Record.js")); var AST = _interopRequireWildcard(require("./SchemaAST.js")); function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } /** * @since 3.10.0 */ /** * @category encoding * @since 3.10.0 */ const make = schema => { const definitions = {}; const ast = AST.isTransformation(schema.ast) && isParseJsonTransformation(schema.ast.from) // Special case top level `parseJson` transformations ? schema.ast.to : schema.ast; const jsonSchema = fromAST(ast, { definitions }); const out = { $schema, $defs: {}, ...jsonSchema }; if (Record.isEmptyRecord(definitions)) { delete out.$defs; } else { out.$defs = definitions; } return out; }; /** * Returns a JSON Schema with additional options and definitions. * * **Warning** * * This function is experimental and subject to change. * * **Options** * * - `definitions`: A record of definitions that are included in the schema. * - `definitionPath`: The path to the definitions within the schema (defaults * to "#/$defs/"). * - `target`: Which spec to target. Possible values are: * - `'jsonSchema7'`: JSON Schema draft-07 (default behavior). * - `'jsonSchema2019-09'`: JSON Schema draft-2019-09. * - `'openApi3.1'`: OpenAPI 3.1. * - `topLevelReferenceStrategy`: Controls the handling of the top-level * reference. Possible values are: * - `"keep"`: Keep the top-level reference (default behavior). * - `"skip"`: Skip the top-level reference. * - `additionalPropertiesStrategy`: Controls the handling of additional properties. Possible values are: * - `"strict"`: Disallow additional properties (default behavior). * - `"allow"`: Allow additional properties. * * @category encoding * @since 3.11.5 * @experimental */ exports.make = make; const fromAST = (ast, options) => { const definitionPath = options.definitionPath ?? "#/$defs/"; const getRef = id => definitionPath + id; const target = options.target ?? "jsonSchema7"; const handleIdentifier = options.topLevelReferenceStrategy !== "skip"; const additionalPropertiesStrategy = options.additionalPropertiesStrategy ?? "strict"; return go(ast, options.definitions, handleIdentifier, [], { getRef, target, additionalPropertiesStrategy }); }; exports.fromAST = fromAST; const constNever = { "$id": "/schemas/never", "not": {} }; const constAny = { "$id": "/schemas/any" }; const constUnknown = { "$id": "/schemas/unknown" }; const constVoid = { "$id": "/schemas/void" }; const constAnyObject = { "$id": "/schemas/object", "anyOf": [{ "type": "object" }, { "type": "array" }] }; const constEmpty = { "$id": "/schemas/%7B%7D", "anyOf": [{ "type": "object" }, { "type": "array" }] }; const $schema = "http://json-schema.org/draft-07/schema#"; const getJsonSchemaAnnotations = (ast, annotated) => { annotated ??= ast; const out = Record.getSomes({ description: AST.getDescriptionAnnotation(annotated), title: AST.getTitleAnnotation(annotated), default: AST.getDefaultAnnotation(annotated) }); const oexamples = AST.getExamplesAnnotation(annotated); if (Option.isSome(oexamples) && oexamples.value.length > 0) { const getOption = ParseResult.getOption(ast, false); const examples = Arr.filterMap(oexamples.value, e => getOption(e)); if (examples.length > 0) { out.examples = examples; } } return out; }; const removeDefaultJsonSchemaAnnotations = (jsonSchemaAnnotations, ast) => { if (jsonSchemaAnnotations["title"] === ast.annotations[AST.TitleAnnotationId]) { delete jsonSchemaAnnotations["title"]; } if (jsonSchemaAnnotations["description"] === ast.annotations[AST.DescriptionAnnotationId]) { delete jsonSchemaAnnotations["description"]; } return jsonSchemaAnnotations; }; const getASTJsonSchemaAnnotations = ast => { const jsonSchemaAnnotations = getJsonSchemaAnnotations(ast); switch (ast._tag) { case "StringKeyword": return removeDefaultJsonSchemaAnnotations(jsonSchemaAnnotations, AST.stringKeyword); case "NumberKeyword": return removeDefaultJsonSchemaAnnotations(jsonSchemaAnnotations, AST.numberKeyword); case "BooleanKeyword": return removeDefaultJsonSchemaAnnotations(jsonSchemaAnnotations, AST.booleanKeyword); default: return jsonSchemaAnnotations; } }; const pruneUndefined = ast => { if (Option.isNone(AST.getJSONSchemaAnnotation(ast))) { return AST.pruneUndefined(ast, pruneUndefined, ast => pruneUndefined(ast.from)); } }; const isParseJsonTransformation = ast => ast.annotations[AST.SchemaIdAnnotationId] === AST.ParseJsonSchemaId; const isOverrideAnnotation = jsonSchema => { return "type" in jsonSchema || "oneOf" in jsonSchema || "anyOf" in jsonSchema || "const" in jsonSchema || "enum" in jsonSchema || "$ref" in jsonSchema; }; // Returns true if the schema is an enum with no other properties other than the // optional "type". This is used to merge enums together. const isMergeableEnum = jsonSchema => { const len = Object.keys(jsonSchema).length; return "enum" in jsonSchema && (len === 1 || "type" in jsonSchema && len === 2); }; // Some validators do not support enums without a type keyword. This function // adds a type keyword to the schema if it is missing and the enum values are // homogeneous. const addEnumType = jsonSchema => { if ("enum" in jsonSchema && !("type" in jsonSchema)) { const type = jsonSchema.enum.every(Predicate.isString) ? "string" : jsonSchema.enum.every(Predicate.isNumber) ? "number" : jsonSchema.enum.every(Predicate.isBoolean) ? "boolean" : undefined; if (type !== undefined) { return { type, ...jsonSchema }; } } return jsonSchema; }; const mergeRefinements = (from, jsonSchema, annotations) => { const out = { ...from, ...annotations, ...jsonSchema }; out.allOf ??= []; const handle = (name, filter) => { if (name in jsonSchema && name in from) { out.allOf.unshift({ [name]: from[name] }); out.allOf = out.allOf.filter(filter); } }; handle("minLength", i => i.minLength > jsonSchema.minLength); handle("maxLength", i => i.maxLength < jsonSchema.maxLength); handle("pattern", i => i.pattern !== jsonSchema.pattern); handle("minItems", i => i.minItems > jsonSchema.minItems); handle("maxItems", i => i.maxItems < jsonSchema.maxItems); handle("minimum", i => i.minimum > jsonSchema.minimum); handle("maximum", i => i.maximum < jsonSchema.maximum); handle("exclusiveMinimum", i => i.exclusiveMinimum > jsonSchema.exclusiveMinimum); handle("exclusiveMaximum", i => i.exclusiveMaximum < jsonSchema.exclusiveMaximum); handle("multipleOf", i => i.multipleOf !== jsonSchema.multipleOf); if (out.allOf.length === 0) { delete out.allOf; } return out; }; function isContentSchemaSupported(options) { switch (options.target) { case "jsonSchema7": return false; case "jsonSchema2019-09": case "openApi3.1": return true; } } function isNullTypeKeywordSupported(options) { switch (options.target) { case "jsonSchema7": case "jsonSchema2019-09": return true; case "openApi3.1": return false; } } // https://swagger.io/docs/specification/v3_0/data-models/data-types/#null function isNullableKeywordSupported(options) { switch (options.target) { case "jsonSchema7": case "jsonSchema2019-09": return false; case "openApi3.1": return true; } } function getAdditionalProperties(options) { switch (options.additionalPropertiesStrategy) { case "allow": return true; case "strict": return false; } } const isNeverJSONSchema = jsonSchema => "$id" in jsonSchema && jsonSchema.$id === "/schemas/never"; const isAnyJSONSchema = jsonSchema => "$id" in jsonSchema && jsonSchema.$id === "/schemas/any"; const isUnknownJSONSchema = jsonSchema => "$id" in jsonSchema && jsonSchema.$id === "/schemas/unknown"; const isVoidJSONSchema = jsonSchema => "$id" in jsonSchema && jsonSchema.$id === "/schemas/void"; const shrink = members => { let i = members.findIndex(isAnyJSONSchema); if (i !== -1) { members = [members[i]]; } i = members.findIndex(isUnknownJSONSchema); if (i !== -1) { members = [members[i]]; } i = members.findIndex(isVoidJSONSchema); if (i !== -1) { members = [members[i]]; } return members; }; const go = (ast, $defs, handleIdentifier, path, options) => { if (handleIdentifier) { const identifier = AST.getJSONIdentifier(ast); if (Option.isSome(identifier)) { const id = identifier.value; const escapedId = id.replace(/~/ig, "~0").replace(/\//ig, "~1"); const out = { $ref: options.getRef(escapedId) }; if (!Record.has($defs, id)) { $defs[id] = out; $defs[id] = go(ast, $defs, false, path, options); } return out; } } const hook = AST.getJSONSchemaAnnotation(ast); if (Option.isSome(hook)) { const handler = hook.value; if (AST.isRefinement(ast)) { const t = AST.getTransformationFrom(ast); if (t === undefined) { return mergeRefinements(go(ast.from, $defs, handleIdentifier, path, options), handler, getJsonSchemaAnnotations(ast)); } else if (!isOverrideAnnotation(handler)) { return go(t, $defs, handleIdentifier, path, options); } } if (AST.isDeclaration(ast)) { return { ...handler, ...getJsonSchemaAnnotations(ast) }; } return handler; } const surrogate = AST.getSurrogateAnnotation(ast); if (Option.isSome(surrogate)) { return go(surrogate.value, $defs, handleIdentifier, path, options); } switch (ast._tag) { case "Declaration": throw new Error(errors_.getJSONSchemaMissingAnnotationErrorMessage(path, ast)); case "Literal": { const literal = ast.literal; if (literal === null) { if (isNullTypeKeywordSupported(options)) { // https://json-schema.org/draft-07/draft-handrews-json-schema-validation-00.pdf // Section 6.1.1 return { type: "null", ...getJsonSchemaAnnotations(ast) }; } else { // OpenAPI 3.1 does not support the "null" type keyword // https://swagger.io/docs/specification/v3_0/data-models/data-types/#null return { // @ts-expect-error enum: [null], ...getJsonSchemaAnnotations(ast) }; } } else if (Predicate.isString(literal)) { return { type: "string", enum: [literal], ...getJsonSchemaAnnotations(ast) }; } else if (Predicate.isNumber(literal)) { return { type: "number", enum: [literal], ...getJsonSchemaAnnotations(ast) }; } else if (Predicate.isBoolean(literal)) { return { type: "boolean", enum: [literal], ...getJsonSchemaAnnotations(ast) }; } throw new Error(errors_.getJSONSchemaMissingAnnotationErrorMessage(path, ast)); } case "UniqueSymbol": throw new Error(errors_.getJSONSchemaMissingAnnotationErrorMessage(path, ast)); case "UndefinedKeyword": throw new Error(errors_.getJSONSchemaMissingAnnotationErrorMessage(path, ast)); case "VoidKeyword": return { ...constVoid, ...getJsonSchemaAnnotations(ast) }; case "NeverKeyword": return { ...constNever, ...getJsonSchemaAnnotations(ast) }; case "UnknownKeyword": return { ...constUnknown, ...getJsonSchemaAnnotations(ast) }; case "AnyKeyword": return { ...constAny, ...getJsonSchemaAnnotations(ast) }; case "ObjectKeyword": return { ...constAnyObject, ...getJsonSchemaAnnotations(ast) }; case "StringKeyword": return { type: "string", ...getASTJsonSchemaAnnotations(ast) }; case "NumberKeyword": return { type: "number", ...getASTJsonSchemaAnnotations(ast) }; case "BooleanKeyword": return { type: "boolean", ...getASTJsonSchemaAnnotations(ast) }; case "BigIntKeyword": throw new Error(errors_.getJSONSchemaMissingAnnotationErrorMessage(path, ast)); case "SymbolKeyword": throw new Error(errors_.getJSONSchemaMissingAnnotationErrorMessage(path, ast)); case "TupleType": { const elements = ast.elements.map((e, i) => ({ ...go(e.type, $defs, true, path.concat(i), options), ...getJsonSchemaAnnotations(e.type, e) })); const rest = ast.rest.map(annotatedAST => ({ ...go(annotatedAST.type, $defs, true, path, options), ...getJsonSchemaAnnotations(annotatedAST.type, annotatedAST) })); const output = { type: "array" }; // --------------------------------------------- // handle elements // --------------------------------------------- const len = ast.elements.length; if (len > 0) { output.minItems = len - ast.elements.filter(element => element.isOptional).length; output.items = elements; } // --------------------------------------------- // handle rest element // --------------------------------------------- const restLength = rest.length; if (restLength > 0) { const head = rest[0]; const isHomogeneous = restLength === 1 && ast.elements.every(e => e.type === ast.rest[0].type); if (isHomogeneous) { output.items = head; } else { output.additionalItems = head; } // --------------------------------------------- // handle post rest elements // --------------------------------------------- if (restLength > 1) { throw new Error(errors_.getJSONSchemaUnsupportedPostRestElementsErrorMessage(path)); } } else { if (len > 0) { output.additionalItems = false; } else { output.maxItems = 0; } } return { ...output, ...getJsonSchemaAnnotations(ast) }; } case "TypeLiteral": { if (ast.propertySignatures.length === 0 && ast.indexSignatures.length === 0) { return { ...constEmpty, ...getJsonSchemaAnnotations(ast) }; } const output = { type: "object", required: [], properties: {}, additionalProperties: getAdditionalProperties(options) }; let patternProperties = undefined; let propertyNames = undefined; for (const is of ast.indexSignatures) { const pruned = pruneUndefined(is.type) ?? is.type; const parameter = is.parameter; switch (parameter._tag) { case "StringKeyword": { output.additionalProperties = go(pruned, $defs, true, path, options); break; } case "TemplateLiteral": { patternProperties = go(pruned, $defs, true, path, options); propertyNames = { type: "string", pattern: AST.getTemplateLiteralRegExp(parameter).source }; break; } case "Refinement": { patternProperties = go(pruned, $defs, true, path, options); propertyNames = go(parameter, $defs, true, path, options); break; } case "SymbolKeyword": { const indexSignaturePath = path.concat("[symbol]"); output.additionalProperties = go(pruned, $defs, true, indexSignaturePath, options); propertyNames = go(parameter, $defs, true, indexSignaturePath, options); break; } } } // --------------------------------------------- // handle property signatures // --------------------------------------------- for (let i = 0; i < ast.propertySignatures.length; i++) { const ps = ast.propertySignatures[i]; const name = ps.name; if (Predicate.isString(name)) { const pruned = pruneUndefined(ps.type); const type = pruned ?? ps.type; output.properties[name] = { ...go(type, $defs, true, path.concat(ps.name), options), ...getJsonSchemaAnnotations(type, ps) }; // --------------------------------------------- // handle optional property signatures // --------------------------------------------- if (!ps.isOptional && pruned === undefined) { output.required.push(name); } } else { throw new Error(errors_.getJSONSchemaUnsupportedKeyErrorMessage(name, path)); } } // --------------------------------------------- // handle index signatures // --------------------------------------------- if (patternProperties !== undefined) { delete output.additionalProperties; output.patternProperties = { "": patternProperties }; } if (propertyNames !== undefined) { output.propertyNames = propertyNames; } return { ...output, ...getJsonSchemaAnnotations(ast) }; } case "Union": { const members = []; for (const type of ast.types) { const jsonSchema = go(type, $defs, true, path, options); if (!isNeverJSONSchema(jsonSchema)) { const last = members[members.length - 1]; if (isMergeableEnum(jsonSchema) && last !== undefined && isMergeableEnum(last)) { members[members.length - 1] = { enum: last.enum.concat(jsonSchema.enum) }; } else { members.push(jsonSchema); } } } const anyOf = shrink(members); const finalize = anyOf => { switch (anyOf.length) { case 0: return { ...constNever, ...getJsonSchemaAnnotations(ast) }; case 1: { return { ...addEnumType(anyOf[0]), ...getJsonSchemaAnnotations(ast) }; } default: return { anyOf: anyOf.map(addEnumType), ...getJsonSchemaAnnotations(ast) }; } }; if (isNullableKeywordSupported(options)) { let nullable = false; const nonNullables = []; for (const s of anyOf) { if ("nullable" in s) { nullable = true; const nn = { ...s }; delete nn.nullable; nonNullables.push(nn); } else if (isMergeableEnum(s)) { const nnes = s.enum.filter(e => e !== null); if (nnes.length < s.enum.length) { nullable = true; if (nnes.length === 0) { continue; } const nn = { ...s }; nn.enum = nnes; nonNullables.push(nn); } } else { nonNullables.push(s); } } if (nullable) { const out = finalize(nonNullables); if (!isAnyJSONSchema(out) && !isUnknownJSONSchema(out)) { // @ts-expect-error out.nullable = nullable; } return out; } } return finalize(anyOf); } case "Enums": { const anyOf = ast.enums.map(e => addEnumType({ title: e[0], enum: [e[1]] })); return anyOf.length >= 1 ? { $comment: "/schemas/enums", anyOf, ...getJsonSchemaAnnotations(ast) } : { ...constNever, ...getJsonSchemaAnnotations(ast) }; } case "Refinement": { // The jsonSchema annotation is required only if the refinement does not have a transformation if (AST.getTransformationFrom(ast) === undefined) { throw new Error(errors_.getJSONSchemaMissingAnnotationErrorMessage(path, ast)); } return go(ast.from, $defs, handleIdentifier, path, options); } case "TemplateLiteral": { const regex = AST.getTemplateLiteralRegExp(ast); return { type: "string", title: String(ast), description: "a template literal", pattern: regex.source, ...getJsonSchemaAnnotations(ast) }; } case "Suspend": { const identifier = Option.orElse(AST.getJSONIdentifier(ast), () => AST.getJSONIdentifier(ast.f())); if (Option.isNone(identifier)) { throw new Error(errors_.getJSONSchemaMissingIdentifierAnnotationErrorMessage(path, ast)); } return go(ast.f(), $defs, handleIdentifier, path, options); } case "Transformation": { if (isParseJsonTransformation(ast.from)) { const out = { "type": "string", "contentMediaType": "application/json" }; if (isContentSchemaSupported(options)) { out["contentSchema"] = go(ast.to, $defs, handleIdentifier, path, options); } return out; } let next = ast.from; if (AST.isTypeLiteralTransformation(ast.transformation)) { // Annotations from the transformation are applied unless there are user-defined annotations on the form side, // ensuring that the user's intended annotations are included in the generated schema. const identifier = AST.getIdentifierAnnotation(ast); if (Option.isSome(identifier) && Option.isNone(AST.getIdentifierAnnotation(next))) { next = AST.annotations(next, { [AST.IdentifierAnnotationId]: identifier.value }); } const title = AST.getTitleAnnotation(ast); if (Option.isSome(title) && Option.isNone(AST.getTitleAnnotation(next))) { next = AST.annotations(next, { [AST.TitleAnnotationId]: title.value }); } const description = AST.getDescriptionAnnotation(ast); if (Option.isSome(description) && Option.isNone(AST.getDescriptionAnnotation(next))) { next = AST.annotations(next, { [AST.DescriptionAnnotationId]: description.value }); } } return go(next, $defs, handleIdentifier, path, options); } } }; //# sourceMappingURL=JSONSchema.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