@sdux-vault/shared 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1256 @@
1
+ import { BehaviorSubject, Subscription, tap } from 'rxjs';
2
+
3
+ // --- AI Model File Path (DO NOT DELETE) ---
4
+ // FilePath: libs > shared > src > typings > global.d.ts
5
+ // Updated: 2026-03-24 12:38
6
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
7
+ // cmd+alt+j (see .vscode/keybindings.json)
8
+ // --- END AI MODEL FILE PATH ---
9
+
10
+ // --- AI Model File Path (DO NOT DELETE) ---
11
+ // FilePath: libs > shared > src > lib > utils > dev-mode > testing-environment.util.ts
12
+ // Updated: 2026-03-09 14:47
13
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
14
+ // cmd+alt+j (see .vscode/keybindings.json)
15
+ // --- END AI MODEL FILE PATH ---
16
+ const isTestEnv = {
17
+ get active() {
18
+ return (
19
+ // eslint-disable-next-line
20
+ typeof globalThis.jasmine !== 'undefined' ||
21
+ // istanbul ignore next
22
+ // eslint-disable-next-line
23
+ typeof globalThis.jest !== 'undefined' ||
24
+ // istanbul ignore next
25
+ // eslint-disable-next-line
26
+ typeof globalThis.vitest !== 'undefined');
27
+ }
28
+ };
29
+
30
+ // --- AI Model File Path (DO NOT DELETE) ---
31
+ // FilePath: libs > shared > src > lib > utils > dev-mode > dev-mode.util.ts
32
+ // Updated: 2026-03-09 14:46
33
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
34
+ // cmd+alt+j (see .vscode/keybindings.json)
35
+ // --- END AI MODEL FILE PATH ---
36
+ let devMode = null;
37
+ const DevMode = {
38
+ get active() {
39
+ return devMode === true;
40
+ },
41
+ setDevMode(isDevMode) {
42
+ if (devMode !== null && !isTestEnv.active) {
43
+ throw new Error('[vault] DevMode has already been initialized.');
44
+ }
45
+ devMode = isDevMode;
46
+ }
47
+ };
48
+
49
+ // --- AI Model File Path (DO NOT DELETE) ---
50
+ // FilePath: libs > shared > src > lib > utils > version > version.register.ts
51
+ // Updated: 2026-03-03 07:47
52
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
53
+ // cmd+alt+j (see .vscode/keybindings.json)
54
+ // --- END AI MODEL FILE PATH ---
55
+ const registerVersion = (packageName, version) => {
56
+ if (!DevMode.active || typeof globalThis === 'undefined')
57
+ return;
58
+ const sdux = (globalThis.sdux ??= {});
59
+ const debug = (sdux.debugWidget ??= {});
60
+ const versions = (debug.versions ??= {});
61
+ if (versions[packageName] === version)
62
+ return;
63
+ versions[packageName] = version;
64
+ };
65
+
66
+ // --- AI Model File Path (DO NOT DELETE) ---
67
+ // FilePath: libs > shared > src > lib > version > version.register.ts
68
+ // Updated: 2026-03-03 08:12
69
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
70
+ // cmd+alt+j (see .vscode/keybindings.json)
71
+ // --- END AI MODEL FILE PATH ---
72
+ const SDUX_PACKAGE = '@sdux-vault/shared';
73
+ const SDUX_VERSION = '0.0.10';
74
+ registerVersion(SDUX_PACKAGE, SDUX_VERSION);
75
+
76
+ /**
77
+ * Runtime-safe registry of all behavior types.
78
+ *
79
+ * This object acts as an enum substitute without introducing JavaScript enum
80
+ * overhead.
81
+ * Values are string literals preserved at runtime and suitable for
82
+ * switch statements, comparisons, and pipeline classification.
83
+ * Each key maps 1:1 to its string literal value.
84
+ * The structure is fully tree-shakable and safely inferable by TypeScript.
85
+ */
86
+ const BehaviorTypes = {
87
+ CoreAfterTap: 'coreAfterTap',
88
+ CoreBeforeTap: 'coreBeforeTap',
89
+ ReplayGlobalError: 'replayGlobalError',
90
+ CoreError: 'coreError',
91
+ CoreErrorCallback: 'coreErrorCallback',
92
+ CoreState: 'coreState',
93
+ DevPipelineObserver: 'devPipelineObserver',
94
+ Encrypt: 'encrypt',
95
+ CoreEmitState: 'coreEmitState',
96
+ ErrorTransform: 'errorTransform',
97
+ Extension: 'extension',
98
+ Filter: 'filter',
99
+ FromObservable: 'fromObservable',
100
+ FromPromise: 'fromPromise',
101
+ FromStream: 'fromStream',
102
+ Interceptor: 'interceptor',
103
+ Merge: 'merge',
104
+ Operator: 'operator',
105
+ Persist: 'persist',
106
+ Reduce: 'reduce',
107
+ Resolve: 'resolve',
108
+ StepwiseFilter: 'stepwiseFilter',
109
+ StepwiseReducer: 'stepwiseReducer',
110
+ StepwiseResolve: 'stepwiseResolve'
111
+ };
112
+
113
+ // --- AI Model File Path (DO NOT DELETE) ---
114
+ // FilePath: libs > shared > src > lib > types > logging > console.type.ts
115
+ // Updated: 2026-03-21 21:00
116
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
117
+ // cmd+alt+j (see .vscode/keybindings.json)
118
+ // --- END AI MODEL FILE PATH ---
119
+ /**
120
+ * Defines the allowable verbosity levels for Vault logging.
121
+ *
122
+ * A `LogLevel` controls the amount of diagnostic output emitted by the
123
+ * vault’s internal debug, warning, or error channels. Higher levels
124
+ * produce more detailed logs, while lower levels suppress output.
125
+ *
126
+ * - `'off'` — no logs are emitted
127
+ * - `'error'` — only errors are logged
128
+ * - `'warn'` — warnings and errors are logged
129
+ * - `'log'` — standard log events, warnings, and errors are logged
130
+ * - `'debug'` — all debug-level information is emitted
131
+ */
132
+ const ConsoleTypes = {
133
+ Error: 'error',
134
+ Warn: 'warn',
135
+ Log: 'log',
136
+ Debug: 'debug'
137
+ };
138
+
139
+ // --- AI Model File Path (DO NOT DELETE) ---
140
+ // FilePath: libs > shared > src > lib > types > logging > log-level.type.ts
141
+ // Updated: 2026-03-21 21:00
142
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
143
+ // cmd+alt+j (see .vscode/keybindings.json)
144
+ // --- END AI MODEL FILE PATH ---
145
+ /**
146
+ * Defines the allowable verbosity levels for Vault logging.
147
+ *
148
+ * A `LogLevel` controls the amount of diagnostic output emitted by the
149
+ * vault’s internal debug, warning, or error channels. Higher levels
150
+ * produce more detailed logs, while lower levels suppress output.
151
+ *
152
+ * - `'off'` — no logs are emitted
153
+ * - `'error'` — only errors are logged
154
+ * - `'warn'` — warnings and errors are logged
155
+ * - `'log'` — standard log events, warnings, and errors are logged
156
+ * - `'debug'` — all debug-level information is emitted
157
+ */
158
+ const LogLevelTypes = {
159
+ Off: 'off',
160
+ Error: 'error',
161
+ Warn: 'warn',
162
+ Log: 'log',
163
+ Debug: 'debug'
164
+ };
165
+
166
+ // --- AI Model File Path (DO NOT DELETE) ---
167
+ // FilePath: libs > shared > src > lib > utils > logger > logger.util.ts
168
+ // Updated: 2026-03-23 16:50
169
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
170
+ // cmd+alt+j (see .vscode/keybindings.json)
171
+ // --- END AI MODEL FILE PATH ---
172
+ let _logLevel = LogLevelTypes.Off;
173
+ /**
174
+ * Prefix applied to all vault-related console output. Used to keep log
175
+ * messages consistently identifiable across all log levels.
176
+ */
177
+ const LOG_PREFIX = '[vault]';
178
+ // eslint-disable-next-line
179
+ function push(level, ...args) {
180
+ const logLevel = getVaultLogLevel();
181
+ if (logLevel === LogLevelTypes.Off)
182
+ return;
183
+ const levels = [ConsoleTypes.Error, ConsoleTypes.Warn, ConsoleTypes.Log, ConsoleTypes.Debug];
184
+ const allowed = levels.indexOf(level) <= levels.indexOf(logLevel);
185
+ if (!allowed)
186
+ return;
187
+ // eslint-disable-next-line
188
+ console[level](LOG_PREFIX, ...args);
189
+ }
190
+ /**
191
+ * Emits an `error`-level Vault log message.
192
+ *
193
+ * @param args - Console arguments to log.
194
+ */
195
+ // eslint-disable-next-line
196
+ const vaultError = (...args) => push('error', ...args);
197
+ /**
198
+ * Emits a `warn`-level Vault log message.
199
+ *
200
+ * @param args - Console arguments to log.
201
+ */
202
+ // eslint-disable-next-line
203
+ const vaultWarn = (...args) => push('warn', ...args);
204
+ /**
205
+ * Emits a `log`-level Vault log message.
206
+ *
207
+ * @param args - Console arguments to log.
208
+ */
209
+ // eslint-disable-next-line
210
+ const vaultLog = (...args) => push('log', ...args);
211
+ /**
212
+ * Emits a `debug`-level Vault log message.
213
+ *
214
+ * @param args - Console arguments to log.
215
+ */
216
+ // eslint-disable-next-line
217
+ const vaultDebug = (...args) => push('debug', ...args);
218
+ function setVaultLogLevel(level) {
219
+ _logLevel = level ?? 'off';
220
+ }
221
+ function getVaultLogLevel() {
222
+ return _logLevel;
223
+ }
224
+
225
+ class AbstractErrorCallbackBehavior {
226
+ behaviorCtx;
227
+ /** Indicates that this error behavior is critical and always executed. */
228
+ critical;
229
+ /** Unique identifier for this behavior instance. */
230
+ key;
231
+ /** Behavior type for orchestrator registration. */
232
+ type = BehaviorTypes.CoreErrorCallback;
233
+ /**
234
+ * Creates a new abstract error behavior instance.
235
+ *
236
+ * @param key - Unique behavior identifier supplied by the behavior factory.
237
+ * @param behaviorCtx - Behavior class context providing injector access and extensibility hooks.
238
+ */
239
+ constructor(key, behaviorCtx) {
240
+ this.behaviorCtx = behaviorCtx;
241
+ this.key = key;
242
+ }
243
+ /**
244
+ * Lifecycle hook invoked when the behavior instance is destroyed.
245
+ *
246
+ * Error behaviors do not allocate runtime resources and therefore require
247
+ * no cleanup. A diagnostic entry is logged for lifecycle visibility.
248
+ */
249
+ destroy() {
250
+ vaultWarn(`${this.key} - destroy "noop"`);
251
+ }
252
+ /**
253
+ * Lifecycle hook invoked when the behavior instance is reset.
254
+ *
255
+ * Error behaviors hold no internal state, making this a no-operation.
256
+ * The hook ensures lifecycle uniformity across all behaviors.
257
+ */
258
+ reset() {
259
+ vaultWarn(`${this.key} - reset "noop"`);
260
+ }
261
+ }
262
+
263
+ /**
264
+ * Abstract base behavior for transforming errors during pipeline execution.
265
+ * This class defines the contract and lifecycle hooks required for error transformation behaviors.
266
+ *
267
+ * --RelatedStart--
268
+ * ErrorTransformBehaviorContract
269
+ * BehaviorClassContext
270
+ * StateSnapshotShape
271
+ * VaultErrorShape
272
+ * --RelatedEnd--
273
+ */
274
+ class AbstractErrorTransformBehavior {
275
+ behaviorCtx;
276
+ /**
277
+ * Indicates that this error transform behavior is critical and always executed.
278
+ */
279
+ critical;
280
+ /**
281
+ * Unique identifier for this behavior instance.
282
+ */
283
+ key;
284
+ /**
285
+ * Behavior type identifier used for orchestrator registration.
286
+ */
287
+ type = BehaviorTypes.ErrorTransform;
288
+ /**
289
+ * Creates a new abstract error transform behavior instance.
290
+ *
291
+ * @param key Unique behavior identifier supplied by the factory.
292
+ * @param behaviorCtx Behavior class context providing configuration and hooks.
293
+ */
294
+ constructor(key, behaviorCtx) {
295
+ this.behaviorCtx = behaviorCtx;
296
+ this.key = key;
297
+ }
298
+ /**
299
+ * Lifecycle hook invoked when the behavior instance is destroyed.
300
+ */
301
+ destroy() {
302
+ vaultWarn(`${this.key} - destroy "noop"`);
303
+ }
304
+ /**
305
+ * Lifecycle hook invoked when the behavior instance is reset.
306
+ */
307
+ reset() {
308
+ vaultWarn(`${this.key} - reset "noop"`);
309
+ }
310
+ }
311
+
312
+ /**
313
+ * Safely converts an arbitrary value into a JSON string representation.
314
+ *
315
+ * This function wraps `JSON.stringify` with enhanced handling for non-serializable
316
+ * values, including:
317
+ * - functions
318
+ * - `Error` objects
319
+ * - `Map` and `Set` instances
320
+ * - circular references
321
+ *
322
+ * If serialization fails for any reason, a fallback string `"[unserializable]"`
323
+ * is returned. The replacer ensures stable and predictable stringification for
324
+ * use in logging and debugging utilities.
325
+ *
326
+ * @param value - The value to stringify safely.
327
+ * @returns A JSON-formatted string or a fallback indicator.
328
+ */
329
+ function safeStringify(value) {
330
+ try {
331
+ return JSON.stringify(value, jsonSafeReplacer, 2);
332
+ }
333
+ catch {
334
+ return '[unserializable]';
335
+ }
336
+ }
337
+ /**
338
+ * Replacer function used by `safeStringify` to handle values that are normally
339
+ * not serializable via `JSON.stringify`.
340
+ *
341
+ * It converts functions, errors, `Map`, and `Set` values into safe structures
342
+ * and detects circular references. If a value cannot be serialized, a fallback
343
+ * marker string is returned.
344
+ *
345
+ * @param _key - The property key being processed (unused).
346
+ * @param val - The value associated with the key.
347
+ * @returns A serializable representation of the value.
348
+ */
349
+ function jsonSafeReplacer(_key, val) {
350
+ if (typeof val === 'function')
351
+ return '[Function]';
352
+ if (val instanceof Error)
353
+ return { message: val.message, stack: val.stack };
354
+ if (val instanceof Map)
355
+ return { map: Array.from(val.entries()) };
356
+ if (val instanceof Set)
357
+ return { set: Array.from(val.values()) };
358
+ // Avoid circular references
359
+ try {
360
+ JSON.stringify(val);
361
+ return val;
362
+ }
363
+ catch {
364
+ return '[Circular]';
365
+ }
366
+ }
367
+
368
+ /** ------------------------------------------
369
+ * INTERNAL CLASS (NOT EXPORTED)
370
+ * ------------------------------------------ */
371
+ class VaultPrivateErrorClass {
372
+ #error$ = new BehaviorSubject(null);
373
+ constructor() {
374
+ vaultDebug('[VaultPrivateErrorService] initialized (singleton instance created)');
375
+ }
376
+ setError(error) {
377
+ vaultDebug(`[VaultPrivateErrorService] setError() ${safeStringify(error)}`);
378
+ this.#error$.next(error);
379
+ }
380
+ getError() {
381
+ vaultDebug('[VaultPrivateErrorService] getError() → observable subscribed');
382
+ return this.#error$.asObservable();
383
+ }
384
+ clear() {
385
+ vaultDebug('[VaultPrivateErrorService] clear() → error reset to null');
386
+ this.#error$.next(null);
387
+ }
388
+ }
389
+ /** ------------------------------------------
390
+ * SINGLETON FACTORY (EXPORTED)
391
+ * ------------------------------------------ */
392
+ let _instance$1 = null;
393
+ function VaultPrivateErrorService() {
394
+ if (!_instance$1) {
395
+ vaultDebug('[VaultPrivateErrorService] creating new singleton instance');
396
+ _instance$1 = new VaultPrivateErrorClass();
397
+ }
398
+ else {
399
+ vaultDebug('[VaultPrivateErrorService] returning existing singleton instance');
400
+ }
401
+ return _instance$1;
402
+ }
403
+
404
+ class VaultErrorServiceClass {
405
+ #privateVaultErrorService = VaultPrivateErrorService();
406
+ #error$ = new BehaviorSubject(null);
407
+ #hasErrorState = false;
408
+ /** Track internal subscription for cleanup */
409
+ #subscription = new Subscription();
410
+ /** Public observable error stream */
411
+ error$ = this.#error$.asObservable();
412
+ constructor() {
413
+ vaultDebug('[VaultErrorService] Initializing service and subscribing to private error stream.');
414
+ // Mirror the private error service into this one
415
+ const sub = this.#privateVaultErrorService.getError().subscribe((err) => {
416
+ vaultDebug(`[VaultErrorService] Received error update from private service: ${err ? err.message : 'null'}`);
417
+ this.#hasErrorState = !!err;
418
+ this.#error$.next(err);
419
+ });
420
+ this.#subscription.add(sub);
421
+ }
422
+ get hasError() {
423
+ return this.#hasErrorState;
424
+ }
425
+ clear() {
426
+ vaultDebug('[VaultErrorService] Clearing current error.');
427
+ this.#privateVaultErrorService.clear();
428
+ }
429
+ }
430
+ // --------------------------------
431
+ // SINGLETON FACTORY (EXPORTED)
432
+ // --------------------------------
433
+ let _instance = null;
434
+ function VaultErrorService() {
435
+ if (!_instance) {
436
+ vaultDebug('[VaultErrorService] Creating new singleton instance.');
437
+ _instance = new VaultErrorServiceClass();
438
+ }
439
+ return _instance;
440
+ }
441
+
442
+ class AbstractActiveController {
443
+ ctx;
444
+ key;
445
+ critical = false;
446
+ hasError = false;
447
+ traceId = null;
448
+ #subscription;
449
+ constructor(key, ctx) {
450
+ this.ctx = ctx;
451
+ this.key = key;
452
+ this.#subscription = VaultErrorService()
453
+ .error$.pipe(tap((error) => {
454
+ vaultDebug(`${this.key} VaultErrorService dispatched event. Raw event: ${safeStringify(error)}.`);
455
+ const newValue = error != null;
456
+ vaultDebug(`${this.key} New transformed error value: "${newValue}".`);
457
+ const revoteDecision = newValue !== this.hasError && this.traceId !== undefined;
458
+ vaultDebug(`${this.key} Revote Decision: ${revoteDecision}. Factors. NewValue: ${newValue} HasError: ${this.hasError} TraceId: ${this.traceId} Rubric: 'newValue !== this.hasError && this.traceId !== undefined'`);
459
+ this.hasError = newValue;
460
+ vaultDebug(`${this.key} this.hasError replace with newValue: "${this.hasError}".`);
461
+ vaultDebug(`${this.key} onExternalTrigger dispatchd with: "${newValue}".`);
462
+ this.onExternalTrigger(newValue);
463
+ if (revoteDecision) {
464
+ vaultDebug(`${this.key} Revote Requesed with traceId: "${this.traceId}".`);
465
+ this.ctx.requestRevote(this.traceId);
466
+ }
467
+ }))
468
+ .subscribe();
469
+ }
470
+ /** Child classes override to react to external error toggles */
471
+ //istanbul ignore next
472
+ onExternalTrigger(_newErrorState) { }
473
+ destroy() {
474
+ this.#subscription.unsubscribe();
475
+ vaultWarn(`${this.key} - destroy`);
476
+ }
477
+ reset() {
478
+ vaultWarn(`${this.key} - reset "noop"`);
479
+ }
480
+ }
481
+
482
+ // --- AI Model File Path (DO NOT DELETE) ---
483
+ // FilePath: libs > shared > src > lib > abstracts > index.ts
484
+ // Updated: 2026-03-23 17:27
485
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
486
+ // cmd+alt+j (see .vscode/keybindings.json)
487
+ // --- END AI MODEL FILE PATH ---
488
+ /* -----------------------------------------------------------
489
+ * Abstracts
490
+ * --------------------------------------------------------- */
491
+
492
+ // --- AI Model File Path (DO NOT DELETE) ---
493
+ // FilePath: libs > shared > src > lib > config > index.ts
494
+ // Updated: 2026-03-23 16:54
495
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
496
+ // cmd+alt+j (see .vscode/keybindings.json)
497
+ // --- END AI MODEL FILE PATH ---
498
+
499
+ // --- AI Model File Path (DO NOT DELETE) ---
500
+ // FilePath: libs > shared > src > lib > constants > behavior-meta.constant.ts
501
+ // Updated: 2026-03-28 14:09
502
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
503
+ // cmd+alt+j (see .vscode/keybindings.json)
504
+ // --- END AI MODEL FILE PATH ---
505
+ const BEHAVIOR_META = Symbol.for('BEHAVIOR_META');
506
+
507
+ const CONTROLLER_META = Symbol.for('CONTROLLER_META');
508
+
509
+ // --- AI Model File Path ---
510
+ // libs > shared > src > lib > constants > dev-tools > devtools-aggregate-key.constant.ts
511
+ /**
512
+ * String token used to uniquely identify the DevTools Aggregate FeatureCell.
513
+ *
514
+ * This key is referenced by the DevTools service, monitor utilities,
515
+ * and the router configuration to ensure all DevTools-related state
516
+ * is consistently mapped to the same FeatureCell instance.
517
+ *
518
+ * The value is stable across versions to maintain compatibility with
519
+ * external tools such as the Chrome DevTools extension.
520
+ */
521
+ const DEVTOOLS_AGGREGATE_KEY_CONSTANT = 'vault::devtools::aggregate:feature::cell';
522
+
523
+ // --- AI Model File Path ---
524
+ // libs > shared > src > lib > constants > dev-tools > devtools-logging-key.constant.ts
525
+ /**
526
+ * String token used to uniquely identify the DevTools Logging FeatureCell.
527
+ *
528
+ * This key is referenced by the DevTools service, monitor utilities,
529
+ * and the router configuration to ensure all DevTools-related state
530
+ * is consistently mapped to the same FeatureCell instance.
531
+ *
532
+ * The value is stable across versions to maintain compatibility with
533
+ * external tools such as the Chrome DevTools extension.
534
+ */
535
+ const DEVTOOLS_LOGGING_KEY_CONSTANT = 'vault::devtools::logging::feature::cell';
536
+
537
+ const VAULT_CLEAR_STATE = Symbol.for('VAULT_CLEAR_STATE');
538
+
539
+ const VAULT_CONTINUE = Symbol.for('VAULT_CONTINUE');
540
+
541
+ const VAULT_NOOP = Symbol.for('VAULT_NOOP');
542
+
543
+ const VAULT_STOP = Symbol.for('VAULT_STOP');
544
+
545
+ // --- AI Model File Path (DO NOT DELETE) ---
546
+ // FilePath: libs > shared > src > lib > constants > public-api.ts
547
+ // Updated: 2026-03-23 18:48
548
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
549
+ // cmd+alt+j (see .vscode/keybindings.json)
550
+ // --- END AI MODEL FILE PATH ---
551
+ /* -----------------------------------------------------------
552
+ * META + DECORATORS
553
+ * --------------------------------------------------------- */
554
+
555
+ // --- AI Model File Path (DO NOT DELETE) ---
556
+ // FilePath: libs > shared > src > lib > contexts > index.ts
557
+ // Updated: 2026-03-23 17:31
558
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
559
+ // cmd+alt+j (see .vscode/keybindings.json)
560
+ // --- END AI MODEL FILE PATH ---
561
+
562
+ // vault-behavior.decorator.ts
563
+ /**
564
+ * Decorator that registers a class as an Vault behavior.
565
+ *
566
+ * The `VaultBehavior` decorator attaches the provided `BehaviorMeta`
567
+ * definition to the target constructor, making the behavior discoverable by
568
+ * the orchestrator during pipeline initialization. Metadata fields such as
569
+ * `type`, `key`, and `critical` are also mirrored onto static properties of
570
+ * the decorated class to support lightweight runtime introspection.
571
+ *
572
+ * This decorator does not modify method logic or structure; it only assigns
573
+ * metadata required for orchestrator classification and behavior lifecycle
574
+ * management.
575
+ *
576
+ * @param meta - Metadata describing the behavior’s category, unique key, and
577
+ * criticality within the pipeline.
578
+ * @returns A class decorator that applies behavior metadata to the target.
579
+ */
580
+ function VaultBehavior(meta) {
581
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
582
+ return function (target) {
583
+ // Attach full metadata for the orchestrator
584
+ target[BEHAVIOR_META] = meta;
585
+ // Also mirror some fields onto static props for convenience
586
+ if (meta.type !== undefined) {
587
+ target.type = meta.type;
588
+ }
589
+ if (meta.key !== undefined) {
590
+ target.key = meta.key;
591
+ }
592
+ if (meta.critical !== undefined) {
593
+ target.critical = meta.critical;
594
+ }
595
+ if (meta.resolveType !== undefined) {
596
+ target.resolveType = meta.resolveType;
597
+ }
598
+ if (meta.wantsConfig !== undefined) {
599
+ target.wantsConfig = meta.wantsConfig;
600
+ }
601
+ else {
602
+ target.wantsConfig = false;
603
+ }
604
+ if (meta.configKey !== undefined) {
605
+ target.configKey = meta.configKey;
606
+ }
607
+ if (meta.needsLicense !== undefined) {
608
+ target.needsLicense = meta.needsLicense;
609
+ }
610
+ else {
611
+ target.needsLicense = false;
612
+ }
613
+ if (meta.licenseId !== undefined) {
614
+ target.licenseId = meta.licenseId;
615
+ }
616
+ };
617
+ }
618
+
619
+ // vault-behavior.decorator.ts
620
+ function VaultController(meta) {
621
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
622
+ return function (target) {
623
+ // Attach full metadata for the orchestrator
624
+ target[CONTROLLER_META] = meta;
625
+ // Also mirror some fields onto static props for convenience
626
+ if (meta.type !== undefined) {
627
+ target.type = meta.type;
628
+ }
629
+ if (meta.key !== undefined) {
630
+ target.key = meta.key;
631
+ }
632
+ if (meta.critical !== undefined) {
633
+ target.critical = meta.critical;
634
+ }
635
+ if (meta.wantsConfig !== undefined) {
636
+ target.wantsConfig = meta.wantsConfig;
637
+ }
638
+ else {
639
+ target.wantsConfig = false;
640
+ }
641
+ if (meta.configKey !== undefined) {
642
+ target.configKey = meta.configKey;
643
+ }
644
+ if (meta.needsLicense !== undefined) {
645
+ target.needsLicense = meta.needsLicense;
646
+ }
647
+ else {
648
+ target.needsLicense = false;
649
+ }
650
+ if (meta.licenseId !== undefined) {
651
+ target.licenseId = meta.licenseId;
652
+ }
653
+ };
654
+ }
655
+
656
+ // --- AI Model File Path (DO NOT DELETE) ---
657
+ // FilePath: libs > shared > src > lib > decorators > index.ts
658
+ // Updated: 2026-03-23 18:29
659
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
660
+ // cmd+alt+j (see .vscode/keybindings.json)
661
+ // --- END AI MODEL FILE PATH ---
662
+ /* -----------------------------------------------------------
663
+ * META + DECORATORS
664
+ * --------------------------------------------------------- */
665
+
666
+ const VaultErrorKindTypes = {
667
+ Usage: 'VaultErrorUsage',
668
+ VaultError: 'VaultError'
669
+ };
670
+
671
+ // --- AI Model File Path (DO NOT DELETE) ---
672
+ // FilePath: libs > shared > src > lib > types > error > vault-error-name.type.ts
673
+ // Updated: 2026-03-12 11:57
674
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
675
+ // cmd+alt+j (see .vscode/keybindings.json)
676
+ // --- END AI MODEL FILE PATH ---
677
+ const VaultErrorNameTypes = {
678
+ EncryptionIntegrity: 'VaultErrorEncryptionIntegrity',
679
+ License: 'VaultErrorLicense',
680
+ Usage: 'VaultErrorUsage',
681
+ VaultError: 'VaultError'
682
+ };
683
+
684
+ // --- AI Model File Path (DO NOT DELETE) ---
685
+ // FilePath: libs > shared > src > lib > errors > vault-error.ts
686
+ // Updated: 2026-03-12 12:08
687
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
688
+ // cmd+alt+j (see .vscode/keybindings.json)
689
+ // --- END AI MODEL FILE PATH ---
690
+ class VaultError extends Error {
691
+ kind;
692
+ constructor(message, name = VaultErrorNameTypes.VaultError, kind = VaultErrorKindTypes.VaultError) {
693
+ super(message);
694
+ this.name = name;
695
+ this.kind = kind;
696
+ // Required for proper instanceof checks in TS / ES5 targets
697
+ Object.setPrototypeOf(this, new.target.prototype);
698
+ // Optional but nice: clean stack trace
699
+ // eslint-disable-next-line
700
+ const anyError = Error;
701
+ if (typeof anyError.captureStackTrace === 'function') {
702
+ anyError.captureStackTrace(this, new.target);
703
+ }
704
+ }
705
+ }
706
+
707
+ // --- AI Model File Path (DO NOT DELETE) ---
708
+ // FilePath: libs > shared > src > lib > errors > vault-error.encryption.integrity.ts
709
+ // Updated: 2026-03-12
710
+ // --- END AI MODEL FILE PATH ---
711
+ /**
712
+ * Thrown when encrypted payload integrity verification fails.
713
+ *
714
+ * This occurs when AES-GCM authentication fails during decryption.
715
+ * Causes may include:
716
+ *
717
+ * - Tampered ciphertext
718
+ * - Modified IV
719
+ * - Incorrect encryption key
720
+ * - Corrupted storage payload
721
+ *
722
+ * AES-GCM provides authenticated encryption, so any modification to the
723
+ * encrypted envelope will cause the WebCrypto decrypt operation to throw.
724
+ */
725
+ class VaultEncryptionIntegrityError extends VaultError {
726
+ constructor() {
727
+ const message = `Encrypted snapshot failed integrity verification.
728
+
729
+ The encrypted payload could not be authenticated during AES-GCM decryption.
730
+
731
+ Possible causes:
732
+
733
+ • The stored ciphertext has been tampered with
734
+ • The stored initialization vector (IV) was modified
735
+ • The encryption key does not match the original key
736
+ • The stored payload is corrupted
737
+
738
+ Vault refuses to restore state from unauthenticated encrypted data.`;
739
+ super(message, VaultErrorNameTypes.EncryptionIntegrity);
740
+ }
741
+ }
742
+
743
+ // --- AI Model File Path (DO NOT DELETE) ---
744
+ // FilePath: libs > shared > src > lib > types > error > vault-error-usage-kind.type.ts
745
+ // Updated: 2026-03-12 11:57
746
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
747
+ // cmd+alt+j (see .vscode/keybindings.json)
748
+ // --- END AI MODEL FILE PATH ---
749
+ const VaultErrorUsageKindTypes = {
750
+ Encryption: 'VaultErrorEncryption',
751
+ License: 'VaultErrorLicense',
752
+ Promise: 'VaultErrorUsagePromise',
753
+ PromiseFactoryRequired: 'VaultErrorUsagePromiseFactoryRequired',
754
+ Usage: 'VaultErrorUsage'
755
+ };
756
+
757
+ // --- AI Model File Path (DO NOT DELETE) ---
758
+ // FilePath: libs > shared > src > lib > errors > vault-error.license.ts
759
+ // Updated: 2026-03-12 11:56
760
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
761
+ // cmd+alt+j (see .vscode/keybindings.json)
762
+ // --- END AI MODEL FILE PATH ---
763
+ class VaultLicenseError extends VaultError {
764
+ constructor(message, kind = VaultErrorUsageKindTypes.License) {
765
+ super(message, VaultErrorNameTypes.License, kind);
766
+ }
767
+ }
768
+
769
+ class VaultUsageError extends VaultError {
770
+ constructor(message, kind = VaultErrorUsageKindTypes.Usage) {
771
+ super(message, VaultErrorNameTypes.Usage, kind);
772
+ }
773
+ }
774
+
775
+ // --- AI Model File Path (DO NOT DELETE) ---
776
+ // FilePath: libs > shared > src > lib > errors > vault-error.usage.promise.ts
777
+ // Updated: 2026-03-12 12:01
778
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
779
+ // cmd+alt+j (see .vscode/keybindings.json)
780
+ // --- END AI MODEL FILE PATH ---
781
+ class VaultUsagePromiseError extends VaultUsageError {
782
+ constructor() {
783
+ const message = `Invalid incoming value: Promise detected.
784
+
785
+ Promises are eager and may resolve or reject before entering the Vault pipeline.
786
+
787
+ Use the following instead a DeferredFactory value
788
+
789
+ This guarantees the promise is created and executed inside the pipeline.`;
790
+ super(message, VaultErrorUsageKindTypes.Promise);
791
+ }
792
+ }
793
+
794
+ class VaultUsagePromiseFactoryRequiredError extends VaultUsageError {
795
+ constructor() {
796
+ const message = `Invalid usage of Promise-based state API.
797
+
798
+ You called a Promise-specific method (replaceState / mergeState),
799
+ but did not provide a function that creates a Promise.
800
+
801
+ Expected:
802
+ • () => Promise<T>
803
+
804
+ Received:
805
+ • A non-function value
806
+
807
+ Promises are eager and may resolve or reject before entering the Vault pipeline.
808
+
809
+ Always wrap promises in a function so they are created and executed
810
+ inside the pipeline.`;
811
+ super(message, VaultErrorUsageKindTypes.PromiseFactoryRequired);
812
+ }
813
+ }
814
+
815
+ // --- AI Model File Path (DO NOT DELETE) ---
816
+ // FilePath: libs > shared > src > lib > errors > index.ts
817
+ // Updated: 2026-03-23 17:21
818
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
819
+ // cmd+alt+j (see .vscode/keybindings.json)
820
+ // --- END AI MODEL FILE PATH ---
821
+ /* -----------------------------------------------------------
822
+ * ERRORS
823
+ * --------------------------------------------------------- */
824
+
825
+ // --- AI Model File Path (DO NOT DELETE) ---
826
+ // FilePath: libs > shared > src > lib > interfaces > index.ts
827
+ // Updated: 2026-03-23 18:45
828
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
829
+ // cmd+alt+j (see .vscode/keybindings.json)
830
+ // --- END AI MODEL FILE PATH ---
831
+
832
+ /* -----------------------------------------------------------
833
+ * SERVICES
834
+ * --------------------------------------------------------- */
835
+
836
+ // --- AI Model File Path (DO NOT DELETE) ---
837
+ // FilePath: libs > shared > src > lib > shapes > index.ts
838
+ // Updated: 2026-03-23 18:42
839
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
840
+ // cmd+alt+j (see .vscode/keybindings.json)
841
+ // --- END AI MODEL FILE PATH ---
842
+
843
+ const ControllerMessageTypes = {
844
+ Attempt: 'attempt',
845
+ Failure: 'failure',
846
+ Finalize: 'Finalize Pipeline',
847
+ Success: 'success',
848
+ Vote: 'vote' // mostly internal
849
+ };
850
+
851
+ const ControllerVotes = {
852
+ Abstain: 'abstain',
853
+ Abort: 'abort',
854
+ Deny: 'deny'
855
+ };
856
+
857
+ const ControllerTypes = {
858
+ CoreAbstain: 'coreAbstain',
859
+ Error: 'error',
860
+ License: 'license',
861
+ Policy: 'policy',
862
+ ReplayGlobalError: 'replayGlobalError',
863
+ Stepwise: 'stepwise'
864
+ };
865
+
866
+ const DecisionOutcomeTypes = {
867
+ Abort: 'abort',
868
+ Abstain: 'abstain',
869
+ Deny: 'deny'
870
+ };
871
+
872
+ // --- AI Model File Path (DO NOT DELETE) ---
873
+ // FilePath: libs > shared > src > lib > types > event > event-boundary.type.ts
874
+ // Updated: 2026-03-10 09:56
875
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
876
+ // cmd+alt+j (see .vscode/keybindings.json)
877
+ // --- END AI MODEL FILE PATH ---
878
+ const EventBoundaryTypes = {
879
+ End: 'end',
880
+ Notification: 'notification',
881
+ Start: 'start',
882
+ Unknown: 'unknown'
883
+ };
884
+
885
+ // --- AI Model File Path (DO NOT DELETE) ---
886
+ // FilePath: libs > shared > src > lib > types > event > event.type.ts
887
+ // Updated: 2026-03-10 09:56
888
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
889
+ // cmd+alt+j (see .vscode/keybindings.json)
890
+ // --- END AI MODEL FILE PATH ---
891
+ const EventTypes = {
892
+ Conductor: 'conductor',
893
+ Controller: 'controller',
894
+ Lifecycle: 'lifecycle',
895
+ Stage: 'stage',
896
+ Unknown: 'unknown'
897
+ };
898
+
899
+ const OperationTypes = {
900
+ Merge: 'merge',
901
+ Replace: 'replace',
902
+ Initialize: 'initialize'
903
+ };
904
+
905
+ /**
906
+ * Enumerates the available resolve strategy identifiers used by resolve
907
+ * behaviors. These identifiers indicate how a FeatureCell obtains its initial
908
+ * and subsequent state values during the resolve stage of the pipeline.
909
+ *
910
+ * - `Value` — Resolve from a synchronous, in-memory value.
911
+ * - `HttpResource` — Resolve using an HTTP-driven resource behavior.
912
+ * - `Observable` — Resolve from an observable stream source.
913
+ * - `Promise` — Resolve from a promise source.
914
+ */
915
+ const ResolveTypes = {
916
+ HttpResource: 'http-resource',
917
+ Observable: 'observable',
918
+ Promise: 'promise',
919
+ Value: 'value'
920
+ };
921
+
922
+ const StateEmitTypes = {
923
+ IncomingPipeline: 'Incoming Pipeline',
924
+ FinalizePipeline: 'Finalize Pipeline',
925
+ PipelineError: 'Pipeline Error',
926
+ PipelineDestroy: 'Pipeline Destroy',
927
+ PipelineReset: 'Pipeline Reset',
928
+ AbortController: 'Abort Controller',
929
+ DenyController: 'Deny Controller'
930
+ };
931
+
932
+ // --- AI Model File Path (DO NOT DELETE) ---
933
+ // FilePath: libs > shared > src > lib > types > index.ts
934
+ // Updated: 2026-03-23 18:51
935
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
936
+ // cmd+alt+j (see .vscode/keybindings.json)
937
+ // --- END AI MODEL FILE PATH ---
938
+ /* -----------------------------------------------------------
939
+ * TYPES (USER-FACING)
940
+ * --------------------------------------------------------- */
941
+
942
+ // --- AI Model File Path (DO NOT DELETE) ---
943
+ // FilePath: libs > shared > src > lib > utils > behavior > define-behavior-key.util.ts
944
+ // Updated: 2026-03-28 10:46
945
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
946
+ // cmd+alt+j (see .vscode/keybindings.json)
947
+ // --- END AI MODEL FILE PATH ---
948
+ /**
949
+ * Creates a normalized behavior key identifier used for behavior registration.
950
+ *
951
+ * A behavior key uniquely identifies a behavior within the Vault pipeline,
952
+ * following the canonical format:
953
+ *
954
+ * `SDUX::<Domain>::<Name>`
955
+ *
956
+ * Both `domain` and `name` are normalized by:
957
+ * - capitalizing the first character
958
+ * - removing all non-alphanumeric characters
959
+ *
960
+ * This ensures consistent and predictable behavior keys for orchestration,
961
+ * diagnostics, and tooling.
962
+ *
963
+ * @param domain - The logical domain or category of the behavior.
964
+ * @param name - The specific behavior name within the domain.
965
+ * @returns A normalized behavior key string.
966
+ */
967
+ function defineBehaviorKey(domain, name) {
968
+ return defineVaultKey('Behavior', domain, name);
969
+ }
970
+ function defineVaultKey(kind, domain, name) {
971
+ const normalize = (s) => s.charAt(0).toUpperCase() + s.slice(1).replace(/[^A-Za-z0-9]/g, '');
972
+ return `SDUX::${kind}::${normalize(domain)}::${normalize(name)}`;
973
+ }
974
+ /**
975
+ * Validates whether a string conforms to the Vault behavior key format.
976
+ *
977
+ * A valid behavior key must follow the structure:
978
+ *
979
+ * `SDUX::<Domain>::<Name>`
980
+ *
981
+ * Where `<Domain>` and `<Name>` begin with an uppercase character and contain
982
+ * only alphanumeric characters.
983
+ *
984
+ * @param key - The behavior key string to validate.
985
+ * @returns `true` if the key matches the required pattern; otherwise `false`.
986
+ */
987
+ function validateBehaviorKey(key) {
988
+ if (typeof key !== 'string')
989
+ return false;
990
+ const pattern = /^SDUX::(Behavior|Controller)::[A-Z][A-Za-z0-9]*::[A-Z][A-Za-z0-9]*$/;
991
+ return pattern.test(key);
992
+ }
993
+
994
+ function defineControllerKey(domain, name) {
995
+ return defineVaultKey('Controller', domain, name);
996
+ }
997
+ function validateControllerKey(key) {
998
+ return validateBehaviorKey(key);
999
+ }
1000
+
1001
+ // --- AI Model File Path (DO NOT DELETE) ---
1002
+ // FilePath: libs > shared > src > lib > utils > deferred-factory > is-deferred-factory.util.ts
1003
+ // Updated: 2026-03-21 20:36
1004
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
1005
+ // cmd+alt+j (see .vscode/keybindings.json)
1006
+ // --- END AI MODEL FILE PATH ---
1007
+ function isDeferredFactory(value) {
1008
+ // eslint-disable-next-line
1009
+ return !!value && typeof value === 'object' && typeof value.value === 'function';
1010
+ }
1011
+
1012
+ /**
1013
+ * Normalizes any thrown error into a canonical `VaultError` structure.
1014
+ *
1015
+ * This ensures that all errors—HTTP, runtime, string, or unknown—
1016
+ * are represented consistently throughout the Vault error pipeline.
1017
+ *
1018
+ * @param err - The raw thrown value.
1019
+ * @param featureCellKey - the origination of the error
1020
+ * @returns A fully normalized `VaultError`.
1021
+ */
1022
+ function createVaultError(err, featureCellKey) {
1023
+ const timestamp = Date.now();
1024
+ // -----------------------------------------
1025
+ // Standard JS Error
1026
+ // -----------------------------------------
1027
+ if (err instanceof Error) {
1028
+ return {
1029
+ message: err.message || 'Unexpected error',
1030
+ details: err.stack,
1031
+ raw: err,
1032
+ timestamp,
1033
+ featureCellKey
1034
+ };
1035
+ }
1036
+ // -----------------------------------------
1037
+ // String error
1038
+ // -----------------------------------------
1039
+ if (typeof err === 'string') {
1040
+ return {
1041
+ message: err,
1042
+ details: err,
1043
+ raw: err,
1044
+ timestamp,
1045
+ featureCellKey
1046
+ };
1047
+ }
1048
+ // -----------------------------------------
1049
+ // Fallback: unknown error
1050
+ // -----------------------------------------
1051
+ return {
1052
+ message: 'Unexpected error',
1053
+ details: err,
1054
+ raw: err,
1055
+ timestamp,
1056
+ featureCellKey
1057
+ };
1058
+ }
1059
+
1060
+ /*
1061
+ | Category | Type / Example | structuredClone behavior | deepFreeze fallback behavior | Isolated? | Notes |
1062
+ | ------------------------ | --------------------- | ------------------------ | ---------------------------------------- | ---------- | ----------------------------- |
1063
+ | **Primitives** | number | Returned as-is | Returned as-is | ✅ Yes | Immutable by definition |
1064
+ | | string | Returned as-is | Returned as-is | ✅ Yes | Immutable |
1065
+ | | boolean | Returned as-is | Returned as-is | ✅ Yes | Immutable |
1066
+ | | bigint | Returned as-is | Returned as-is | ✅ Yes | Immutable |
1067
+ | | symbol | Returned as-is | Returned as-is | ✅ Yes | Identity preserved |
1068
+ | | undefined | Returned as-is | Returned as-is | ✅ Yes | No mutation possible |
1069
+ | | null | Returned as-is | Returned as-is | ✅ Yes | No mutation possible |
1070
+ | **Plain Objects** | `{ a: 1 }` | Deep cloned | Same reference, deeply frozen | ✅ Yes | Fallback prevents mutation |
1071
+ | **Arrays** | `[1,2,3]` | Deep cloned | Same reference, frozen + elements frozen | ✅ Yes | Structural mutation blocked |
1072
+ | **Functions** | `() => {}` | ❌ Throws | Returned as-is | ⚠️ Partial | Body & closures mutable |
1073
+ | **Promises** | `Promise.resolve()` | ❌ Throws | Returned as-is | ⚠️ Partial | Internal state mutable |
1074
+ | **Dates** | `new Date()` | Cloned | Frozen original | ✅ Yes | Time value preserved |
1075
+ | **RegExp** | `/abc/g` | Cloned | Frozen original | ✅ Yes | Pattern preserved |
1076
+ | **Error** | `new Error()` | Cloned | Frozen original | ⚠️ Partial | Stack may differ |
1077
+ | **Map** | `new Map()` | Deep cloned | Frozen object, entries mutable | ⚠️ Partial | `.set()` still works |
1078
+ | **Set** | `new Set()` | Deep cloned | Frozen object, entries mutable | ⚠️ Partial | `.add()` still works |
1079
+ | **WeakMap** | `new WeakMap()` | ❌ Throws | Returned as-is | ❌ No | Cannot be isolated |
1080
+ | **WeakSet** | `new WeakSet()` | ❌ Throws | Returned as-is | ❌ No | Cannot be frozen |
1081
+ | **TypedArray** | `Uint8Array` | Cloned | Frozen | ✅ Yes | Buffer copied or locked |
1082
+ | **ArrayBuffer** | `ArrayBuffer` | Cloned | Frozen | ✅ Yes | Memory isolated |
1083
+ | **DataView** | `DataView` | Cloned | Frozen | ✅ Yes | Backing buffer safe |
1084
+ | **Observable (RxJS)** | `new Observable()` | ❌ Throws | Frozen object | ⚠️ Partial | Internal emissions mutable |
1085
+ | **Class Instance** | `new Foo()` | Prototype stripped | Frozen instance | ⚠️ Partial | Methods lost on clone |
1086
+ | **Object.create(null)** | null-proto object | Cloned | Frozen original | ✅ Yes | Prototype preserved on clone |
1087
+ | **Cyclic Objects** | `{ self }` | Cloned with cycles | Frozen safely | ✅ Yes | WeakSet prevents recursion |
1088
+ | **Getters / Setters** | `{ get x(){} }` | Getter invoked | Getter not invoked | ⚠️ Partial | Side effects possible |
1089
+ | **Non-enumerable props** | `defineProperty` | Dropped | Frozen but preserved | ⚠️ Partial | Visibility differs |
1090
+ | **Symbol-keyed props** | `{ [sym]: 1 }` | Dropped | Frozen but ignored | ⚠️ Partial | Symbols skipped intentionally |
1091
+ | **DOM Nodes** | `HTMLElement` | ❌ Throws | Frozen object | ❌ No | Host object semantics |
1092
+ | **Proxy (well-formed)** | `new Proxy()` | Cloned | Frozen target | ⚠️ Partial | Depends on handler |
1093
+ | **Proxy (malicious)** | fake ownKeys | ❌ Throws | ❌ Throws | ❌ No | Engine invariant violation |
1094
+ | **JSON-like data** | POJO graphs | Deep cloned | Frozen | ✅ Yes | Ideal use case |
1095
+ | **Modules** | ES module namespace | ❌ Throws | Returned as-is | ❌ No | Immutable by spec |
1096
+ | **Intl objects** | `Intl.DateTimeFormat` | Cloned | Frozen | ⚠️ Partial | Internal slots opaque |
1097
+ */
1098
+ function deepFreeze(obj, seen = new WeakSet()) {
1099
+ if (obj === null || typeof obj !== 'object')
1100
+ return obj;
1101
+ const o = obj;
1102
+ if (seen.has(o))
1103
+ return obj;
1104
+ seen.add(o);
1105
+ if (!Object.isFrozen(o))
1106
+ Object.freeze(o);
1107
+ for (const key of Reflect.ownKeys(o)) {
1108
+ const desc = Object.getOwnPropertyDescriptor(o, key);
1109
+ /* istanbul ignore next -- impossible after Object.freeze due to Proxy invariants */
1110
+ if (!desc)
1111
+ continue;
1112
+ // Only recurse into data properties; do NOT invoke getters
1113
+ if ('value' in desc) {
1114
+ // eslint-disable-next-line
1115
+ deepFreeze(desc.value, seen);
1116
+ }
1117
+ }
1118
+ return obj;
1119
+ }
1120
+ const isolateValue = (value) => {
1121
+ if (value === null || typeof value !== 'object')
1122
+ return value;
1123
+ try {
1124
+ // Works even if structuredClone is missing: ReferenceError is caught
1125
+ return structuredClone(value);
1126
+ }
1127
+ catch {
1128
+ return deepFreeze(value);
1129
+ }
1130
+ };
1131
+
1132
+ /**
1133
+ * Indicates whether a final pipeline value represents a NOOP condition.
1134
+ *
1135
+ * @param current - The computed pipeline result.
1136
+ * @returns `true` if the value is the `VAULT_NOOP` sentinel.
1137
+ */
1138
+ const isVaultNoop = (current) => {
1139
+ return current === VAULT_NOOP;
1140
+ };
1141
+ const isVaultClearState = (current) => {
1142
+ return current === VAULT_CLEAR_STATE;
1143
+ };
1144
+ const isVaultContinue = (current) => {
1145
+ return current === VAULT_CONTINUE;
1146
+ };
1147
+ /**
1148
+ * Checks whether a value is exactly `null`.
1149
+ *
1150
+ * @param current - The value to check.
1151
+ * @returns `true` if the value is `null`.
1152
+ */
1153
+ const isNull = (current) => current === null;
1154
+ /**
1155
+ * Checks whether a value is exactly `undefined`.
1156
+ *
1157
+ * @param current - The value to check.
1158
+ * @returns `true` if the value is `undefined`.
1159
+ */
1160
+ const isUndefined = (current) => current === undefined;
1161
+ /**
1162
+ * Determines whether a value is defined (not `undefined`).
1163
+ * Note: This intentionally does *not* exclude `null`.
1164
+ *
1165
+ * @param current - The value to check.
1166
+ * @returns `true` if the value is not `undefined`.
1167
+ */
1168
+ const isDefined = (current) => !isUndefined(current);
1169
+ /**
1170
+ * Determines whether a value is nullish — meaning either `null` or `undefined`.
1171
+ *
1172
+ * @param current - The value to inspect.
1173
+ * @returns `true` for `null` or `undefined`, otherwise `false`.
1174
+ */
1175
+ const isNullish = (current) => current == null;
1176
+ // eslint-disable-next-line
1177
+ const isFunction = (value) => typeof value === 'function';
1178
+ const isObject = (value) => typeof value === 'object' && value !== null;
1179
+ const isStateInputShape = (value) => {
1180
+ if (value === null || typeof value !== 'object')
1181
+ return false;
1182
+ const v = value;
1183
+ const hasKnownKey = 'loading' in v || 'value' in v || 'error' in v;
1184
+ return hasKnownKey;
1185
+ };
1186
+
1187
+ function isPromise(value) {
1188
+ return (
1189
+ // eslint-disable-next-line
1190
+ !!value && (typeof value === 'object' || typeof value === 'function') && typeof value.then === 'function');
1191
+ }
1192
+
1193
+ /**
1194
+ * Type guard that determines whether a value is an `HttpResourceRef<T>`.
1195
+ *
1196
+ * An `HttpResourceRef` is a structured object produced by Angular’s
1197
+ * `HttpClient` resource APIs. It contains a standardized shape used by
1198
+ * Vault to detect and normalize resource-backed state transitions.
1199
+ *
1200
+ * This utility checks only for the presence of the canonical
1201
+ * `HttpResourceRef` fields (`value`, `isLoading`, `error`, `hasValue`)
1202
+ * and does not validate the internal content of those properties.
1203
+ *
1204
+ * @typeParam T - The resource value type.
1205
+ *
1206
+ * @param obj - The value to test.
1207
+ * @returns `true` if the value matches the structural shape of an
1208
+ * `HttpResourceRef<T>`, otherwise `false`.
1209
+ */
1210
+ // eslint-disable-next-line
1211
+ function isHttpResourceRef(obj) {
1212
+ return !!(obj &&
1213
+ typeof obj === 'object' &&
1214
+ 'value' in obj &&
1215
+ 'isLoading' in obj &&
1216
+ 'error' in obj &&
1217
+ 'hasValue' in obj);
1218
+ }
1219
+
1220
+ // --- AI Model File Path (DO NOT DELETE) ---
1221
+ // FilePath: libs > shared > src > lib > utils > index.ts
1222
+ // Updated: 2026-03-24 09:59
1223
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
1224
+ // cmd+alt+j (see .vscode/keybindings.json)
1225
+ // --- END AI MODEL FILE PATH ---
1226
+ /* -----------------------------------------------------------
1227
+ * UTILITY FUNCTIONS (SAFE TO WILDCARD)
1228
+ * --------------------------------------------------------- */
1229
+
1230
+ // --- AI Model File Path (DO NOT DELETE) ---
1231
+ // FilePath: libs > shared > src > public-api.ts
1232
+ // Updated: 2026-03-23 16:55
1233
+ // Generated by pathcomment [tab] (see .vscode/typescript.code-snippets) or
1234
+ // cmd+alt+j (see .vscode/keybindings.json)
1235
+ // --- END AI MODEL FILE PATH ---
1236
+ /*
1237
+ * Public API Surface of @sdux-vault/shared
1238
+ *
1239
+ * IMPORTANT:
1240
+ * - JSDoc is preserved only when using named exports.
1241
+ * - Avoid `export *` for public-facing interfaces, behaviors, and types.
1242
+ * - Internal utilities may still use `export *`.
1243
+ */
1244
+ /* -----------------------------------------------------------
1245
+ * INTENTIONAL SIDE EFFECTS
1246
+ * --------------------------------------------------------- */
1247
+ /**
1248
+ * This is to handle fluent api requirements for behaviors and controllers
1249
+ */
1250
+
1251
+ /**
1252
+ * Generated bundle index. Do not edit.
1253
+ */
1254
+
1255
+ export { AbstractActiveController, AbstractErrorCallbackBehavior, AbstractErrorTransformBehavior, BEHAVIOR_META, BehaviorTypes, CONTROLLER_META, ControllerMessageTypes, ControllerTypes, ControllerVotes, DEVTOOLS_AGGREGATE_KEY_CONSTANT, DEVTOOLS_LOGGING_KEY_CONSTANT, DecisionOutcomeTypes, DevMode, EventBoundaryTypes, EventTypes, LogLevelTypes, OperationTypes, ResolveTypes, StateEmitTypes, VAULT_CLEAR_STATE, VAULT_CONTINUE, VAULT_NOOP, VAULT_STOP, VaultBehavior, VaultController, VaultEncryptionIntegrityError, VaultError, VaultErrorKindTypes, VaultErrorNameTypes, VaultErrorService, VaultErrorUsageKindTypes, VaultLicenseError, VaultPrivateErrorService, VaultUsageError, VaultUsagePromiseError, VaultUsagePromiseFactoryRequiredError, createVaultError, defineBehaviorKey, defineControllerKey, getVaultLogLevel, isDeferredFactory, isDefined, isFunction, isHttpResourceRef, isNull, isNullish, isObject, isPromise, isStateInputShape, isTestEnv, isUndefined, isVaultClearState, isVaultContinue, isVaultNoop, isolateValue, registerVersion, safeStringify, setVaultLogLevel, validateBehaviorKey, validateControllerKey, vaultDebug, vaultError, vaultLog, vaultWarn };
1256
+ //# sourceMappingURL=sdux-vault-shared.mjs.map