UNPKG

@elsikora/nestjs-crud-automator

Version:

A library for automating the creation of CRUD operations in NestJS.

166 lines (162 loc) 5.49 kB
'use strict'; var node_buffer = require('node:buffer'); /** * Owns the generated-route authorization decision used after guard execution. * Subscriber-facing decisions are detached views and can never mutate this snapshot. */ class ApiControllerGeneratedSecuritySnapshot { static create(decision) { return decision ? freezeValue(cloneValue(decision)) : undefined; } static createMutableScopeWhere(snapshot) { return cloneValue(snapshot?.scope?.where); } static createSubscriberView(snapshot, resource) { if (!snapshot) { return undefined; } const view = cloneValue(snapshot); if (resource !== undefined) { view.resource = resource; } return view; } static detach(value) { return cloneValue(value); } static withResource(snapshot, resource) { if (!snapshot || resource === undefined) { return snapshot; } return Object.freeze({ ...snapshot, resource, }); } } /** * Clones a security graph through own descriptors so no mutable container aliases its source. * Function values are intentionally retained as executable identities; their containers are detached. * @template T - Value type. * @param {T} value - Value to clone. * @returns {T} Detached clone. */ function cloneValue(value) { return cloneValueWithReferences(value, new WeakMap()); } /** * Clones one value while preserving cycles within the detached graph. * @template T - Value type. * @param {T} value - Current value. * @param {WeakMap<object, object>} references - Source-to-clone references. * @returns {T} Detached value. */ function cloneValueWithReferences(value, references) { if (value === null || typeof value !== "object") { return value; } const source = value; const existing = references.get(source); if (existing) { return existing; } if (value instanceof Date) { return new Date(value); } if (value instanceof RegExp) { return new RegExp(value.source, value.flags); } if (node_buffer.Buffer.isBuffer(value)) { return node_buffer.Buffer.from(value); } if (value instanceof ArrayBuffer || ArrayBuffer.isView(value)) { return structuredClone(value); } if (value instanceof Map) { const clone = new Map(); references.set(source, clone); for (const [key, item] of value) { clone.set(cloneValueWithReferences(key, references), cloneValueWithReferences(item, references)); } return clone; } if (value instanceof Set) { const clone = new Set(); references.set(source, clone); for (const item of value) { clone.add(cloneValueWithReferences(item, references)); } return clone; } const clone = Array.isArray(value) ? [] : Object.create(Object.getPrototypeOf(value)); references.set(source, clone); for (const key of Reflect.ownKeys(source)) { if (Array.isArray(value) && key === "length") { continue; } const descriptor = Object.getOwnPropertyDescriptor(source, key); if (!descriptor) { continue; } Object.defineProperty(clone, key, { ...descriptor, // Subscriber views must remain independently mutable even when cloned from a frozen canonical snapshot. // eslint-disable-next-line @elsikora/typescript/naming-convention configurable: true, ...("value" in descriptor ? { value: cloneValueWithReferences(descriptor.value, references), // eslint-disable-next-line @elsikora/typescript/naming-convention writable: true, } : {}), }); } return clone; } /** * Recursively freezes detached security containers without mutating executable function identities. * @template T - Value type. * @param {T} value - Detached value. * @returns {T} Deeply frozen value. */ function freezeValue(value) { freezeValueWithReferences(value, new WeakSet()); return value; } /** * Freezes one detached value while preserving cyclic graphs. * @param {unknown} value - Current value. * @param {WeakSet<object>} references - Already visited objects. * @returns {void} */ function freezeValueWithReferences(value, references) { if (!value || typeof value !== "object" || references.has(value)) { return; } references.add(value); if (value instanceof Map) { for (const [key, item] of value) { freezeValueWithReferences(key, references); freezeValueWithReferences(item, references); } } else if (value instanceof Set) { for (const item of value) { freezeValueWithReferences(item, references); } } else { for (const key of Reflect.ownKeys(value)) { const descriptor = Object.getOwnPropertyDescriptor(value, key); if (descriptor && "value" in descriptor) { freezeValueWithReferences(descriptor.value, references); } } } if (!ArrayBuffer.isView(value)) { Object.freeze(value); } } exports.ApiControllerGeneratedSecuritySnapshot = ApiControllerGeneratedSecuritySnapshot; //# sourceMappingURL=security-snapshot.class.js.map