/** * A depopulate copy operation consumed by {@link copyAndDepopulate}. */ interface ProcessCopy { /** * Dotted source path on `docObject` whose populated value should be * relocated to {@link ProcessCopy.dest}. {@link copyAndDepopulate} walks * intermediate segments and, at the leaf, copies the original objects to * {@link ProcessCopy.dest} and replaces the leaf with the `idField` * value(s) of those objects. * * Examples: * `src: 'items'` -> depopulate `docObject.items` * `src: 'pear.items'` -> depopulate `docObject.pear.items` * * Empty strings are treated as safe no-ops. Unsafe segments * (`__proto__`, `prototype`, `constructor`) throw a descriptive `Error`. */ src: string; /** * Dotted destination path on `docObject` where the moved objects will be * written. Unsafe segments (`__proto__`, `prototype`, `constructor`) * throw a descriptive `Error`. Empty and missing destinations are safe * no-ops. */ dest: string; } /** * Options for {@link copyAndDepopulate}. */ interface CopyAndDepopulateOptions { /** * When `true` (default), `docObject` is mutated in place and returned. * When `false`, a deep clone is produced via `cloneDeep` and the input is * left untouched. Both modes produce value-identical output; only object * identity differs. */ mutable?: boolean; /** * Identifier field pulled from each relocated record to replace the * original populated value. Defaults to `'_id'`. * * For nested populated arrays, every leaf record must carry this field. * Records missing the id field throw a descriptive `Error`. * Primitive array members (non-record scalars) cannot be depopulated and * are left in place as a safe no-op. */ idField?: string; } /** * A path copy operation consumed by {@link copyPaths} and the `COPY` task. * Reuses the same `{ src, dest }` shape as {@link ProcessCopy}. */ type ProcessPathCopy = ProcessCopy; /** * A path move operation consumed by {@link movePaths} and the `MOVE` task. * Reuses the same `{ src, dest }` shape as {@link ProcessCopy}. */ type ProcessPathMove = ProcessCopy; /** * A slice operation consumed by {@link sliceArrays} and the `SLICE` task. */ interface ProcessSlice { /** * Dotted source path of the array to slice. Intermediate segments fan out * across arrays like {@link copyAndDepopulate}. Missing, null, or * non-array leaves are safe no-ops. */ src: string; /** * Dotted destination path (relative to the leaf parent) where the sliced * window is written. When omitted, the slice is applied in place at `src`. * Empty-string destinations are safe no-ops. */ dest?: string; /** * Number of leading array members to skip. Defaults to `0`. Must be a * non-negative safe integer when present. */ skip?: number; /** * Maximum number of array members to keep from `skip`. When omitted, the * tail from `skip` to the end is kept. When present it is clamped to * `maxSlice` (default `1000`). Must be a non-negative safe integer. */ limit?: number; } /** * A count operation consumed by {@link countPaths} and the `COUNT` task. */ interface ProcessCount { /** * Dotted source path whose size is measured. Arrays measure length, plain * objects measure key count, present scalars count as `1`, and * null/undefined leaves count as `0`. Missing leaves are safe no-ops. */ src: string; /** * Dotted destination path (relative to the leaf parent) where the numeric * count is written. Empty destinations are safe no-ops. */ dest: string; } /** * A mask operation consumed by {@link maskPaths} and the `MASK` task. */ interface ProcessMask { /** * Dotted source path to redact. Each resolved leaf present on its parent * is replaced with `replacement`. Missing leaves are safe no-ops. */ src: string; /** * Replacement value written at `src`. Defaults to `'***'` when the key is * absent. An explicitly provided value (including `null`) is used as-is. */ replacement?: unknown; } /** * Shared mutable/clone option for path processors. */ interface ProcessorOptions { /** * When `true` (default), `docObject` is mutated in place and returned. * When `false`, a deep clone is produced via `cloneDeep` and the input is * left untouched. */ mutable?: boolean; } /** * Options for {@link sliceArrays}. */ interface SliceProcessorOptions extends ProcessorOptions { /** * Upper bound applied to a client-requested `limit`. Defaults to `1000`, * matching the `listHardLimit` default. Must be a non-negative safe * integer when present. */ maxSlice?: number; } /** * Conservative default output for {@link copyAndDepopulate}. * * The exact transformed shape depends on runtime path strings, so the default * type intentionally does not claim that populated input leaves still have * their original object shape. Provide an explicit output type argument when * the operation set is known by the caller. */ type CopyAndDepopulateOutput = Record; /** * Hardened processor that relocates populated documents to a destination * path and replaces the original location with their proposed * "depopulated" form: a single id for plain-object values, or an array of * ids for populated arrays. * * Key semantics: * - Operations run sequentially in the order supplied. Each operation * sees the state produced by the previous one. Two operations that * reference the same `src` therefore intentionally chain - the second * operation will find the id value/type left by the first and treat it * as a safe no-op if it can no longer be depopulated (e.g. it is now an * array of primitive ids rather than records). * - Missing, null, or scalar intermediate segments in `src` are safe * no-ops: nothing is copied, nothing is replaced, and no error is * thrown. The object identity of intermediates is unchanged. * - An array leaf whose members are all plain records is depopulated to * an array of ids. Records missing the id field throw a descriptive * error; primitive/scalar array members prevent depopulation and the * leaf is left in place as a safe no-op. * - A plain-object leaf is depopulated to a single id value; a missing id * field throws a descriptive error. * - `__proto__`, `prototype`, and `constructor` segments in either `src` * or `dest` throw a descriptive error. No operation can mutate * `Object.prototype` or any object's prototype. * - Empty `src` or `dest` strings are safe no-ops. * * @typeParam Output - Object shape produced by the depopulation. Defaults to a * conservative record because `src` and `dest` are runtime paths. * * @throws Error when an operation path contains `__proto__`, `prototype`, or * `constructor`, or when a populated record is missing the configured id field. */ declare const copyAndDepopulate: (docObject: object, operations: ProcessCopy[], options?: CopyAndDepopulateOptions) => Output; /** * Conservative default output for path processors. */ type ProcessorOutput = Record; /** * Copy the value at `src` to `dest` without modifying `src`. * * Semantics mirror {@link copyAndDepopulate} traversal: intermediate segments * fan out across arrays, missing/null/scalar intermediates are safe no-ops, * and unsafe (`__proto__`, `prototype`, `constructor`) or empty paths are * handled the same way. The copied value is deep-cloned so later tasks in * the chain cannot alias `src` through `dest`. Copying a path onto itself * is a safe no-op. * * @throws Error when a path contains an unsafe segment. */ declare const copyPaths: (docObject: object, operations: ProcessCopy[], options?: ProcessorOptions) => Output; /** * Move the value at `src` to `dest` and delete `src`. * * Traversal and safety semantics match {@link copyPaths}. Moving a path onto * itself is a safe no-op. A `dest` nested under the moved leaf (for example * `src: 'a'`, `dest: 'a.b'`) copies without deleting `src` so the freshly * written destination is not removed. * * @throws Error when a path contains an unsafe segment. */ declare const movePaths: (docObject: object, operations: ProcessCopy[], options?: ProcessorOptions) => Output; /** * Slice the array at `src` to `[skip, skip + limit)` and write the window to * `dest` (default: in place at `src`). * * Missing, null, or non-array leaves are safe no-ops. `skip` defaults to `0`; * an omitted `limit` keeps the tail from `skip`. A present `limit` is clamped * to `maxSlice` (default `1000`) so client-requested windows stay bounded. * * @throws Error when a path contains an unsafe segment or when * `skip`/`limit`/`maxSlice` is not a non-negative safe integer. */ declare const sliceArrays: (docObject: object, operations: ProcessSlice[], options?: SliceProcessorOptions) => Output; /** * Write the size of `src` to `dest`: array length, plain-object key count, * `0` for null/undefined leaves, and `1` for other present scalars. * * Missing leaves are safe no-ops (no destination is created). * * @throws Error when a path contains an unsafe segment. */ declare const countPaths: (docObject: object, operations: ProcessCount[], options?: ProcessorOptions) => Output; /** * Replace the value at `src` with `replacement` (default `'***'`). * * Only existing leaves are redacted; missing paths are safe no-ops and no * new keys are created. Intermediate segments fan out across arrays like * {@link copyAndDepopulate}. * * @throws Error when a path contains an unsafe segment. */ declare const maskPaths: (docObject: object, operations: ProcessMask[], options?: ProcessorOptions) => Output; export { type CopyAndDepopulateOptions, type CopyAndDepopulateOutput, type ProcessCopy, type ProcessCount, type ProcessMask, type ProcessPathCopy, type ProcessPathMove, type ProcessSlice, type ProcessorOptions, type ProcessorOutput, type SliceProcessorOptions, copyAndDepopulate, copyPaths, countPaths, maskPaths, movePaths, sliceArrays };