72 lines
2.5 KiB
JavaScript
72 lines
2.5 KiB
JavaScript
"use strict";
|
|
/* tslint:disable no-string-throw */
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.isObjectReference = exports.isArrayEnd = exports.isArrayReference = exports.find = void 0;
|
|
const hasOwnProperty_1 = require("@jsonjoy.com/util/lib/hasOwnProperty");
|
|
const { isArray } = Array;
|
|
/**
|
|
* Finds a target in document specified by JSON Pointer. Also returns the
|
|
* object containing the target and key used to reference that object.
|
|
*
|
|
* Throws Error('NOT_FOUND') if pointer does not result into a value in the middle
|
|
* of the path. If the last element of the path does not result into a value, the
|
|
* lookup succeeds with `val` set to `undefined`. It can be used to discriminate
|
|
* missing values, because `undefined` is not a valid JSON value.
|
|
*
|
|
* If last element in array is targeted using "-", e.g. "/arr/-", use
|
|
* `isArrayEnd` to verify that:
|
|
*
|
|
* ```js
|
|
* const ref = find({arr: [1, 2, 3], ['arr', '-']});
|
|
* if (isArrayReference(ref)) {
|
|
* if (isArrayEnd(ref)) {
|
|
* // ...
|
|
* }
|
|
* }
|
|
* ```
|
|
*
|
|
* @param skipLast Number of steps to skip at the end. Useful to find reference of
|
|
* parent step, without constructing a new `Path` array.
|
|
*/
|
|
const find = (val, path) => {
|
|
const pathLength = path.length;
|
|
if (!pathLength)
|
|
return { val };
|
|
let obj;
|
|
let key;
|
|
for (let i = 0; i < pathLength; i++) {
|
|
obj = val;
|
|
key = path[i];
|
|
if (isArray(obj)) {
|
|
const length = obj.length;
|
|
if (key === '-')
|
|
key = length;
|
|
else {
|
|
if (typeof key === 'string') {
|
|
const key2 = ~~key;
|
|
if ('' + key2 !== key)
|
|
throw new Error('INVALID_INDEX');
|
|
key = key2;
|
|
if (key < 0)
|
|
throw new Error('INVALID_INDEX');
|
|
}
|
|
}
|
|
val = obj[key];
|
|
}
|
|
else if (typeof obj === 'object' && !!obj) {
|
|
val = (0, hasOwnProperty_1.hasOwnProperty)(obj, key) ? obj[key] : undefined;
|
|
}
|
|
else
|
|
throw new Error('NOT_FOUND');
|
|
}
|
|
const ref = { val, obj, key };
|
|
return ref;
|
|
};
|
|
exports.find = find;
|
|
const isArrayReference = (ref) => isArray(ref.obj) && typeof ref.key === 'number';
|
|
exports.isArrayReference = isArrayReference;
|
|
const isArrayEnd = (ref) => ref.obj.length === ref.key;
|
|
exports.isArrayEnd = isArrayEnd;
|
|
const isObjectReference = (ref) => typeof ref.obj === 'object' && typeof ref.key === 'string';
|
|
exports.isObjectReference = isObjectReference;
|