@stryke/json
Version:
A package containing JSON parsing/stringify utilities used by Storm Software.
67 lines (65 loc) • 2.26 kB
JavaScript
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
let _stryke_type_checks_is_set_object = require("@stryke/type-checks/is-set-object");
let _stryke_type_checks_is_string = require("@stryke/type-checks/is-string");
//#region src/pointer/find-reference.ts
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 val - Document to search in.
* @param path - JSON Pointer path.
* @returns Reference to the target.
*/
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 ((0, _stryke_type_checks_is_string.isString)(key)) {
const key2 = Math.trunc(Number.parseInt(key));
if (String(key2) !== key) throw new Error("INVALID_INDEX");
key = key2;
if (key < 0) throw new Error("INVALID_INDEX");
}
if (key) val = obj[key];
} else if ((0, _stryke_type_checks_is_set_object.isSetObject)(obj)) val = key && key in obj ? obj[key] : void 0;
else throw new Error("NOT_FOUND");
}
return {
val,
obj,
key
};
};
const isArrayReference = (ref) => isArray(ref.obj) && typeof ref.key === "number";
const isArrayEnd = (ref) => ref.obj.length === ref.key;
const isObjectReference = (ref) => typeof ref.obj === "object" && typeof ref.key === "string";
//#endregion
exports.find = find;
exports.isArrayEnd = isArrayEnd;
exports.isArrayReference = isArrayReference;
exports.isObjectReference = isObjectReference;