Befor generating
This commit is contained in:
+42
@@ -0,0 +1,42 @@
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const definitionsDirectory = path.resolve(__dirname, '../../definitions');
|
||||
const outputDirectory = path.resolve(__dirname, '../../schemas');
|
||||
console.log(`Looking for separate definitions in the following directory: ${definitionsDirectory}`);
|
||||
console.log(`Using the following output directory: ${outputDirectory}`);
|
||||
|
||||
/**
|
||||
* When run, go through all versions that have split definitions and bundles them together.
|
||||
*/
|
||||
(async () => {
|
||||
const versions = await fs.promises.readdir(definitionsDirectory);
|
||||
console.log(`Ensuring output directory is present ${outputDirectory}`);
|
||||
if (!fs.existsSync(outputDirectory)) {
|
||||
await fs.promises.mkdir(outputDirectory);
|
||||
}
|
||||
console.log(`The following versions have separate definitions: ${versions.join(',')}`);
|
||||
for (const version of versions) {
|
||||
const Bundler = require("@hyperjump/json-schema-bundle");
|
||||
try{
|
||||
console.log(`Bundling the following version together: ${version}`);
|
||||
const versionDir = path.resolve(definitionsDirectory, version);
|
||||
const definitions = await fs.promises.readdir(versionDir);
|
||||
const definitionFiles = definitions.filter((value) => {return !value.includes('asyncapi')}).map((file) => fs.readFileSync(path.resolve(versionDir, file)));
|
||||
const definitionJson = definitionFiles.map((file) => JSON.parse(file));
|
||||
for (const jsonFile of definitionJson) {
|
||||
Bundler.add(jsonFile);
|
||||
}
|
||||
const filePathToBundle = `file://${versionDir}/asyncapi.json`;
|
||||
const fileToBundle = await Bundler.get(filePathToBundle);
|
||||
const bundledSchema = await Bundler.bundle(fileToBundle);
|
||||
bundledSchema.description = `!!Auto generated!! \n Do not manually edit. ${bundledSchema.description ?? ''}`;
|
||||
const outputFile = path.resolve(outputDirectory, `${version}.json`);
|
||||
console.log(`Writing the bundled file to: ${outputFile}`);
|
||||
await fs.promises.writeFile(outputFile, JSON.stringify(bundledSchema, null, 4));
|
||||
}catch(e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
console.log('done');
|
||||
})();
|
||||
|
||||
Generated
Vendored
+149
@@ -0,0 +1,149 @@
|
||||
{
|
||||
"name": "bundler",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"node_modules/@hyperjump/json-pointer": {
|
||||
"version": "0.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@hyperjump/json-pointer/-/json-pointer-0.9.1.tgz",
|
||||
"integrity": "sha512-tiDl/9MOkkiUQ5t+wq4PhtPghgWmFyBwU9Q6xRkXksg2s/6GNxNPcO/MzOjJoDAeCY1XXajNUIkco7wvhNmlOA==",
|
||||
"dependencies": {
|
||||
"just-curry-it": "^3.2.1"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/jdesrosiers"
|
||||
}
|
||||
},
|
||||
"node_modules/@hyperjump/json-schema": {
|
||||
"version": "0.18.3",
|
||||
"resolved": "https://registry.npmjs.org/@hyperjump/json-schema/-/json-schema-0.18.3.tgz",
|
||||
"integrity": "sha512-HKrrsuJOlYdqpHEr/eRU99LCiAe8ZH4LUkQOQOMa/P8pNSgs4FQHMKy3sgkmgLSgdmQbRX2/hA+yn2Ts/gS0lA==",
|
||||
"dependencies": {
|
||||
"@hyperjump/json-schema-core": "^0.23.4",
|
||||
"fastest-stable-stringify": "^2.0.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/jdesrosiers"
|
||||
}
|
||||
},
|
||||
"node_modules/@hyperjump/json-schema-bundle": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@hyperjump/json-schema-bundle/-/json-schema-bundle-0.1.3.tgz",
|
||||
"integrity": "sha512-UjmmtyIgaMXRXKmkJDQhvGAQFSfaPYBRue4tk3qeISrD468vziCWI2Km0RgfeXVxgy5xgqEPyi9DLXUqD4KWDQ==",
|
||||
"dependencies": {
|
||||
"@hyperjump/json-schema": "^0.18.3",
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/jdesrosiers"
|
||||
}
|
||||
},
|
||||
"node_modules/@hyperjump/json-schema-core": {
|
||||
"version": "0.23.4",
|
||||
"resolved": "https://registry.npmjs.org/@hyperjump/json-schema-core/-/json-schema-core-0.23.4.tgz",
|
||||
"integrity": "sha512-rHORA3qPk2JKOJOgwgXzGkMnad0neoPiHK8tPrITNxCcVM+AwPkTK+ABogNhbFG4lipWVF4gB3XHJ2qxfQuSAw==",
|
||||
"dependencies": {
|
||||
"@hyperjump/json-pointer": "^0.9.1",
|
||||
"@hyperjump/pact": "^0.2.0",
|
||||
"content-type": "^1.0.4",
|
||||
"node-fetch": "^2.6.5",
|
||||
"pubsub-js": "^1.9.1",
|
||||
"url-resolve-browser": "^1.2.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/jdesrosiers"
|
||||
}
|
||||
},
|
||||
"node_modules/@hyperjump/pact": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@hyperjump/pact/-/pact-0.2.0.tgz",
|
||||
"integrity": "sha512-RHt0XRFsADXbqopurGZfCUNL7mPc0695TD2HNDqs4RCK5Db/1lDU2Bhk9EsyFmCBE9N1/boyvdKWjT1UYHIebg==",
|
||||
"dependencies": {
|
||||
"just-curry-it": "^3.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/jdesrosiers"
|
||||
}
|
||||
},
|
||||
"node_modules/content-type": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
|
||||
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/fastest-stable-stringify": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz",
|
||||
"integrity": "sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q=="
|
||||
},
|
||||
"node_modules/just-curry-it": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/just-curry-it/-/just-curry-it-3.2.1.tgz",
|
||||
"integrity": "sha512-Q8206k8pTY7krW32cdmPsP+DqqLgWx/hYPSj9/+7SYqSqz7UuwPbfSe07lQtvuuaVyiSJveXk0E5RydOuWwsEg=="
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||
"dependencies": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "4.x || >=6.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"encoding": "^0.1.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"encoding": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/pubsub-js": {
|
||||
"version": "1.9.4",
|
||||
"resolved": "https://registry.npmjs.org/pubsub-js/-/pubsub-js-1.9.4.tgz",
|
||||
"integrity": "sha512-hJYpaDvPH4w8ZX/0Fdf9ma1AwRgU353GfbaVfPjfJQf1KxZ2iHaHl3fAUw1qlJIR5dr4F3RzjGaWohYUEyoh7A=="
|
||||
},
|
||||
"node_modules/tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
|
||||
},
|
||||
"node_modules/url-resolve-browser": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/url-resolve-browser/-/url-resolve-browser-1.2.0.tgz",
|
||||
"integrity": "sha512-L9PBPnlKNDFzt9ElK4br8I8Tufdm1xgv1GhMeiP7ZC87x0b7mr+4vSh13kmPq5km80JKX+UD2BeEFTCrFZ6xDA=="
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
|
||||
},
|
||||
"node_modules/whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
|
||||
"dependencies": {
|
||||
"tr46": "~0.0.3",
|
||||
"webidl-conversions": "^3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Jason Desrosiers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
Generated
Vendored
+73
@@ -0,0 +1,73 @@
|
||||
JSON Pointer
|
||||
============
|
||||
|
||||
This is an implementation of RFC-6901 JSON Pointer. JSON Pointer is designed for
|
||||
referring to data values within a JSON document. It's designed to be URL
|
||||
friendly so it can be used as a URL fragment that points to a specific part of
|
||||
the JSON document.
|
||||
|
||||
Installation
|
||||
------------
|
||||
Includes support for node.js JavaScript (CommonJS and ES Modules), TypeScript,
|
||||
and browsers.
|
||||
|
||||
```bash
|
||||
npm install @hyperjump/json-pointer
|
||||
```
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
```javascript
|
||||
const JsonPointer = require("@hyperjump/json-pointer");
|
||||
|
||||
const value = {
|
||||
"foo": {
|
||||
"bar": 42
|
||||
}
|
||||
};
|
||||
|
||||
// Construct pointers
|
||||
const fooPointer = JsonPointer.append(JsonPointer.nil, "foo"); // "/foo"
|
||||
const fooBarPointer = JsonPointer.append(fooPointer, "bar"); // "/foo/bar"
|
||||
|
||||
// Get a value from a pointer
|
||||
const getFooBar = JsonPointer.get(fooBarPointer);
|
||||
getFooBar(value); // 42
|
||||
|
||||
// Set a value from a pointer
|
||||
// New value is returned without modifying the original
|
||||
const setFooBar = JsonPointer.set(fooBarPointer);
|
||||
setFooBar(value, 33); // { "foo": { "bar": 33 } }
|
||||
|
||||
// Assign a value from a pointer
|
||||
// The original value is changed and no value is returned
|
||||
const assignFooBar = JsonPointer.assign(fooBarPointer);
|
||||
assignFooBar(value, 33); // { "foo": { "bar": 33 } }
|
||||
|
||||
// Unset a value from a pointer
|
||||
// New value is returned without modifying the original
|
||||
const unsetFooBar = JsonPointer.unset(fooBarPointer);
|
||||
setFooBar(value); // { "foo": {} }
|
||||
|
||||
// Delete a value from a pointer
|
||||
// The original value is changed and no value is returned
|
||||
const deleteFooBar = JsonPointer.remove(fooBarPointer);
|
||||
deleteFooBar(value); // { "foo": {} }
|
||||
```
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
### Tests
|
||||
|
||||
Run the tests
|
||||
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
|
||||
Run the tests with a continuous test runner
|
||||
```bash
|
||||
npm test -- --watch
|
||||
```
|
||||
Generated
Vendored
+181
@@ -0,0 +1,181 @@
|
||||
define(function () { 'use strict';
|
||||
|
||||
var justCurryIt = curry$1;
|
||||
|
||||
/*
|
||||
function add(a, b, c) {
|
||||
return a + b + c;
|
||||
}
|
||||
curry(add)(1)(2)(3); // 6
|
||||
curry(add)(1)(2)(2); // 5
|
||||
curry(add)(2)(4, 3); // 9
|
||||
|
||||
function add(...args) {
|
||||
return args.reduce((sum, n) => sum + n, 0)
|
||||
}
|
||||
var curryAdd4 = curry(add, 4)
|
||||
curryAdd4(1)(2, 3)(4); // 10
|
||||
|
||||
function converter(ratio, input) {
|
||||
return (input*ratio).toFixed(1);
|
||||
}
|
||||
const curriedConverter = curry(converter)
|
||||
const milesToKm = curriedConverter(1.62);
|
||||
milesToKm(35); // 56.7
|
||||
milesToKm(10); // 16.2
|
||||
*/
|
||||
|
||||
function curry$1(fn, arity) {
|
||||
return function curried() {
|
||||
if (arity == null) {
|
||||
arity = fn.length;
|
||||
}
|
||||
var args = [].slice.call(arguments);
|
||||
if (args.length >= arity) {
|
||||
return fn.apply(this, args);
|
||||
} else {
|
||||
return function() {
|
||||
return curried.apply(this, args.concat([].slice.call(arguments)));
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const curry = justCurryIt;
|
||||
|
||||
|
||||
const nil = "";
|
||||
|
||||
const compile = (pointer) => {
|
||||
if (pointer.length > 0 && pointer[0] !== "/") {
|
||||
throw Error("Invalid JSON Pointer");
|
||||
}
|
||||
|
||||
return pointer.split("/").slice(1).map(unescape);
|
||||
};
|
||||
|
||||
const get = (pointer, value = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
|
||||
const fn = (value) => ptr.reduce(([value, pointer], segment) => {
|
||||
return [applySegment(value, segment, pointer), append(segment, pointer)];
|
||||
}, [value, ""])[0];
|
||||
|
||||
return value === undefined ? fn : fn(value);
|
||||
};
|
||||
|
||||
const set = (pointer, subject = undefined, value = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = curry((subject, value) => _set(ptr, subject, value, nil));
|
||||
return subject === undefined ? fn : fn(subject, value);
|
||||
};
|
||||
|
||||
const _set = (pointer, subject, value, cursor) => {
|
||||
if (pointer.length === 0) {
|
||||
return value;
|
||||
} else if (pointer.length > 1) {
|
||||
const segment = pointer.shift();
|
||||
return { ...subject, [segment]: _set(pointer, applySegment(subject, segment, cursor), value, append(segment, cursor)) };
|
||||
} else if (Array.isArray(subject)) {
|
||||
const clonedSubject = [...subject];
|
||||
const segment = computeSegment(subject, pointer[0]);
|
||||
clonedSubject[segment] = value;
|
||||
return clonedSubject;
|
||||
} else if (typeof subject === "object" && subject !== null) {
|
||||
return { ...subject, [pointer[0]]: value };
|
||||
} else {
|
||||
return applySegment(subject, pointer[0], cursor);
|
||||
}
|
||||
};
|
||||
|
||||
const assign = (pointer, subject = undefined, value = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = curry((subject, value) => _assign(ptr, subject, value, nil));
|
||||
return subject === undefined ? fn : fn(subject, value);
|
||||
};
|
||||
|
||||
const _assign = (pointer, subject, value, cursor) => {
|
||||
if (pointer.length === 0) {
|
||||
return;
|
||||
} else if (pointer.length === 1 && !isScalar(subject)) {
|
||||
const segment = computeSegment(subject, pointer[0]);
|
||||
subject[segment] = value;
|
||||
} else {
|
||||
const segment = pointer.shift();
|
||||
_assign(pointer, applySegment(subject, segment, cursor), value, append(segment, cursor));
|
||||
}
|
||||
};
|
||||
|
||||
const unset = (pointer, subject = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = (subject) => _unset(ptr, subject, nil);
|
||||
return subject === undefined ? fn : fn(subject);
|
||||
};
|
||||
|
||||
const _unset = (pointer, subject, cursor) => {
|
||||
if (pointer.length == 0) {
|
||||
return undefined;
|
||||
} else if (pointer.length > 1) {
|
||||
const segment = pointer.shift();
|
||||
const value = applySegment(subject, segment, cursor);
|
||||
return { ...subject, [segment]: _unset(pointer, value, append(segment, cursor)) };
|
||||
} else if (Array.isArray(subject)) {
|
||||
return subject.filter((_, ndx) => ndx != pointer[0]);
|
||||
} else if (typeof subject === "object" && subject !== null) {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const { [pointer[0]]: _, ...result } = subject;
|
||||
return result;
|
||||
} else {
|
||||
return applySegment(subject, pointer[0], cursor);
|
||||
}
|
||||
};
|
||||
|
||||
const remove = (pointer, subject = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = (subject) => _remove(ptr, subject, nil);
|
||||
return subject === undefined ? fn : fn(subject);
|
||||
};
|
||||
|
||||
const _remove = (pointer, subject, cursor) => {
|
||||
if (pointer.length === 0) {
|
||||
return;
|
||||
} else if (pointer.length > 1) {
|
||||
const segment = pointer.shift();
|
||||
const value = applySegment(subject, segment, cursor);
|
||||
_remove(pointer, value, append(segment, cursor));
|
||||
} else if (Array.isArray(subject)) {
|
||||
subject.splice(pointer[0], 1);
|
||||
} else if (typeof subject === "object" && subject !== null) {
|
||||
delete subject[pointer[0]];
|
||||
} else {
|
||||
applySegment(subject, pointer[0], cursor);
|
||||
}
|
||||
};
|
||||
|
||||
const append = curry((segment, pointer) => pointer + "/" + escape(segment));
|
||||
|
||||
const escape = (segment) => segment.toString().replace(/~/g, "~0").replace(/\//g, "~1");
|
||||
const unescape = (segment) => segment.toString().replace(/~1/g, "/").replace(/~0/g, "~");
|
||||
const computeSegment = (value, segment) => Array.isArray(value) && segment === "-" ? value.length : segment;
|
||||
|
||||
const applySegment = (value, segment, cursor = "") => {
|
||||
if (value === undefined) {
|
||||
throw TypeError(`Value at '${cursor}' is undefined and does not have property '${segment}'`);
|
||||
} else if (value === null) {
|
||||
throw TypeError(`Value at '${cursor}' is null and does not have property '${segment}'`);
|
||||
} else if (isScalar(value)) {
|
||||
throw TypeError(`Value at '${cursor}' is a ${typeof value} and does not have property '${segment}'`);
|
||||
} else {
|
||||
const computedSegment = computeSegment(value, segment);
|
||||
return value[computedSegment];
|
||||
}
|
||||
};
|
||||
|
||||
const isScalar = (value) => value === null || typeof value !== "object";
|
||||
|
||||
var lib = { nil, append, get, set, assign, unset, remove };
|
||||
|
||||
return lib;
|
||||
|
||||
});
|
||||
//# sourceMappingURL=json-pointer-amd.js.map
|
||||
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
define((function(){"use strict";const e=function(e,t){return function r(){null==t&&(t=e.length);var n=[].slice.call(arguments);return n.length>=t?e.apply(this,n):function(){return r.apply(this,n.concat([].slice.call(arguments)))}}},t=e=>{if(e.length>0&&"/"!==e[0])throw Error("Invalid JSON Pointer");return e.split("/").slice(1).map(u)},r=(e,t,n,i)=>{if(0===e.length)return n;if(e.length>1){const o=e.shift();return{...t,[o]:r(e,c(t,o,i),n,l(o,i))}}if(Array.isArray(t)){const r=[...t];return r[a(t,e[0])]=n,r}return"object"==typeof t&&null!==t?{...t,[e[0]]:n}:c(t,e[0],i)},n=(e,t,r,i)=>{if(0!==e.length)if(1!==e.length||f(t)){const o=e.shift();n(e,c(t,o,i),r,l(o,i))}else{t[a(t,e[0])]=r}},i=(e,t,r)=>{if(0!=e.length){if(e.length>1){const n=e.shift(),o=c(t,n,r);return{...t,[n]:i(e,o,l(n,r))}}if(Array.isArray(t))return t.filter(((t,r)=>r!=e[0]));if("object"==typeof t&&null!==t){const{[e[0]]:r,...n}=t;return n}return c(t,e[0],r)}},o=(e,t,r)=>{if(0!==e.length)if(e.length>1){const n=e.shift(),i=c(t,n,r);o(e,i,l(n,r))}else Array.isArray(t)?t.splice(e[0],1):"object"==typeof t&&null!==t?delete t[e[0]]:c(t,e[0],r)},l=e(((e,t)=>t+"/"+s(e))),s=e=>e.toString().replace(/~/g,"~0").replace(/\//g,"~1"),u=e=>e.toString().replace(/~1/g,"/").replace(/~0/g,"~"),a=(e,t)=>Array.isArray(e)&&"-"===t?e.length:t,c=(e,t,r="")=>{if(void 0===e)throw TypeError(`Value at '${r}' is undefined and does not have property '${t}'`);if(null===e)throw TypeError(`Value at '${r}' is null and does not have property '${t}'`);if(f(e))throw TypeError(`Value at '${r}' is a ${typeof e} and does not have property '${t}'`);return e[a(e,t)]},f=e=>null===e||"object"!=typeof e;return{nil:"",append:l,get:(e,r)=>{const n=t(e),i=e=>n.reduce((([e,t],r)=>[c(e,r,t),l(r,t)]),[e,""])[0];return void 0===r?i:i(r)},set:(n,i,o)=>{const l=t(n),s=e(((e,t)=>r(l,e,t,"")));return void 0===i?s:s(i,o)},assign:(r,i,o)=>{const l=t(r),s=e(((e,t)=>n(l,e,t,"")));return void 0===i?s:s(i,o)},unset:(e,r)=>{const n=t(e),o=e=>i(n,e,"");return void 0===r?o:o(r)},remove:(e,r)=>{const n=t(e),i=e=>o(n,e,"");return void 0===r?i:i(r)}}}));
|
||||
//# sourceMappingURL=json-pointer-amd.min.js.map
|
||||
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+179
@@ -0,0 +1,179 @@
|
||||
'use strict';
|
||||
|
||||
var justCurryIt = curry$1;
|
||||
|
||||
/*
|
||||
function add(a, b, c) {
|
||||
return a + b + c;
|
||||
}
|
||||
curry(add)(1)(2)(3); // 6
|
||||
curry(add)(1)(2)(2); // 5
|
||||
curry(add)(2)(4, 3); // 9
|
||||
|
||||
function add(...args) {
|
||||
return args.reduce((sum, n) => sum + n, 0)
|
||||
}
|
||||
var curryAdd4 = curry(add, 4)
|
||||
curryAdd4(1)(2, 3)(4); // 10
|
||||
|
||||
function converter(ratio, input) {
|
||||
return (input*ratio).toFixed(1);
|
||||
}
|
||||
const curriedConverter = curry(converter)
|
||||
const milesToKm = curriedConverter(1.62);
|
||||
milesToKm(35); // 56.7
|
||||
milesToKm(10); // 16.2
|
||||
*/
|
||||
|
||||
function curry$1(fn, arity) {
|
||||
return function curried() {
|
||||
if (arity == null) {
|
||||
arity = fn.length;
|
||||
}
|
||||
var args = [].slice.call(arguments);
|
||||
if (args.length >= arity) {
|
||||
return fn.apply(this, args);
|
||||
} else {
|
||||
return function() {
|
||||
return curried.apply(this, args.concat([].slice.call(arguments)));
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const curry = justCurryIt;
|
||||
|
||||
|
||||
const nil = "";
|
||||
|
||||
const compile = (pointer) => {
|
||||
if (pointer.length > 0 && pointer[0] !== "/") {
|
||||
throw Error("Invalid JSON Pointer");
|
||||
}
|
||||
|
||||
return pointer.split("/").slice(1).map(unescape);
|
||||
};
|
||||
|
||||
const get = (pointer, value = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
|
||||
const fn = (value) => ptr.reduce(([value, pointer], segment) => {
|
||||
return [applySegment(value, segment, pointer), append(segment, pointer)];
|
||||
}, [value, ""])[0];
|
||||
|
||||
return value === undefined ? fn : fn(value);
|
||||
};
|
||||
|
||||
const set = (pointer, subject = undefined, value = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = curry((subject, value) => _set(ptr, subject, value, nil));
|
||||
return subject === undefined ? fn : fn(subject, value);
|
||||
};
|
||||
|
||||
const _set = (pointer, subject, value, cursor) => {
|
||||
if (pointer.length === 0) {
|
||||
return value;
|
||||
} else if (pointer.length > 1) {
|
||||
const segment = pointer.shift();
|
||||
return { ...subject, [segment]: _set(pointer, applySegment(subject, segment, cursor), value, append(segment, cursor)) };
|
||||
} else if (Array.isArray(subject)) {
|
||||
const clonedSubject = [...subject];
|
||||
const segment = computeSegment(subject, pointer[0]);
|
||||
clonedSubject[segment] = value;
|
||||
return clonedSubject;
|
||||
} else if (typeof subject === "object" && subject !== null) {
|
||||
return { ...subject, [pointer[0]]: value };
|
||||
} else {
|
||||
return applySegment(subject, pointer[0], cursor);
|
||||
}
|
||||
};
|
||||
|
||||
const assign = (pointer, subject = undefined, value = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = curry((subject, value) => _assign(ptr, subject, value, nil));
|
||||
return subject === undefined ? fn : fn(subject, value);
|
||||
};
|
||||
|
||||
const _assign = (pointer, subject, value, cursor) => {
|
||||
if (pointer.length === 0) {
|
||||
return;
|
||||
} else if (pointer.length === 1 && !isScalar(subject)) {
|
||||
const segment = computeSegment(subject, pointer[0]);
|
||||
subject[segment] = value;
|
||||
} else {
|
||||
const segment = pointer.shift();
|
||||
_assign(pointer, applySegment(subject, segment, cursor), value, append(segment, cursor));
|
||||
}
|
||||
};
|
||||
|
||||
const unset = (pointer, subject = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = (subject) => _unset(ptr, subject, nil);
|
||||
return subject === undefined ? fn : fn(subject);
|
||||
};
|
||||
|
||||
const _unset = (pointer, subject, cursor) => {
|
||||
if (pointer.length == 0) {
|
||||
return undefined;
|
||||
} else if (pointer.length > 1) {
|
||||
const segment = pointer.shift();
|
||||
const value = applySegment(subject, segment, cursor);
|
||||
return { ...subject, [segment]: _unset(pointer, value, append(segment, cursor)) };
|
||||
} else if (Array.isArray(subject)) {
|
||||
return subject.filter((_, ndx) => ndx != pointer[0]);
|
||||
} else if (typeof subject === "object" && subject !== null) {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const { [pointer[0]]: _, ...result } = subject;
|
||||
return result;
|
||||
} else {
|
||||
return applySegment(subject, pointer[0], cursor);
|
||||
}
|
||||
};
|
||||
|
||||
const remove = (pointer, subject = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = (subject) => _remove(ptr, subject, nil);
|
||||
return subject === undefined ? fn : fn(subject);
|
||||
};
|
||||
|
||||
const _remove = (pointer, subject, cursor) => {
|
||||
if (pointer.length === 0) {
|
||||
return;
|
||||
} else if (pointer.length > 1) {
|
||||
const segment = pointer.shift();
|
||||
const value = applySegment(subject, segment, cursor);
|
||||
_remove(pointer, value, append(segment, cursor));
|
||||
} else if (Array.isArray(subject)) {
|
||||
subject.splice(pointer[0], 1);
|
||||
} else if (typeof subject === "object" && subject !== null) {
|
||||
delete subject[pointer[0]];
|
||||
} else {
|
||||
applySegment(subject, pointer[0], cursor);
|
||||
}
|
||||
};
|
||||
|
||||
const append = curry((segment, pointer) => pointer + "/" + escape(segment));
|
||||
|
||||
const escape = (segment) => segment.toString().replace(/~/g, "~0").replace(/\//g, "~1");
|
||||
const unescape = (segment) => segment.toString().replace(/~1/g, "/").replace(/~0/g, "~");
|
||||
const computeSegment = (value, segment) => Array.isArray(value) && segment === "-" ? value.length : segment;
|
||||
|
||||
const applySegment = (value, segment, cursor = "") => {
|
||||
if (value === undefined) {
|
||||
throw TypeError(`Value at '${cursor}' is undefined and does not have property '${segment}'`);
|
||||
} else if (value === null) {
|
||||
throw TypeError(`Value at '${cursor}' is null and does not have property '${segment}'`);
|
||||
} else if (isScalar(value)) {
|
||||
throw TypeError(`Value at '${cursor}' is a ${typeof value} and does not have property '${segment}'`);
|
||||
} else {
|
||||
const computedSegment = computeSegment(value, segment);
|
||||
return value[computedSegment];
|
||||
}
|
||||
};
|
||||
|
||||
const isScalar = (value) => value === null || typeof value !== "object";
|
||||
|
||||
var lib = { nil, append, get, set, assign, unset, remove };
|
||||
|
||||
module.exports = lib;
|
||||
//# sourceMappingURL=json-pointer-cjs.js.map
|
||||
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
"use strict";const e=function(e,r){return function t(){null==r&&(r=e.length);var n=[].slice.call(arguments);return n.length>=r?e.apply(this,n):function(){return t.apply(this,n.concat([].slice.call(arguments)))}}},r=e=>{if(e.length>0&&"/"!==e[0])throw Error("Invalid JSON Pointer");return e.split("/").slice(1).map(a)},t=(e,r,n,o)=>{if(0===e.length)return n;if(e.length>1){const i=e.shift();return{...r,[i]:t(e,c(r,i,o),n,l(i,o))}}if(Array.isArray(r)){const t=[...r];return t[u(r,e[0])]=n,t}return"object"==typeof r&&null!==r?{...r,[e[0]]:n}:c(r,e[0],o)},n=(e,r,t,o)=>{if(0!==e.length)if(1!==e.length||f(r)){const i=e.shift();n(e,c(r,i,o),t,l(i,o))}else{r[u(r,e[0])]=t}},o=(e,r,t)=>{if(0!=e.length){if(e.length>1){const n=e.shift(),i=c(r,n,t);return{...r,[n]:o(e,i,l(n,t))}}if(Array.isArray(r))return r.filter(((r,t)=>t!=e[0]));if("object"==typeof r&&null!==r){const{[e[0]]:t,...n}=r;return n}return c(r,e[0],t)}},i=(e,r,t)=>{if(0!==e.length)if(e.length>1){const n=e.shift(),o=c(r,n,t);i(e,o,l(n,t))}else Array.isArray(r)?r.splice(e[0],1):"object"==typeof r&&null!==r?delete r[e[0]]:c(r,e[0],t)},l=e(((e,r)=>r+"/"+s(e))),s=e=>e.toString().replace(/~/g,"~0").replace(/\//g,"~1"),a=e=>e.toString().replace(/~1/g,"/").replace(/~0/g,"~"),u=(e,r)=>Array.isArray(e)&&"-"===r?e.length:r,c=(e,r,t="")=>{if(void 0===e)throw TypeError(`Value at '${t}' is undefined and does not have property '${r}'`);if(null===e)throw TypeError(`Value at '${t}' is null and does not have property '${r}'`);if(f(e))throw TypeError(`Value at '${t}' is a ${typeof e} and does not have property '${r}'`);return e[u(e,r)]},f=e=>null===e||"object"!=typeof e;var p={nil:"",append:l,get:(e,t)=>{const n=r(e),o=e=>n.reduce((([e,r],t)=>[c(e,t,r),l(t,r)]),[e,""])[0];return void 0===t?o:o(t)},set:(n,o,i)=>{const l=r(n),s=e(((e,r)=>t(l,e,r,"")));return void 0===o?s:s(o,i)},assign:(t,o,i)=>{const l=r(t),s=e(((e,r)=>n(l,e,r,"")));return void 0===o?s:s(o,i)},unset:(e,t)=>{const n=r(e),i=e=>o(n,e,"");return void 0===t?i:i(t)},remove:(e,t)=>{const n=r(e),o=e=>i(n,e,"");return void 0===t?o:o(t)}};module.exports=p;
|
||||
//# sourceMappingURL=json-pointer-cjs.min.js.map
|
||||
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+177
@@ -0,0 +1,177 @@
|
||||
var justCurryIt = curry$1;
|
||||
|
||||
/*
|
||||
function add(a, b, c) {
|
||||
return a + b + c;
|
||||
}
|
||||
curry(add)(1)(2)(3); // 6
|
||||
curry(add)(1)(2)(2); // 5
|
||||
curry(add)(2)(4, 3); // 9
|
||||
|
||||
function add(...args) {
|
||||
return args.reduce((sum, n) => sum + n, 0)
|
||||
}
|
||||
var curryAdd4 = curry(add, 4)
|
||||
curryAdd4(1)(2, 3)(4); // 10
|
||||
|
||||
function converter(ratio, input) {
|
||||
return (input*ratio).toFixed(1);
|
||||
}
|
||||
const curriedConverter = curry(converter)
|
||||
const milesToKm = curriedConverter(1.62);
|
||||
milesToKm(35); // 56.7
|
||||
milesToKm(10); // 16.2
|
||||
*/
|
||||
|
||||
function curry$1(fn, arity) {
|
||||
return function curried() {
|
||||
if (arity == null) {
|
||||
arity = fn.length;
|
||||
}
|
||||
var args = [].slice.call(arguments);
|
||||
if (args.length >= arity) {
|
||||
return fn.apply(this, args);
|
||||
} else {
|
||||
return function() {
|
||||
return curried.apply(this, args.concat([].slice.call(arguments)));
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const curry = justCurryIt;
|
||||
|
||||
|
||||
const nil = "";
|
||||
|
||||
const compile = (pointer) => {
|
||||
if (pointer.length > 0 && pointer[0] !== "/") {
|
||||
throw Error("Invalid JSON Pointer");
|
||||
}
|
||||
|
||||
return pointer.split("/").slice(1).map(unescape);
|
||||
};
|
||||
|
||||
const get = (pointer, value = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
|
||||
const fn = (value) => ptr.reduce(([value, pointer], segment) => {
|
||||
return [applySegment(value, segment, pointer), append(segment, pointer)];
|
||||
}, [value, ""])[0];
|
||||
|
||||
return value === undefined ? fn : fn(value);
|
||||
};
|
||||
|
||||
const set = (pointer, subject = undefined, value = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = curry((subject, value) => _set(ptr, subject, value, nil));
|
||||
return subject === undefined ? fn : fn(subject, value);
|
||||
};
|
||||
|
||||
const _set = (pointer, subject, value, cursor) => {
|
||||
if (pointer.length === 0) {
|
||||
return value;
|
||||
} else if (pointer.length > 1) {
|
||||
const segment = pointer.shift();
|
||||
return { ...subject, [segment]: _set(pointer, applySegment(subject, segment, cursor), value, append(segment, cursor)) };
|
||||
} else if (Array.isArray(subject)) {
|
||||
const clonedSubject = [...subject];
|
||||
const segment = computeSegment(subject, pointer[0]);
|
||||
clonedSubject[segment] = value;
|
||||
return clonedSubject;
|
||||
} else if (typeof subject === "object" && subject !== null) {
|
||||
return { ...subject, [pointer[0]]: value };
|
||||
} else {
|
||||
return applySegment(subject, pointer[0], cursor);
|
||||
}
|
||||
};
|
||||
|
||||
const assign = (pointer, subject = undefined, value = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = curry((subject, value) => _assign(ptr, subject, value, nil));
|
||||
return subject === undefined ? fn : fn(subject, value);
|
||||
};
|
||||
|
||||
const _assign = (pointer, subject, value, cursor) => {
|
||||
if (pointer.length === 0) {
|
||||
return;
|
||||
} else if (pointer.length === 1 && !isScalar(subject)) {
|
||||
const segment = computeSegment(subject, pointer[0]);
|
||||
subject[segment] = value;
|
||||
} else {
|
||||
const segment = pointer.shift();
|
||||
_assign(pointer, applySegment(subject, segment, cursor), value, append(segment, cursor));
|
||||
}
|
||||
};
|
||||
|
||||
const unset = (pointer, subject = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = (subject) => _unset(ptr, subject, nil);
|
||||
return subject === undefined ? fn : fn(subject);
|
||||
};
|
||||
|
||||
const _unset = (pointer, subject, cursor) => {
|
||||
if (pointer.length == 0) {
|
||||
return undefined;
|
||||
} else if (pointer.length > 1) {
|
||||
const segment = pointer.shift();
|
||||
const value = applySegment(subject, segment, cursor);
|
||||
return { ...subject, [segment]: _unset(pointer, value, append(segment, cursor)) };
|
||||
} else if (Array.isArray(subject)) {
|
||||
return subject.filter((_, ndx) => ndx != pointer[0]);
|
||||
} else if (typeof subject === "object" && subject !== null) {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const { [pointer[0]]: _, ...result } = subject;
|
||||
return result;
|
||||
} else {
|
||||
return applySegment(subject, pointer[0], cursor);
|
||||
}
|
||||
};
|
||||
|
||||
const remove = (pointer, subject = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = (subject) => _remove(ptr, subject, nil);
|
||||
return subject === undefined ? fn : fn(subject);
|
||||
};
|
||||
|
||||
const _remove = (pointer, subject, cursor) => {
|
||||
if (pointer.length === 0) {
|
||||
return;
|
||||
} else if (pointer.length > 1) {
|
||||
const segment = pointer.shift();
|
||||
const value = applySegment(subject, segment, cursor);
|
||||
_remove(pointer, value, append(segment, cursor));
|
||||
} else if (Array.isArray(subject)) {
|
||||
subject.splice(pointer[0], 1);
|
||||
} else if (typeof subject === "object" && subject !== null) {
|
||||
delete subject[pointer[0]];
|
||||
} else {
|
||||
applySegment(subject, pointer[0], cursor);
|
||||
}
|
||||
};
|
||||
|
||||
const append = curry((segment, pointer) => pointer + "/" + escape(segment));
|
||||
|
||||
const escape = (segment) => segment.toString().replace(/~/g, "~0").replace(/\//g, "~1");
|
||||
const unescape = (segment) => segment.toString().replace(/~1/g, "/").replace(/~0/g, "~");
|
||||
const computeSegment = (value, segment) => Array.isArray(value) && segment === "-" ? value.length : segment;
|
||||
|
||||
const applySegment = (value, segment, cursor = "") => {
|
||||
if (value === undefined) {
|
||||
throw TypeError(`Value at '${cursor}' is undefined and does not have property '${segment}'`);
|
||||
} else if (value === null) {
|
||||
throw TypeError(`Value at '${cursor}' is null and does not have property '${segment}'`);
|
||||
} else if (isScalar(value)) {
|
||||
throw TypeError(`Value at '${cursor}' is a ${typeof value} and does not have property '${segment}'`);
|
||||
} else {
|
||||
const computedSegment = computeSegment(value, segment);
|
||||
return value[computedSegment];
|
||||
}
|
||||
};
|
||||
|
||||
const isScalar = (value) => value === null || typeof value !== "object";
|
||||
|
||||
var lib = { nil, append, get, set, assign, unset, remove };
|
||||
|
||||
export { lib as default };
|
||||
//# sourceMappingURL=json-pointer-esm.js.map
|
||||
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
const e=function(e,r){return function t(){null==r&&(r=e.length);var n=[].slice.call(arguments);return n.length>=r?e.apply(this,n):function(){return t.apply(this,n.concat([].slice.call(arguments)))}}},r=e=>{if(e.length>0&&"/"!==e[0])throw Error("Invalid JSON Pointer");return e.split("/").slice(1).map(a)},t=(e,r,n,o)=>{if(0===e.length)return n;if(e.length>1){const l=e.shift();return{...r,[l]:t(e,c(r,l,o),n,i(l,o))}}if(Array.isArray(r)){const t=[...r];return t[u(r,e[0])]=n,t}return"object"==typeof r&&null!==r?{...r,[e[0]]:n}:c(r,e[0],o)},n=(e,r,t,o)=>{if(0!==e.length)if(1!==e.length||f(r)){const l=e.shift();n(e,c(r,l,o),t,i(l,o))}else{r[u(r,e[0])]=t}},o=(e,r,t)=>{if(0!=e.length){if(e.length>1){const n=e.shift(),l=c(r,n,t);return{...r,[n]:o(e,l,i(n,t))}}if(Array.isArray(r))return r.filter(((r,t)=>t!=e[0]));if("object"==typeof r&&null!==r){const{[e[0]]:t,...n}=r;return n}return c(r,e[0],t)}},l=(e,r,t)=>{if(0!==e.length)if(e.length>1){const n=e.shift(),o=c(r,n,t);l(e,o,i(n,t))}else Array.isArray(r)?r.splice(e[0],1):"object"==typeof r&&null!==r?delete r[e[0]]:c(r,e[0],t)},i=e(((e,r)=>r+"/"+s(e))),s=e=>e.toString().replace(/~/g,"~0").replace(/\//g,"~1"),a=e=>e.toString().replace(/~1/g,"/").replace(/~0/g,"~"),u=(e,r)=>Array.isArray(e)&&"-"===r?e.length:r,c=(e,r,t="")=>{if(void 0===e)throw TypeError(`Value at '${t}' is undefined and does not have property '${r}'`);if(null===e)throw TypeError(`Value at '${t}' is null and does not have property '${r}'`);if(f(e))throw TypeError(`Value at '${t}' is a ${typeof e} and does not have property '${r}'`);return e[u(e,r)]},f=e=>null===e||"object"!=typeof e;var p={nil:"",append:i,get:(e,t)=>{const n=r(e),o=e=>n.reduce((([e,r],t)=>[c(e,t,r),i(t,r)]),[e,""])[0];return void 0===t?o:o(t)},set:(n,o,l)=>{const i=r(n),s=e(((e,r)=>t(i,e,r,"")));return void 0===o?s:s(o,l)},assign:(t,o,l)=>{const i=r(t),s=e(((e,r)=>n(i,e,r,"")));return void 0===o?s:s(o,l)},unset:(e,t)=>{const n=r(e),l=e=>o(n,e,"");return void 0===t?l:l(t)},remove:(e,t)=>{const n=r(e),o=e=>l(n,e,"");return void 0===t?o:o(t)}};export{p as default};
|
||||
//# sourceMappingURL=json-pointer-esm.min.js.map
|
||||
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+182
@@ -0,0 +1,182 @@
|
||||
var JsonPointer = (function () {
|
||||
'use strict';
|
||||
|
||||
var justCurryIt = curry$1;
|
||||
|
||||
/*
|
||||
function add(a, b, c) {
|
||||
return a + b + c;
|
||||
}
|
||||
curry(add)(1)(2)(3); // 6
|
||||
curry(add)(1)(2)(2); // 5
|
||||
curry(add)(2)(4, 3); // 9
|
||||
|
||||
function add(...args) {
|
||||
return args.reduce((sum, n) => sum + n, 0)
|
||||
}
|
||||
var curryAdd4 = curry(add, 4)
|
||||
curryAdd4(1)(2, 3)(4); // 10
|
||||
|
||||
function converter(ratio, input) {
|
||||
return (input*ratio).toFixed(1);
|
||||
}
|
||||
const curriedConverter = curry(converter)
|
||||
const milesToKm = curriedConverter(1.62);
|
||||
milesToKm(35); // 56.7
|
||||
milesToKm(10); // 16.2
|
||||
*/
|
||||
|
||||
function curry$1(fn, arity) {
|
||||
return function curried() {
|
||||
if (arity == null) {
|
||||
arity = fn.length;
|
||||
}
|
||||
var args = [].slice.call(arguments);
|
||||
if (args.length >= arity) {
|
||||
return fn.apply(this, args);
|
||||
} else {
|
||||
return function() {
|
||||
return curried.apply(this, args.concat([].slice.call(arguments)));
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const curry = justCurryIt;
|
||||
|
||||
|
||||
const nil = "";
|
||||
|
||||
const compile = (pointer) => {
|
||||
if (pointer.length > 0 && pointer[0] !== "/") {
|
||||
throw Error("Invalid JSON Pointer");
|
||||
}
|
||||
|
||||
return pointer.split("/").slice(1).map(unescape);
|
||||
};
|
||||
|
||||
const get = (pointer, value = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
|
||||
const fn = (value) => ptr.reduce(([value, pointer], segment) => {
|
||||
return [applySegment(value, segment, pointer), append(segment, pointer)];
|
||||
}, [value, ""])[0];
|
||||
|
||||
return value === undefined ? fn : fn(value);
|
||||
};
|
||||
|
||||
const set = (pointer, subject = undefined, value = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = curry((subject, value) => _set(ptr, subject, value, nil));
|
||||
return subject === undefined ? fn : fn(subject, value);
|
||||
};
|
||||
|
||||
const _set = (pointer, subject, value, cursor) => {
|
||||
if (pointer.length === 0) {
|
||||
return value;
|
||||
} else if (pointer.length > 1) {
|
||||
const segment = pointer.shift();
|
||||
return { ...subject, [segment]: _set(pointer, applySegment(subject, segment, cursor), value, append(segment, cursor)) };
|
||||
} else if (Array.isArray(subject)) {
|
||||
const clonedSubject = [...subject];
|
||||
const segment = computeSegment(subject, pointer[0]);
|
||||
clonedSubject[segment] = value;
|
||||
return clonedSubject;
|
||||
} else if (typeof subject === "object" && subject !== null) {
|
||||
return { ...subject, [pointer[0]]: value };
|
||||
} else {
|
||||
return applySegment(subject, pointer[0], cursor);
|
||||
}
|
||||
};
|
||||
|
||||
const assign = (pointer, subject = undefined, value = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = curry((subject, value) => _assign(ptr, subject, value, nil));
|
||||
return subject === undefined ? fn : fn(subject, value);
|
||||
};
|
||||
|
||||
const _assign = (pointer, subject, value, cursor) => {
|
||||
if (pointer.length === 0) {
|
||||
return;
|
||||
} else if (pointer.length === 1 && !isScalar(subject)) {
|
||||
const segment = computeSegment(subject, pointer[0]);
|
||||
subject[segment] = value;
|
||||
} else {
|
||||
const segment = pointer.shift();
|
||||
_assign(pointer, applySegment(subject, segment, cursor), value, append(segment, cursor));
|
||||
}
|
||||
};
|
||||
|
||||
const unset = (pointer, subject = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = (subject) => _unset(ptr, subject, nil);
|
||||
return subject === undefined ? fn : fn(subject);
|
||||
};
|
||||
|
||||
const _unset = (pointer, subject, cursor) => {
|
||||
if (pointer.length == 0) {
|
||||
return undefined;
|
||||
} else if (pointer.length > 1) {
|
||||
const segment = pointer.shift();
|
||||
const value = applySegment(subject, segment, cursor);
|
||||
return { ...subject, [segment]: _unset(pointer, value, append(segment, cursor)) };
|
||||
} else if (Array.isArray(subject)) {
|
||||
return subject.filter((_, ndx) => ndx != pointer[0]);
|
||||
} else if (typeof subject === "object" && subject !== null) {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const { [pointer[0]]: _, ...result } = subject;
|
||||
return result;
|
||||
} else {
|
||||
return applySegment(subject, pointer[0], cursor);
|
||||
}
|
||||
};
|
||||
|
||||
const remove = (pointer, subject = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = (subject) => _remove(ptr, subject, nil);
|
||||
return subject === undefined ? fn : fn(subject);
|
||||
};
|
||||
|
||||
const _remove = (pointer, subject, cursor) => {
|
||||
if (pointer.length === 0) {
|
||||
return;
|
||||
} else if (pointer.length > 1) {
|
||||
const segment = pointer.shift();
|
||||
const value = applySegment(subject, segment, cursor);
|
||||
_remove(pointer, value, append(segment, cursor));
|
||||
} else if (Array.isArray(subject)) {
|
||||
subject.splice(pointer[0], 1);
|
||||
} else if (typeof subject === "object" && subject !== null) {
|
||||
delete subject[pointer[0]];
|
||||
} else {
|
||||
applySegment(subject, pointer[0], cursor);
|
||||
}
|
||||
};
|
||||
|
||||
const append = curry((segment, pointer) => pointer + "/" + escape(segment));
|
||||
|
||||
const escape = (segment) => segment.toString().replace(/~/g, "~0").replace(/\//g, "~1");
|
||||
const unescape = (segment) => segment.toString().replace(/~1/g, "/").replace(/~0/g, "~");
|
||||
const computeSegment = (value, segment) => Array.isArray(value) && segment === "-" ? value.length : segment;
|
||||
|
||||
const applySegment = (value, segment, cursor = "") => {
|
||||
if (value === undefined) {
|
||||
throw TypeError(`Value at '${cursor}' is undefined and does not have property '${segment}'`);
|
||||
} else if (value === null) {
|
||||
throw TypeError(`Value at '${cursor}' is null and does not have property '${segment}'`);
|
||||
} else if (isScalar(value)) {
|
||||
throw TypeError(`Value at '${cursor}' is a ${typeof value} and does not have property '${segment}'`);
|
||||
} else {
|
||||
const computedSegment = computeSegment(value, segment);
|
||||
return value[computedSegment];
|
||||
}
|
||||
};
|
||||
|
||||
const isScalar = (value) => value === null || typeof value !== "object";
|
||||
|
||||
var lib = { nil, append, get, set, assign, unset, remove };
|
||||
|
||||
return lib;
|
||||
|
||||
}());
|
||||
//# sourceMappingURL=json-pointer-iife.js.map
|
||||
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
var JsonPointer=function(){"use strict";const r=function(r,t){return function e(){null==t&&(t=r.length);var n=[].slice.call(arguments);return n.length>=t?r.apply(this,n):function(){return e.apply(this,n.concat([].slice.call(arguments)))}}},t=r=>{if(r.length>0&&"/"!==r[0])throw Error("Invalid JSON Pointer");return r.split("/").slice(1).map(u)},e=(r,t,n,o)=>{if(0===r.length)return n;if(r.length>1){const i=r.shift();return{...t,[i]:e(r,c(t,i,o),n,l(i,o))}}if(Array.isArray(t)){const e=[...t];return e[a(t,r[0])]=n,e}return"object"==typeof t&&null!==t?{...t,[r[0]]:n}:c(t,r[0],o)},n=(r,t,e,o)=>{if(0!==r.length)if(1!==r.length||f(t)){const i=r.shift();n(r,c(t,i,o),e,l(i,o))}else{t[a(t,r[0])]=e}},o=(r,t,e)=>{if(0!=r.length){if(r.length>1){const n=r.shift(),i=c(t,n,e);return{...t,[n]:o(r,i,l(n,e))}}if(Array.isArray(t))return t.filter(((t,e)=>e!=r[0]));if("object"==typeof t&&null!==t){const{[r[0]]:e,...n}=t;return n}return c(t,r[0],e)}},i=(r,t,e)=>{if(0!==r.length)if(r.length>1){const n=r.shift(),o=c(t,n,e);i(r,o,l(n,e))}else Array.isArray(t)?t.splice(r[0],1):"object"==typeof t&&null!==t?delete t[r[0]]:c(t,r[0],e)},l=r(((r,t)=>t+"/"+s(r))),s=r=>r.toString().replace(/~/g,"~0").replace(/\//g,"~1"),u=r=>r.toString().replace(/~1/g,"/").replace(/~0/g,"~"),a=(r,t)=>Array.isArray(r)&&"-"===t?r.length:t,c=(r,t,e="")=>{if(void 0===r)throw TypeError(`Value at '${e}' is undefined and does not have property '${t}'`);if(null===r)throw TypeError(`Value at '${e}' is null and does not have property '${t}'`);if(f(r))throw TypeError(`Value at '${e}' is a ${typeof r} and does not have property '${t}'`);return r[a(r,t)]},f=r=>null===r||"object"!=typeof r;return{nil:"",append:l,get:(r,e)=>{const n=t(r),o=r=>n.reduce((([r,t],e)=>[c(r,e,t),l(e,t)]),[r,""])[0];return void 0===e?o:o(e)},set:(n,o,i)=>{const l=t(n),s=r(((r,t)=>e(l,r,t,"")));return void 0===o?s:s(o,i)},assign:(e,o,i)=>{const l=t(e),s=r(((r,t)=>n(l,r,t,"")));return void 0===o?s:s(o,i)},unset:(r,e)=>{const n=t(r),i=r=>o(n,r,"");return void 0===e?i:i(e)},remove:(r,e)=>{const n=t(r),o=r=>i(n,r,"");return void 0===e?o:o(e)}}}();
|
||||
//# sourceMappingURL=json-pointer-iife.min.js.map
|
||||
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+184
@@ -0,0 +1,184 @@
|
||||
System.register('JsonPointer', [], function (exports) {
|
||||
'use strict';
|
||||
return {
|
||||
execute: function () {
|
||||
|
||||
var justCurryIt = curry$1;
|
||||
|
||||
/*
|
||||
function add(a, b, c) {
|
||||
return a + b + c;
|
||||
}
|
||||
curry(add)(1)(2)(3); // 6
|
||||
curry(add)(1)(2)(2); // 5
|
||||
curry(add)(2)(4, 3); // 9
|
||||
|
||||
function add(...args) {
|
||||
return args.reduce((sum, n) => sum + n, 0)
|
||||
}
|
||||
var curryAdd4 = curry(add, 4)
|
||||
curryAdd4(1)(2, 3)(4); // 10
|
||||
|
||||
function converter(ratio, input) {
|
||||
return (input*ratio).toFixed(1);
|
||||
}
|
||||
const curriedConverter = curry(converter)
|
||||
const milesToKm = curriedConverter(1.62);
|
||||
milesToKm(35); // 56.7
|
||||
milesToKm(10); // 16.2
|
||||
*/
|
||||
|
||||
function curry$1(fn, arity) {
|
||||
return function curried() {
|
||||
if (arity == null) {
|
||||
arity = fn.length;
|
||||
}
|
||||
var args = [].slice.call(arguments);
|
||||
if (args.length >= arity) {
|
||||
return fn.apply(this, args);
|
||||
} else {
|
||||
return function() {
|
||||
return curried.apply(this, args.concat([].slice.call(arguments)));
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const curry = justCurryIt;
|
||||
|
||||
|
||||
const nil = "";
|
||||
|
||||
const compile = (pointer) => {
|
||||
if (pointer.length > 0 && pointer[0] !== "/") {
|
||||
throw Error("Invalid JSON Pointer");
|
||||
}
|
||||
|
||||
return pointer.split("/").slice(1).map(unescape);
|
||||
};
|
||||
|
||||
const get = (pointer, value = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
|
||||
const fn = (value) => ptr.reduce(([value, pointer], segment) => {
|
||||
return [applySegment(value, segment, pointer), append(segment, pointer)];
|
||||
}, [value, ""])[0];
|
||||
|
||||
return value === undefined ? fn : fn(value);
|
||||
};
|
||||
|
||||
const set = (pointer, subject = undefined, value = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = curry((subject, value) => _set(ptr, subject, value, nil));
|
||||
return subject === undefined ? fn : fn(subject, value);
|
||||
};
|
||||
|
||||
const _set = (pointer, subject, value, cursor) => {
|
||||
if (pointer.length === 0) {
|
||||
return value;
|
||||
} else if (pointer.length > 1) {
|
||||
const segment = pointer.shift();
|
||||
return { ...subject, [segment]: _set(pointer, applySegment(subject, segment, cursor), value, append(segment, cursor)) };
|
||||
} else if (Array.isArray(subject)) {
|
||||
const clonedSubject = [...subject];
|
||||
const segment = computeSegment(subject, pointer[0]);
|
||||
clonedSubject[segment] = value;
|
||||
return clonedSubject;
|
||||
} else if (typeof subject === "object" && subject !== null) {
|
||||
return { ...subject, [pointer[0]]: value };
|
||||
} else {
|
||||
return applySegment(subject, pointer[0], cursor);
|
||||
}
|
||||
};
|
||||
|
||||
const assign = (pointer, subject = undefined, value = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = curry((subject, value) => _assign(ptr, subject, value, nil));
|
||||
return subject === undefined ? fn : fn(subject, value);
|
||||
};
|
||||
|
||||
const _assign = (pointer, subject, value, cursor) => {
|
||||
if (pointer.length === 0) {
|
||||
return;
|
||||
} else if (pointer.length === 1 && !isScalar(subject)) {
|
||||
const segment = computeSegment(subject, pointer[0]);
|
||||
subject[segment] = value;
|
||||
} else {
|
||||
const segment = pointer.shift();
|
||||
_assign(pointer, applySegment(subject, segment, cursor), value, append(segment, cursor));
|
||||
}
|
||||
};
|
||||
|
||||
const unset = (pointer, subject = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = (subject) => _unset(ptr, subject, nil);
|
||||
return subject === undefined ? fn : fn(subject);
|
||||
};
|
||||
|
||||
const _unset = (pointer, subject, cursor) => {
|
||||
if (pointer.length == 0) {
|
||||
return undefined;
|
||||
} else if (pointer.length > 1) {
|
||||
const segment = pointer.shift();
|
||||
const value = applySegment(subject, segment, cursor);
|
||||
return { ...subject, [segment]: _unset(pointer, value, append(segment, cursor)) };
|
||||
} else if (Array.isArray(subject)) {
|
||||
return subject.filter((_, ndx) => ndx != pointer[0]);
|
||||
} else if (typeof subject === "object" && subject !== null) {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const { [pointer[0]]: _, ...result } = subject;
|
||||
return result;
|
||||
} else {
|
||||
return applySegment(subject, pointer[0], cursor);
|
||||
}
|
||||
};
|
||||
|
||||
const remove = (pointer, subject = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = (subject) => _remove(ptr, subject, nil);
|
||||
return subject === undefined ? fn : fn(subject);
|
||||
};
|
||||
|
||||
const _remove = (pointer, subject, cursor) => {
|
||||
if (pointer.length === 0) {
|
||||
return;
|
||||
} else if (pointer.length > 1) {
|
||||
const segment = pointer.shift();
|
||||
const value = applySegment(subject, segment, cursor);
|
||||
_remove(pointer, value, append(segment, cursor));
|
||||
} else if (Array.isArray(subject)) {
|
||||
subject.splice(pointer[0], 1);
|
||||
} else if (typeof subject === "object" && subject !== null) {
|
||||
delete subject[pointer[0]];
|
||||
} else {
|
||||
applySegment(subject, pointer[0], cursor);
|
||||
}
|
||||
};
|
||||
|
||||
const append = curry((segment, pointer) => pointer + "/" + escape(segment));
|
||||
|
||||
const escape = (segment) => segment.toString().replace(/~/g, "~0").replace(/\//g, "~1");
|
||||
const unescape = (segment) => segment.toString().replace(/~1/g, "/").replace(/~0/g, "~");
|
||||
const computeSegment = (value, segment) => Array.isArray(value) && segment === "-" ? value.length : segment;
|
||||
|
||||
const applySegment = (value, segment, cursor = "") => {
|
||||
if (value === undefined) {
|
||||
throw TypeError(`Value at '${cursor}' is undefined and does not have property '${segment}'`);
|
||||
} else if (value === null) {
|
||||
throw TypeError(`Value at '${cursor}' is null and does not have property '${segment}'`);
|
||||
} else if (isScalar(value)) {
|
||||
throw TypeError(`Value at '${cursor}' is a ${typeof value} and does not have property '${segment}'`);
|
||||
} else {
|
||||
const computedSegment = computeSegment(value, segment);
|
||||
return value[computedSegment];
|
||||
}
|
||||
};
|
||||
|
||||
const isScalar = (value) => value === null || typeof value !== "object";
|
||||
|
||||
var lib = exports('default', { nil, append, get, set, assign, unset, remove });
|
||||
|
||||
}
|
||||
};
|
||||
});
|
||||
//# sourceMappingURL=json-pointer-system.js.map
|
||||
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
System.register("JsonPointer",[],(function(e){"use strict";return{execute:function(){const t=function(e,t){return function r(){null==t&&(t=e.length);var n=[].slice.call(arguments);return n.length>=t?e.apply(this,n):function(){return r.apply(this,n.concat([].slice.call(arguments)))}}},r=e=>{if(e.length>0&&"/"!==e[0])throw Error("Invalid JSON Pointer");return e.split("/").slice(1).map(a)},n=(e,t,r,o)=>{if(0===e.length)return r;if(e.length>1){const i=e.shift();return{...t,[i]:n(e,f(t,i,o),r,s(i,o))}}if(Array.isArray(t)){const n=[...t];return n[c(t,e[0])]=r,n}return"object"==typeof t&&null!==t?{...t,[e[0]]:r}:f(t,e[0],o)},o=(e,t,r,n)=>{if(0!==e.length)if(1!==e.length||p(t)){const i=e.shift();o(e,f(t,i,n),r,s(i,n))}else{t[c(t,e[0])]=r}},i=(e,t,r)=>{if(0!=e.length){if(e.length>1){const n=e.shift(),o=f(t,n,r);return{...t,[n]:i(e,o,s(n,r))}}if(Array.isArray(t))return t.filter(((t,r)=>r!=e[0]));if("object"==typeof t&&null!==t){const{[e[0]]:r,...n}=t;return n}return f(t,e[0],r)}},l=(e,t,r)=>{if(0!==e.length)if(e.length>1){const n=e.shift(),o=f(t,n,r);l(e,o,s(n,r))}else Array.isArray(t)?t.splice(e[0],1):"object"==typeof t&&null!==t?delete t[e[0]]:f(t,e[0],r)},s=t(((e,t)=>t+"/"+u(e))),u=e=>e.toString().replace(/~/g,"~0").replace(/\//g,"~1"),a=e=>e.toString().replace(/~1/g,"/").replace(/~0/g,"~"),c=(e,t)=>Array.isArray(e)&&"-"===t?e.length:t,f=(e,t,r="")=>{if(void 0===e)throw TypeError(`Value at '${r}' is undefined and does not have property '${t}'`);if(null===e)throw TypeError(`Value at '${r}' is null and does not have property '${t}'`);if(p(e))throw TypeError(`Value at '${r}' is a ${typeof e} and does not have property '${t}'`);return e[c(e,t)]},p=e=>null===e||"object"!=typeof e;e("default",{nil:"",append:s,get:(e,t)=>{const n=r(e),o=e=>n.reduce((([e,t],r)=>[f(e,r,t),s(r,t)]),[e,""])[0];return void 0===t?o:o(t)},set:(e,o,i)=>{const l=r(e),s=t(((e,t)=>n(l,e,t,"")));return void 0===o?s:s(o,i)},assign:(e,n,i)=>{const l=r(e),s=t(((e,t)=>o(l,e,t,"")));return void 0===n?s:s(n,i)},unset:(e,t)=>{const n=r(e),o=e=>i(n,e,"");return void 0===t?o:o(t)},remove:(e,t)=>{const n=r(e),o=e=>l(n,e,"");return void 0===t?o:o(t)}})}}}));
|
||||
//# sourceMappingURL=json-pointer-system.min.js.map
|
||||
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+185
@@ -0,0 +1,185 @@
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
||||
typeof define === 'function' && define.amd ? define(factory) :
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.JsonPointer = factory());
|
||||
}(this, (function () { 'use strict';
|
||||
|
||||
var justCurryIt = curry$1;
|
||||
|
||||
/*
|
||||
function add(a, b, c) {
|
||||
return a + b + c;
|
||||
}
|
||||
curry(add)(1)(2)(3); // 6
|
||||
curry(add)(1)(2)(2); // 5
|
||||
curry(add)(2)(4, 3); // 9
|
||||
|
||||
function add(...args) {
|
||||
return args.reduce((sum, n) => sum + n, 0)
|
||||
}
|
||||
var curryAdd4 = curry(add, 4)
|
||||
curryAdd4(1)(2, 3)(4); // 10
|
||||
|
||||
function converter(ratio, input) {
|
||||
return (input*ratio).toFixed(1);
|
||||
}
|
||||
const curriedConverter = curry(converter)
|
||||
const milesToKm = curriedConverter(1.62);
|
||||
milesToKm(35); // 56.7
|
||||
milesToKm(10); // 16.2
|
||||
*/
|
||||
|
||||
function curry$1(fn, arity) {
|
||||
return function curried() {
|
||||
if (arity == null) {
|
||||
arity = fn.length;
|
||||
}
|
||||
var args = [].slice.call(arguments);
|
||||
if (args.length >= arity) {
|
||||
return fn.apply(this, args);
|
||||
} else {
|
||||
return function() {
|
||||
return curried.apply(this, args.concat([].slice.call(arguments)));
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const curry = justCurryIt;
|
||||
|
||||
|
||||
const nil = "";
|
||||
|
||||
const compile = (pointer) => {
|
||||
if (pointer.length > 0 && pointer[0] !== "/") {
|
||||
throw Error("Invalid JSON Pointer");
|
||||
}
|
||||
|
||||
return pointer.split("/").slice(1).map(unescape);
|
||||
};
|
||||
|
||||
const get = (pointer, value = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
|
||||
const fn = (value) => ptr.reduce(([value, pointer], segment) => {
|
||||
return [applySegment(value, segment, pointer), append(segment, pointer)];
|
||||
}, [value, ""])[0];
|
||||
|
||||
return value === undefined ? fn : fn(value);
|
||||
};
|
||||
|
||||
const set = (pointer, subject = undefined, value = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = curry((subject, value) => _set(ptr, subject, value, nil));
|
||||
return subject === undefined ? fn : fn(subject, value);
|
||||
};
|
||||
|
||||
const _set = (pointer, subject, value, cursor) => {
|
||||
if (pointer.length === 0) {
|
||||
return value;
|
||||
} else if (pointer.length > 1) {
|
||||
const segment = pointer.shift();
|
||||
return { ...subject, [segment]: _set(pointer, applySegment(subject, segment, cursor), value, append(segment, cursor)) };
|
||||
} else if (Array.isArray(subject)) {
|
||||
const clonedSubject = [...subject];
|
||||
const segment = computeSegment(subject, pointer[0]);
|
||||
clonedSubject[segment] = value;
|
||||
return clonedSubject;
|
||||
} else if (typeof subject === "object" && subject !== null) {
|
||||
return { ...subject, [pointer[0]]: value };
|
||||
} else {
|
||||
return applySegment(subject, pointer[0], cursor);
|
||||
}
|
||||
};
|
||||
|
||||
const assign = (pointer, subject = undefined, value = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = curry((subject, value) => _assign(ptr, subject, value, nil));
|
||||
return subject === undefined ? fn : fn(subject, value);
|
||||
};
|
||||
|
||||
const _assign = (pointer, subject, value, cursor) => {
|
||||
if (pointer.length === 0) {
|
||||
return;
|
||||
} else if (pointer.length === 1 && !isScalar(subject)) {
|
||||
const segment = computeSegment(subject, pointer[0]);
|
||||
subject[segment] = value;
|
||||
} else {
|
||||
const segment = pointer.shift();
|
||||
_assign(pointer, applySegment(subject, segment, cursor), value, append(segment, cursor));
|
||||
}
|
||||
};
|
||||
|
||||
const unset = (pointer, subject = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = (subject) => _unset(ptr, subject, nil);
|
||||
return subject === undefined ? fn : fn(subject);
|
||||
};
|
||||
|
||||
const _unset = (pointer, subject, cursor) => {
|
||||
if (pointer.length == 0) {
|
||||
return undefined;
|
||||
} else if (pointer.length > 1) {
|
||||
const segment = pointer.shift();
|
||||
const value = applySegment(subject, segment, cursor);
|
||||
return { ...subject, [segment]: _unset(pointer, value, append(segment, cursor)) };
|
||||
} else if (Array.isArray(subject)) {
|
||||
return subject.filter((_, ndx) => ndx != pointer[0]);
|
||||
} else if (typeof subject === "object" && subject !== null) {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const { [pointer[0]]: _, ...result } = subject;
|
||||
return result;
|
||||
} else {
|
||||
return applySegment(subject, pointer[0], cursor);
|
||||
}
|
||||
};
|
||||
|
||||
const remove = (pointer, subject = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = (subject) => _remove(ptr, subject, nil);
|
||||
return subject === undefined ? fn : fn(subject);
|
||||
};
|
||||
|
||||
const _remove = (pointer, subject, cursor) => {
|
||||
if (pointer.length === 0) {
|
||||
return;
|
||||
} else if (pointer.length > 1) {
|
||||
const segment = pointer.shift();
|
||||
const value = applySegment(subject, segment, cursor);
|
||||
_remove(pointer, value, append(segment, cursor));
|
||||
} else if (Array.isArray(subject)) {
|
||||
subject.splice(pointer[0], 1);
|
||||
} else if (typeof subject === "object" && subject !== null) {
|
||||
delete subject[pointer[0]];
|
||||
} else {
|
||||
applySegment(subject, pointer[0], cursor);
|
||||
}
|
||||
};
|
||||
|
||||
const append = curry((segment, pointer) => pointer + "/" + escape(segment));
|
||||
|
||||
const escape = (segment) => segment.toString().replace(/~/g, "~0").replace(/\//g, "~1");
|
||||
const unescape = (segment) => segment.toString().replace(/~1/g, "/").replace(/~0/g, "~");
|
||||
const computeSegment = (value, segment) => Array.isArray(value) && segment === "-" ? value.length : segment;
|
||||
|
||||
const applySegment = (value, segment, cursor = "") => {
|
||||
if (value === undefined) {
|
||||
throw TypeError(`Value at '${cursor}' is undefined and does not have property '${segment}'`);
|
||||
} else if (value === null) {
|
||||
throw TypeError(`Value at '${cursor}' is null and does not have property '${segment}'`);
|
||||
} else if (isScalar(value)) {
|
||||
throw TypeError(`Value at '${cursor}' is a ${typeof value} and does not have property '${segment}'`);
|
||||
} else {
|
||||
const computedSegment = computeSegment(value, segment);
|
||||
return value[computedSegment];
|
||||
}
|
||||
};
|
||||
|
||||
const isScalar = (value) => value === null || typeof value !== "object";
|
||||
|
||||
var lib = { nil, append, get, set, assign, unset, remove };
|
||||
|
||||
return lib;
|
||||
|
||||
})));
|
||||
//# sourceMappingURL=json-pointer-umd.js.map
|
||||
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).JsonPointer=t()}(this,(function(){"use strict";const e=function(e,t){return function r(){null==t&&(t=e.length);var n=[].slice.call(arguments);return n.length>=t?e.apply(this,n):function(){return r.apply(this,n.concat([].slice.call(arguments)))}}},t=e=>{if(e.length>0&&"/"!==e[0])throw Error("Invalid JSON Pointer");return e.split("/").slice(1).map(u)},r=(e,t,n,o)=>{if(0===e.length)return n;if(e.length>1){const i=e.shift();return{...t,[i]:r(e,a(t,i,o),n,l(i,o))}}if(Array.isArray(t)){const r=[...t];return r[f(t,e[0])]=n,r}return"object"==typeof t&&null!==t?{...t,[e[0]]:n}:a(t,e[0],o)},n=(e,t,r,o)=>{if(0!==e.length)if(1!==e.length||c(t)){const i=e.shift();n(e,a(t,i,o),r,l(i,o))}else{t[f(t,e[0])]=r}},o=(e,t,r)=>{if(0!=e.length){if(e.length>1){const n=e.shift(),i=a(t,n,r);return{...t,[n]:o(e,i,l(n,r))}}if(Array.isArray(t))return t.filter(((t,r)=>r!=e[0]));if("object"==typeof t&&null!==t){const{[e[0]]:r,...n}=t;return n}return a(t,e[0],r)}},i=(e,t,r)=>{if(0!==e.length)if(e.length>1){const n=e.shift(),o=a(t,n,r);i(e,o,l(n,r))}else Array.isArray(t)?t.splice(e[0],1):"object"==typeof t&&null!==t?delete t[e[0]]:a(t,e[0],r)},l=e(((e,t)=>t+"/"+s(e))),s=e=>e.toString().replace(/~/g,"~0").replace(/\//g,"~1"),u=e=>e.toString().replace(/~1/g,"/").replace(/~0/g,"~"),f=(e,t)=>Array.isArray(e)&&"-"===t?e.length:t,a=(e,t,r="")=>{if(void 0===e)throw TypeError(`Value at '${r}' is undefined and does not have property '${t}'`);if(null===e)throw TypeError(`Value at '${r}' is null and does not have property '${t}'`);if(c(e))throw TypeError(`Value at '${r}' is a ${typeof e} and does not have property '${t}'`);return e[f(e,t)]},c=e=>null===e||"object"!=typeof e;return{nil:"",append:l,get:(e,r)=>{const n=t(e),o=e=>n.reduce((([e,t],r)=>[a(e,r,t),l(r,t)]),[e,""])[0];return void 0===r?o:o(r)},set:(n,o,i)=>{const l=t(n),s=e(((e,t)=>r(l,e,t,"")));return void 0===o?s:s(o,i)},assign:(r,o,i)=>{const l=t(r),s=e(((e,t)=>n(l,e,t,"")));return void 0===o?s:s(o,i)},unset:(e,r)=>{const n=t(e),i=e=>o(n,e,"");return void 0===r?i:i(r)},remove:(e,r)=>{const n=t(e),o=e=>i(n,e,"");return void 0===r?o:o(r)}}}));
|
||||
//# sourceMappingURL=json-pointer-umd.min.js.map
|
||||
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+65
@@ -0,0 +1,65 @@
|
||||
export type JsonPointer = {
|
||||
nil: "";
|
||||
append: (
|
||||
(segment: string, pointer: string) => string
|
||||
) & (
|
||||
(segment: string) => (pointer: string) => string
|
||||
);
|
||||
get: (
|
||||
(pointer: string, subject: Pointable) => unknown
|
||||
) & (
|
||||
(pointer: string) => Getter
|
||||
);
|
||||
set: (
|
||||
<A extends Pointable>(pointer: string, subject: A, value: unknown) => A
|
||||
) & (
|
||||
(pointer: string) => Setter
|
||||
);
|
||||
assign: (
|
||||
<A extends Pointable>(pointer: string, subject: A, value: unknown) => void
|
||||
) & (
|
||||
(pointer: string) => Assigner
|
||||
);
|
||||
unset: (
|
||||
<A extends Pointable>(pointer: string, subject: A) => A
|
||||
) & (
|
||||
(pointer: string) => Unsetter
|
||||
);
|
||||
remove: (
|
||||
(pointer: string, subject: Pointable) => void
|
||||
) & (
|
||||
(pointer: string) => Remover
|
||||
);
|
||||
}
|
||||
|
||||
export type Getter = (subject: Pointable) => unknown;
|
||||
export type Setter = (
|
||||
<A extends Pointable>(subject: A, value: unknown) => A
|
||||
) & (
|
||||
<A extends Pointable>(subject: A) => (value: unknown) => A
|
||||
);
|
||||
export type Assigner = (
|
||||
<A extends Pointable>(subject: A, value: unknown) => void
|
||||
) & (
|
||||
<A extends Pointable>(subject: A) => (value: unknown) => void
|
||||
);
|
||||
export type Unsetter = <A extends Pointable>(subject: A) => A;
|
||||
export type Remover = (subject: Pointable) => void;
|
||||
|
||||
export type Json = string | number | boolean | null | JsonObject | Json[];
|
||||
export type JsonObject = {
|
||||
[property: string]: Json;
|
||||
};
|
||||
|
||||
export type Pointable = JsonObject | Json[];
|
||||
|
||||
declare const JsonPointer: JsonPointer;
|
||||
export const nil: JsonPointer["nil"];
|
||||
export const append: JsonPointer["append"];
|
||||
export const get: JsonPointer["get"];
|
||||
export const set: JsonPointer["set"];
|
||||
export const assign: JsonPointer["assign"];
|
||||
export const unset: JsonPointer["unset"];
|
||||
export const remove: JsonPointer["remove"];
|
||||
|
||||
export default JsonPointer;
|
||||
Generated
Vendored
+133
@@ -0,0 +1,133 @@
|
||||
const curry = require("just-curry-it");
|
||||
|
||||
|
||||
const nil = "";
|
||||
|
||||
const compile = (pointer) => {
|
||||
if (pointer.length > 0 && pointer[0] !== "/") {
|
||||
throw Error("Invalid JSON Pointer");
|
||||
}
|
||||
|
||||
return pointer.split("/").slice(1).map(unescape);
|
||||
};
|
||||
|
||||
const get = (pointer, value = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
|
||||
const fn = (value) => ptr.reduce(([value, pointer], segment) => {
|
||||
return [applySegment(value, segment, pointer), append(segment, pointer)];
|
||||
}, [value, ""])[0];
|
||||
|
||||
return value === undefined ? fn : fn(value);
|
||||
};
|
||||
|
||||
const set = (pointer, subject = undefined, value = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = curry((subject, value) => _set(ptr, subject, value, nil));
|
||||
return subject === undefined ? fn : fn(subject, value);
|
||||
};
|
||||
|
||||
const _set = (pointer, subject, value, cursor) => {
|
||||
if (pointer.length === 0) {
|
||||
return value;
|
||||
} else if (pointer.length > 1) {
|
||||
const segment = pointer.shift();
|
||||
return { ...subject, [segment]: _set(pointer, applySegment(subject, segment, cursor), value, append(segment, cursor)) };
|
||||
} else if (Array.isArray(subject)) {
|
||||
const clonedSubject = [...subject];
|
||||
const segment = computeSegment(subject, pointer[0]);
|
||||
clonedSubject[segment] = value;
|
||||
return clonedSubject;
|
||||
} else if (typeof subject === "object" && subject !== null) {
|
||||
return { ...subject, [pointer[0]]: value };
|
||||
} else {
|
||||
return applySegment(subject, pointer[0], cursor);
|
||||
}
|
||||
};
|
||||
|
||||
const assign = (pointer, subject = undefined, value = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = curry((subject, value) => _assign(ptr, subject, value, nil));
|
||||
return subject === undefined ? fn : fn(subject, value);
|
||||
};
|
||||
|
||||
const _assign = (pointer, subject, value, cursor) => {
|
||||
if (pointer.length === 0) {
|
||||
return;
|
||||
} else if (pointer.length === 1 && !isScalar(subject)) {
|
||||
const segment = computeSegment(subject, pointer[0]);
|
||||
subject[segment] = value;
|
||||
} else {
|
||||
const segment = pointer.shift();
|
||||
_assign(pointer, applySegment(subject, segment, cursor), value, append(segment, cursor));
|
||||
}
|
||||
};
|
||||
|
||||
const unset = (pointer, subject = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = (subject) => _unset(ptr, subject, nil);
|
||||
return subject === undefined ? fn : fn(subject);
|
||||
};
|
||||
|
||||
const _unset = (pointer, subject, cursor) => {
|
||||
if (pointer.length == 0) {
|
||||
return undefined;
|
||||
} else if (pointer.length > 1) {
|
||||
const segment = pointer.shift();
|
||||
const value = applySegment(subject, segment, cursor);
|
||||
return { ...subject, [segment]: _unset(pointer, value, append(segment, cursor)) };
|
||||
} else if (Array.isArray(subject)) {
|
||||
return subject.filter((_, ndx) => ndx != pointer[0]);
|
||||
} else if (typeof subject === "object" && subject !== null) {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const { [pointer[0]]: _, ...result } = subject;
|
||||
return result;
|
||||
} else {
|
||||
return applySegment(subject, pointer[0], cursor);
|
||||
}
|
||||
};
|
||||
|
||||
const remove = (pointer, subject = undefined) => {
|
||||
const ptr = compile(pointer);
|
||||
const fn = (subject) => _remove(ptr, subject, nil);
|
||||
return subject === undefined ? fn : fn(subject);
|
||||
};
|
||||
|
||||
const _remove = (pointer, subject, cursor) => {
|
||||
if (pointer.length === 0) {
|
||||
return;
|
||||
} else if (pointer.length > 1) {
|
||||
const segment = pointer.shift();
|
||||
const value = applySegment(subject, segment, cursor);
|
||||
_remove(pointer, value, append(segment, cursor));
|
||||
} else if (Array.isArray(subject)) {
|
||||
subject.splice(pointer[0], 1);
|
||||
} else if (typeof subject === "object" && subject !== null) {
|
||||
delete subject[pointer[0]];
|
||||
} else {
|
||||
applySegment(subject, pointer[0], cursor);
|
||||
}
|
||||
};
|
||||
|
||||
const append = curry((segment, pointer) => pointer + "/" + escape(segment));
|
||||
|
||||
const escape = (segment) => segment.toString().replace(/~/g, "~0").replace(/\//g, "~1");
|
||||
const unescape = (segment) => segment.toString().replace(/~1/g, "/").replace(/~0/g, "~");
|
||||
const computeSegment = (value, segment) => Array.isArray(value) && segment === "-" ? value.length : segment;
|
||||
|
||||
const applySegment = (value, segment, cursor = "") => {
|
||||
if (value === undefined) {
|
||||
throw TypeError(`Value at '${cursor}' is undefined and does not have property '${segment}'`);
|
||||
} else if (value === null) {
|
||||
throw TypeError(`Value at '${cursor}' is null and does not have property '${segment}'`);
|
||||
} else if (isScalar(value)) {
|
||||
throw TypeError(`Value at '${cursor}' is a ${typeof value} and does not have property '${segment}'`);
|
||||
} else {
|
||||
const computedSegment = computeSegment(value, segment);
|
||||
return value[computedSegment];
|
||||
}
|
||||
};
|
||||
|
||||
const isScalar = (value) => value === null || typeof value !== "object";
|
||||
|
||||
module.exports = { nil, append, get, set, assign, unset, remove };
|
||||
Generated
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
import JsonPointer from "./index.js";
|
||||
|
||||
|
||||
export const append = JsonPointer.append;
|
||||
export const assign = JsonPointer.assign;
|
||||
export const remove = JsonPointer.remove;
|
||||
export const get = JsonPointer.get;
|
||||
export const set = JsonPointer.set;
|
||||
export const unset = JsonPointer.unset;
|
||||
Generated
Vendored
+88
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"_args": [
|
||||
[
|
||||
"@hyperjump/json-pointer@0.9.1",
|
||||
"/Users/wookiee/sources/asyncapi-node/tools/bundler"
|
||||
]
|
||||
],
|
||||
"_from": "@hyperjump/json-pointer@0.9.1",
|
||||
"_id": "@hyperjump/json-pointer@0.9.1",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-tiDl/9MOkkiUQ5t+wq4PhtPghgWmFyBwU9Q6xRkXksg2s/6GNxNPcO/MzOjJoDAeCY1XXajNUIkco7wvhNmlOA==",
|
||||
"_location": "/@hyperjump/json-pointer",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "version",
|
||||
"registry": true,
|
||||
"raw": "@hyperjump/json-pointer@0.9.1",
|
||||
"name": "@hyperjump/json-pointer",
|
||||
"escapedName": "@hyperjump%2fjson-pointer",
|
||||
"scope": "@hyperjump",
|
||||
"rawSpec": "0.9.1",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "0.9.1"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/@hyperjump/json-schema-core"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/@hyperjump/json-pointer/-/json-pointer-0.9.1.tgz",
|
||||
"_spec": "0.9.1",
|
||||
"_where": "/Users/wookiee/sources/asyncapi-node/tools/bundler",
|
||||
"author": {
|
||||
"name": "Jason Desrosiers",
|
||||
"email": "jdesrosi@gmail.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/hyperjump-io/json-pointer/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"just-curry-it": "^3.2.1"
|
||||
},
|
||||
"description": "An RFC-6901 JSON Pointer implementation",
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-commonjs": "^20.0.0",
|
||||
"@rollup/plugin-node-resolve": "^13.0.4",
|
||||
"@types/chai": "^4.2.21",
|
||||
"@types/mocha": "^9.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.29.3",
|
||||
"@typescript-eslint/parser": "^4.29.3",
|
||||
"chai": "^4.3.4",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-import-resolver-node": "^0.3.6",
|
||||
"eslint-import-resolver-typescript": "^2.4.0",
|
||||
"eslint-plugin-import": "^2.24.2",
|
||||
"mocha": "^9.1.1",
|
||||
"rollup": "^2.56.3",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"ts-node": "^10.2.1",
|
||||
"typescript": "^4.4.2"
|
||||
},
|
||||
"exports": {
|
||||
"require": "./lib/index.js",
|
||||
"import": "./lib/index.mjs"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/jdesrosiers"
|
||||
},
|
||||
"homepage": "https://github.com/hyperjump-io/json-pointer#readme",
|
||||
"keywords": [
|
||||
"JSON Pointer",
|
||||
"RFC-6901"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "lib/index.js",
|
||||
"name": "@hyperjump/json-pointer",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/hyperjump-io/json-pointer.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rollup --config rollup.config.js",
|
||||
"clean": "xargs -a .gitignore rm -rf",
|
||||
"lint": "eslint lib",
|
||||
"prepublishOnly": "npm run build",
|
||||
"test": "mocha --require ts-node/register 'lib/**/*.spec.ts'"
|
||||
},
|
||||
"version": "0.9.1"
|
||||
}
|
||||
Generated
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 Jason Desrosiers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
Generated
Vendored
+159
@@ -0,0 +1,159 @@
|
||||
# Hyperjump - JSON Schema Bundle
|
||||
|
||||
JSON Schema Bundle (JSB) is an implementation of the official JSON Schema
|
||||
bundling process introduced in the Draft 2020-12 specification. Given a schema
|
||||
with external references, any external schemas will be embedded in the schema
|
||||
resulting in a Compound Schema Document with all the schemas necessary to
|
||||
evaluate the given schema.
|
||||
|
||||
The bundling process allows schemas to be embedded without needing to modify any
|
||||
references which means you get the same output details whether you validate the
|
||||
bundle or the original unbundled schemas.
|
||||
|
||||
JSON Schema Bundle (JSB) is built on [JSON Schema Core](https://github.com/hyperjump-io/json-schema-core).
|
||||
|
||||
* Supported JSON Schema Dialects
|
||||
* draft-04 | draft-06 | draft-07 | Draft 2019-09 | Draft 2020-12
|
||||
* Support for custom dialects can be configured
|
||||
* Schemas can reference other schemas using a different draft
|
||||
* Load schemas from filesystem (file://), network (http(s)://), or JavaScript
|
||||
|
||||
## Install
|
||||
JSB includes support for node.js JavaScript (CommonJS and ES Modules),
|
||||
TypeScript, and browsers.
|
||||
|
||||
### Node.js
|
||||
```bash
|
||||
npm install @hyperjump/json-schema-bundle
|
||||
```
|
||||
|
||||
### Browser
|
||||
When in a browser context, JSB is designed to use the browser's `fetch`
|
||||
implementation instead of a node.js fetch clone. The Webpack bundler does this
|
||||
properly without any extra configuration, but if you are using the Rollup
|
||||
bundler you will need to include the `browser: true` option in your Rollup
|
||||
configuration.
|
||||
|
||||
```javascript
|
||||
plugins: [
|
||||
resolve({
|
||||
browser: true
|
||||
}),
|
||||
commonjs()
|
||||
]
|
||||
```
|
||||
|
||||
### Versioning
|
||||
This project is in beta and there may be breaking changes at any time. When it's
|
||||
stable enough, I'll publish v1.0.0 and follow semantic versioning from there on
|
||||
out.
|
||||
|
||||
## Usage
|
||||
```javascript
|
||||
const Bundler = require("@hyperjump/json-schema-bundle");
|
||||
|
||||
|
||||
// Optionally load schema manually
|
||||
Bundler.add({
|
||||
"$id": "https://json-schema.hyperjump.io/schemas/string",
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
|
||||
"type": "string"
|
||||
});
|
||||
|
||||
// Get the initial schema to pass to the bundler
|
||||
const main = await Bundler.get(`file://${__dirname}/schemas/main.schema.json`);
|
||||
|
||||
// The bundler will fetch from the file system, network, or internal schemas as
|
||||
// needed to build to bundle.
|
||||
const bundle = await Bundler.bundle(main);
|
||||
```
|
||||
|
||||
## TypeScript
|
||||
Although the package is written in JavaScript, type definitions are included for
|
||||
TypeScript support. The following example shows the types you might want to
|
||||
know.
|
||||
|
||||
```typescript
|
||||
import Bundler from "@hyperjump/json-schema-bundle";
|
||||
import type { SchemaDocument, Draft202012Schema, InvalidSchemaError } from "@hyperjump/json-schema-bundle";
|
||||
|
||||
|
||||
(async function () {
|
||||
const schemaJson: Draft202012Schema = {
|
||||
"$id": "https://json-schema.hyperjump.io/schemas/string",
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
|
||||
"type": "string"
|
||||
};
|
||||
Bundler.add(schemaJson);
|
||||
|
||||
try {
|
||||
const main: SchemaDocument = await Bundler.get(`file://${__dirname}/schemas/main.schema.json`);
|
||||
const bundle: Draft202012Schema = await Bundler.bundle(main);
|
||||
console.log(JSON.stringify(bundle, null, " "));
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof InvalidSchemaError) {
|
||||
console.log(error.output);
|
||||
} else {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
}());
|
||||
```
|
||||
|
||||
## API
|
||||
* **add**: (schema: object, url?: URI, schemaVersion?: string) => SDoc
|
||||
|
||||
Load a schema. See [JSC - $id](https://github.com/hyperjump-io/json-schema-core#id)
|
||||
and [JSC - $schema](https://github.com/hyperjump-io/json-schema-core#schema-1)
|
||||
for more information.
|
||||
* **get**: (url: URI, contextDoc?: SDoc, recursive: boolean = false) => Promise\<SDoc>
|
||||
|
||||
Fetch a schema. Schemas can come from an HTTP request, a file, or a schema
|
||||
that was added with `add`.
|
||||
* **bundle**: (schema: SDoc, options: Options) => Promise\<SchemaObject>
|
||||
|
||||
Create a bundled schema starting with the given schema. External schemas
|
||||
will be fetched from the filesystem, the network, or internally as needed.
|
||||
|
||||
Options:
|
||||
* alwaysIncludeDialect: boolean (default: false) -- Include dialect even
|
||||
when it isn't strictly needed
|
||||
* bundleMode: "flat" | "full" (default: "flat") -- When bundling schemas
|
||||
that already contain bundled schemas, "flat" mode with remove nested
|
||||
embedded schemas and put them all in the top level `$defs`. When using
|
||||
"full" mode, it will keep the already embedded schemas around, which will
|
||||
result in some embedded schema duplication.
|
||||
* definitionNamingStrategy: "uri" | "uuid" (default: "uri") -- By default
|
||||
the name used in definitions for embedded schemas will match the
|
||||
identifier of the embedded schema. This naming is unlikely to collide
|
||||
with actual definitions, but if you want to be sure, you can use the
|
||||
"uuid" strategy instead to be sure you get a unique name.
|
||||
* **setMetaOutputFormat**: (outputFormat: OutputFormat = DETAILED) => undefined
|
||||
|
||||
Set the output format for meta-validation. Meta-validation output is only
|
||||
returned if meta-validation results in an error.
|
||||
* **setShouldMetaValidate**: (isEnabled: boolean) => undefined
|
||||
|
||||
Enable or disable meta-validation.
|
||||
* **OutputFormat**: [**FLAG** | **BASIC** | **DETAILED** | **VERBOSE**]
|
||||
|
||||
See [JSC - Output](https://github.com/hyperjump-io/json-schema-core#output)
|
||||
for more information on output formats.
|
||||
|
||||
## Contributing
|
||||
|
||||
### Tests
|
||||
|
||||
Run the tests
|
||||
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
|
||||
Run the tests with a continuous test runner
|
||||
|
||||
```bash
|
||||
npm test -- --watch
|
||||
```
|
||||
Generated
Vendored
+5595
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+2
File diff suppressed because one or more lines are too long
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+5593
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+2
File diff suppressed because one or more lines are too long
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+5589
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+2
File diff suppressed because one or more lines are too long
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+5598
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+2
File diff suppressed because one or more lines are too long
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+5596
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+2
File diff suppressed because one or more lines are too long
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+5599
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+2
File diff suppressed because one or more lines are too long
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
BIN
Binary file not shown.
Generated
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
const splitUri = (url) => {
|
||||
const indexOfHash = url.indexOf("#");
|
||||
const ndx = indexOfHash === -1 ? url.length : indexOfHash;
|
||||
const urlReference = url.slice(0, ndx);
|
||||
const urlFragment = url.slice(ndx + 1);
|
||||
|
||||
return [decodeURI(urlReference), decodeURI(urlFragment)];
|
||||
};
|
||||
|
||||
module.exports = { splitUri };
|
||||
Generated
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
const { Core } = require("@hyperjump/json-schema-core");
|
||||
const { splitUri } = require("./common");
|
||||
|
||||
|
||||
const collectExternalIds = (schemaUri, externalIds, ast, dynamicAnchors) => {
|
||||
const keywordId = ast[schemaUri][0];
|
||||
const id = splitUri(schemaUri)[0];
|
||||
Core.getKeyword(keywordId).collectExternalIds(schemaUri, externalIds, ast, { ...ast.metaData[id].dynamicAnchors, ...dynamicAnchors });
|
||||
};
|
||||
|
||||
module.exports = { collectExternalIds };
|
||||
Generated
Vendored
+39
@@ -0,0 +1,39 @@
|
||||
const JsonSchema = require("@hyperjump/json-schema");
|
||||
const { Core, Schema } = require("@hyperjump/json-schema-core");
|
||||
const Keywords = require("./keywords");
|
||||
|
||||
|
||||
Schema.setConfig("http://json-schema.org/draft-04/schema", "bundlingLocation", "/definitions");
|
||||
|
||||
Core.defineVocabulary("http://json-schema.org/draft-04/schema", {
|
||||
"validate": Keywords.validate,
|
||||
"additionalItems": Keywords.additionalItems,
|
||||
"additionalProperties": Keywords.additionalProperties,
|
||||
"allOf": Keywords.allOf,
|
||||
"anyOf": Keywords.anyOf,
|
||||
"default": JsonSchema.Keywords.metaData,
|
||||
"definitions": JsonSchema.Keywords.definitions,
|
||||
"dependencies": Keywords.dependencies,
|
||||
"description": JsonSchema.Keywords.metaData,
|
||||
"enum": JsonSchema.Keywords.enum,
|
||||
"format": JsonSchema.Keywords.metaData,
|
||||
"items": Keywords.items,
|
||||
"maxItems": JsonSchema.Keywords.maxItems,
|
||||
"maxLength": JsonSchema.Keywords.maxLength,
|
||||
"maxProperties": JsonSchema.Keywords.maxProperties,
|
||||
"maximum": JsonSchema.Keywords.maximumExclusiveMaximum,
|
||||
"minItems": JsonSchema.Keywords.minItems,
|
||||
"minLength": JsonSchema.Keywords.minLength,
|
||||
"minProperties": JsonSchema.Keywords.minProperties,
|
||||
"minimum": JsonSchema.Keywords.minimumExclusiveMinimum,
|
||||
"multipleOf": JsonSchema.Keywords.multipleOf,
|
||||
"not": Keywords.not,
|
||||
"oneOf": Keywords.oneOf,
|
||||
"pattern": JsonSchema.Keywords.pattern,
|
||||
"patternProperties": Keywords.patternProperties,
|
||||
"properties": Keywords.properties,
|
||||
"required": JsonSchema.Keywords.required,
|
||||
"title": JsonSchema.Keywords.metaData,
|
||||
"type": JsonSchema.Keywords.type,
|
||||
"uniqueItems": JsonSchema.Keywords.uniqueItems
|
||||
});
|
||||
Generated
Vendored
+45
@@ -0,0 +1,45 @@
|
||||
const JsonSchema = require("@hyperjump/json-schema");
|
||||
const { Core, Schema } = require("@hyperjump/json-schema-core");
|
||||
const Keywords = require("./keywords");
|
||||
|
||||
|
||||
Schema.setConfig("http://json-schema.org/draft-06/schema", "bundlingLocation", "/definitions");
|
||||
|
||||
Core.defineVocabulary("http://json-schema.org/draft-06/schema", {
|
||||
"validate": Keywords.validate,
|
||||
"additionalItems": Keywords.additionalItems6,
|
||||
"additionalProperties": Keywords.additionalProperties6,
|
||||
"allOf": Keywords.allOf,
|
||||
"anyOf": Keywords.anyOf,
|
||||
"const": JsonSchema.Keywords.const,
|
||||
"contains": Keywords.contains,
|
||||
"default": JsonSchema.Keywords.metaData,
|
||||
"definitions": JsonSchema.Keywords.definitions,
|
||||
"dependencies": Keywords.dependencies,
|
||||
"description": JsonSchema.Keywords.metaData,
|
||||
"enum": JsonSchema.Keywords.enum,
|
||||
"examples": JsonSchema.Keywords.metaData,
|
||||
"exclusiveMaximum": JsonSchema.Keywords.exclusiveMaximum,
|
||||
"exclusiveMinimum": JsonSchema.Keywords.exclusiveMinimum,
|
||||
"format": JsonSchema.Keywords.metaData,
|
||||
"items": Keywords.items,
|
||||
"maxItems": JsonSchema.Keywords.maxItems,
|
||||
"maxLength": JsonSchema.Keywords.maxLength6,
|
||||
"maxProperties": JsonSchema.Keywords.maxProperties,
|
||||
"maximum": JsonSchema.Keywords.maximum,
|
||||
"minItems": JsonSchema.Keywords.minItems,
|
||||
"minLength": JsonSchema.Keywords.minLength6,
|
||||
"minProperties": JsonSchema.Keywords.minProperties,
|
||||
"minimum": JsonSchema.Keywords.minimum,
|
||||
"multipleOf": JsonSchema.Keywords.multipleOf,
|
||||
"not": Keywords.not,
|
||||
"oneOf": Keywords.oneOf,
|
||||
"pattern": JsonSchema.Keywords.pattern,
|
||||
"patternProperties": Keywords.patternProperties,
|
||||
"properties": Keywords.properties,
|
||||
"propertyNames": Keywords.propertyNames,
|
||||
"required": JsonSchema.Keywords.required,
|
||||
"title": JsonSchema.Keywords.metaData,
|
||||
"type": JsonSchema.Keywords.type,
|
||||
"uniqueItems": JsonSchema.Keywords.uniqueItems
|
||||
});
|
||||
Generated
Vendored
+49
@@ -0,0 +1,49 @@
|
||||
const JsonSchema = require("@hyperjump/json-schema");
|
||||
const { Core, Schema } = require("@hyperjump/json-schema-core");
|
||||
const Keywords = require("./keywords");
|
||||
|
||||
|
||||
Schema.setConfig("http://json-schema.org/draft-07/schema", "bundlingLocation", "/definitions");
|
||||
|
||||
Core.defineVocabulary("http://json-schema.org/draft-07/schema", {
|
||||
"validate": Keywords.validate,
|
||||
"additionalItems": Keywords.additionalItems6,
|
||||
"additionalProperties": Keywords.additionalProperties6,
|
||||
"allOf": Keywords.allOf,
|
||||
"anyOf": Keywords.anyOf,
|
||||
"const": JsonSchema.Keywords.const,
|
||||
"contains": Keywords.contains,
|
||||
"default": JsonSchema.Keywords.metaData,
|
||||
"definitions": JsonSchema.Keywords.definitions,
|
||||
"dependencies": Keywords.dependencies,
|
||||
"description": JsonSchema.Keywords.metaData,
|
||||
"enum": JsonSchema.Keywords.enum,
|
||||
"exclusiveMaximum": JsonSchema.Keywords.exclusiveMaximum,
|
||||
"exclusiveMinimum": JsonSchema.Keywords.exclusiveMinimum,
|
||||
"format": JsonSchema.Keywords.metaData,
|
||||
"if": Keywords.if,
|
||||
"then": Keywords.then,
|
||||
"else": Keywords.else,
|
||||
"items": Keywords.items,
|
||||
"maxItems": JsonSchema.Keywords.maxItems,
|
||||
"maxLength": JsonSchema.Keywords.maxLength6,
|
||||
"maxProperties": JsonSchema.Keywords.maxProperties,
|
||||
"maximum": JsonSchema.Keywords.maximum,
|
||||
"minItems": JsonSchema.Keywords.minItems,
|
||||
"minLength": JsonSchema.Keywords.minLength6,
|
||||
"minProperties": JsonSchema.Keywords.minProperties,
|
||||
"minimum": JsonSchema.Keywords.minimum,
|
||||
"multipleOf": JsonSchema.Keywords.multipleOf,
|
||||
"not": Keywords.not,
|
||||
"oneOf": Keywords.oneOf,
|
||||
"pattern": JsonSchema.Keywords.pattern,
|
||||
"patternProperties": Keywords.patternProperties,
|
||||
"properties": Keywords.properties,
|
||||
"propertyNames": Keywords.propertyNames,
|
||||
"readOnly": JsonSchema.Keywords.metaData,
|
||||
"required": JsonSchema.Keywords.required,
|
||||
"title": JsonSchema.Keywords.metaData,
|
||||
"type": JsonSchema.Keywords.type,
|
||||
"uniqueItems": JsonSchema.Keywords.uniqueItems,
|
||||
"writeOnly": JsonSchema.Keywords.metaData
|
||||
});
|
||||
Generated
Vendored
+33
@@ -0,0 +1,33 @@
|
||||
const JsonSchema = require("@hyperjump/json-schema");
|
||||
const { Core, Schema } = require("@hyperjump/json-schema-core");
|
||||
const Keywords = require("./keywords");
|
||||
|
||||
|
||||
Schema.setConfig("https://json-schema.org/draft/2019-09/schema", "bundlingLocation", "/$defs");
|
||||
|
||||
Core.defineVocabulary("https://json-schema.org/draft/2019-09/vocab/core", {
|
||||
"validate": Keywords.validate,
|
||||
"$defs": JsonSchema.Keywords.definitions,
|
||||
"$recursiveRef": JsonSchema.Keywords.dynamicRef,
|
||||
"$ref": Keywords.ref
|
||||
});
|
||||
|
||||
Core.defineVocabulary("https://json-schema.org/draft/2019-09/vocab/applicator", {
|
||||
"additionalItems": Keywords.additionalItems6,
|
||||
"additionalProperties": Keywords.additionalProperties6,
|
||||
"allOf": Keywords.allOf,
|
||||
"anyOf": Keywords.anyOf,
|
||||
"contains": Keywords.containsMinContainsMaxContains,
|
||||
"dependentSchemas": Keywords.dependentSchemas,
|
||||
"if": Keywords.if,
|
||||
"then": Keywords.then,
|
||||
"else": Keywords.else,
|
||||
"items": Keywords.items,
|
||||
"not": Keywords.not,
|
||||
"oneOf": Keywords.oneOf,
|
||||
"patternProperties": Keywords.patternProperties,
|
||||
"properties": Keywords.properties,
|
||||
"propertyNames": Keywords.propertyNames,
|
||||
"unevaluatedItems": Keywords.unevaluatedItems,
|
||||
"unevaluatedProperties": Keywords.unevaluatedProperties
|
||||
});
|
||||
Generated
Vendored
+36
@@ -0,0 +1,36 @@
|
||||
const JsonSchema = require("@hyperjump/json-schema");
|
||||
const { Core, Schema } = require("@hyperjump/json-schema-core");
|
||||
const Keywords = require("./keywords");
|
||||
|
||||
|
||||
Schema.setConfig("https://json-schema.org/draft/2020-12/schema", "bundlingLocation", "/$defs");
|
||||
|
||||
Core.defineVocabulary("https://json-schema.org/draft/2020-12/vocab/core", {
|
||||
"validate": Keywords.validate,
|
||||
"$defs": JsonSchema.Keywords.definitions,
|
||||
"$dynamicRef": JsonSchema.Keywords.dynamicRef,
|
||||
"$ref": Keywords.ref
|
||||
});
|
||||
|
||||
Core.defineVocabulary("https://json-schema.org/draft/2020-12/vocab/applicator", {
|
||||
"additionalProperties": Keywords.additionalProperties6,
|
||||
"allOf": Keywords.allOf,
|
||||
"anyOf": Keywords.anyOf,
|
||||
"contains": Keywords.containsMinContainsMaxContains,
|
||||
"dependentSchemas": Keywords.dependentSchemas,
|
||||
"if": Keywords.if,
|
||||
"then": Keywords.then,
|
||||
"else": Keywords.else,
|
||||
"items": Keywords.items202012,
|
||||
"not": Keywords.not,
|
||||
"oneOf": Keywords.oneOf,
|
||||
"patternProperties": Keywords.patternProperties,
|
||||
"prefixItems": Keywords.tupleItems,
|
||||
"properties": Keywords.properties,
|
||||
"propertyNames": Keywords.propertyNames
|
||||
});
|
||||
|
||||
Core.defineVocabulary("https://json-schema.org/draft/2020-12/vocab/unevaluated", {
|
||||
"unevaluatedItems": Keywords.unevaluatedItems,
|
||||
"unevaluatedProperties": Keywords.unevaluatedProperties
|
||||
});
|
||||
Generated
Vendored
+47
@@ -0,0 +1,47 @@
|
||||
import type { Core, Schema, SchemaDocument, SchemaObject, InvalidSchemaError } from "@hyperjump/json-schema-core";
|
||||
|
||||
|
||||
export type JsonSchemaBundler = {
|
||||
add: typeof Schema.add;
|
||||
get: typeof Schema.get;
|
||||
bundle: (schemaDoc: SchemaDocument, options?: BundleOptions) => Promise<SchemaObject>;
|
||||
FULL: "full";
|
||||
FLAT: "flat";
|
||||
URI: "uri";
|
||||
UUID: "uuid";
|
||||
setMetaOutputFormat: typeof Core.setMetaOutputFormat;
|
||||
setShouldMetaValidate: typeof Core.setShouldMetaValidate;
|
||||
FLAG: typeof Core.FLAG;
|
||||
BASIC: typeof Core.BASIC;
|
||||
DETAILED: typeof Core.DETAILED;
|
||||
VERBOSE: typeof Core.VERBOSE;
|
||||
InvalidSchemaError: typeof InvalidSchemaError;
|
||||
};
|
||||
|
||||
export type BundleOptions = {
|
||||
alwaysIncludeDialect?: boolean;
|
||||
bundleMode?: BundleMode;
|
||||
definitionNamingStrategy: DefinitionNamingStrategy;
|
||||
};
|
||||
|
||||
export type BundleMode = JsonSchemaBundler["FULL"] | JsonSchemaBundler["FLAT"];
|
||||
export type DefinitionNamingStrategy = JsonSchemaBundler["URI"] | JsonSchemaBundler["UUID"];
|
||||
|
||||
export const add: JsonSchemaBundler["add"];
|
||||
export const get: JsonSchemaBundler["get"];
|
||||
export const bundle: JsonSchemaBundler["bundle"];
|
||||
export const FULL: JsonSchemaBundler["FULL"];
|
||||
export const FLAT: JsonSchemaBundler["FLAT"];
|
||||
export const URI: JsonSchemaBundler["URI"];
|
||||
export const UUID: JsonSchemaBundler["UUID"];
|
||||
export const setMetaOutputFormat: JsonSchemaBundler["setMetaOutputFormat"];
|
||||
export const setShouldMetaValidate: JsonSchemaBundler["setShouldMetaValidate"];
|
||||
export const FLAG: JsonSchemaBundler["FLAG"];
|
||||
export const BASIC: JsonSchemaBundler["BASIC"];
|
||||
export const DETAILED: JsonSchemaBundler["DETAILED"];
|
||||
export const VERBOSE: JsonSchemaBundler["VERBOSE"];
|
||||
|
||||
export * from "@hyperjump/json-schema";
|
||||
|
||||
declare const jsonSchemaBundler: JsonSchemaBundler;
|
||||
export default jsonSchemaBundler;
|
||||
Generated
Vendored
+82
@@ -0,0 +1,82 @@
|
||||
const { v4: uuid } = require("uuid");
|
||||
const JsonSchema = require("@hyperjump/json-schema");
|
||||
const JsonPointer = require("@hyperjump/json-pointer");
|
||||
const { Core, Schema, InvalidSchemaError } = require("@hyperjump/json-schema-core");
|
||||
const Bundle = require("./core");
|
||||
const { splitUri } = require("./common");
|
||||
|
||||
require("./draft-04");
|
||||
require("./draft-06");
|
||||
require("./draft-07");
|
||||
require("./draft-2019-09");
|
||||
require("./draft-2020-12");
|
||||
|
||||
|
||||
const FULL = "full";
|
||||
const FLAT = "flat";
|
||||
const URI = "uri";
|
||||
const UUID = "uuid";
|
||||
|
||||
const defaultOptions = {
|
||||
alwaysIncludeDialect: false,
|
||||
bundleMode: FLAT,
|
||||
definitionNamingStrategy: URI
|
||||
};
|
||||
|
||||
const bundle = async (schemaDoc, options = {}) => {
|
||||
const fullOptions = { ...defaultOptions, ...options };
|
||||
|
||||
const { ast, schemaUri } = await Core.compile(schemaDoc);
|
||||
const subSchemaUris = new Set();
|
||||
Bundle.collectExternalIds(schemaUri, subSchemaUris, ast, {});
|
||||
const externalIds = new Set([...subSchemaUris].map((uri) => splitUri(uri)[0]));
|
||||
externalIds.delete(schemaDoc.id);
|
||||
|
||||
const bundled = Schema.toSchema(schemaDoc, {
|
||||
includeEmbedded: fullOptions.bundleMode === FULL
|
||||
});
|
||||
|
||||
const bundlingLocation = Schema.getConfig(schemaDoc.schemaVersion, "bundlingLocation");
|
||||
if (JsonPointer.get(bundlingLocation, bundled) === undefined && externalIds.size > 0) {
|
||||
JsonPointer.assign(bundlingLocation, bundled, {});
|
||||
}
|
||||
|
||||
for (const uri of externalIds.values()) {
|
||||
const externalSchema = await JsonSchema.get(uri);
|
||||
const embeddedSchema = Schema.toSchema(externalSchema, {
|
||||
parentId: schemaDoc.id,
|
||||
parentDialect: fullOptions.alwaysIncludeDialect ? "" : schemaDoc.schemaVersion,
|
||||
includeEmbedded: fullOptions.bundleMode === FULL
|
||||
});
|
||||
let id;
|
||||
if (fullOptions.definitionNamingStrategy === URI) {
|
||||
const embeddedToken = Schema.getConfig(externalSchema.schemaVersion, "embeddedToken");
|
||||
id = embeddedSchema[embeddedToken];
|
||||
} else if (fullOptions.definitionNamingStrategy === UUID) {
|
||||
id = uuid();
|
||||
} else {
|
||||
throw Error(`Unknown definition naming stragety: ${fullOptions.definitionNamingStrategy}`);
|
||||
}
|
||||
const pointer = JsonPointer.append(id, bundlingLocation);
|
||||
JsonPointer.assign(pointer, bundled, embeddedSchema);
|
||||
}
|
||||
|
||||
return bundled;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
add: JsonSchema.add,
|
||||
get: Schema.get,
|
||||
bundle: bundle,
|
||||
FULL: FULL,
|
||||
FLAT: FLAT,
|
||||
URI: URI,
|
||||
UUID: UUID,
|
||||
setMetaOutputFormat: Core.setMetaOutputFormat,
|
||||
setShouldMetaValidate: Core.setShouldMetaValidate,
|
||||
FLAG: Core.FLAG,
|
||||
BASIC: Core.BASIC,
|
||||
DETAILED: Core.DETAILED,
|
||||
VERBOSE: Core.VERBOSE,
|
||||
InvalidSchemaError: InvalidSchemaError
|
||||
};
|
||||
Generated
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
import Bundler from "./index.js";
|
||||
|
||||
|
||||
export const add = Bundler.add;
|
||||
export const get = Bundler.get;
|
||||
export const bundle = Bundler.bundle;
|
||||
export const FULL = Bundler.FULL;
|
||||
export const FLAT = Bundler.FLAT;
|
||||
export const URI = Bundler.URI;
|
||||
export const UUID = Bundler.UUID;
|
||||
export const setMetaOutputFormat = Bundler.setMetaOutputFormat;
|
||||
export const setShouldMetaValidate = Bundler.setShouldMetaValidate;
|
||||
export const FLAG = Bundler.FLAG;
|
||||
export const BASIC = Bundler.BASIC;
|
||||
export const DETAILED = Bundler.DETAILED;
|
||||
export const VERBOSE = Bundler.VERBOSE;
|
||||
export const InvalidSchemaError = Bundler.InvalidSchemaError;
|
||||
Generated
Vendored
+221
@@ -0,0 +1,221 @@
|
||||
const JsonSchema = require("@hyperjump/json-schema");
|
||||
const { Core } = require("@hyperjump/json-schema-core");
|
||||
const Bundle = require("./core");
|
||||
|
||||
|
||||
const validate = {
|
||||
...JsonSchema.Keywords.validate,
|
||||
collectExternalIds: (schemaUri, externalIds, ast, dynamicAnchors) => {
|
||||
const nodes = ast[schemaUri][2];
|
||||
if (externalIds.has(schemaUri) || typeof nodes === "boolean") {
|
||||
return;
|
||||
}
|
||||
externalIds.add(schemaUri);
|
||||
|
||||
for (const [keywordId, , keywordValue] of nodes) {
|
||||
const keyword = Core.getKeyword(keywordId);
|
||||
|
||||
if (keyword.collectExternalIds) {
|
||||
keyword.collectExternalIds(keywordValue, externalIds, ast, dynamicAnchors);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const ref = {
|
||||
...JsonSchema.Keywords.ref,
|
||||
collectExternalIds: Bundle.collectExternalIds
|
||||
};
|
||||
|
||||
const additionalItems = {
|
||||
...JsonSchema.Keywords.additionalItems,
|
||||
collectExternalIds: ([, additionalItems], externalIds, ast, dynamicAnchors) => {
|
||||
if (typeof additionalItems === "string") {
|
||||
Bundle.collectExternalIds(additionalItems, externalIds, ast, dynamicAnchors);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const additionalProperties = {
|
||||
...JsonSchema.Keywords.additionalProperties,
|
||||
collectExternalIds: ([, , additionalProperties], externalIds, ast, dynamicAnchors) => {
|
||||
if (typeof additionalProperties === "string") {
|
||||
Bundle.collectExternalIds(additionalProperties, externalIds, ast, dynamicAnchors);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const additionalItems6 = {
|
||||
...JsonSchema.Keywords.additionalItems6,
|
||||
collectExternalIds: ([, additionalItems], externalIds, ast, dynamicAnchors) => {
|
||||
Bundle.collectExternalIds(additionalItems, externalIds, ast, dynamicAnchors);
|
||||
}
|
||||
};
|
||||
|
||||
const additionalProperties6 = {
|
||||
...JsonSchema.Keywords.additionalProperties6,
|
||||
collectExternalIds: ([, , additionalProperties], externalIds, ast, dynamicAnchors) => {
|
||||
Bundle.collectExternalIds(additionalProperties, externalIds, ast, dynamicAnchors);
|
||||
}
|
||||
};
|
||||
|
||||
const allOf = {
|
||||
...JsonSchema.Keywords.allOf,
|
||||
collectExternalIds: (allOf, externalIds, ast, dynamicAnchors) => {
|
||||
allOf.forEach((schemaUri) => Bundle.collectExternalIds(schemaUri, externalIds, ast, dynamicAnchors));
|
||||
}
|
||||
};
|
||||
|
||||
const anyOf = {
|
||||
...JsonSchema.Keywords.anyOf,
|
||||
collectExternalIds: (anyOf, externalIds, ast, dynamicAnchors) => {
|
||||
anyOf.forEach((schemaUri) => Bundle.collectExternalIds(schemaUri, externalIds, ast, dynamicAnchors));
|
||||
}
|
||||
};
|
||||
|
||||
const contains = {
|
||||
...JsonSchema.Keywords.contains,
|
||||
collectExternalIds: Bundle.collectExternalIds
|
||||
};
|
||||
|
||||
const containsMinContainsMaxContains = {
|
||||
...JsonSchema.Keywords.containsMinContainsMaxContains,
|
||||
collectExternalIds: ({ contains }, externalIds, ast, dynamicAnchors) => {
|
||||
Bundle.collectExternalIds(contains, externalIds, ast, dynamicAnchors);
|
||||
}
|
||||
};
|
||||
|
||||
const dependencies = {
|
||||
...JsonSchema.Keywords.dependencies,
|
||||
collectExternalIds: (dependentSchemas, externalIds, ast, dynamicAnchors) => {
|
||||
Object.values(dependentSchemas).forEach(([, dependency]) => {
|
||||
if (typeof dependency === "string") {
|
||||
Bundle.collectExternalIds(dependency, externalIds, ast, dynamicAnchors);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const dependentSchemas = {
|
||||
...JsonSchema.Keywords.dependentSchemas,
|
||||
collectExternalIds: (dependentSchemas, externalIds, ast, dynamicAnchors) => {
|
||||
Object.values(dependentSchemas).forEach(([, schemaUri]) => Bundle.collectExternalIds(schemaUri, externalIds, ast, dynamicAnchors));
|
||||
}
|
||||
};
|
||||
|
||||
const if_ = {
|
||||
...JsonSchema.Keywords.if,
|
||||
collectExternalIds: Bundle.collectExternalIds
|
||||
};
|
||||
|
||||
const then = {
|
||||
...JsonSchema.Keywords.then,
|
||||
collectExternalIds: ([, then], externalIds, ast, dynamicAnchors) => {
|
||||
Bundle.collectExternalIds(then, externalIds, ast, dynamicAnchors);
|
||||
}
|
||||
};
|
||||
|
||||
const else_ = {
|
||||
...JsonSchema.Keywords.else,
|
||||
collectExternalIds: ([, elseSchema], externalIds, ast, dynamicAnchors) => {
|
||||
Bundle.collectExternalIds(elseSchema, externalIds, ast, dynamicAnchors);
|
||||
}
|
||||
};
|
||||
|
||||
const items = {
|
||||
...JsonSchema.Keywords.items,
|
||||
collectExternalIds: (items, externalIds, ast, dynamicAnchors) => {
|
||||
if (typeof items === "string") {
|
||||
Bundle.collectExternalIds(items, externalIds, ast, dynamicAnchors);
|
||||
} else {
|
||||
items.forEach((schemaUri) => Bundle.collectExternalIds(schemaUri, externalIds, ast, dynamicAnchors));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const items202012 = {
|
||||
...JsonSchema.Keywords.items202012,
|
||||
collectExternalIds: ([, items], externalIds, ast, dynamicAnchors) => {
|
||||
Bundle.collectExternalIds(items, externalIds, ast, dynamicAnchors);
|
||||
}
|
||||
};
|
||||
|
||||
const not = {
|
||||
...JsonSchema.Keywords.not,
|
||||
collectExternalIds: Bundle.collectExternalIds
|
||||
};
|
||||
|
||||
const oneOf = {
|
||||
...JsonSchema.Keywords.oneOf,
|
||||
collectExternalIds: (oneOf, externalIds, ast, dynamicAnchors) => {
|
||||
oneOf.forEach((schemaUri) => Bundle.collectExternalIds(schemaUri, externalIds, ast, dynamicAnchors));
|
||||
}
|
||||
};
|
||||
|
||||
const patternProperties = {
|
||||
...JsonSchema.Keywords.patternProperties,
|
||||
collectExternalIds: (patternProperties, externalIds, ast, dynamicAnchors) => {
|
||||
patternProperties.forEach(([, schemaUri]) => Bundle.collectExternalIds(schemaUri, externalIds, ast, dynamicAnchors));
|
||||
}
|
||||
};
|
||||
|
||||
const tupleItems = {
|
||||
...JsonSchema.Keywords.tupleItems,
|
||||
collectExternalIds: (tupleItems, externalIds, ast, dynamicAnchors) => {
|
||||
tupleItems.forEach((schemaUri) => Bundle.collectExternalIds(schemaUri, externalIds, ast, dynamicAnchors));
|
||||
}
|
||||
};
|
||||
|
||||
const properties = {
|
||||
...JsonSchema.Keywords.properties,
|
||||
collectExternalIds: (properties, externalIds, ast, dynamicAnchors) => {
|
||||
Object.values(properties).forEach((schemaUri) => Bundle.collectExternalIds(schemaUri, externalIds, ast, dynamicAnchors));
|
||||
}
|
||||
};
|
||||
|
||||
const propertyNames = {
|
||||
...JsonSchema.Keywords.propertyNames,
|
||||
collectExternalIds: Bundle.collectExternalIds
|
||||
};
|
||||
|
||||
const unevaluatedItems = {
|
||||
...JsonSchema.Keywords.unevaluatedItems,
|
||||
collectExternalIds: ([, unevaluatedItems], externalIds, ast, dynamicAnchors) => {
|
||||
Bundle.collectExternalIds(unevaluatedItems, externalIds, ast, dynamicAnchors);
|
||||
}
|
||||
};
|
||||
|
||||
const unevaluatedProperties = {
|
||||
...JsonSchema.Keywords.unevaluatedProperties,
|
||||
collectExternalIds: ([, unevaluatedProperties], externalIds, ast, dynamicAnchors) => {
|
||||
Bundle.collectExternalIds(unevaluatedProperties, externalIds, ast, dynamicAnchors);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
validate,
|
||||
ref,
|
||||
additionalItems,
|
||||
additionalItems6,
|
||||
additionalProperties,
|
||||
additionalProperties6,
|
||||
allOf,
|
||||
anyOf,
|
||||
contains,
|
||||
containsMinContainsMaxContains,
|
||||
dependencies,
|
||||
dependentSchemas,
|
||||
if: if_,
|
||||
then,
|
||||
else: else_,
|
||||
items,
|
||||
items202012,
|
||||
not,
|
||||
oneOf,
|
||||
patternProperties,
|
||||
tupleItems,
|
||||
properties,
|
||||
propertyNames,
|
||||
unevaluatedItems,
|
||||
unevaluatedProperties
|
||||
};
|
||||
Generated
Vendored
+99
@@ -0,0 +1,99 @@
|
||||
{
|
||||
"_args": [
|
||||
[
|
||||
"@hyperjump/json-schema-bundle@0.1.3",
|
||||
"/Users/wookiee/sources/asyncapi-node/tools/bundler"
|
||||
]
|
||||
],
|
||||
"_from": "@hyperjump/json-schema-bundle@0.1.3",
|
||||
"_id": "@hyperjump/json-schema-bundle@0.1.3",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-UjmmtyIgaMXRXKmkJDQhvGAQFSfaPYBRue4tk3qeISrD468vziCWI2Km0RgfeXVxgy5xgqEPyi9DLXUqD4KWDQ==",
|
||||
"_location": "/@hyperjump/json-schema-bundle",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "version",
|
||||
"registry": true,
|
||||
"raw": "@hyperjump/json-schema-bundle@0.1.3",
|
||||
"name": "@hyperjump/json-schema-bundle",
|
||||
"escapedName": "@hyperjump%2fjson-schema-bundle",
|
||||
"scope": "@hyperjump",
|
||||
"rawSpec": "0.1.3",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "0.1.3"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/@hyperjump/json-schema-bundle/-/json-schema-bundle-0.1.3.tgz",
|
||||
"_spec": "0.1.3",
|
||||
"_where": "/Users/wookiee/sources/asyncapi-node/tools/bundler",
|
||||
"author": {
|
||||
"name": "Jason Desrosiers",
|
||||
"email": "jdesrosi@gmail.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/hyperjump-io/json-schema-bundle/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hyperjump/json-schema": "^0.18.3",
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"description": "A tool for bundling JSON Schema documents",
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-commonjs": "^21.0.1",
|
||||
"@rollup/plugin-node-resolve": "^13.0.6",
|
||||
"@types/chai": "^4.2.22",
|
||||
"@types/mocha": "^9.0.0",
|
||||
"@types/uuid": "^8.3.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.3.1",
|
||||
"@typescript-eslint/parser": "^5.3.1",
|
||||
"chai": "^4.3.4",
|
||||
"eslint": "^8.2.0",
|
||||
"eslint-import-resolver-node": "^0.3.6",
|
||||
"eslint-import-resolver-typescript": "^2.5.0",
|
||||
"eslint-plugin-import": "^2.25.2",
|
||||
"mocha": "^9.1.3",
|
||||
"rollup": "^2.59.0",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"ts-node": "^10.4.0",
|
||||
"typescript": "^4.4.4"
|
||||
},
|
||||
"exports": {
|
||||
"require": "./lib/index.js",
|
||||
"import": "./lib/index.mjs"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/jdesrosiers"
|
||||
},
|
||||
"homepage": "https://github.com/hyperjump-io/json-schema-bundle#readme",
|
||||
"keywords": [
|
||||
"JSON Schema",
|
||||
"json-schema",
|
||||
"jsonschema",
|
||||
"schema",
|
||||
"bundle",
|
||||
"bundler",
|
||||
"$ref",
|
||||
"external",
|
||||
"reference",
|
||||
"Compound Schema Document",
|
||||
"embedded"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "lib/index.js",
|
||||
"name": "@hyperjump/json-schema-bundle",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/hyperjump-io/json-schema-bundle.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rollup --config rollup.config.js",
|
||||
"clean": "xargs -a .gitignore rm -rf",
|
||||
"lint": "eslint lib",
|
||||
"prepublishOnly": "npm run build",
|
||||
"test": "mocha --require ts-node/register 'lib/**/*.spec.ts'"
|
||||
},
|
||||
"version": "0.1.3"
|
||||
}
|
||||
Generated
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Jason Desrosiers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
Generated
Vendored
+753
@@ -0,0 +1,753 @@
|
||||
# Hyperjump - JSON Schema Core
|
||||
JSON Schema Core (JSC) is a framework for building JSON Schema based validators
|
||||
and other tools.
|
||||
|
||||
It includes tools for:
|
||||
* Working with schemas (`$id`, `$schema`, `$ref`, etc)
|
||||
* Working with instances
|
||||
* Building custom keywords
|
||||
* Building custom vocabularies
|
||||
* Standard output formats
|
||||
* Custom output formats
|
||||
* Compiling schemas for validating multiple instances
|
||||
|
||||
## Install
|
||||
JSC is designed to run in a vanilla node.js environment, but has no dependencies
|
||||
on node.js specific libraries so it can be bundled for the browser. No
|
||||
compilers, preprocessors, or bundlers are used.
|
||||
JSC includes support for node.js JavaScript (CommonJS and ES Modules),
|
||||
TypeScript, and browsers.
|
||||
|
||||
### Node.js
|
||||
```bash
|
||||
npm install @hyperjump/json-schema-core
|
||||
```
|
||||
|
||||
### Browser
|
||||
When in a browser context, JSC is designed to use the browser's `fetch`
|
||||
implementation instead of a node.js fetch clone. The Webpack bundler does this
|
||||
properly without any extra configuration, but if you are using the Rollup
|
||||
bundler you will need to include the `browser: true` option in your Rollup
|
||||
configuration.
|
||||
|
||||
```javascript
|
||||
plugins: [
|
||||
resolve({
|
||||
browser: true
|
||||
}),
|
||||
commonjs()
|
||||
]
|
||||
```
|
||||
|
||||
## Schema
|
||||
A Schema Document (SDoc) is a structure that includes the schema, the id, and a
|
||||
JSON Pointer. The "value" of an SDoc is the portion of the schema that the JSON
|
||||
pointer points to. This allows an SDoc to represent any value in the schema
|
||||
while maintaining enough context to follow `$ref`s and track the position in the
|
||||
document.
|
||||
|
||||
* **Schema.add**: (schema: object, url?: URI, schemaVersion?: string) => URI
|
||||
|
||||
Load a schema. Returns the identifier for the schema. See the "$id" and
|
||||
"$schema" sections for more details.
|
||||
* **Schema.get**: (url: URI, contextDoc?: SDoc) => Promise<SDoc>
|
||||
|
||||
Fetch a schema. Schemas can come from an HTTP request, a file, or a schema
|
||||
that was added with `Schema.add`.
|
||||
* **Schema.uri**: (doc: SDoc) => URI
|
||||
|
||||
Returns a URI including the id and JSON Pointer that represents a value
|
||||
within the schema.
|
||||
* **Schema.getAnchorPointer**: (doc: SDoc, anchor: string) => any
|
||||
|
||||
Get a JSON Pointer for the location in the schema that the anchor refers to.
|
||||
* **Schema.value**: (doc: SDoc) => any
|
||||
|
||||
The portion of the schema the document's JSON Pointer points to.
|
||||
* **Schema.typeOf**: (doc: SDoc, type: string) => boolean
|
||||
|
||||
Determines if the JSON type of the given doc matches the given type
|
||||
* **Schema.has**: (key: string, doc: SDoc) => Promise<SDoc>
|
||||
|
||||
Similar to `key in schema`.
|
||||
* **Schema.step**: (key: string, doc: SDoc) => Promise<SDoc>
|
||||
|
||||
Similar to `schema[key]`, but returns an SDoc.
|
||||
* **Schema.entries**: (doc: SDoc) => Promise<[[string, SDoc]]>
|
||||
|
||||
Similar to `Object.entries`, but returns SDocs for values.
|
||||
* **Schema.keys**: (doc: SDoc) => [string]
|
||||
|
||||
Similar to `Object.keys`.
|
||||
* **Schema.map**: (fn: (item: Promise<SDoc>, index: integer) => T, doc: SDoc) => Promise<[T]>
|
||||
|
||||
A `map` function for an SDoc whose value is an array.
|
||||
* **Schema.length**: (doc: SDoc) => number
|
||||
|
||||
Similar to `Array.prototype.length`.
|
||||
* **Schema.toSchema**: (doc: SDoc, options: ToSchemaOptions) => object
|
||||
|
||||
Get a raw schema from a Schema Document.
|
||||
* **ToSchemaOptions**: object
|
||||
|
||||
* parentId: string (default: "") -- `file://` URIs will be generated
|
||||
relative to this path.
|
||||
* parentDialect: string (default: "") -- If the dialect of the schema
|
||||
* matches this value, the `$schema` keyword will be omitted.
|
||||
* includeEmbedded: boolean (default: true) -- If false, embedded schemas
|
||||
will be unbundled from the schema.
|
||||
|
||||
### Schema Identification
|
||||
JSC requires that all schemas are identified by at least one URI. There are two
|
||||
types of schema identifiers, internal and external. An internal identifier is an
|
||||
identifier that is specified within the schema using `$id`. An external
|
||||
identifier is an identifier that is specified outside of the schema. In JSC, an
|
||||
external identifier can be either the URL a schema is retrieved with, or the
|
||||
identifier specified when using `Schema.add` to load a schema.
|
||||
|
||||
JSC can fetch schemas from the web or from the file system, but when fetching
|
||||
from the file system, there are limitations for security reasons. If
|
||||
your schema has an identifier with an http scheme (**http**://example.com), it's
|
||||
not allowed to reference schemas with a file scheme
|
||||
(**file**:///path/to/my/schemas).
|
||||
|
||||
Internal identifiers (`$id`s) are resolved against the external identifier of
|
||||
the schema (if one exists) and the resulting URI is used to identify the schema.
|
||||
All identifiers must be absolute URIs. External identifiers are required to be
|
||||
absolute URIs and internal identifiers must resolve to absolute URIs.
|
||||
|
||||
```javascript
|
||||
const { Core, Schema } = require("@hyperjump/json-schema-core");
|
||||
|
||||
|
||||
// Example: Inline schema with external identifier
|
||||
const schemaJson = {
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"type": "string"
|
||||
}
|
||||
Schema.add(schemaJson, "http://example.com/schemas/string");
|
||||
const schema = await Schema.get("http://example.com/schemas/string");
|
||||
|
||||
// Example: Inline schema with internal identifier
|
||||
const schemaJson = {
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "http://example.com/schemas/string",
|
||||
"type": "string"
|
||||
}
|
||||
Schema.add(schemaJson);
|
||||
const schema = await Schema.get("http://example.com/schemas/string");
|
||||
|
||||
// Example: Inline schema with no identifier
|
||||
const schemaJson = {
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"type": "string"
|
||||
}
|
||||
Schema.add(schemaJson); // Error: Couldn't determine an identifier for the schema
|
||||
|
||||
// Given the following schema at http://example.com/schemas/foo
|
||||
// {
|
||||
// "$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
// "$id": "http://example.com/schemas/string",
|
||||
// "type": "string"
|
||||
// }
|
||||
|
||||
// Example: Fetch schema from external HTTP identifier
|
||||
const schema = await Schema.get("http://example.com/schemas/string");
|
||||
|
||||
// Example: Fetch schema from internal identifier
|
||||
const schema = await Schema.get("http://example.com/schemas/foo");
|
||||
|
||||
// Given the following schema at http://example.com/schemas/bar
|
||||
// {
|
||||
// "$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
// "$id": "string",
|
||||
// "type": "string"
|
||||
// }
|
||||
|
||||
// Example: Fetch schema from internal identifier resolved against external identifier
|
||||
const schema = await Schema.get("http://example.com/schemas/string");
|
||||
|
||||
// Given the following schema at /path/to/my/schemas/string.schema.json
|
||||
// {
|
||||
// "$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
// "type": "string"
|
||||
// }
|
||||
|
||||
// Example: Fetch schema from external FILE identifier
|
||||
const schema = await Schema.get("file:///path/to/my/schemas/string.schema.json");
|
||||
|
||||
// Given the following schema at /path/to/my/schemas/string.schema.json
|
||||
// {
|
||||
// "$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
// "type": "string"
|
||||
// }
|
||||
//
|
||||
// Given the following schema at http://example.com/schemas/baz
|
||||
// {
|
||||
// "$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
// "$ref": "file:///path/to/my/schemas/string.schema.json"
|
||||
// }
|
||||
|
||||
// Example: Reference file from network context
|
||||
const schema = await Schema.get("http://example.com/schemas/baz");
|
||||
await Core.validate(schema); // Error: Can't access file resource from network context
|
||||
```
|
||||
|
||||
### $schema
|
||||
JSC is designed to support multiple drafts of JSON Schema and it makes no
|
||||
assumption about what draft your schema uses. You need to specify it in some
|
||||
way. The preferred way is to the use `$schema` in all of your schemas, but you
|
||||
can also specify what draft to use when adding a schema using `Schema.add`. If a
|
||||
draft is specified in `Schema.add` and the schema has a `$schema`, the
|
||||
`$schema` will be used. If no draft is specified, you will get an error.
|
||||
|
||||
```javascript
|
||||
// Example: Internal schema version
|
||||
const schemaJSON = {
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "http://example.com/schemas/string",
|
||||
"type": "string"
|
||||
};
|
||||
Schema.add(schemaJSON);
|
||||
|
||||
// Example: External schema version
|
||||
const schemaJSON = {
|
||||
"type": "string"
|
||||
};
|
||||
Schema.add(schemaJSON, "http://example.com/schemas/string", "https://json-schema.org/draft/2020-12/schema");
|
||||
|
||||
// Example: No schema version
|
||||
const schemaJSON = {
|
||||
"$id": "http://example.com/schemas/string",
|
||||
"type": "string"
|
||||
};
|
||||
Schema.add(schemaJSON); // Error: Couldn't determine schema version
|
||||
|
||||
// Given the following schema at http://example.com/schemas/foo
|
||||
// {
|
||||
// "type": "string"
|
||||
// }
|
||||
|
||||
// Example: No schema version external
|
||||
const schema = Schema.get("http://example.com/schemas/string"); // Error: Couldn't determine schema version
|
||||
```
|
||||
|
||||
## Instance
|
||||
An Instance Document (IDoc) is like a Schema Document (SDoc) except with much
|
||||
more limited functionality.
|
||||
|
||||
* **Instance.cons**: (instance: any) => IDoc
|
||||
|
||||
Construct a IDoc from a value.
|
||||
* **Instance.get**: (url: URI, contextDoc: IDoc) => IDoc
|
||||
|
||||
Apply a same-resource reference to a IDoc.
|
||||
* **Instance.uri**: (doc: IDoc) => URI
|
||||
|
||||
Returns a URI including the id and JSON Pointer that represents a value
|
||||
within the instance.
|
||||
* **Instance.value**: (doc: IDoc) => any
|
||||
|
||||
The portion of the instance that the document's JSON Pointer points to.
|
||||
* **Instance.has**: (key: string, doc: IDoc) => any
|
||||
|
||||
Similar to `key in instance`.
|
||||
* **Instance.typeOf**: (doc: IDoc, type: string) => boolean
|
||||
|
||||
Determines if the JSON type of the given doc matches the given type.
|
||||
* **Instance.step**: (key: string, doc: IDoc) => IDoc
|
||||
|
||||
Similar to `schema[key]`, but returns a IDoc.
|
||||
* **Instance.entries**: (doc: IDoc) => [string, IDoc]
|
||||
|
||||
Similar to `Object.entries`, but returns IDocs for values.
|
||||
* **Instance.keys**: (doc: IDoc) => [string]
|
||||
|
||||
Similar to `Object.keys`.
|
||||
* **Instance.map**: (fn: (item: IDoc, index: integer) => T, doc: IDoc) => [T]
|
||||
|
||||
A `map` function for a IDoc whose value is an array.
|
||||
* **Instance.reduce**: (fn: (accumulator: T, item: IDoc, index: integer) => T, initial: T, doc: IDoc) => T
|
||||
|
||||
A `reduce` function for a IDoc whose value is an array.
|
||||
* **Instance.every**: (fn: (doc: IDoc, index: integer) => boolean, doc: IDoc) => boolean
|
||||
|
||||
An `every` function for a IDoc whose value is an array.
|
||||
* **Instance.some**: (fn: (doc: IDoc, index: integer) => boolean, doc: IDoc) => boolean
|
||||
|
||||
A `some` function for a IDoc whose value is an array.
|
||||
* **Instance.length**: (doc: IDoc) => number
|
||||
|
||||
Similar to `Array.prototype.length`.
|
||||
|
||||
## Validation
|
||||
Some helper functions are provided to assist in building validation functions.
|
||||
|
||||
* **Core.validate**: (schema: SDoc, value: any, outputFormat: OutputFormat = Core.FLAG) => Promise<Output>
|
||||
|
||||
A curried function that validates a JavaScript value against a schema.
|
||||
* **Core.compile**: (schema: SDoc) => Promise<CompiledSchema>
|
||||
|
||||
Compile a schema to be used interpreted later. A compiled schema is a JSON
|
||||
serializable structure that can be serialized an restored for later use.
|
||||
* **Core.interpret**: (schema: CompiledSchema, instance: Instance, outputFormat = Core.FLAG) => <Output>
|
||||
|
||||
A curried function for validating an instance against a compiled schema.
|
||||
|
||||
```javascript
|
||||
const { Core, Schema } = require("@hyperjump/json-schema-core");
|
||||
|
||||
|
||||
// Example: Inline schema with external identifier
|
||||
Schema.add({
|
||||
"$id": "http://example.com/schemas/string",
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"type": "string"
|
||||
});
|
||||
const schema = await Schema.get("http://example.com/schemas/string");
|
||||
|
||||
// Generate a validation function from a Schema Document
|
||||
const isString = await Core.validate(schema);
|
||||
|
||||
// Validate a value from a Schema Document in one step
|
||||
const result = await Core.validate(schema, "foo");
|
||||
|
||||
// Compile a Schema Document for use later
|
||||
const compiledSchema = await Core.compile(schema);
|
||||
|
||||
// Generate a validation function from a compiled schema
|
||||
const isString = Core.interpret(compiledSchema);
|
||||
|
||||
// Validate an instance from a compiled schema
|
||||
const result = Core.interpret(compiledSchema, Instance.cons("foo"));
|
||||
```
|
||||
|
||||
## Output
|
||||
JSC supports all of the standard output formats specified for JSON Schema
|
||||
draft 2019-09 and 2020-12 and is separately configurable for instance validation
|
||||
and meta-validtion.
|
||||
|
||||
This implementation does not include the suggested `keywordLocation` property in
|
||||
the output unit. I think `absoluteKeywordLocation`+`instanceLocation` is
|
||||
sufficient for debugging and it's awkward for the output to produce JSON
|
||||
Pointers that potentially won't resolve because they cross schema boundaries.
|
||||
|
||||
This implementation includes an extra property in the output unit called
|
||||
`keyword`. This is an identifier (URI) for the keyword that was validated. With
|
||||
the standard output unit fields, we can see what keyword was validated by
|
||||
inspecting the last segment of the `absoluteKeywordLocation` property. But,
|
||||
since JSC can support multiple JSON Schema versions, we would have to pull up
|
||||
the actual schema to find what draft was used. The `schema` property gives us
|
||||
enough information to not have to go back to the schema to know what draft is
|
||||
being used.
|
||||
|
||||
By default JSC will validate all schemas against their meta-schema. However, the
|
||||
only time you really need this is when developing schemas. When JSC is running
|
||||
in a production environment or you are working with third-party schemas that you
|
||||
trust to be correct, you can turn off meta-validation to boost performance.
|
||||
|
||||
* **Core.setMetaOutputFormat**: (outputFormat: OutputFormat) => undefined
|
||||
|
||||
Set the output format used for schema validation. Default Core.DETAILED
|
||||
* **Core.setShouldMetaValidate**: (shouldMetaValidate: boolean) => undefined
|
||||
|
||||
Turn schema validation on or off. Default true
|
||||
* **OutputFormat**: An enum of available output formats
|
||||
|
||||
* Core.FLAG - Default for instance validation
|
||||
* Core.BASIC
|
||||
* Core.DETAILED - Default for meta-validation
|
||||
* Core.VERBOSE
|
||||
|
||||
```javascript
|
||||
const { Core, Schema } = require("@hyperjump/json-schema-core");
|
||||
|
||||
|
||||
// Example: Specify instance validation output format
|
||||
Schema.add({
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "http://example.com/schemas/string",
|
||||
"type": "string"
|
||||
});
|
||||
const schema = await Schema.get("http://example.com/schemas/string");
|
||||
const isString = await Core.validate(schema);
|
||||
const output = isString(42, Core.BASIC); // => {
|
||||
// "keyword": "https://json-schema.org/draft/2020-12/schema",
|
||||
// "absoluteKeywordLocation": "http://example.com/schemas/string#",
|
||||
// "instanceLocation": "#",
|
||||
// "valid": false,
|
||||
// "errors": [
|
||||
// {
|
||||
// "keyword": "https://json-schema.org/draft/2020-12/schema#type",
|
||||
// "absoluteKeywordLocation": "http://example.com/schemas/string#/type",
|
||||
// "instanceLocation": "#",
|
||||
// "valid": false
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
|
||||
// Example: Specify meta-validation output format
|
||||
Schema.add({
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "http://example.com/schemas/foo",
|
||||
"type": "this-is-not-a-valid-type"
|
||||
});
|
||||
Core.setMetaOutputFormat(Core.BASIC);
|
||||
const schema = await Schema.get("http://example.com/schemas/foo");
|
||||
const isString = await Core.validate(schema); // InvalidSchemaError: {
|
||||
// "keyword": "https://json-schema.org/draft/2020-12/schema",
|
||||
// "absoluteKeywordLocation": "https://json-schema.org/draft/2020-12/schema#",
|
||||
// "instanceLocation": "#",
|
||||
// "valid": false,
|
||||
// "errors": [
|
||||
// {
|
||||
// "keyword": "https://json-schema.org/draft/2020-12/schema#allOf",
|
||||
// "absoluteKeywordLocation": "https://json-schema.org/draft/2020-12/schema#/allOf",
|
||||
// "instanceLocation": "#",
|
||||
// "valid": false
|
||||
// }
|
||||
// ...
|
||||
// ]
|
||||
// }
|
||||
|
||||
// Example: Turn off schema validation
|
||||
Core.setShouldMetaValidate(false);
|
||||
const schema = await Schema.get("http://example.com/schemas/foo"); // Load invalid schema
|
||||
const isString = await Core.validate(schema); // Schema compilation succeeds even though schema is invalid
|
||||
```
|
||||
|
||||
## PubSub
|
||||
JSC emits events that you can subscribe to and work with however your
|
||||
application needs. For now, the only event is the `"result"` event that emits
|
||||
output units every time a keyword is validated. Internally, JSC uses these
|
||||
events to build standard output formats. Other events can be added when
|
||||
use-cases are identified for them.
|
||||
|
||||
```javascript
|
||||
const PubSub = require("pubsub-js");
|
||||
const { Core, Schema } = require("@hyperjump/json-schema-core");
|
||||
|
||||
|
||||
Schema.add({
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "http://example.com/schemas/string",
|
||||
"type": "string"
|
||||
});
|
||||
const schema = await Schema.get("http://example.com/schemas/string");
|
||||
const isString = await Core.validate(schema);
|
||||
|
||||
const results = [];
|
||||
const subscriptionToken = PubSub.subscribe("result", (message, result) => {
|
||||
results.push(result);
|
||||
});
|
||||
isString(42);
|
||||
PubSub.unsubscribe(subscriptionToken);
|
||||
results; // => [
|
||||
// {
|
||||
// "keyword": "https://json-schema.org/draft/2020-12/schema",
|
||||
// "absoluteKeywordLocation": "http://example.com/schemas/string#",
|
||||
// "instanceLocation": "#",
|
||||
// "valid": false
|
||||
// },
|
||||
// {
|
||||
// "keyword": "https://json-schema.org/draft/2020-12/schema#type",
|
||||
// "absoluteKeywordLocation": "http://example.com/schemas/string#/type",
|
||||
// "instanceLocation": "#",
|
||||
// "valid": false
|
||||
// }
|
||||
// ]
|
||||
```
|
||||
|
||||
## Customize
|
||||
JSC uses a micro-kernel architecture, so it's highly customizable. Everything
|
||||
is a plugin, even the validation logic. This allows you to use JSC as a
|
||||
framework for building other types of JSON Schema based tools such as code
|
||||
generators or form generators.
|
||||
|
||||
In addition to this documentation you should be able to look at the
|
||||
[JSV](https://github.com/hyperjump-io/json-schema-validator) code to see an
|
||||
example of how to add your custom plugins because it's all implemented the same
|
||||
way.
|
||||
|
||||
* **Schema.setConfig**: (schemaVersion: string, configName: string, configValue: string) => undefined
|
||||
|
||||
Set a configuration value for a schemaVersion.
|
||||
* **Schema.getConfig**: (schemaVersion: string, configName: string) => any
|
||||
|
||||
Get a configuration value for a schemaVersion.
|
||||
|
||||
### References
|
||||
The `$ref` keyword has changed a couple times over the last several drafts. JSC
|
||||
allows you to configure which version(s) of `$ref`s you want to support. There
|
||||
are several types of references.
|
||||
|
||||
* **JSON Reference**: *(draft-04/06/07)* In draft-04, references were defined in
|
||||
a separate spec from JSON Schema. The JSON Schema spec only constrained `$ref`
|
||||
in how URIs are resolved with respect to `id`. Then in draft-06/07, JSON
|
||||
Schema absorbed the JSON Reference spec and further constrained `$ref` to only
|
||||
be allowed where schemas are allowed. JSC doesn't support this constraint
|
||||
because it can't be done in a keyword agnostic way.
|
||||
|
||||
* **JSON Schema Reference**: *(draft-2019-09+)* In draft 2019-09, a reference
|
||||
was changed from being an object with a `$ref` property to the value of a
|
||||
`$ref` keyword. This allowed `$ref` to behave more like a keyword.
|
||||
|
||||
* **Dynamic JSON Schema Reference**: *(draft-2019-09+)* In draft 2019-09, the
|
||||
concept of a dynamic scope reference was added to make it easier to extend
|
||||
recursive schemas. This was added to support building custom meta-schemas.
|
||||
|
||||
Draft-04/6/7 style references are configured via dialect configuration using
|
||||
`Schema.setConfig`. Draft-2019-09+ style references are just keywords and can be
|
||||
added as part of a vocabulary.
|
||||
|
||||
```javascript
|
||||
const { Schema } = require("@hyperjump/json-schema-core");
|
||||
|
||||
|
||||
// Configure draft-04/6/7 style references
|
||||
Schema.setConfig("http://json-schema.org/draft-04/schema", "jrefToken", "$ref");
|
||||
|
||||
// Configure draft-2019-09+ style references
|
||||
Core.defineVocabulary("https://example.com/draft/custom/vocab/core", {
|
||||
"$ref": Keywords.ref,
|
||||
"$dynamicRef": Keywords.dynamicRef,
|
||||
...
|
||||
});
|
||||
```
|
||||
|
||||
### Identifiers
|
||||
The `$id` keyword has seen it's fair share of churn as well. Although the spec
|
||||
around this keyword was rewritten and clarified many times, the vast majority of
|
||||
changes have simply been name changes. JSC allows you to configure which version
|
||||
you want to support.
|
||||
|
||||
* **id**: *(draft-04)* A base URI used to resolve reference URIs.
|
||||
|
||||
* **$id**: *(draft-06/07)* Same as `id`, just a different name.
|
||||
|
||||
* **$id**: *(draft-2019-09+)* Same as `$id` except with same-document reference
|
||||
support split out into `$anchor`.
|
||||
|
||||
* **$anchor**: *(draft-2019-09+)* Same-document reference.
|
||||
|
||||
* **$recursiveAnchor**: *(draft-2019-09)* Dynamic scope same-document reference.
|
||||
Value is a boolean that is only allowed at the root of a schema.
|
||||
|
||||
* **$dynamicAnchor**: *(draft-2020-12)* Dynamic scope same-document reference.
|
||||
Value is a string and works like `$anchor`.
|
||||
|
||||
In draft-2019-09, `$id` was redefined from being a resolution scope modifier to
|
||||
being an inlined reference. This means that JSON Pointers can not cross into
|
||||
schemas with `$id`s. So far, JSC only supports these bounded `$id`s. If I come
|
||||
up with a way to relax this constraint for old draft implementations, I will,
|
||||
but since there is no sensible reason to want such a thing, it's a low priority.
|
||||
|
||||
In JSON Schema, properties called `$id` are only considered identifiers if they
|
||||
appear in a schema. JSC is keyword agnostic, so it doesn't know what is a schema
|
||||
and what isn't. Therefore, an `$id` might be treated as an identifier in places
|
||||
it's not expected to. This is unlikely, but not impossible.
|
||||
|
||||
```javascript
|
||||
const { Schema } = require("@hyperjump/json-schema-core");
|
||||
|
||||
|
||||
// Configure draft-2019-09+ style identifiers
|
||||
Schema.setConfig("https://json-schema.org/draft/2020-12/schema", "baseToken", "$id");
|
||||
Schema.setConfig("https://json-schema.org/draft/2002-12/schema", "embeddedToken", "$id");
|
||||
Schema.setConfig("https://json-schema.org/draft/2020-12/schema", "anchorToken", "$anchor");
|
||||
Schema.setConfig("https://json-schema.org/draft/2020-12/schema", "recursiveAnchorToken", "$recursiveAnchor");
|
||||
|
||||
// Configure draft-06/7 style references
|
||||
Schema.setConfig("http://json-schema.org/draft-04/schema", "baseToken", "$id");
|
||||
Schema.setConfig("http://json-schema.org/draft-04/schema", "embeddedToken", "$id");
|
||||
Schema.setConfig("http://json-schema.org/draft-04/schema", "anchorToken", "$id");
|
||||
|
||||
// Configure draft-04 style references
|
||||
Schema.setConfig("http://json-schema.org/draft-04/schema", "baseToken", "id");
|
||||
Schema.setConfig("http://json-schema.org/draft-04/schema", "embeddedToken", "id");
|
||||
Schema.setConfig("http://json-schema.org/draft-04/schema", "anchorToken", "id");
|
||||
```
|
||||
|
||||
### Custom Meta-Schemas
|
||||
Let's say you want to use a custom meta-schema that does stricter validation
|
||||
than the standard meta-schema. Once you have your custom meta-schema ready, it's
|
||||
just a couple lines of code to start using it.
|
||||
|
||||
```javascript
|
||||
const { Core, Schema } = require("@hyperjump/json-schema-core");
|
||||
|
||||
|
||||
// Optional: Load your meta-schema. If you don't do this, JSC will fetch it
|
||||
// using it's identifier when it's needed.
|
||||
Schema.add({
|
||||
"$id": "https://example.com/draft/2020-12-strict/schema",
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$vocabulary": {
|
||||
"https://json-schema.org/draft/2020-12/vocab/core": true,
|
||||
"https://json-schema.org/draft/2020-12/vocab/applicator": true,
|
||||
"https://json-schema.org/draft/2020-12/vocab/validation": true,
|
||||
"https://json-schema.org/draft/2020-12/vocab/meta-data": true,
|
||||
"https://json-schema.org/draft/2020-12/vocab/format-annotation": true,
|
||||
"https://json-schema.org/draft/2020-12/vocab/content": true
|
||||
},
|
||||
...
|
||||
});
|
||||
|
||||
// Use the URI you chose for your meta-schema for the `$schema` in you schemas.
|
||||
Schema.add({
|
||||
"$id": "http://example.com/schemas/string",
|
||||
"$schema": "http://example.com/draft/2020-12-strict/schema",
|
||||
"type": "string"
|
||||
});
|
||||
const schema = await Schema.get("http://example.com/schemas/string");
|
||||
await Core.validate(schema, "foo");
|
||||
```
|
||||
|
||||
### Keywords
|
||||
A keyword implementation is a module with at least the functions: `compile` and
|
||||
`interpret`. In the `compile` step, you can do any processing steps necessary to
|
||||
do the actual validation in the `interpret` step. The most common things to do
|
||||
in the `compile` step is to follow references and compile sub-schemas. The
|
||||
`interpret` step takes the result of the `compile` step and returns a boolean
|
||||
value indicating whether validation has passed or failed.
|
||||
|
||||
If your custom keyword is an applicator and your dialect supports
|
||||
`unevaluatedProperties` and `unevaluatedItems`, you'll also need to provide the
|
||||
`collectEvaluatedProperties` and `collectEvaluatedItems` functions.
|
||||
|
||||
You can Use the [JSV](https://github.com/hyperjump-io/json-schema-validator)
|
||||
keyword implementations as examples when creating your own keywords.
|
||||
|
||||
* **Core.getKeyword**: (keywordId: string) => Keyword
|
||||
|
||||
Retreive a keyword by it's identifier.
|
||||
* **Core.hasKeyword**: (keywordId: string) => boolean
|
||||
|
||||
Query whether a keyword implementation exists.
|
||||
* **Core.compileSchema**: (schema: SDoc, ast: AST) => undefined
|
||||
|
||||
Compile a schema.
|
||||
* **Core.interpretSchmea**: (schemaUri: string, instance: Instance, ast: AST, dynamicAnchors: Map[anchor: String, uri: String]) => boolean
|
||||
|
||||
Finds the compiled schema in the ast for the schemaUri and validates the
|
||||
instance against the it. The result is a boolean indicating if the keyword
|
||||
passes validation.
|
||||
* **Core.collectEvaluatedProperties**: (schemaUri: string, instance: Instance, ast: AST, dynamicAnchors: Map[anchor: String, uri: String]) => string[]
|
||||
|
||||
Walk a schema and collect any property names that are evaluated by the
|
||||
schemas it finds. A property is not considered evaluated if the schema
|
||||
containing it is not valid.
|
||||
* **Core.collectEvaluatedItems**: (schemaUri: string, instance: Instance, ast: AST, dynamicAnchors: Map[anchor: String, uri: String]) => number
|
||||
|
||||
Walk a schema and collect maximum number of items that are evaluated by the
|
||||
schemas it finds. An item is not considered evaluated if the schema
|
||||
containing it is not valid.
|
||||
|
||||
This example implements an `if`/`then`/`else`-like keyword called `cond`.
|
||||
`cond` is an array of schemas where the first is the `if` schema, the second is
|
||||
the `then` schema, and the third is the `else` schema.
|
||||
|
||||
```javascript
|
||||
const { Core, Schema } = require("@hyperjump/json-schema-core");
|
||||
|
||||
|
||||
module.exports = {
|
||||
compile: async (schema, ast) => {
|
||||
const schemas = await Schema.map((schema) => Core.compileSchema(schema, ast), schema);
|
||||
return Promise.all(schemas);
|
||||
},
|
||||
|
||||
interpret: (cond, instance, ast, dynamicAnchors) => {
|
||||
return Core.interpretSchema(cond[0], instance, ast, dynamicAnchors)
|
||||
? (cond[1] ? Core.interpretSchema(cond[1], instance, ast, dynamicAnchors) : true)
|
||||
: (cond[2] ? Core.interpretSchema(cond[2], instance, ast, dynamicAnchors) : true);
|
||||
},
|
||||
|
||||
collectEvaluatedProperties: (cond, instance, ast, dynamicAnchors) => {
|
||||
const propertyNames = Core.collectEvaluatedProperties(cond[0], instance, ast, dynamicAnchors);
|
||||
const branch = propertyNames ? 1 : 2;
|
||||
|
||||
if (cond[branch]) {
|
||||
const branchPropertyNames = Core.collectEvaluatedProperties(cond[branch], instance, ast, dynamicAnchors);
|
||||
return branchPropertyNames && (propertyNames || []).concat(branchPropertyNames);
|
||||
} else {
|
||||
return propertyNames || [];
|
||||
}
|
||||
},
|
||||
|
||||
collectEvaluatedItems: (cond, instance, ast, dynamicAnchors) => {
|
||||
const evaluatedIndexes = Core.collectEvaluatedItems(cond[0], instance, ast, dynamicAnchors);
|
||||
const branch = evaluatedIndexes !== false ? 1 : 2;
|
||||
|
||||
if (cond[branch]) {
|
||||
const branchEvaluatedIndexes = Core.collectEvaluatedItems(cond[branch], instance, ast, dynamicAnchors);
|
||||
return branchEvaluatedIndexes !== false && new Set([...evaluatedIndexes || new Set(), ...branchEvaluatedIndexes]);
|
||||
} else {
|
||||
return evaluatedIndexes || new Set();
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
In order to use an keyword in an implementation, you need to add it to a
|
||||
vocabulary.
|
||||
|
||||
### Vocabularies
|
||||
A vocabulary is just a named collection of keywords.
|
||||
|
||||
* **Core.defineVocabulary**: (vocabularyId: string, keywords: { [keywordId]: Keyword }) => undefined
|
||||
|
||||
Define a vocabulary giving it an identifier and an object that maps keyword
|
||||
identifiers to keyword implementations.
|
||||
|
||||
```javascript
|
||||
const { Core, Schema } = require("@hyperjump/json-schema-core");
|
||||
const cond = require("./keywords/cond");
|
||||
|
||||
|
||||
// Choose a URI for your vocabulary and add keywords
|
||||
Core.defineVocabulary("https://example.com/draft/custom/vocab/conditionals", {
|
||||
cond: cond
|
||||
});
|
||||
|
||||
// Create a new meta-schema an add your vocabulary to `$vocabulary`
|
||||
Schema.add({
|
||||
"$id": "https://example.com/draft/custom/schema",
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$vocabulary": {
|
||||
...
|
||||
"https://example.com/draft/custom/vocab/conditionals": true
|
||||
},
|
||||
...
|
||||
});
|
||||
|
||||
// Try it out
|
||||
Schema.add({
|
||||
"$id": "http://example.com/schemas/cond-example",
|
||||
"$schema": "https://example.com/draft/custom/schema",
|
||||
"type": "integer",
|
||||
"cond": [
|
||||
{ "minimum": 10 },
|
||||
{ "multipleOf": 3 },
|
||||
{ "multipleOf": 2 }
|
||||
]
|
||||
});
|
||||
const schema = await Schema.get("http://example.com/schemas/cond-example");
|
||||
await Core.validate(schema, 42);
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
### Tests
|
||||
|
||||
Run the tests
|
||||
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
|
||||
Run the tests with a continuous test runner
|
||||
|
||||
```bash
|
||||
npm test -- --watch
|
||||
```
|
||||
Generated
Vendored
+1875
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+2
File diff suppressed because one or more lines are too long
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+1873
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+2
File diff suppressed because one or more lines are too long
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+1863
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+2
File diff suppressed because one or more lines are too long
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+1878
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+2
File diff suppressed because one or more lines are too long
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+1870
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+2
File diff suppressed because one or more lines are too long
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+1879
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+2
File diff suppressed because one or more lines are too long
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
export type JsonType = "null" | "boolean" | "object" | "array" | "number" | "integer" | "string";
|
||||
|
||||
export const pathRelative: (from: string, to: string) => string;
|
||||
Generated
Vendored
+102
@@ -0,0 +1,102 @@
|
||||
const resolveUrl = require("url-resolve-browser");
|
||||
|
||||
|
||||
const isObject = (value) => typeof value === "object" && !Array.isArray(value) && value !== null;
|
||||
const isType = {
|
||||
null: (value) => value === null,
|
||||
boolean: (value) => typeof value === "boolean",
|
||||
object: isObject,
|
||||
array: (value) => Array.isArray(value),
|
||||
number: (value) => typeof value === "number",
|
||||
integer: (value) => Number.isInteger(value),
|
||||
string: (value) => typeof value === "string"
|
||||
};
|
||||
const jsonTypeOf = (value, type) => isType[type](value);
|
||||
|
||||
const splitUrl = (url) => {
|
||||
const indexOfHash = url.indexOf("#");
|
||||
const ndx = indexOfHash === -1 ? url.length : indexOfHash;
|
||||
const urlReference = url.slice(0, ndx);
|
||||
const urlFragment = url.slice(ndx + 1);
|
||||
|
||||
return [decodeURI(urlReference), decodeURI(urlFragment)];
|
||||
};
|
||||
|
||||
const getScheme = (url) => {
|
||||
const matches = RegExp(/^(.+):\/\//).exec(url);
|
||||
return matches ? matches[1] : "";
|
||||
};
|
||||
|
||||
const safeResolveUrl = (contextUrl, url) => {
|
||||
const resolvedUrl = resolveUrl(contextUrl, url);
|
||||
const contextId = splitUrl(contextUrl)[0];
|
||||
if (contextId && getScheme(resolvedUrl) === "file" && getScheme(contextId) !== "file") {
|
||||
throw Error(`Can't access file '${resolvedUrl}' resource from network context '${contextUrl}'`);
|
||||
}
|
||||
return resolvedUrl;
|
||||
};
|
||||
|
||||
const CHAR_BACKWARD_SLASH = 47;
|
||||
|
||||
const pathRelative = (from, to) => {
|
||||
if (from === to) {
|
||||
return "";
|
||||
}
|
||||
|
||||
let toStart = 1;
|
||||
const fromLen = from.length - 1;
|
||||
const toLen = to.length - toStart;
|
||||
|
||||
// Compare paths to find the longest common path from root
|
||||
const length = fromLen < toLen ? fromLen : toLen;
|
||||
let lastCommonSep = -1;
|
||||
let i = 0;
|
||||
for (; i < length; i++) {
|
||||
const fromCode = from.charCodeAt(i + 1);
|
||||
if (fromCode !== to.charCodeAt(toStart + i)) {
|
||||
break;
|
||||
} else if (fromCode === CHAR_BACKWARD_SLASH) {
|
||||
lastCommonSep = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (toLen > length) {
|
||||
if (to.charCodeAt(toStart + i) === CHAR_BACKWARD_SLASH) {
|
||||
return to.slice(toStart + i + 1);
|
||||
}
|
||||
if (i === 0) {
|
||||
return to.slice(toStart + i);
|
||||
}
|
||||
}
|
||||
if (fromLen > length) {
|
||||
if (from.charCodeAt(i + 1) === CHAR_BACKWARD_SLASH) {
|
||||
lastCommonSep = i;
|
||||
} else if (length === 0) {
|
||||
lastCommonSep = 0;
|
||||
}
|
||||
}
|
||||
|
||||
let out = "";
|
||||
// Generate the relative path based on the path difference between `to` and `from`
|
||||
for (i = lastCommonSep + 2; i <= from.length; ++i) {
|
||||
if (i === from.length || from.charCodeAt(i) === CHAR_BACKWARD_SLASH) {
|
||||
out += out.length === 0 ? ".." : "/..";
|
||||
}
|
||||
}
|
||||
|
||||
toStart += lastCommonSep;
|
||||
|
||||
// Lastly, append the rest of the destination (`to`) path that comes after
|
||||
// the common path parts
|
||||
if (out.length > 0) {
|
||||
return `${out}${to.slice(toStart, to.length)}`;
|
||||
}
|
||||
|
||||
if (to.charCodeAt(toStart) === CHAR_BACKWARD_SLASH) {
|
||||
++toStart;
|
||||
}
|
||||
|
||||
return to.slice(toStart, to.length);
|
||||
};
|
||||
|
||||
module.exports = { jsonTypeOf, splitUrl, safeResolveUrl, pathRelative };
|
||||
Generated
Vendored
+68
@@ -0,0 +1,68 @@
|
||||
import type { Schema, SchemaDocument, SchemaObject, Anchors } from "./schema";
|
||||
import type { Vocabulary, Compile, Interpret, CollectEvaluatedProperties, CollectEvaluatedItems } from "./keywords";
|
||||
|
||||
|
||||
export type Core = {
|
||||
validate: (
|
||||
(schema: SchemaDocument, value: unknown, outputFormat?: OutputFormat) => Promise<Result>
|
||||
) & (
|
||||
(schema: SchemaDocument) => Promise<Validator>
|
||||
);
|
||||
compile: (schema: SchemaDocument<SchemaObject>) => Promise<CompiledSchema>;
|
||||
interpret: (
|
||||
(compiledSchema: CompiledSchema, value: unknown, outputFormat?: OutputFormat) => Result
|
||||
) & (
|
||||
(compiledSchema: CompiledSchema) => Validator
|
||||
);
|
||||
setMetaOutputFormat: (format: OutputFormat) => void;
|
||||
setShouldMetaValidate: (isEnabled: boolean) => void;
|
||||
FLAG: "FLAG";
|
||||
BASIC: "BASIC";
|
||||
DETAILED: "DETAILED";
|
||||
VERBOSE: "VERBOSE";
|
||||
add: Schema["add"];
|
||||
getKeyword: <A>(id: string) => {
|
||||
compile: Compile<A>;
|
||||
interpret: Interpret<A>;
|
||||
collectEvaluatedProperties: CollectEvaluatedProperties<A>;
|
||||
collectEvaluatedItems: CollectEvaluatedItems<A>;
|
||||
};
|
||||
hasKeyword: (id: string) => boolean;
|
||||
defineVocabulary: (id: string, keywords: Vocabulary) => void;
|
||||
compileSchema: Compile<string>;
|
||||
interpretSchema: Interpret<string>;
|
||||
collectEvaluatedProperties: CollectEvaluatedProperties<string>;
|
||||
collectEvaluatedItems: CollectEvaluatedItems<string>;
|
||||
};
|
||||
|
||||
export type Validator = (value: unknown, outputFormat?: OutputFormat) => Result;
|
||||
|
||||
export type OutputFormat = "FLAG" | "BASIC" | "DETAILED" | "VERBOSE" | string;
|
||||
|
||||
export type CompiledSchema = {
|
||||
schemaUri: string;
|
||||
ast: AST;
|
||||
};
|
||||
|
||||
export type AST = {
|
||||
metaData: Record<string, MetaData>;
|
||||
} & Record<string, Node<Node<unknown>[] | boolean>>;
|
||||
|
||||
export type Node<A> = [keywordId: string, schemaUri: string, keywordValue: A];
|
||||
|
||||
export type MetaData = {
|
||||
id: string;
|
||||
dynamicAnchors: Anchors;
|
||||
anchors: Anchors;
|
||||
};
|
||||
|
||||
export type Result = {
|
||||
keyword: string;
|
||||
absoluteKeywordLocation: string;
|
||||
instanceLocation: string;
|
||||
valid: boolean;
|
||||
errors?: Result[];
|
||||
};
|
||||
|
||||
declare const core: Core;
|
||||
export default core;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user