|
28 | 28 | }(this, function (exports, Ajv, jsonlint, requireSchemaDraft) {
|
29 | 29 | 'use strict'
|
30 | 30 |
|
31 |
| - function compile (schema, environment) { |
32 |
| - var options = {} |
33 |
| - if (typeof environment === 'object' && !(environment instanceof String)) { |
34 |
| - options = environment |
35 |
| - environment = options.environment |
| 31 | + function addErrorLocation (problem, input, tokens, dataPath) { |
| 32 | + var token = tokens.find(function (token) { |
| 33 | + return dataPath === jsonlint.pathToPointer(token.path) |
| 34 | + }) |
| 35 | + if (token) { |
| 36 | + var location = token.location.start |
| 37 | + var offset = location.offset |
| 38 | + var line = location.line |
| 39 | + var column = location.column |
| 40 | + var texts = jsonlint.getErrorTexts(problem.reason, input, offset, line, column) |
| 41 | + problem.message = texts.message |
| 42 | + problem.exzerpt = texts.exzerpt |
| 43 | + if (texts.pointer) { |
| 44 | + problem.pointer = texts.pointer |
| 45 | + problem.location = { |
| 46 | + start: { |
| 47 | + column: column, |
| 48 | + line: line, |
| 49 | + offset: offset |
| 50 | + } |
| 51 | + } |
| 52 | + } |
| 53 | + return true |
| 54 | + } |
| 55 | + } |
| 56 | + |
| 57 | + function errorToProblem (error, input, tokens) { |
| 58 | + var dataPath = error.dataPath |
| 59 | + var schemaPath = error.schemaPath |
| 60 | + var reason = (dataPath || '/') + ' ' + error.message + '; see ' + schemaPath |
| 61 | + var problem = { |
| 62 | + reason: reason, |
| 63 | + dataPath: dataPath, |
| 64 | + schemaPath: schemaPath |
| 65 | + } |
| 66 | + if (!addErrorLocation(problem, input, tokens, dataPath)) { |
| 67 | + problem.message = reason |
| 68 | + } |
| 69 | + return problem |
| 70 | + } |
| 71 | + |
| 72 | + function createError (errors, data, input, options) { |
| 73 | + if (!input) { |
| 74 | + input = JSON.stringify(data, undefined, 2) |
36 | 75 | }
|
| 76 | + if (!options) { |
| 77 | + options = {} |
| 78 | + } |
| 79 | + Object.assign(options, { |
| 80 | + tokenLocations: true, |
| 81 | + tokenPaths: true |
| 82 | + }) |
| 83 | + var tokens = jsonlint.tokenize(input, options) |
| 84 | + // var problems = errors.map(function (error) { |
| 85 | + // return errorToProblem(error, input, tokens) |
| 86 | + // }) |
| 87 | + // var message = problems |
| 88 | + // .map(function (problem) { |
| 89 | + // return problem.message |
| 90 | + // }) |
| 91 | + // .join('\n') |
| 92 | + var problem = errorToProblem(errors[0], input, tokens) |
| 93 | + var error = new SyntaxError(problem.message) |
| 94 | + Object.assign(error, problem) |
| 95 | + return error |
| 96 | + } |
| 97 | + |
| 98 | + function createAjv (environment) { |
| 99 | + var ajvOptions = { jsonPointers: true } |
37 | 100 | var ajv
|
38 | 101 | if (!environment) {
|
39 |
| - ajv = new Ajv({ schemaId: 'auto' }) |
| 102 | + ajvOptions.schemaId = 'auto' |
| 103 | + ajv = new Ajv(ajvOptions) |
40 | 104 | ajv.addMetaSchema(requireSchemaDraft('json-schema-draft-04'))
|
41 | 105 | ajv.addMetaSchema(requireSchemaDraft('json-schema-draft-06'))
|
42 | 106 | } else if (environment === 'json-schema-draft-07') {
|
43 |
| - ajv = new Ajv() |
| 107 | + ajv = new Ajv(ajvOptions) |
44 | 108 | } else if (environment === 'json-schema-draft-06') {
|
45 |
| - ajv = new Ajv() |
| 109 | + ajv = new Ajv(ajvOptions) |
46 | 110 | ajv.addMetaSchema(requireSchemaDraft('json-schema-draft-06'))
|
47 | 111 | } else if (environment === 'json-schema-draft-04') {
|
48 |
| - ajv = new Ajv({ schemaId: 'id' }) |
| 112 | + ajvOptions.schemaId = 'id' |
| 113 | + ajv = new Ajv(ajvOptions) |
49 | 114 | ajv.addMetaSchema(requireSchemaDraft('json-schema-draft-04'))
|
50 | 115 | } else {
|
51 |
| - throw new Error('Unsupported environment for the JSON schema validation: "' + |
| 116 | + throw new RangeError('Unsupported environment for the JSON schema validation: "' + |
52 | 117 | environment + '".')
|
53 | 118 | }
|
54 |
| - var validate |
| 119 | + return ajv |
| 120 | + } |
| 121 | + |
| 122 | + function compileSchema (ajv, schema, parseOptions) { |
| 123 | + var parsed |
55 | 124 | try {
|
56 |
| - schema = jsonlint.parse(schema, { |
57 |
| - mode: options.mode, |
58 |
| - ignoreComments: options.ignoreComments, |
59 |
| - ignoreTrailingCommas: options.ignoreTrailingCommas, |
60 |
| - allowSingleQuotedStrings: options.allowSingleQuotedStrings, |
61 |
| - allowDuplicateObjectKeys: options.allowDuplicateObjectKeys |
62 |
| - }) |
63 |
| - validate = ajv.compile(schema) |
| 125 | + parsed = jsonlint.parse(schema, parseOptions) |
64 | 126 | } catch (error) {
|
65 |
| - throw new Error('Compiling the JSON schema failed.\n' + error.message) |
| 127 | + error.message = 'Parsing the JSON schema failed.\n' + error.message |
| 128 | + throw error |
| 129 | + } |
| 130 | + try { |
| 131 | + return ajv.compile(parsed) |
| 132 | + } catch (originalError) { |
| 133 | + var errors = ajv.errors |
| 134 | + var betterError = errors |
| 135 | + ? createError(errors, parsed, schema, parseOptions) |
| 136 | + : originalError |
| 137 | + betterError.message = 'Compiling the JSON schema failed.\n' + betterError.message |
| 138 | + throw betterError |
| 139 | + } |
| 140 | + } |
| 141 | + |
| 142 | + function compile (schema, environment) { |
| 143 | + var options = {} |
| 144 | + if (typeof environment === 'object' && !(environment instanceof String)) { |
| 145 | + options = environment |
| 146 | + environment = options.environment |
66 | 147 | }
|
67 |
| - return function (data) { |
68 |
| - var result = validate(data) |
69 |
| - if (!result) { |
70 |
| - var message = ajv.errorsText(validate.errors) |
71 |
| - throw new Error(message) |
| 148 | + var ajv = createAjv(environment) |
| 149 | + var parseOptions = { |
| 150 | + mode: options.mode, |
| 151 | + ignoreComments: options.ignoreComments, |
| 152 | + ignoreTrailingCommas: options.ignoreTrailingCommas, |
| 153 | + allowSingleQuotedStrings: options.allowSingleQuotedStrings, |
| 154 | + allowDuplicateObjectKeys: options.allowDuplicateObjectKeys |
| 155 | + } |
| 156 | + var validate = compileSchema(ajv, schema, parseOptions) |
| 157 | + return function (data, input, options) { |
| 158 | + if (typeof data === 'string' || data instanceof String) { |
| 159 | + options = input |
| 160 | + input = data |
| 161 | + data = jsonlint.parse(input, options) |
| 162 | + } else if (!(typeof input === 'string' || input instanceof String)) { |
| 163 | + options = input |
| 164 | + input = undefined |
| 165 | + } |
| 166 | + if (validate(data)) { |
| 167 | + return data |
72 | 168 | }
|
| 169 | + throw createError(validate.errors, data, input, options) |
73 | 170 | }
|
74 | 171 | }
|
75 | 172 |
|
|
0 commit comments