{"version":3,"file":"JsonSchema.js","sourceRoot":"","sources":["../src/JsonSchema.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport * as os from 'os';\nimport * as path from 'path';\n\nimport { FileSystem } from './FileSystem';\nimport { JsonFile, type JsonObject } from './JsonFile';\n\nimport Ajv, { type Options as AjvOptions, type ErrorObject, type ValidateFunction } from 'ajv';\nimport AjvDraft04 from 'ajv-draft-04';\nimport addFormats from 'ajv-formats';\n\ninterface ISchemaWithId {\n // draft-04 uses \"id\"\n id: string | undefined;\n // draft-06 and higher uses \"$id\"\n $id: string | undefined;\n}\n\n/**\n * Specifies the version of json-schema to be validated against.\n * https://json-schema.org/specification\n * @public\n */\nexport type JsonSchemaVersion = 'draft-04' | 'draft-07';\n\n/**\n * A definition for a custom format to consider during validation.\n * @public\n */\nexport interface IJsonSchemaCustomFormat {\n /**\n * The base JSON type.\n */\n type: T extends string ? 'string' : T extends number ? 'number' : never;\n\n /**\n * A validation function for the format.\n * @param data - The raw field data to validate.\n * @returns whether the data is valid according to the format.\n */\n validate: (data: T) => boolean;\n}\n\n/**\n * Callback function arguments for {@link JsonSchema.validateObjectWithCallback}\n * @public\n */\nexport interface IJsonSchemaErrorInfo {\n /**\n * The ajv error list, formatted as an indented text string.\n */\n details: string;\n}\n\n/**\n * Options for {@link JsonSchema.validateObjectWithCallback}\n * @public\n */\nexport interface IJsonSchemaValidateObjectWithOptions {\n /**\n * If true, the root-level `$schema` property in a JSON object being validated will be ignored during validation.\n * If this is set to `true` and the schema requires a `$schema` property, validation will fail.\n */\n ignoreSchemaField?: boolean;\n}\n\n/**\n * Options for {@link JsonSchema.validateObject}\n * @public\n */\nexport interface IJsonSchemaValidateOptions extends IJsonSchemaValidateObjectWithOptions {\n /**\n * A custom header that will be used to report schema errors.\n * @remarks\n * If omitted, the default header is \"JSON validation failed:\". The error message starts with\n * the header, followed by the full input filename, followed by the ajv error list.\n * If you wish to customize all aspects of the error message, use JsonFile.loadAndValidateWithCallback()\n * or JsonSchema.validateObjectWithCallback().\n */\n customErrorHeader?: string;\n}\n\n/**\n * Options for {@link JsonSchema.fromFile} and {@link JsonSchema.fromLoadedObject}\n * @public\n */\nexport interface IJsonSchemaLoadOptions {\n /**\n * Other schemas that this schema references, e.g. via the \"$ref\" directive.\n * @remarks\n * The tree of dependent schemas may reference the same schema more than once.\n * However, if the same schema \"$id\" is used by two different JsonSchema instances,\n * an error will be reported. This means you cannot load the same filename twice\n * and use them both together, and you cannot have diamond dependencies on different\n * versions of the same schema. Although technically this would be possible to support,\n * it normally indicates an error or design problem.\n *\n * JsonSchema also does not allow circular references between schema dependencies.\n */\n dependentSchemas?: JsonSchema[];\n\n /**\n * The json-schema version to target for validation.\n *\n * @defaultValue draft-07\n *\n * @remarks\n * If the a version is not explicitly set, the schema object's `$schema` property\n * will be inspected to determine the version. If a `$schema` property is not found\n * or does not match an expected URL, the default version will be used.\n */\n schemaVersion?: JsonSchemaVersion;\n\n /**\n * Any custom formats to consider during validation. Some standard formats are supported\n * out-of-the-box (e.g. emails, uris), but additional formats can be defined here. You could\n * for example define generic numeric formats (e.g. uint8) or domain-specific formats.\n */\n customFormats?: Record | IJsonSchemaCustomFormat>;\n}\n\n/**\n * Options for {@link JsonSchema.fromFile}\n * @public\n */\nexport type IJsonSchemaFromFileOptions = IJsonSchemaLoadOptions;\n\n/**\n * Options for {@link JsonSchema.fromLoadedObject}\n * @public\n */\nexport type IJsonSchemaFromObjectOptions = IJsonSchemaLoadOptions;\n\nconst JSON_SCHEMA_URL_PREFIX_BY_JSON_SCHEMA_VERSION: Map = new Map([\n ['draft-04', 'http://json-schema.org/draft-04/schema'],\n ['draft-07', 'http://json-schema.org/draft-07/schema']\n]);\n\n/**\n * Helper function to determine the json-schema version to target for validation.\n */\nfunction _inferJsonSchemaVersion({ $schema }: JsonObject): JsonSchemaVersion | undefined {\n if ($schema) {\n for (const [jsonSchemaVersion, urlPrefix] of JSON_SCHEMA_URL_PREFIX_BY_JSON_SCHEMA_VERSION) {\n if ($schema.startsWith(urlPrefix)) {\n return jsonSchemaVersion;\n }\n }\n }\n}\n\n/**\n * Represents a JSON schema that can be used to validate JSON data files loaded by the JsonFile class.\n * @remarks\n * The schema itself is normally loaded and compiled later, only if it is actually required to validate\n * an input. To avoid schema errors at runtime, it's recommended to create a unit test that calls\n * JsonSchema.ensureCompiled() for each of your schema objects.\n *\n * @public\n */\nexport class JsonSchema {\n private _dependentSchemas: JsonSchema[] = [];\n private _filename: string = '';\n private _validator: ValidateFunction | undefined = undefined;\n private _schemaObject: JsonObject | undefined = undefined;\n private _schemaVersion: JsonSchemaVersion | undefined = undefined;\n private _customFormats:\n | Record | IJsonSchemaCustomFormat>\n | undefined = undefined;\n\n private constructor() {}\n\n /**\n * Registers a JsonSchema that will be loaded from a file on disk.\n * @remarks\n * NOTE: An error occurs if the file does not exist; however, the file itself is not loaded or validated\n * until it the schema is actually used.\n */\n public static fromFile(filename: string, options?: IJsonSchemaFromFileOptions): JsonSchema {\n // This is a quick and inexpensive test to avoid the catch the most common errors early.\n // Full validation will happen later in JsonSchema.compile().\n if (!FileSystem.exists(filename)) {\n throw new Error('Schema file not found: ' + filename);\n }\n\n const schema: JsonSchema = new JsonSchema();\n schema._filename = filename;\n\n if (options) {\n schema._dependentSchemas = options.dependentSchemas || [];\n schema._schemaVersion = options.schemaVersion;\n schema._customFormats = options.customFormats;\n }\n\n return schema;\n }\n\n /**\n * Registers a JsonSchema that will be loaded from an object.\n */\n public static fromLoadedObject(\n schemaObject: JsonObject,\n options?: IJsonSchemaFromObjectOptions\n ): JsonSchema {\n const schema: JsonSchema = new JsonSchema();\n schema._schemaObject = schemaObject;\n\n if (options) {\n schema._dependentSchemas = options.dependentSchemas || [];\n schema._schemaVersion = options.schemaVersion;\n schema._customFormats = options.customFormats;\n }\n\n return schema;\n }\n\n private static _collectDependentSchemas(\n collectedSchemas: JsonSchema[],\n dependentSchemas: JsonSchema[],\n seenObjects: Set,\n seenIds: Set\n ): void {\n for (const dependentSchema of dependentSchemas) {\n // It's okay for the same schema to appear multiple times in the tree, but we only process it once\n if (seenObjects.has(dependentSchema)) {\n continue;\n }\n seenObjects.add(dependentSchema);\n\n const schemaId: string = dependentSchema._ensureLoaded();\n if (schemaId === '') {\n throw new Error(\n `This schema ${dependentSchema.shortName} cannot be referenced` +\n ' because is missing the \"id\" (draft-04) or \"$id\" field'\n );\n }\n if (seenIds.has(schemaId)) {\n throw new Error(\n `This schema ${dependentSchema.shortName} has the same \"id\" (draft-04) or \"$id\" as another schema in this set`\n );\n }\n\n seenIds.add(schemaId);\n\n collectedSchemas.push(dependentSchema);\n\n JsonSchema._collectDependentSchemas(\n collectedSchemas,\n dependentSchema._dependentSchemas,\n seenObjects,\n seenIds\n );\n }\n }\n\n /**\n * Used to nicely format the ZSchema error tree.\n */\n private static _formatErrorDetails(errorDetails: ErrorObject[]): string {\n return JsonSchema._formatErrorDetailsHelper(errorDetails, '', '');\n }\n\n /**\n * Used by _formatErrorDetails.\n */\n private static _formatErrorDetailsHelper(\n errorDetails: ErrorObject[],\n indent: string,\n buffer: string\n ): string {\n for (const errorDetail of errorDetails) {\n buffer += os.EOL + indent + `Error: #${errorDetail.instancePath}`;\n\n buffer += os.EOL + indent + ` ${errorDetail.message}`;\n if (errorDetail.params?.additionalProperty) {\n buffer += `: ${errorDetail.params?.additionalProperty}`;\n }\n }\n\n return buffer;\n }\n\n /**\n * Returns a short name for this schema, for use in error messages.\n * @remarks\n * If the schema was loaded from a file, then the base filename is used. Otherwise, the \"$id\"\n * field is used if available.\n */\n public get shortName(): string {\n if (!this._filename) {\n if (this._schemaObject) {\n const schemaWithId: ISchemaWithId = this._schemaObject as ISchemaWithId;\n if (schemaWithId.id) {\n return schemaWithId.id;\n } else if (schemaWithId.$id) {\n return schemaWithId.$id;\n }\n }\n return '(anonymous schema)';\n } else {\n return path.basename(this._filename);\n }\n }\n\n /**\n * If not already done, this loads the schema from disk and compiles it.\n * @remarks\n * Any dependencies will be compiled as well.\n */\n public ensureCompiled(): void {\n this._ensureLoaded();\n\n if (!this._validator) {\n const targetSchemaVersion: JsonSchemaVersion | undefined =\n this._schemaVersion ?? _inferJsonSchemaVersion(this._schemaObject);\n const validatorOptions: AjvOptions = {\n strictSchema: true,\n allowUnionTypes: true\n };\n\n let validator: Ajv;\n // Keep legacy support for older draft-04 schema\n switch (targetSchemaVersion) {\n case 'draft-04': {\n validator = new AjvDraft04(validatorOptions);\n break;\n }\n\n case 'draft-07':\n default: {\n validator = new Ajv(validatorOptions);\n break;\n }\n }\n\n // Enable json-schema format validation\n // https://ajv.js.org/packages/ajv-formats.html\n addFormats(validator);\n if (this._customFormats) {\n for (const [name, format] of Object.entries(this._customFormats)) {\n validator.addFormat(name, { ...format, async: false });\n }\n }\n\n const collectedSchemas: JsonSchema[] = [];\n const seenObjects: Set = new Set();\n const seenIds: Set = new Set();\n\n JsonSchema._collectDependentSchemas(collectedSchemas, this._dependentSchemas, seenObjects, seenIds);\n\n // Validate each schema in order. We specifically do not supply them all together, because we want\n // to make sure that circular references will fail to validate.\n for (const collectedSchema of collectedSchemas) {\n validator.validateSchema(collectedSchema._schemaObject) as boolean;\n if (validator.errors && validator.errors.length > 0) {\n throw new Error(\n `Failed to validate schema \"${collectedSchema.shortName}\":` +\n os.EOL +\n JsonSchema._formatErrorDetails(validator.errors)\n );\n }\n validator.addSchema(collectedSchema._schemaObject);\n }\n\n this._validator = validator.compile(this._schemaObject);\n }\n }\n\n /**\n * Validates the specified JSON object against this JSON schema. If the validation fails,\n * an exception will be thrown.\n * @param jsonObject - The JSON data to be validated\n * @param filenameForErrors - The filename that the JSON data was available, or an empty string\n * if not applicable\n * @param options - Other options that control the validation\n */\n public validateObject(\n jsonObject: JsonObject,\n filenameForErrors: string,\n options?: IJsonSchemaValidateOptions\n ): void {\n this.validateObjectWithCallback(\n jsonObject,\n (errorInfo: IJsonSchemaErrorInfo) => {\n const prefix: string = options?.customErrorHeader ?? 'JSON validation failed:';\n\n throw new Error(prefix + os.EOL + filenameForErrors + os.EOL + errorInfo.details);\n },\n options\n );\n }\n\n /**\n * Validates the specified JSON object against this JSON schema. If the validation fails,\n * a callback is called for each validation error.\n */\n public validateObjectWithCallback(\n jsonObject: JsonObject,\n errorCallback: (errorInfo: IJsonSchemaErrorInfo) => void,\n options?: IJsonSchemaValidateObjectWithOptions\n ): void {\n this.ensureCompiled();\n\n if (options?.ignoreSchemaField) {\n const {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n $schema,\n ...remainder\n } = jsonObject;\n jsonObject = remainder;\n }\n\n if (this._validator && !this._validator(jsonObject)) {\n const errorDetails: string = JsonSchema._formatErrorDetails(this._validator.errors!);\n\n const args: IJsonSchemaErrorInfo = {\n details: errorDetails\n };\n errorCallback(args);\n }\n }\n\n private _ensureLoaded(): string {\n if (!this._schemaObject) {\n this._schemaObject = JsonFile.load(this._filename);\n }\n return (this._schemaObject as ISchemaWithId).id || (this._schemaObject as ISchemaWithId).$id || '';\n }\n}\n"]}