@conduit-client/jsonschema-validate 3.0.0 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +3 -69
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -3,73 +3,7 @@
|
|
|
3
3
|
* All rights reserved.
|
|
4
4
|
* For full license text, see the LICENSE.txt file
|
|
5
5
|
*/
|
|
6
|
-
|
|
7
|
-
* Copyright (c) 2022, Salesforce, Inc.,
|
|
8
|
-
* All rights reserved.
|
|
9
|
-
* For full license text, see the LICENSE.txt file
|
|
10
|
-
*/
|
|
11
|
-
const { isArray } = Array;
|
|
12
|
-
const { stringify } = JSON;
|
|
13
|
-
class Ok {
|
|
14
|
-
constructor(value) {
|
|
15
|
-
this.value = value;
|
|
16
|
-
}
|
|
17
|
-
isOk() {
|
|
18
|
-
return true;
|
|
19
|
-
}
|
|
20
|
-
isErr() {
|
|
21
|
-
return !this.isOk();
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
class Err {
|
|
25
|
-
constructor(error) {
|
|
26
|
-
this.error = error;
|
|
27
|
-
}
|
|
28
|
-
isOk() {
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
|
-
isErr() {
|
|
32
|
-
return !this.isOk();
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
const ok = (value) => new Ok(value);
|
|
36
|
-
const err = (err2) => new Err(err2);
|
|
37
|
-
function deepEquals(x, y) {
|
|
38
|
-
if (x === void 0) {
|
|
39
|
-
return y === void 0;
|
|
40
|
-
} else if (x === null) {
|
|
41
|
-
return y === null;
|
|
42
|
-
} else if (y === null) {
|
|
43
|
-
return x === null;
|
|
44
|
-
} else if (isArray(x)) {
|
|
45
|
-
if (!isArray(y) || x.length !== y.length) {
|
|
46
|
-
return false;
|
|
47
|
-
}
|
|
48
|
-
for (let i = 0; i < x.length; ++i) {
|
|
49
|
-
if (!deepEquals(x[i], y[i])) {
|
|
50
|
-
return false;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return true;
|
|
54
|
-
} else if (typeof x === "object") {
|
|
55
|
-
if (typeof y !== "object") {
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
58
|
-
const xkeys = Object.keys(x);
|
|
59
|
-
const ykeys = Object.keys(y);
|
|
60
|
-
if (xkeys.length !== ykeys.length) {
|
|
61
|
-
return false;
|
|
62
|
-
}
|
|
63
|
-
for (let i = 0; i < xkeys.length; ++i) {
|
|
64
|
-
const key = xkeys[i];
|
|
65
|
-
if (!deepEquals(x[key], y[key])) {
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return true;
|
|
70
|
-
}
|
|
71
|
-
return x === y;
|
|
72
|
-
}
|
|
6
|
+
import { deepEquals, JSONStringify, ok, err } from "@conduit-client/utils";
|
|
73
7
|
class JsonSchemaViolationError extends Error {
|
|
74
8
|
constructor(message, validationErrors) {
|
|
75
9
|
super(message);
|
|
@@ -398,7 +332,7 @@ function validateEnum(data, enumValue, path) {
|
|
|
398
332
|
if (!enumValue.some((value) => deepEquals(value, data))) {
|
|
399
333
|
return invalidSchemaResponseWithError(
|
|
400
334
|
new JsonSchemaViolationError(
|
|
401
|
-
`Data at ${path} did not match any values in enum. Expected value in: [${enumValue.map((value) =>
|
|
335
|
+
`Data at ${path} did not match any values in enum. Expected value in: [${enumValue.map((value) => JSONStringify(value)).join()}]`
|
|
402
336
|
)
|
|
403
337
|
);
|
|
404
338
|
}
|
|
@@ -408,7 +342,7 @@ function validateConst(data, constValue, path) {
|
|
|
408
342
|
if (!deepEquals(constValue, data)) {
|
|
409
343
|
return invalidSchemaResponseWithError(
|
|
410
344
|
new JsonSchemaViolationError(
|
|
411
|
-
`Data at ${path} did not match const. Expected: ${
|
|
345
|
+
`Data at ${path} did not match const. Expected: ${JSONStringify(constValue)}`
|
|
412
346
|
)
|
|
413
347
|
);
|
|
414
348
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../utils/dist/index.js","../src/index.ts"],"sourcesContent":["/*!\n * Copyright (c) 2022, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nfunction bfs(start, predicate, getChildren) {\n const queue = [...start];\n const visited = /* @__PURE__ */ new Set([...start]);\n const matches2 = /* @__PURE__ */ new Set();\n while (queue.length) {\n const curr = queue.shift();\n if (predicate(curr)) {\n matches2.add(curr);\n }\n const children = getChildren(curr);\n for (const child of children) {\n if (!visited.has(child)) {\n visited.add(child);\n queue.push(child);\n }\n }\n }\n return matches2;\n}\nfunction lineFormatter(position, message, filePath) {\n return `${message} (${filePath}:${position.line}:${position.column})`;\n}\nclass DefaultFileParserLogger {\n constructor(services, filePath) {\n this.services = services;\n this.filePath = filePath;\n }\n trace(position, message) {\n this.services.logger.trace(this.format(position, message));\n }\n debug(position, message) {\n this.services.logger.debug(this.format(position, message));\n }\n info(position, message) {\n this.services.logger.info(this.format(position, message));\n }\n warn(position, message) {\n this.services.logger.warn(this.format(position, message));\n }\n error(position, message) {\n this.services.logger.error(this.format(position, message));\n }\n format(position, message) {\n return lineFormatter(position, message, this.filePath);\n }\n}\nfunction matches(test, s) {\n if (test === void 0) {\n return false;\n } else if (typeof test === \"string\") {\n return s === test;\n } else if (test instanceof RegExp) {\n return test.test(s);\n } else if (typeof test === \"function\") {\n return test(s);\n }\n return test.some((m) => matches(m, s));\n}\nfunction includes(incexc, s) {\n if (matches(incexc.exclude, s)) {\n return false;\n }\n if (matches(incexc.include, s)) {\n return true;\n }\n if (incexc.include) {\n return false;\n }\n return true;\n}\nconst { create, freeze, keys, entries } = Object;\nconst { hasOwnProperty } = Object.prototype;\nconst { isArray } = Array;\nconst { push, indexOf, slice } = Array.prototype;\nconst { stringify, parse } = JSON;\nconst WeakSetConstructor = WeakSet;\nconst LogLevelMap = {\n TRACE: 4,\n DEBUG: 3,\n INFO: 2,\n WARN: 1,\n ERROR: 0\n};\nclass ConsoleLogger {\n constructor(level = \"WARN\", printer = console.log, formatter = (level2, message) => `${level2}: ${message}`) {\n this.level = level;\n this.printer = printer;\n this.formatter = formatter;\n this.messages = [];\n }\n trace(message) {\n this.log(\"TRACE\", message);\n }\n debug(message) {\n this.log(\"DEBUG\", message);\n }\n info(message) {\n this.log(\"INFO\", message);\n }\n warn(message) {\n this.log(\"WARN\", message);\n }\n error(message) {\n this.log(\"ERROR\", message);\n }\n log(level, message) {\n if (LogLevelMap[level] > LogLevelMap[this.level]) {\n return;\n }\n this.printer(this.formatter(level, message));\n }\n}\nfunction loggerService(level, printer, formatter) {\n return new ConsoleLogger(level, printer, formatter);\n}\nclass Ok {\n constructor(value) {\n this.value = value;\n }\n isOk() {\n return true;\n }\n isErr() {\n return !this.isOk();\n }\n}\nclass Err {\n constructor(error) {\n this.error = error;\n }\n isOk() {\n return false;\n }\n isErr() {\n return !this.isOk();\n }\n}\nconst ok = (value) => new Ok(value);\nconst err = (err2) => new Err(err2);\nclass DataNotFoundError extends Error {\n constructor(message) {\n super(message);\n this.name = \"DataNotFoundError\";\n }\n}\nclass DataIncompleteError extends Error {\n constructor(message, partialData) {\n super(message);\n this.partialData = partialData;\n this.name = \"DataIncompleteError\";\n }\n}\nfunction isDataNotFoundError(error) {\n return error instanceof DataNotFoundError || error.name === \"DataNotFoundError\";\n}\nfunction isDataIncompleteError(error) {\n return error instanceof DataIncompleteError || error.name === \"DataIncompleteError\";\n}\nfunction isCacheHitOrError(value) {\n if (value.isErr() && (isDataIncompleteError(value.error) || isDataNotFoundError(value.error))) {\n return false;\n }\n return true;\n}\nfunction isCacheMiss(value) {\n return !isCacheHitOrError(value);\n}\nfunction isResult(value) {\n return value != null && typeof value === \"object\" && \"isOk\" in value && \"isErr\" in value && typeof value.isOk === \"function\" && typeof value.isErr === \"function\" && (value.isOk() === true && value.isErr() === false && \"value\" in value || value.isOk() === false && value.isErr() === true && \"error\" in value);\n}\nfunction setOverlaps(setA, setB) {\n for (const element of setA) {\n if (setB.has(element)) {\n return true;\n }\n }\n return false;\n}\nfunction setDifference(setA, setB) {\n const differenceSet = /* @__PURE__ */ new Set();\n for (const element of setA) {\n if (!setB.has(element)) {\n differenceSet.add(element);\n }\n }\n return differenceSet;\n}\nfunction addAllToSet(targetSet, sourceSet) {\n for (const element of sourceSet) {\n targetSet.add(element);\n }\n}\nconst toTypeScriptSafeIdentifier = (s) => s.length >= 1 ? s[0].replace(/[^$_\\p{ID_Start}]/u, \"_\") + s.slice(1).replace(/[^$\\u200c\\u200d\\p{ID_Continue}]/gu, \"_\") : \"\";\nfunction isSubscribable(obj) {\n return typeof obj === \"object\" && obj !== null && \"subscribe\" in obj && typeof obj.subscribe === \"function\" && \"refresh\" in obj && typeof obj.refresh === \"function\";\n}\nfunction isSubscribableResult(x) {\n if (!isResult(x)) {\n return false;\n }\n return isSubscribable(x.isOk() ? x.value : x.error);\n}\nfunction buildSubscribableResult(result, subscribe, refresh) {\n if (result.isOk()) {\n return ok({ data: result.value, subscribe, refresh });\n } else {\n return err({ failure: result.error, subscribe, refresh });\n }\n}\nfunction resolvedPromiseLike(result) {\n if (isPromiseLike(result)) {\n return result.then((nextResult) => nextResult);\n }\n return {\n then: (onFulfilled, _onRejected) => {\n try {\n return resolvedPromiseLike(onFulfilled(result));\n } catch (e) {\n if (onFulfilled === void 0) {\n return resolvedPromiseLike(result);\n }\n return rejectedPromiseLike(e);\n }\n }\n };\n}\nfunction rejectedPromiseLike(reason) {\n if (isPromiseLike(reason)) {\n return reason.then((nextResult) => nextResult);\n }\n return {\n then: (_onFulfilled, onRejected) => {\n if (typeof onRejected === \"function\") {\n try {\n return resolvedPromiseLike(onRejected(reason));\n } catch (e) {\n return rejectedPromiseLike(e);\n }\n }\n return rejectedPromiseLike(reason);\n }\n };\n}\nfunction isPromiseLike(x) {\n return typeof (x == null ? void 0 : x.then) === \"function\";\n}\nfunction racesync(values) {\n for (const value of values) {\n let settled = void 0;\n if (isPromiseLike(value)) {\n value.then(\n (_) => {\n settled = value;\n },\n (_) => {\n settled = value;\n }\n );\n } else {\n settled = resolvedPromiseLike(value);\n }\n if (settled !== void 0) {\n return settled;\n }\n }\n return Promise.race(values);\n}\nfunction withResolvers() {\n let resolve, reject;\n const promise = new Promise((res, rej) => {\n resolve = res;\n reject = rej;\n });\n return { promise, resolve, reject };\n}\nfunction deepEquals(x, y) {\n if (x === void 0) {\n return y === void 0;\n } else if (x === null) {\n return y === null;\n } else if (y === null) {\n return x === null;\n } else if (isArray(x)) {\n if (!isArray(y) || x.length !== y.length) {\n return false;\n }\n for (let i = 0; i < x.length; ++i) {\n if (!deepEquals(x[i], y[i])) {\n return false;\n }\n }\n return true;\n } else if (typeof x === \"object\") {\n if (typeof y !== \"object\") {\n return false;\n }\n const xkeys = Object.keys(x);\n const ykeys = Object.keys(y);\n if (xkeys.length !== ykeys.length) {\n return false;\n }\n for (let i = 0; i < xkeys.length; ++i) {\n const key = xkeys[i];\n if (!deepEquals(x[key], y[key])) {\n return false;\n }\n }\n return true;\n }\n return x === y;\n}\nfunction stableJSONStringify(node) {\n if (node && node.toJSON && typeof node.toJSON === \"function\") {\n node = node.toJSON();\n }\n if (node === void 0) {\n return;\n }\n if (typeof node === \"number\") {\n return isFinite(node) ? \"\" + node : \"null\";\n }\n if (typeof node !== \"object\") {\n return stringify(node);\n }\n let i;\n let out;\n if (isArray(node)) {\n out = \"[\";\n for (i = 0; i < node.length; i++) {\n if (i) {\n out += \",\";\n }\n out += stableJSONStringify(node[i]) || \"null\";\n }\n return out + \"]\";\n }\n if (node === null) {\n return \"null\";\n }\n const objKeys = keys(node).sort();\n out = \"\";\n for (i = 0; i < objKeys.length; i++) {\n const key = objKeys[i];\n const value = stableJSONStringify(node[key]);\n if (!value) {\n continue;\n }\n if (out) {\n out += \",\";\n }\n out += stringify(key) + \":\" + value;\n }\n return \"{\" + out + \"}\";\n}\nfunction toError(x) {\n if (x instanceof Error) {\n return x;\n }\n return new Error(typeof x === \"string\" ? x : JSON.stringify(x));\n}\nfunction deepCopy(x) {\n const stringified = stringify(x);\n return stringified ? parse(stringified) : void 0;\n}\nfunction readableStreamToAsyncIterable(stream) {\n if (stream.locked) {\n return err(new Error(\"ReadableStream is already locked\"));\n }\n if (Symbol.asyncIterator in stream) {\n return ok(stream);\n }\n const reader = stream.getReader();\n return ok({\n [Symbol.asyncIterator]: () => ({\n next: async () => {\n try {\n const result = await reader.read();\n if (result.done) {\n try {\n reader.releaseLock();\n } catch {\n }\n return { done: true, value: void 0 };\n }\n return {\n done: false,\n value: result.value\n };\n } catch (e) {\n try {\n reader.releaseLock();\n } catch {\n }\n throw e;\n }\n },\n return: async (value) => {\n try {\n await reader.cancel();\n } catch {\n }\n try {\n reader.releaseLock();\n } catch {\n }\n return { done: true, value };\n },\n throw: async (exception) => {\n try {\n await reader.cancel();\n } catch {\n }\n try {\n reader.releaseLock();\n } catch {\n }\n throw exception;\n }\n })\n });\n}\nfunction satisfies(provided, requested) {\n const providedN = provided.split(\".\").map((s) => parseInt(s));\n const requestedN = requested.split(\".\").map((s) => parseInt(s));\n return providedN[0] === requestedN[0] && providedN[1] >= requestedN[1];\n}\nfunction stringIsVersion(s) {\n const versionParts = s.split(\".\");\n return (versionParts.length === 2 || versionParts.length === 3) && versionParts.every((part) => part.match(/^\\d+$/));\n}\nvar HttpStatusCode = /* @__PURE__ */ ((HttpStatusCode2) => {\n HttpStatusCode2[HttpStatusCode2[\"Ok\"] = 200] = \"Ok\";\n HttpStatusCode2[HttpStatusCode2[\"Created\"] = 201] = \"Created\";\n HttpStatusCode2[HttpStatusCode2[\"NoContent\"] = 204] = \"NoContent\";\n HttpStatusCode2[HttpStatusCode2[\"NotModified\"] = 304] = \"NotModified\";\n HttpStatusCode2[HttpStatusCode2[\"BadRequest\"] = 400] = \"BadRequest\";\n HttpStatusCode2[HttpStatusCode2[\"Unauthorized\"] = 401] = \"Unauthorized\";\n HttpStatusCode2[HttpStatusCode2[\"Forbidden\"] = 403] = \"Forbidden\";\n HttpStatusCode2[HttpStatusCode2[\"NotFound\"] = 404] = \"NotFound\";\n HttpStatusCode2[HttpStatusCode2[\"ServerError\"] = 500] = \"ServerError\";\n HttpStatusCode2[HttpStatusCode2[\"GatewayTimeout\"] = 504] = \"GatewayTimeout\";\n return HttpStatusCode2;\n})(HttpStatusCode || {});\nfunction getFetchResponseFromAuraError(err2) {\n if (err2.data !== void 0 && err2.data.statusCode !== void 0) {\n let data = {};\n data = err2.data;\n if (err2.id !== void 0) {\n data.id = err2.id;\n }\n return new FetchResponse(data.statusCode, data);\n }\n return new FetchResponse(500, {\n error: err2.message\n });\n}\nasync function coerceResponseToFetchResponse(response) {\n const { status } = response;\n const responseHeaders = {};\n response.headers.forEach((value, key) => {\n responseHeaders[key] = value;\n });\n let responseBody = null;\n if (status !== 204) {\n const contentType = responseHeaders[\"content-type\"];\n responseBody = contentType && contentType.startsWith(\"application/json\") ? await response.json() : await response.text();\n }\n return new FetchResponse(status, responseBody, responseHeaders);\n}\nfunction getStatusText(status) {\n switch (status) {\n case 200:\n return \"OK\";\n case 201:\n return \"Created\";\n case 304:\n return \"Not Modified\";\n case 400:\n return \"Bad Request\";\n case 404:\n return \"Not Found\";\n case 500:\n return \"Server Error\";\n default:\n return `Unexpected HTTP Status Code: ${status}`;\n }\n}\nclass FetchResponse extends Error {\n constructor(status, body, headers) {\n super();\n this.status = status;\n this.body = body;\n this.headers = headers || {};\n this.ok = status >= 200 && this.status <= 299;\n this.statusText = getStatusText(status);\n }\n}\nconst deeplyFrozen = new WeakSetConstructor();\nfunction deepFreeze(value) {\n if (typeof value !== \"object\" || value === null || deeplyFrozen.has(value)) {\n return;\n }\n deeplyFrozen.add(value);\n if (isArray(value)) {\n for (let i = 0, len = value.length; i < len; i += 1) {\n deepFreeze(value[i]);\n }\n } else {\n const keys$1 = keys(value);\n for (let i = 0, len = keys$1.length; i < len; i += 1) {\n deepFreeze(value[keys$1[i]]);\n }\n }\n freeze(value);\n}\nfunction isScalar(value) {\n return typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\" || value === null || value === void 0;\n}\nfunction isScalarObject(value) {\n return Object.values(value).every((value2) => isScalar(value2));\n}\nfunction isScalarArray(value) {\n return value.every((item) => isScalar(item));\n}\nfunction encodeQueryParam(paramName, value, explode) {\n switch (typeof value) {\n case \"string\":\n return [`${paramName}=${encodeURIComponent(value)}`];\n case \"number\":\n case \"boolean\":\n return [`${paramName}=${value}`];\n case \"object\":\n if (value === null) {\n return [];\n }\n if (isArray(value)) {\n if (!isScalarArray(value)) {\n throw new Error(`Unsupported non-scalar array type for ${paramName}`);\n }\n if (explode) {\n return value.map(\n (item) => `${paramName}=${item ? encodeURIComponent(item) : item}`\n );\n }\n return [\n `${paramName}=${value.map((item) => item ? encodeURIComponent(item) : item).join(\",\")}`\n ];\n }\n if (!isScalarObject(value)) {\n throw new Error(`Unsupported non-scalar object type for ${paramName}`);\n }\n if (explode) {\n return entries(value).map(\n ([key, value2]) => `${key}=${value2 ? encodeURIComponent(value2) : value2}`\n );\n }\n return [\n `${paramName}=${entries(value).flat().map((item) => item ? encodeURIComponent(item) : item).join(\",\")}`\n ];\n default:\n return [];\n }\n}\nclass InternalError extends Error {\n constructor(data) {\n super();\n this.data = data;\n this.type = \"internal\";\n }\n}\nclass UserVisibleError extends Error {\n constructor(data) {\n super();\n this.data = data;\n this.type = \"user-visible\";\n }\n}\nfunction isUserVisibleError(error) {\n return error instanceof Error && \"type\" in error && error.type === \"user-visible\";\n}\nfunction logError(error) {\n if (isUserVisibleError(error)) {\n return;\n }\n console.error(\"OneStore Command threw an error that we did not expect\", error);\n}\nfunction applyDecorators(baseCommand, decorators, options) {\n if (!decorators || decorators.length === 0) {\n return baseCommand;\n }\n return decorators.reduce((command, decorator) => decorator(command, options), baseCommand);\n}\nexport {\n isArray as ArrayIsArray,\n indexOf as ArrayPrototypeIndexOf,\n push as ArrayPrototypePush,\n slice as ArrayPrototypeSlice,\n ConsoleLogger,\n DataIncompleteError,\n DataNotFoundError,\n DefaultFileParserLogger,\n Err,\n FetchResponse,\n HttpStatusCode,\n InternalError,\n parse as JSONParse,\n stringify as JSONStringify,\n LogLevelMap,\n create as ObjectCreate,\n entries as ObjectEntries,\n freeze as ObjectFreeze,\n keys as ObjectKeys,\n hasOwnProperty as ObjectPrototypeHasOwnProperty,\n Ok,\n UserVisibleError,\n WeakSetConstructor,\n addAllToSet,\n applyDecorators,\n bfs,\n buildSubscribableResult,\n coerceResponseToFetchResponse,\n deepCopy,\n deepEquals,\n deepFreeze,\n encodeQueryParam,\n err,\n getFetchResponseFromAuraError,\n includes,\n isCacheHitOrError,\n isCacheMiss,\n isDataIncompleteError,\n isDataNotFoundError,\n isPromiseLike,\n isResult,\n isSubscribable,\n isSubscribableResult,\n isUserVisibleError,\n lineFormatter,\n logError,\n loggerService,\n ok,\n racesync,\n readableStreamToAsyncIterable,\n rejectedPromiseLike,\n resolvedPromiseLike,\n satisfies,\n setDifference,\n setOverlaps,\n stableJSONStringify,\n stringIsVersion,\n toError,\n toTypeScriptSafeIdentifier,\n withResolvers\n};\n//# sourceMappingURL=index.js.map\n","import { deepEquals, err, JSONStringify, ok } from '@conduit-client/utils';\nimport type { Result } from '@conduit-client/utils';\n\n// Based on https://json-schema.org/understanding-json-schema/\nexport type JSONSchema =\n | ObjectType\n | ArrayType\n | ScalarType\n | AnyOf\n | OneOf\n | AllOf\n | Not\n | RefType\n | EnumType\n | ConstType\n | boolean /* booleans are used to indicate if schema matches anything or nothing */;\n\nexport type BaseType = {\n enum?: any[]; // Enum can hold an array of allowed values of any type.\n const?: any; // Const represents a single allowed value.\n};\n\nexport type RefType = BaseType & { $ref: string };\n\nexport type EnumType = BaseType & {\n enum: any[];\n};\n\nexport type ConstType = BaseType & {\n const: any;\n};\n\n// Based on https://json-schema.org/understanding-json-schema/reference/object.html\nexport type ObjectType = BaseType & {\n type: 'object';\n properties: Record<string, JSONSchema>;\n required: string[];\n additionalProperties: JSONSchema;\n};\n\n// Based on https://json-schema.org/understanding-json-schema/reference/array.html\nexport type ArrayType = BaseType & {\n type: 'array';\n items: JSONSchema;\n minItems?: number;\n maxItems?: number;\n};\n\nexport type AnyOf = BaseType & {\n anyOf: JSONSchema[];\n};\n\nexport type OneOf = BaseType & {\n oneOf: JSONSchema[];\n};\n\nexport type AllOf = BaseType & {\n allOf: JSONSchema[];\n};\n\nexport type Not = BaseType & {\n not: JSONSchema;\n};\n\ntype ScalarType = IntegerType | NumberType | StringType | BooleanType | NullType;\n\nexport type IntegerType = BaseType & { type: 'integer' };\nexport type NumberType = BaseType & { type: 'number' };\nexport type StringType = BaseType & { type: 'string' };\nexport type BooleanType = BaseType & { type: 'boolean' };\nexport type NullType = BaseType & { type: 'null' };\nexport type JsonSchemaValidationError =\n | JsonSchemaViolationError\n | MinItemsViolationError\n | MaxItemsViolationError\n | IncorrectTypeError\n | AdditionalPropertiesError\n | MissingRequiredPropertyError\n | InvalidRefError;\n\nexport interface JsonSchemaValidationResponse {\n isValid: boolean;\n errors: Array<JsonSchemaValidationError>;\n}\n\nexport class JsonSchemaViolationError extends Error {\n public validationErrors: JsonSchemaValidationError[] = [];\n constructor(message?: string, validationErrors?: Array<JsonSchemaValidationError>) {\n super(message);\n this.validationErrors = validationErrors || [];\n }\n}\nexport class MinItemsViolationError extends JsonSchemaViolationError {}\nexport class MaxItemsViolationError extends JsonSchemaViolationError {}\nexport class IncorrectTypeError extends JsonSchemaViolationError {}\nexport class AdditionalPropertiesError extends JsonSchemaViolationError {}\nexport class MissingRequiredPropertyError extends JsonSchemaViolationError {}\nexport class InvalidRefError extends JsonSchemaViolationError {}\n\nclass JsonSchemaErrorCollector {\n errors: Array<JsonSchemaValidationError>;\n constructor() {\n this.errors = [];\n }\n add(error: JsonSchemaValidationError) {\n this.errors.push(error);\n }\n append(response: Result<boolean, JsonSchemaValidationError[]>) {\n if (response.isErr()) {\n this.errors.push(...response.error);\n }\n }\n hasErrors() {\n return this.errors.length > 0;\n }\n prepend(error: JsonSchemaValidationError) {\n this.errors.unshift(error);\n }\n toValidationResponse(): Result<boolean, JsonSchemaViolationError[]> {\n return !this.hasErrors() ? ok(true) : err(this.errors);\n }\n}\n\nfunction createThrowableError(errors: Array<JsonSchemaValidationError>): JsonSchemaValidationError {\n if (errors[0] instanceof MinItemsViolationError) {\n return new MinItemsViolationError(errors[0].message, errors);\n }\n if (errors[0] instanceof MaxItemsViolationError) {\n return new MaxItemsViolationError(errors[0].message, errors);\n }\n if (errors[0] instanceof IncorrectTypeError) {\n return new IncorrectTypeError(errors[0].message, errors);\n }\n if (errors[0] instanceof AdditionalPropertiesError) {\n return new AdditionalPropertiesError(errors[0].message, errors);\n }\n if (errors[0] instanceof MissingRequiredPropertyError) {\n return new MissingRequiredPropertyError(errors[0].message, errors);\n }\n if (errors[0] instanceof InvalidRefError) {\n return new InvalidRefError(errors[0].message, errors);\n }\n // any non-specific validation errors\n return new JsonSchemaViolationError(errors[0].message, errors);\n}\n\n/**\n * Validates a value against a schema in a TypeScript-friendly way.\n *\n * @typeParam Type TypeScript type that matches schema\n * @param data data to be checked\n * @param schema JSONSchema that matches Type\n */\nexport function assertIsValid<Type>(data: unknown, schema: JSONSchema): asserts data is Type {\n const validationResponse = validateJsonSchema(data, schema);\n if (validationResponse.isErr()) {\n throw createThrowableError(validationResponse.error);\n }\n}\n\nfunction incorrectTypeError(expected: string, actual: string, path: string): IncorrectTypeError {\n return new IncorrectTypeError(\n `Expected type ${expected} at path '${path}', found type ${actual}.`\n );\n}\n\nfunction validSchemaResponse(): Result<boolean, JsonSchemaValidationError[]> {\n return ok(true);\n}\n\nfunction invalidSchemaResponseWithError(\n error: JsonSchemaValidationError\n): Result<boolean, JsonSchemaViolationError[]> {\n return err([error]);\n}\n\nexport function validateJsonSchema(\n data: unknown,\n schema: JSONSchema,\n path: string = '$',\n document: JSONSchema = schema\n): Result<boolean, JsonSchemaValidationError[]> {\n if (schema === true) return validSchemaResponse();\n if (schema === false)\n return invalidSchemaResponseWithError(\n new JsonSchemaViolationError(`Data at ${path} has schema 'false'`)\n );\n\n const dataType = data === null ? 'null' : Array.isArray(data) ? 'array' : typeof data;\n const errorCollector = new JsonSchemaErrorCollector();\n if ('anyOf' in schema) {\n errorCollector.append(validateAnyOf(data, schema, path, document));\n } else if ('oneOf' in schema) {\n errorCollector.append(validateOneOf(data, schema, path, document));\n } else if ('allOf' in schema) {\n errorCollector.append(validateAllOf(data, schema, path, document));\n } else if ('not' in schema) {\n errorCollector.append(validateNot(data, schema, path, document));\n } else if ('$ref' in schema) {\n errorCollector.append(validateRef(data, schema, path, document));\n } else if ('type' in schema) {\n if (schema.type === 'object') {\n if (dataType !== 'object') {\n errorCollector.add(incorrectTypeError('object', dataType, path));\n } else {\n errorCollector.append(\n validateObject(data as Record<string, unknown>, schema, path, document)\n );\n }\n } else if (schema.type === 'array') {\n if (dataType !== 'array') {\n errorCollector.add(incorrectTypeError('array', dataType, path));\n } else {\n errorCollector.append(\n validateArray(data as Array<unknown>, schema, path, document)\n );\n }\n } else {\n errorCollector.append(\n validateScalar(data as string | number | boolean | null, schema, path)\n );\n }\n }\n if (schema.enum) {\n errorCollector.append(validateEnum(data, schema.enum, path));\n }\n if (schema.const) {\n errorCollector.append(validateConst(data, schema.const, path));\n }\n\n return errorCollector.toValidationResponse();\n}\n\nfunction validateAnyOf(\n data: unknown,\n schema: AnyOf,\n path: string,\n document: JSONSchema\n): Result<boolean, JsonSchemaValidationError[]> {\n let isValid = false;\n const errorCollector = new JsonSchemaErrorCollector();\n\n for (let i = 0, { length } = schema.anyOf; i < length; i++) {\n const element = schema.anyOf[i];\n const validationResponse = validateJsonSchema(\n data,\n element,\n `${path}.anyOf[${i}]`,\n document\n );\n if (validationResponse.isOk()) {\n isValid = true;\n break;\n } else {\n errorCollector.append(validationResponse);\n }\n }\n\n if (!isValid) {\n errorCollector.prepend(\n new JsonSchemaViolationError(`Data at ${path} did not match any subschema in anyOf.`)\n );\n return errorCollector.toValidationResponse();\n }\n\n return validSchemaResponse();\n}\n\nfunction validateOneOf(\n data: unknown,\n schema: OneOf,\n path: string,\n document: JSONSchema\n): Result<boolean, JsonSchemaValidationError[]> {\n let validSubShemaPaths: string[] = [];\n const errorCollector = new JsonSchemaErrorCollector();\n\n for (let i = 0, { length } = schema.oneOf; i < length; i++) {\n const element = schema.oneOf[i];\n const oneOfPath = `${path}.oneOf[${i}]`;\n const validationResponse = validateJsonSchema(data, element, oneOfPath, document);\n if (validationResponse.isOk()) {\n validSubShemaPaths.push(oneOfPath);\n } else {\n errorCollector.append(validationResponse);\n }\n }\n\n if (validSubShemaPaths.length === 0) {\n errorCollector.prepend(\n new JsonSchemaViolationError(`Data at ${path} did not match any subschema in oneOf.`)\n );\n return errorCollector.toValidationResponse();\n } else if (validSubShemaPaths.length > 1) {\n errorCollector.prepend(\n new JsonSchemaViolationError(\n `Data at ${path} matched multiple subschemas: [${validSubShemaPaths.join(', ')}].`\n )\n );\n return errorCollector.toValidationResponse();\n }\n\n return validSchemaResponse();\n}\n\nfunction validateAllOf(\n data: unknown,\n schema: AllOf,\n path: string,\n document: JSONSchema\n): Result<boolean, JsonSchemaValidationError[]> {\n let isValid = true;\n const errorCollector = new JsonSchemaErrorCollector();\n\n for (let i = 0, { length } = schema.allOf; i < length; i++) {\n const element = schema.allOf[i];\n const validationResponse = validateJsonSchema(\n data,\n element,\n `${path}.allOf[${i}]`,\n document\n );\n if (!validationResponse.isOk()) {\n errorCollector.append(validationResponse);\n isValid = false;\n }\n }\n\n if (!isValid) {\n errorCollector.prepend(\n new JsonSchemaViolationError(`Data at ${path} did not match some subschemas in allOf.`)\n );\n }\n return errorCollector.toValidationResponse();\n}\n\nfunction validateNot(data: unknown, schema: Not, path: string, document: JSONSchema) {\n const validationResponse = validateJsonSchema(data, schema.not, path, document);\n if (validationResponse.isOk()) {\n return invalidSchemaResponseWithError(\n new JsonSchemaViolationError(\n `Data at ${path} validated against the schema of a not clause.`\n )\n );\n }\n return validSchemaResponse();\n}\n\nfunction validateObject(\n data: Record<string, unknown>,\n schema: ObjectType,\n path: string,\n document: JSONSchema\n): Result<boolean, JsonSchemaValidationError[]> {\n const schemaKeys = Object.keys(schema.properties);\n const requiredKeys = new Set(schema.required);\n\n const schemaKeySet = new Set(schemaKeys);\n const errorCollector = new JsonSchemaErrorCollector();\n Object.keys(data).forEach((key) => {\n if (!schemaKeySet.has(key)) {\n errorCollector.append(\n validateJsonSchema(\n data[key],\n schema.additionalProperties,\n `${path}.additionalProperties[${key}]`,\n document\n )\n );\n }\n });\n\n for (let i = 0, length = schemaKeys.length; i < length; i++) {\n const key = schemaKeys[i];\n const keyInData = key in data && (data as any)[key] !== undefined;\n if (requiredKeys.has(key) && !keyInData) {\n errorCollector.add(\n new MissingRequiredPropertyError(\n `Object at path '${path}' is missing required property '${key}'.`\n )\n );\n }\n\n if (keyInData) {\n errorCollector.append(\n validateJsonSchema(\n (data as any)[key] as unknown,\n schema.properties[key],\n `${path}.${key}`,\n document\n )\n );\n }\n }\n return errorCollector.toValidationResponse();\n}\n\nfunction validateArray(\n data: Array<unknown>,\n schema: ArrayType,\n path: string,\n document: JSONSchema\n): Result<boolean, JsonSchemaValidationError[]> {\n if (schema.minItems !== undefined && data.length < schema.minItems) {\n return invalidSchemaResponseWithError(\n new MinItemsViolationError(\n `Array at path '${path}' fails minItems constraint. Has ${data.length} items, needs at least ${schema.minItems}.`\n )\n );\n }\n\n if (schema.maxItems !== undefined && data.length > schema.maxItems) {\n return invalidSchemaResponseWithError(\n new MaxItemsViolationError(\n `Array at path '${path}' fails maxItems constraint. Has ${data.length} items, needs at most ${schema.maxItems}.`\n )\n );\n }\n const errorCollector = new JsonSchemaErrorCollector();\n data.forEach((element, index) =>\n errorCollector.append(\n validateJsonSchema(element, schema.items, `${path}[${index}]`, document)\n )\n );\n return errorCollector.toValidationResponse();\n}\n\nfunction validateScalar(\n data: number | string | boolean | null,\n schema: ScalarType,\n path: string\n): Result<boolean, JsonSchemaValidationError[]> {\n const schemaDataType = schema.type;\n const dataType = typeof data;\n\n if (schemaDataType === 'integer') {\n if (dataType !== 'number' || !Number.isInteger(data)) {\n return invalidSchemaResponseWithError(incorrectTypeError('integer', dataType, path));\n }\n } else if (schemaDataType === 'number') {\n if (dataType !== 'number') {\n return invalidSchemaResponseWithError(incorrectTypeError('number', dataType, path));\n }\n } else if (schemaDataType === 'string') {\n if (dataType !== 'string') {\n return invalidSchemaResponseWithError(incorrectTypeError('string', dataType, path));\n }\n } else if (schemaDataType === 'boolean') {\n if (dataType !== 'boolean') {\n return invalidSchemaResponseWithError(incorrectTypeError('boolean', dataType, path));\n }\n } else if (schemaDataType === 'null') {\n if (data !== null) {\n return invalidSchemaResponseWithError(incorrectTypeError('null', dataType, path));\n }\n } else {\n return invalidSchemaResponseWithError(\n new IncorrectTypeError(`Unknown schema data type: ${schemaDataType}.`)\n );\n }\n return validSchemaResponse();\n}\nfunction validateRef(\n data: unknown,\n schema: RefType,\n path: string,\n document: JSONSchema\n): Result<boolean, JsonSchemaValidationError[]> {\n if (!schema.$ref.startsWith('#')) {\n return invalidSchemaResponseWithError(\n new InvalidRefError(\n `$ref values that do not refer to the current document are unsupported (must start with '#')`\n )\n );\n }\n try {\n const schemaToValidate = findSchemaAtPath(document, schema.$ref);\n return validateJsonSchema(data, schemaToValidate, path, document);\n } catch (e) {\n return invalidSchemaResponseWithError(e as InvalidRefError);\n }\n}\n\nfunction validateEnum(\n data: unknown,\n enumValue: any[],\n path: string\n): Result<boolean, JsonSchemaValidationError[]> {\n if (!enumValue.some((value) => deepEquals(value, data))) {\n return invalidSchemaResponseWithError(\n new JsonSchemaViolationError(\n `Data at ${path} did not match any values in enum. Expected value in: [${enumValue.map((value) => JSONStringify(value)).join()}]`\n )\n );\n }\n return validSchemaResponse();\n}\n\nfunction validateConst(\n data: unknown,\n constValue: any,\n path: string\n): Result<boolean, JsonSchemaValidationError[]> {\n if (!deepEquals(constValue, data)) {\n return invalidSchemaResponseWithError(\n new JsonSchemaViolationError(\n `Data at ${path} did not match const. Expected: ${JSONStringify(constValue)}`\n )\n );\n }\n return validSchemaResponse();\n}\n\nfunction findSchemaAtPath(document: JSONSchema, ref: string): JSONSchema {\n if (ref === '#') return document;\n\n const keys = ref.replace(/^#\\//, '').split('/');\n let current: any = document; // document is JSONSchema but doesn't like dereferencing w/ string\n\n let path: string = '#';\n for (const key of keys) {\n path = `${path}/${key}`;\n if (current[key] === undefined) {\n throw new InvalidRefError(\n `Invalid $ref value '${ref}'. Cannot find target schema at '${path}'`\n );\n }\n current = current[key];\n }\n\n return current as JSONSchema;\n}\n"],"names":["JSONStringify"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import { deepEquals, err, JSONStringify, ok } from '@conduit-client/utils';\nimport type { Result } from '@conduit-client/utils';\n\n// Based on https://json-schema.org/understanding-json-schema/\nexport type JSONSchema =\n | ObjectType\n | ArrayType\n | ScalarType\n | AnyOf\n | OneOf\n | AllOf\n | Not\n | RefType\n | EnumType\n | ConstType\n | boolean /* booleans are used to indicate if schema matches anything or nothing */;\n\nexport type BaseType = {\n enum?: any[]; // Enum can hold an array of allowed values of any type.\n const?: any; // Const represents a single allowed value.\n};\n\nexport type RefType = BaseType & { $ref: string };\n\nexport type EnumType = BaseType & {\n enum: any[];\n};\n\nexport type ConstType = BaseType & {\n const: any;\n};\n\n// Based on https://json-schema.org/understanding-json-schema/reference/object.html\nexport type ObjectType = BaseType & {\n type: 'object';\n properties: Record<string, JSONSchema>;\n required: string[];\n additionalProperties: JSONSchema;\n};\n\n// Based on https://json-schema.org/understanding-json-schema/reference/array.html\nexport type ArrayType = BaseType & {\n type: 'array';\n items: JSONSchema;\n minItems?: number;\n maxItems?: number;\n};\n\nexport type AnyOf = BaseType & {\n anyOf: JSONSchema[];\n};\n\nexport type OneOf = BaseType & {\n oneOf: JSONSchema[];\n};\n\nexport type AllOf = BaseType & {\n allOf: JSONSchema[];\n};\n\nexport type Not = BaseType & {\n not: JSONSchema;\n};\n\ntype ScalarType = IntegerType | NumberType | StringType | BooleanType | NullType;\n\nexport type IntegerType = BaseType & { type: 'integer' };\nexport type NumberType = BaseType & { type: 'number' };\nexport type StringType = BaseType & { type: 'string' };\nexport type BooleanType = BaseType & { type: 'boolean' };\nexport type NullType = BaseType & { type: 'null' };\nexport type JsonSchemaValidationError =\n | JsonSchemaViolationError\n | MinItemsViolationError\n | MaxItemsViolationError\n | IncorrectTypeError\n | AdditionalPropertiesError\n | MissingRequiredPropertyError\n | InvalidRefError;\n\nexport interface JsonSchemaValidationResponse {\n isValid: boolean;\n errors: Array<JsonSchemaValidationError>;\n}\n\nexport class JsonSchemaViolationError extends Error {\n public validationErrors: JsonSchemaValidationError[] = [];\n constructor(message?: string, validationErrors?: Array<JsonSchemaValidationError>) {\n super(message);\n this.validationErrors = validationErrors || [];\n }\n}\nexport class MinItemsViolationError extends JsonSchemaViolationError {}\nexport class MaxItemsViolationError extends JsonSchemaViolationError {}\nexport class IncorrectTypeError extends JsonSchemaViolationError {}\nexport class AdditionalPropertiesError extends JsonSchemaViolationError {}\nexport class MissingRequiredPropertyError extends JsonSchemaViolationError {}\nexport class InvalidRefError extends JsonSchemaViolationError {}\n\nclass JsonSchemaErrorCollector {\n errors: Array<JsonSchemaValidationError>;\n constructor() {\n this.errors = [];\n }\n add(error: JsonSchemaValidationError) {\n this.errors.push(error);\n }\n append(response: Result<boolean, JsonSchemaValidationError[]>) {\n if (response.isErr()) {\n this.errors.push(...response.error);\n }\n }\n hasErrors() {\n return this.errors.length > 0;\n }\n prepend(error: JsonSchemaValidationError) {\n this.errors.unshift(error);\n }\n toValidationResponse(): Result<boolean, JsonSchemaViolationError[]> {\n return !this.hasErrors() ? ok(true) : err(this.errors);\n }\n}\n\nfunction createThrowableError(errors: Array<JsonSchemaValidationError>): JsonSchemaValidationError {\n if (errors[0] instanceof MinItemsViolationError) {\n return new MinItemsViolationError(errors[0].message, errors);\n }\n if (errors[0] instanceof MaxItemsViolationError) {\n return new MaxItemsViolationError(errors[0].message, errors);\n }\n if (errors[0] instanceof IncorrectTypeError) {\n return new IncorrectTypeError(errors[0].message, errors);\n }\n if (errors[0] instanceof AdditionalPropertiesError) {\n return new AdditionalPropertiesError(errors[0].message, errors);\n }\n if (errors[0] instanceof MissingRequiredPropertyError) {\n return new MissingRequiredPropertyError(errors[0].message, errors);\n }\n if (errors[0] instanceof InvalidRefError) {\n return new InvalidRefError(errors[0].message, errors);\n }\n // any non-specific validation errors\n return new JsonSchemaViolationError(errors[0].message, errors);\n}\n\n/**\n * Validates a value against a schema in a TypeScript-friendly way.\n *\n * @typeParam Type TypeScript type that matches schema\n * @param data data to be checked\n * @param schema JSONSchema that matches Type\n */\nexport function assertIsValid<Type>(data: unknown, schema: JSONSchema): asserts data is Type {\n const validationResponse = validateJsonSchema(data, schema);\n if (validationResponse.isErr()) {\n throw createThrowableError(validationResponse.error);\n }\n}\n\nfunction incorrectTypeError(expected: string, actual: string, path: string): IncorrectTypeError {\n return new IncorrectTypeError(\n `Expected type ${expected} at path '${path}', found type ${actual}.`\n );\n}\n\nfunction validSchemaResponse(): Result<boolean, JsonSchemaValidationError[]> {\n return ok(true);\n}\n\nfunction invalidSchemaResponseWithError(\n error: JsonSchemaValidationError\n): Result<boolean, JsonSchemaViolationError[]> {\n return err([error]);\n}\n\nexport function validateJsonSchema(\n data: unknown,\n schema: JSONSchema,\n path: string = '$',\n document: JSONSchema = schema\n): Result<boolean, JsonSchemaValidationError[]> {\n if (schema === true) return validSchemaResponse();\n if (schema === false)\n return invalidSchemaResponseWithError(\n new JsonSchemaViolationError(`Data at ${path} has schema 'false'`)\n );\n\n const dataType = data === null ? 'null' : Array.isArray(data) ? 'array' : typeof data;\n const errorCollector = new JsonSchemaErrorCollector();\n if ('anyOf' in schema) {\n errorCollector.append(validateAnyOf(data, schema, path, document));\n } else if ('oneOf' in schema) {\n errorCollector.append(validateOneOf(data, schema, path, document));\n } else if ('allOf' in schema) {\n errorCollector.append(validateAllOf(data, schema, path, document));\n } else if ('not' in schema) {\n errorCollector.append(validateNot(data, schema, path, document));\n } else if ('$ref' in schema) {\n errorCollector.append(validateRef(data, schema, path, document));\n } else if ('type' in schema) {\n if (schema.type === 'object') {\n if (dataType !== 'object') {\n errorCollector.add(incorrectTypeError('object', dataType, path));\n } else {\n errorCollector.append(\n validateObject(data as Record<string, unknown>, schema, path, document)\n );\n }\n } else if (schema.type === 'array') {\n if (dataType !== 'array') {\n errorCollector.add(incorrectTypeError('array', dataType, path));\n } else {\n errorCollector.append(\n validateArray(data as Array<unknown>, schema, path, document)\n );\n }\n } else {\n errorCollector.append(\n validateScalar(data as string | number | boolean | null, schema, path)\n );\n }\n }\n if (schema.enum) {\n errorCollector.append(validateEnum(data, schema.enum, path));\n }\n if (schema.const) {\n errorCollector.append(validateConst(data, schema.const, path));\n }\n\n return errorCollector.toValidationResponse();\n}\n\nfunction validateAnyOf(\n data: unknown,\n schema: AnyOf,\n path: string,\n document: JSONSchema\n): Result<boolean, JsonSchemaValidationError[]> {\n let isValid = false;\n const errorCollector = new JsonSchemaErrorCollector();\n\n for (let i = 0, { length } = schema.anyOf; i < length; i++) {\n const element = schema.anyOf[i];\n const validationResponse = validateJsonSchema(\n data,\n element,\n `${path}.anyOf[${i}]`,\n document\n );\n if (validationResponse.isOk()) {\n isValid = true;\n break;\n } else {\n errorCollector.append(validationResponse);\n }\n }\n\n if (!isValid) {\n errorCollector.prepend(\n new JsonSchemaViolationError(`Data at ${path} did not match any subschema in anyOf.`)\n );\n return errorCollector.toValidationResponse();\n }\n\n return validSchemaResponse();\n}\n\nfunction validateOneOf(\n data: unknown,\n schema: OneOf,\n path: string,\n document: JSONSchema\n): Result<boolean, JsonSchemaValidationError[]> {\n let validSubShemaPaths: string[] = [];\n const errorCollector = new JsonSchemaErrorCollector();\n\n for (let i = 0, { length } = schema.oneOf; i < length; i++) {\n const element = schema.oneOf[i];\n const oneOfPath = `${path}.oneOf[${i}]`;\n const validationResponse = validateJsonSchema(data, element, oneOfPath, document);\n if (validationResponse.isOk()) {\n validSubShemaPaths.push(oneOfPath);\n } else {\n errorCollector.append(validationResponse);\n }\n }\n\n if (validSubShemaPaths.length === 0) {\n errorCollector.prepend(\n new JsonSchemaViolationError(`Data at ${path} did not match any subschema in oneOf.`)\n );\n return errorCollector.toValidationResponse();\n } else if (validSubShemaPaths.length > 1) {\n errorCollector.prepend(\n new JsonSchemaViolationError(\n `Data at ${path} matched multiple subschemas: [${validSubShemaPaths.join(', ')}].`\n )\n );\n return errorCollector.toValidationResponse();\n }\n\n return validSchemaResponse();\n}\n\nfunction validateAllOf(\n data: unknown,\n schema: AllOf,\n path: string,\n document: JSONSchema\n): Result<boolean, JsonSchemaValidationError[]> {\n let isValid = true;\n const errorCollector = new JsonSchemaErrorCollector();\n\n for (let i = 0, { length } = schema.allOf; i < length; i++) {\n const element = schema.allOf[i];\n const validationResponse = validateJsonSchema(\n data,\n element,\n `${path}.allOf[${i}]`,\n document\n );\n if (!validationResponse.isOk()) {\n errorCollector.append(validationResponse);\n isValid = false;\n }\n }\n\n if (!isValid) {\n errorCollector.prepend(\n new JsonSchemaViolationError(`Data at ${path} did not match some subschemas in allOf.`)\n );\n }\n return errorCollector.toValidationResponse();\n}\n\nfunction validateNot(data: unknown, schema: Not, path: string, document: JSONSchema) {\n const validationResponse = validateJsonSchema(data, schema.not, path, document);\n if (validationResponse.isOk()) {\n return invalidSchemaResponseWithError(\n new JsonSchemaViolationError(\n `Data at ${path} validated against the schema of a not clause.`\n )\n );\n }\n return validSchemaResponse();\n}\n\nfunction validateObject(\n data: Record<string, unknown>,\n schema: ObjectType,\n path: string,\n document: JSONSchema\n): Result<boolean, JsonSchemaValidationError[]> {\n const schemaKeys = Object.keys(schema.properties);\n const requiredKeys = new Set(schema.required);\n\n const schemaKeySet = new Set(schemaKeys);\n const errorCollector = new JsonSchemaErrorCollector();\n Object.keys(data).forEach((key) => {\n if (!schemaKeySet.has(key)) {\n errorCollector.append(\n validateJsonSchema(\n data[key],\n schema.additionalProperties,\n `${path}.additionalProperties[${key}]`,\n document\n )\n );\n }\n });\n\n for (let i = 0, length = schemaKeys.length; i < length; i++) {\n const key = schemaKeys[i];\n const keyInData = key in data && (data as any)[key] !== undefined;\n if (requiredKeys.has(key) && !keyInData) {\n errorCollector.add(\n new MissingRequiredPropertyError(\n `Object at path '${path}' is missing required property '${key}'.`\n )\n );\n }\n\n if (keyInData) {\n errorCollector.append(\n validateJsonSchema(\n (data as any)[key] as unknown,\n schema.properties[key],\n `${path}.${key}`,\n document\n )\n );\n }\n }\n return errorCollector.toValidationResponse();\n}\n\nfunction validateArray(\n data: Array<unknown>,\n schema: ArrayType,\n path: string,\n document: JSONSchema\n): Result<boolean, JsonSchemaValidationError[]> {\n if (schema.minItems !== undefined && data.length < schema.minItems) {\n return invalidSchemaResponseWithError(\n new MinItemsViolationError(\n `Array at path '${path}' fails minItems constraint. Has ${data.length} items, needs at least ${schema.minItems}.`\n )\n );\n }\n\n if (schema.maxItems !== undefined && data.length > schema.maxItems) {\n return invalidSchemaResponseWithError(\n new MaxItemsViolationError(\n `Array at path '${path}' fails maxItems constraint. Has ${data.length} items, needs at most ${schema.maxItems}.`\n )\n );\n }\n const errorCollector = new JsonSchemaErrorCollector();\n data.forEach((element, index) =>\n errorCollector.append(\n validateJsonSchema(element, schema.items, `${path}[${index}]`, document)\n )\n );\n return errorCollector.toValidationResponse();\n}\n\nfunction validateScalar(\n data: number | string | boolean | null,\n schema: ScalarType,\n path: string\n): Result<boolean, JsonSchemaValidationError[]> {\n const schemaDataType = schema.type;\n const dataType = typeof data;\n\n if (schemaDataType === 'integer') {\n if (dataType !== 'number' || !Number.isInteger(data)) {\n return invalidSchemaResponseWithError(incorrectTypeError('integer', dataType, path));\n }\n } else if (schemaDataType === 'number') {\n if (dataType !== 'number') {\n return invalidSchemaResponseWithError(incorrectTypeError('number', dataType, path));\n }\n } else if (schemaDataType === 'string') {\n if (dataType !== 'string') {\n return invalidSchemaResponseWithError(incorrectTypeError('string', dataType, path));\n }\n } else if (schemaDataType === 'boolean') {\n if (dataType !== 'boolean') {\n return invalidSchemaResponseWithError(incorrectTypeError('boolean', dataType, path));\n }\n } else if (schemaDataType === 'null') {\n if (data !== null) {\n return invalidSchemaResponseWithError(incorrectTypeError('null', dataType, path));\n }\n } else {\n return invalidSchemaResponseWithError(\n new IncorrectTypeError(`Unknown schema data type: ${schemaDataType}.`)\n );\n }\n return validSchemaResponse();\n}\nfunction validateRef(\n data: unknown,\n schema: RefType,\n path: string,\n document: JSONSchema\n): Result<boolean, JsonSchemaValidationError[]> {\n if (!schema.$ref.startsWith('#')) {\n return invalidSchemaResponseWithError(\n new InvalidRefError(\n `$ref values that do not refer to the current document are unsupported (must start with '#')`\n )\n );\n }\n try {\n const schemaToValidate = findSchemaAtPath(document, schema.$ref);\n return validateJsonSchema(data, schemaToValidate, path, document);\n } catch (e) {\n return invalidSchemaResponseWithError(e as InvalidRefError);\n }\n}\n\nfunction validateEnum(\n data: unknown,\n enumValue: any[],\n path: string\n): Result<boolean, JsonSchemaValidationError[]> {\n if (!enumValue.some((value) => deepEquals(value, data))) {\n return invalidSchemaResponseWithError(\n new JsonSchemaViolationError(\n `Data at ${path} did not match any values in enum. Expected value in: [${enumValue.map((value) => JSONStringify(value)).join()}]`\n )\n );\n }\n return validSchemaResponse();\n}\n\nfunction validateConst(\n data: unknown,\n constValue: any,\n path: string\n): Result<boolean, JsonSchemaValidationError[]> {\n if (!deepEquals(constValue, data)) {\n return invalidSchemaResponseWithError(\n new JsonSchemaViolationError(\n `Data at ${path} did not match const. Expected: ${JSONStringify(constValue)}`\n )\n );\n }\n return validSchemaResponse();\n}\n\nfunction findSchemaAtPath(document: JSONSchema, ref: string): JSONSchema {\n if (ref === '#') return document;\n\n const keys = ref.replace(/^#\\//, '').split('/');\n let current: any = document; // document is JSONSchema but doesn't like dereferencing w/ string\n\n let path: string = '#';\n for (const key of keys) {\n path = `${path}/${key}`;\n if (current[key] === undefined) {\n throw new InvalidRefError(\n `Invalid $ref value '${ref}'. Cannot find target schema at '${path}'`\n );\n }\n current = current[key];\n }\n\n return current as JSONSchema;\n}\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@conduit-client/jsonschema-validate",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Luvio Next JSON Schema Validation",
|
|
6
6
|
"type": "module",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"watch": "npm run build --watch"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@conduit-client/utils": "3.
|
|
26
|
+
"@conduit-client/utils": "3.3.0"
|
|
27
27
|
},
|
|
28
28
|
"volta": {
|
|
29
29
|
"extends": "../../../package.json"
|