@stryke/json
Version:
A package containing JSON parsing/stringify utilities used by Storm Software.
1 lines • 20.9 kB
Source Map (JSON)
{"version":3,"file":"schema.mjs","names":[],"sources":["../src/schema.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n 🗲 Storm Software - Stryke\n\n This code was released as part of the Stryke project. Stryke\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/stryke.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/stryke\n Documentation: https://docs.stormsoftware.com/projects/stryke\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport type { StandardJSONSchemaV1 } from \"@standard-schema/spec\";\nimport { isFunction } from \"@stryke/type-checks/is-function\";\nimport { isObject } from \"@stryke/type-checks/is-object\";\nimport { isSetObject } from \"@stryke/type-checks/is-set-object\";\nimport { isString } from \"@stryke/type-checks/is-string\";\nimport type {\n JsonSchemaAllOfType,\n JsonSchemaAnyOfType,\n JsonSchemaArrayType,\n JsonSchemaBooleanType,\n JsonSchemaLiteralType,\n JsonSchemaMetadata,\n JsonSchemaNumberType,\n JsonSchemaObjectType,\n JsonSchemaPrimitiveLiteralType,\n JsonSchemaRecordType,\n JsonSchemaStringType,\n JsonSchemaTupleType,\n JsonSchemaType\n} from \"./types\";\n\n/**\n * Type guard for {@link JsonSchemaAllOfType}\n *\n * @param schema - The schema to check\n * @returns True if the schema is a {@link JsonSchemaAllOfType}, false otherwise\n */\nexport function isJsonSchemaAllOfType(\n schema: any\n): schema is JsonSchemaAllOfType {\n if (isSetObject(schema) && \"type\" in schema && schema.type === \"string\") {\n return false;\n }\n\n return isSetObject(schema) && \"allOf\" in schema;\n}\n\n/**\n * Type guard for {@link JsonSchemaAnyOfType}\n *\n * @param schema - The schema to check\n * @returns True if the schema is a {@link JsonSchemaAnyOfType}, false otherwise\n */\nexport function isJsonSchemaAnyOfType(\n schema: any\n): schema is JsonSchemaAnyOfType {\n return (\n isSetObject(schema) && \"anyOf\" in schema && Array.isArray(schema.anyOf)\n );\n}\n\n/**\n * Type guard for {@link JsonSchemaObjectType}\n *\n * @param schema - The schema to check\n * @returns True if the schema is a {@link JsonSchemaObjectType}, false otherwise\n */\nexport function isJsonSchemaObjectType(\n schema: any\n): schema is JsonSchemaObjectType {\n return isSetObject(schema) && \"type\" in schema && schema.type === \"object\";\n}\n\n/**\n * Type guard for {@link JsonSchemaStringType}\n *\n * @param schema - The schema to check\n * @returns True if the schema is a {@link JsonSchemaStringType}, false otherwise\n */\nexport function isJsonSchemaStringType(\n schema: any\n): schema is JsonSchemaStringType {\n return isSetObject(schema) && \"type\" in schema && schema.type === \"string\";\n}\n\n/**\n * Type guard for {@link JsonSchemaNumberType}\n *\n * @param schema - The schema to check\n * @returns True if the schema is a {@link JsonSchemaNumberType}, false otherwise\n */\nexport function isJsonSchemaNumberType(\n schema: any\n): schema is JsonSchemaNumberType {\n return (\n isSetObject(schema) &&\n \"type\" in schema &&\n (schema.type === \"number\" || schema.type === \"integer\")\n );\n}\n\n/**\n * Type guard for {@link JsonSchemaBooleanType}\n *\n * @param schema - The schema to check\n * @returns True if the schema is a {@link JsonSchemaBooleanType}, false otherwise\n */\nexport function isJsonSchemaBooleanType(\n schema: any\n): schema is JsonSchemaBooleanType {\n return isSetObject(schema) && \"type\" in schema && schema.type === \"boolean\";\n}\n\n/**\n * Type guard for {@link JsonSchemaArrayType}\n *\n * @param schema - The schema to check\n * @returns True if the schema is a {@link JsonSchemaArrayType}, false otherwise\n */\nexport function isJsonSchemaArrayType(\n schema: any\n): schema is JsonSchemaArrayType {\n return (\n isSetObject(schema) &&\n \"type\" in schema &&\n schema.type === \"array\" &&\n \"items\" in schema\n );\n}\n\n/**\n * Type guard for {@link JsonSchemaTupleType}\n *\n * @param schema - The schema to check\n * @returns True if the schema is a {@link JsonSchemaTupleType}, false otherwise\n */\nexport function isJsonSchemaTupleType(\n schema: any\n): schema is JsonSchemaTupleType {\n return (\n isSetObject(schema) &&\n \"type\" in schema &&\n schema.type === \"array\" &&\n \"items\" in schema &&\n Array.isArray(schema.items)\n );\n}\n\n/**\n * Type guard for {@link JsonSchemaPrimitiveLiteralType}\n *\n * @param schema - The schema to check\n * @returns True if the schema is a {@link JsonSchemaPrimitiveLiteralType}, false otherwise\n */\nexport function isJsonSchemaPrimitiveLiteralType(\n schema: any\n): schema is JsonSchemaPrimitiveLiteralType {\n if (!isSetObject(schema) || !(\"type\" in schema)) {\n return false;\n }\n\n const { type } = schema;\n\n return (\n (type === \"string\" ||\n type === \"number\" ||\n type === \"integer\" ||\n type === \"boolean\") &&\n \"const\" in schema\n );\n}\n\n/**\n * Type guard for {@link JsonSchemaLiteralType}\n *\n * @param schema - The schema to check\n * @returns True if the schema is a {@link JsonSchemaLiteralType}, false otherwise\n */\nexport function isJsonSchemaLiteralType(\n schema: any\n): schema is JsonSchemaLiteralType {\n if (isJsonSchemaPrimitiveLiteralType(schema)) {\n return true;\n }\n\n if (!isSetObject(schema) || !(\"type\" in schema)) {\n return false;\n }\n\n return schema.type === \"object\" || schema.type === \"array\";\n}\n\nexport function isJsonSchemaRecordType(\n schema: any\n): schema is JsonSchemaRecordType {\n return (\n isSetObject(schema) &&\n \"type\" in schema &&\n schema.type === \"object\" &&\n \"additionalProperties\" in schema &&\n isSetObject(schema.additionalProperties) &&\n \"propertyNames\" in schema &&\n isSetObject(schema.propertyNames)\n );\n}\n\nexport function isJsonSchemaMetadata(\n schema: any\n): schema is JsonSchemaMetadata {\n return (\n isSetObject(schema) &&\n (!(\"$id\" in schema) || isString(schema.$id)) &&\n (!(\"$schema\" in schema) || isString(schema.$schema)) &&\n (!(\"$comment\" in schema) || isString(schema.$comment)) &&\n (!(\"$defs\" in schema) || isObject(schema.$defs)) &&\n (!(\"$dynamicRef\" in schema) || isString(schema.$dynamicRef)) &&\n (!(\"$dynamicAnchor\" in schema) || isString(schema.$dynamicAnchor)) &&\n (!(\"name\" in schema) || isString(schema.name)) &&\n (!(\"title\" in schema) || isString(schema.title)) &&\n (!(\"description\" in schema) || isString(schema.description)) &&\n (!(\"alias\" in schema) ||\n isString(schema.alias) ||\n (Array.isArray(schema.alias) && schema.alias.every(isString)))\n );\n}\n\n/**\n * Type guard to check if a value is a {@link StandardJSONSchemaV1 | Standard JSON Schema}.\n *\n * @remarks\n * This function checks if the value has the structure of a Standard JSON Schema, which includes a `~standard` property with a `jsonSchema` object that has `input` and `output` functions.\n *\n * @see https://standardschema.dev/json-schema\n *\n * @param value - The value to check.\n * @returns True if the value is a {@link StandardJSONSchemaV1 | Standard JSON Schema}, false otherwise.\n */\nexport function isStandardJsonSchema<Input = unknown, Output = Input>(\n value: any\n): value is StandardJSONSchemaV1<Input, Output> {\n return (\n isSetObject(value) &&\n \"~standard\" in value &&\n isSetObject(value[\"~standard\"]) &&\n \"jsonSchema\" in value[\"~standard\"] &&\n isSetObject(value[\"~standard\"].jsonSchema) &&\n \"input\" in value[\"~standard\"].jsonSchema &&\n isFunction(value[\"~standard\"].jsonSchema.input) &&\n \"output\" in value[\"~standard\"].jsonSchema &&\n isFunction(value[\"~standard\"].jsonSchema.output)\n );\n}\n\n/**\n * Merges multiple {@link JsonSchemaMetadata} objects into a single object, combining their properties. If there are conflicting properties, the last one will take precedence.\n *\n * @param schemas - The schemas to merge\n * @returns The merged {@link JsonSchemaMetadata} object, or undefined if no valid schemas are provided\n */\nexport function mergeMetadataSchemaSafe(\n ...schemas: JsonSchemaMetadata[]\n): JsonSchemaMetadata | undefined {\n const filtered = schemas.filter(isJsonSchemaMetadata);\n if (filtered.length === 0) {\n return undefined;\n }\n\n let result = {} as JsonSchemaMetadata;\n for (const schema of filtered) {\n result = {\n ...result,\n ...schema,\n $defs: {\n ...result.$defs,\n ...schema.$defs\n }\n };\n }\n\n return result;\n}\n\n/**\n * Merges multiple {@link JsonSchemaMetadata} objects into a single object, combining their properties. If there are conflicting properties, the last one will take precedence.\n *\n * @remarks\n * If any of the provided schemas are not valid {@link JsonSchemaMetadata} objects, or if no valid schemas are provided for merging, this function will throw an error. Use {@link mergeMetadataSchemaSafe} if you want to ignore invalid schemas instead.\n *\n * @param schemas - The schemas to merge\n * @returns The merged {@link JsonSchemaMetadata} object\n * @throws Error if any of the provided schemas are not valid {@link JsonSchemaMetadata} objects, or if no valid schemas are provided for merging. Use {@link mergeMetadataSchemaSafe} if you want to ignore invalid schemas instead.\n */\nexport function mergeMetadataSchemaStrict(\n ...schemas: JsonSchemaMetadata[]\n): JsonSchemaMetadata {\n const filtered = schemas.filter(isJsonSchemaMetadata);\n if (filtered.length !== schemas.length) {\n throw new Error(\n `All schemas must be of type JsonSchemaMetadata - found ${\n schemas.length - filtered.length\n } invalid schema types`\n );\n }\n\n return mergeMetadataSchemaSafe(...schemas)!;\n}\n\n/**\n * Merges multiple {@link JsonSchemaObjectType} schemas into a single schema, combining their properties and required fields. If there are no valid object type schemas, throws an error.\n *\n * @remarks If there are overlapping properties, the last schema's property definition will take precedence. Required fields from all schemas will be combined, and duplicates will be removed. If all of the provided schemas are not valid {@link JsonSchemaObjectType} objects, or if no valid object type schemas are provided for merging, this function will throw an error. Use {@link mergeObjectTypeSchemaSafe} if you want to ignore invalid schemas instead.\n *\n * @param schemas - The schemas to merge\n * @returns The merged {@link JsonSchemaMetadata} object\n * @throws Error if all of the provided schemas are not valid {@link JsonSchemaObjectType} objects, or if no valid object type schemas are provided for merging. Use {@link mergeObjectTypeSchemaSafe} if you want to ignore invalid schemas instead.\n */\nexport function mergeMetadataSchema(\n ...schemas: JsonSchemaMetadata[]\n): JsonSchemaMetadata {\n const merged = mergeMetadataSchemaSafe(...schemas);\n if (!merged) {\n throw new Error(\"No valid JsonSchemaMetadata objects provided for merge\");\n }\n\n return merged;\n}\n\n/**\n * Merges multiple {@link JsonSchemaMetadata} objects into a single object, combining their properties. If there are conflicting properties, the last one will take precedence.\n *\n * @param schemas - The schemas to merge\n * @returns The merged {@link JsonSchemaMetadata} object, or undefined if no valid schemas are provided\n */\nexport function mergeObjectTypeSchemaSafe(\n ...schemas: JsonSchemaObjectType[]\n): JsonSchemaObjectType | undefined {\n const filtered = schemas.filter(isJsonSchemaObjectType);\n if (filtered.length === 0) {\n return undefined;\n }\n\n const mergedProperties: Record<string, JsonSchemaType> = {};\n const mergedRequired: Set<string> = new Set();\n\n for (const schema of filtered) {\n Object.assign(mergedProperties, schema.properties);\n if (schema.required) {\n for (const prop of schema.required) {\n mergedRequired.add(prop);\n }\n }\n }\n\n return {\n ...mergeObjectTypeSchemaSafe(...schemas),\n type: \"object\",\n properties: mergedProperties,\n required: Array.from(mergedRequired)\n };\n}\n\n/**\n * Merges multiple {@link JsonSchemaObjectType} objects into a single object, combining their properties. If there are conflicting properties, the last one will take precedence.\n *\n * @remarks\n * If any of the provided schemas are not valid {@link JsonSchemaObjectType} objects, or if no valid schemas are provided for merging, this function will throw an error. Use {@link mergeObjectTypeSchemaSafe} if you want to ignore invalid schemas instead.\n *\n * @param schemas - The schemas to merge\n * @returns The merged {@link JsonSchemaObjectType} object\n * @throws Error if any of the provided schemas are not valid {@link JsonSchemaObjectType} objects, or if no valid schemas are provided for merging. Use {@link mergeObjectTypeSchemaSafe} if you want to ignore invalid schemas instead.\n */\nexport function mergeObjectTypeSchemaStrict(\n ...schemas: JsonSchemaObjectType[]\n): JsonSchemaObjectType {\n const filtered = schemas.filter(isJsonSchemaObjectType);\n if (filtered.length !== schemas.length) {\n throw new Error(\n `All schemas must be of type JsonSchemaObjectType - found ${\n schemas.length - filtered.length\n } invalid schema types`\n );\n }\n\n return mergeObjectTypeSchemaSafe(...schemas)!;\n}\n\n/**\n * Merges multiple {@link JsonSchemaObjectType} schemas into a single schema, combining their properties and required fields. If there are no valid object type schemas, throws an error.\n *\n * @remarks If there are overlapping properties, the last schema's property definition will take precedence. Required fields from all schemas will be combined, and duplicates will be removed. If all of the provided schemas are not valid {@link JsonSchemaObjectType} objects, or if no valid object type schemas are provided for merging, this function will throw an error. Use {@link mergeObjectTypeSchemaSafe} if you want to ignore invalid schemas instead.\n *\n * @param schemas - The schemas to merge\n * @returns The merged {@link JsonSchemaObjectType} object\n * @throws Error if all of the provided schemas are not valid {@link JsonSchemaObjectType} objects, or if no valid object type schemas are provided for merging. Use {@link mergeObjectTypeSchemaSafe} if you want to ignore invalid schemas instead.\n */\nexport function mergeObjectTypeSchema(\n ...schemas: JsonSchemaObjectType[]\n): JsonSchemaObjectType {\n const merged = mergeObjectTypeSchemaSafe(...schemas);\n if (!merged) {\n throw new Error(\"No valid JsonSchemaObjectType objects provided for merge\");\n }\n\n return merged;\n}\n\n/**\n * Extracts a {@link JsonSchemaObjectType} from a given {@link JsonSchemaType}, if it exists.\n *\n * @param schema - The schema to extract the object type from\n * @returns The extracted {@link JsonSchemaObjectType}, or undefined if it does not exist\n */\nexport function extractObjectTypeSchema(\n schema: JsonSchemaType\n): JsonSchemaObjectType | undefined {\n if (isJsonSchemaObjectType(schema)) {\n return schema;\n }\n\n if (isJsonSchemaAllOfType(schema)) {\n const extracted = schema.allOf\n .map(extractObjectTypeSchema)\n .filter((s): s is JsonSchemaObjectType => s !== undefined);\n if (extracted.length === 0) {\n return undefined;\n }\n\n return mergeObjectTypeSchemaSafe(...extracted);\n }\n\n if (isJsonSchemaAnyOfType(schema)) {\n const extracted = schema.anyOf\n .map(extractObjectTypeSchema)\n .filter((s): s is JsonSchemaObjectType => s !== undefined);\n if (extracted.length === 0 || extracted.length !== schema.anyOf.length) {\n return undefined;\n }\n\n const [first, ...rest] = extracted as [\n JsonSchemaObjectType,\n ...JsonSchemaObjectType[]\n ];\n const commonProperties: Record<string, JsonSchemaType> = {};\n for (const [key, value] of Object.entries(first.properties)) {\n if (rest.every(s => s.properties && key in s.properties)) {\n commonProperties[key] = value;\n }\n }\n\n const commonRequired = (first.required ?? []).filter(prop =>\n rest.every(s => s.required?.includes(prop))\n );\n\n return {\n type: \"object\",\n properties: commonProperties,\n required: commonRequired\n };\n }\n\n if (isJsonSchemaRecordType(schema)) {\n return {\n type: \"object\",\n properties: {},\n additionalProperties: schema.additionalProperties,\n required: []\n };\n }\n\n return undefined;\n}\n"],"mappings":"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"}