@sinclair/typebox
Version:
Json Schema Type Builder with Static Type Resolution for TypeScript
127 lines (125 loc) • 4 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.ValuePointerRootDeleteError = exports.ValuePointerRootSetError = void 0;
exports.Format = Format;
exports.Set = Set;
exports.Delete = Delete;
exports.Has = Has;
exports.Get = Get;
const index_1 = require("../../type/error/index");
// ------------------------------------------------------------------
// Errors
// ------------------------------------------------------------------
class ValuePointerRootSetError extends index_1.TypeBoxError {
constructor(value, path, update) {
super('Cannot set root value');
this.value = value;
this.path = path;
this.update = update;
}
}
exports.ValuePointerRootSetError = ValuePointerRootSetError;
class ValuePointerRootDeleteError extends index_1.TypeBoxError {
constructor(value, path) {
super('Cannot delete root value');
this.value = value;
this.path = path;
}
}
exports.ValuePointerRootDeleteError = ValuePointerRootDeleteError;
// ------------------------------------------------------------------
// ValuePointer
// ------------------------------------------------------------------
/** Provides functionality to update values through RFC6901 string pointers */
// prettier-ignore
function Escape(component) {
return component.indexOf('~') === -1 ? component : component.replace(/~1/g, '/').replace(/~0/g, '~');
}
/** Formats the given pointer into navigable key components */
// prettier-ignore
function* Format(pointer) {
if (pointer === '')
return;
let [start, end] = [0, 0];
for (let i = 0; i < pointer.length; i++) {
const char = pointer.charAt(i);
if (char === '/') {
if (i === 0) {
start = i + 1;
}
else {
end = i;
yield Escape(pointer.slice(start, end));
start = i + 1;
}
}
else {
end = i;
}
}
yield Escape(pointer.slice(start));
}
/** Sets the value at the given pointer. If the value at the pointer does not exist it is created */
// prettier-ignore
function Set(value, pointer, update) {
if (pointer === '')
throw new ValuePointerRootSetError(value, pointer, update);
let [owner, next, key] = [null, value, ''];
for (const component of Format(pointer)) {
if (next[component] === undefined)
next[component] = {};
owner = next;
next = next[component];
key = component;
}
owner[key] = update;
}
/** Deletes a value at the given pointer */
// prettier-ignore
function Delete(value, pointer) {
if (pointer === '')
throw new ValuePointerRootDeleteError(value, pointer);
let [owner, next, key] = [null, value, ''];
for (const component of Format(pointer)) {
if (next[component] === undefined || next[component] === null)
return;
owner = next;
next = next[component];
key = component;
}
if (Array.isArray(owner)) {
const index = parseInt(key);
owner.splice(index, 1);
}
else {
delete owner[key];
}
}
/** Returns true if a value exists at the given pointer */
// prettier-ignore
function Has(value, pointer) {
if (pointer === '')
return true;
let [owner, next, key] = [null, value, ''];
for (const component of Format(pointer)) {
if (next[component] === undefined)
return false;
owner = next;
next = next[component];
key = component;
}
return Object.getOwnPropertyNames(owner).includes(key);
}
/** Gets the value at the given pointer */
// prettier-ignore
function Get(value, pointer) {
if (pointer === '')
return value;
let current = value;
for (const component of Format(pointer)) {
if (current[component] === undefined)
return undefined;
current = current[component];
}
return current;
}
;