@signaltree/core 4.0.1 → 4.0.2
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.
- package/package.json +2 -2
- package/README.md +0 -1469
- package/dist/enhancers/batching/index.d.ts +0 -495
- package/dist/enhancers/batching/index.js +0 -406
- package/dist/enhancers/batching/index.js.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/batching/index.d.ts +0 -2
- package/dist/enhancers/batching/types/packages/core/src/enhancers/batching/index.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/batching/jest.config.d.ts +0 -16
- package/dist/enhancers/batching/types/packages/core/src/enhancers/batching/jest.config.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/batching/lib/batching.d.ts +0 -262
- package/dist/enhancers/batching/types/packages/core/src/enhancers/batching/lib/batching.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/batching/test-setup.d.ts +0 -2
- package/dist/enhancers/batching/types/packages/core/src/enhancers/batching/test-setup.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/computed/index.d.ts +0 -2
- package/dist/enhancers/batching/types/packages/core/src/enhancers/computed/index.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/computed/jest.config.d.ts +0 -16
- package/dist/enhancers/batching/types/packages/core/src/enhancers/computed/jest.config.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/computed/lib/computed.d.ts +0 -68
- package/dist/enhancers/batching/types/packages/core/src/enhancers/computed/lib/computed.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/devtools/index.d.ts +0 -2
- package/dist/enhancers/batching/types/packages/core/src/enhancers/devtools/index.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/devtools/jest.config.d.ts +0 -16
- package/dist/enhancers/batching/types/packages/core/src/enhancers/devtools/jest.config.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/devtools/lib/devtools.d.ts +0 -129
- package/dist/enhancers/batching/types/packages/core/src/enhancers/devtools/lib/devtools.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/devtools/test-setup.d.ts +0 -2
- package/dist/enhancers/batching/types/packages/core/src/enhancers/devtools/test-setup.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/entities/index.d.ts +0 -2
- package/dist/enhancers/batching/types/packages/core/src/enhancers/entities/index.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/entities/jest.config.d.ts +0 -16
- package/dist/enhancers/batching/types/packages/core/src/enhancers/entities/jest.config.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/entities/lib/entities.d.ts +0 -39
- package/dist/enhancers/batching/types/packages/core/src/enhancers/entities/lib/entities.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/entities/test-setup.d.ts +0 -2
- package/dist/enhancers/batching/types/packages/core/src/enhancers/entities/test-setup.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/index.d.ts +0 -38
- package/dist/enhancers/batching/types/packages/core/src/enhancers/index.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/memoization/index.d.ts +0 -2
- package/dist/enhancers/batching/types/packages/core/src/enhancers/memoization/index.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/memoization/jest.config.d.ts +0 -16
- package/dist/enhancers/batching/types/packages/core/src/enhancers/memoization/jest.config.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/memoization/lib/memoization.d.ts +0 -190
- package/dist/enhancers/batching/types/packages/core/src/enhancers/memoization/lib/memoization.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/memoization/test-setup.d.ts +0 -2
- package/dist/enhancers/batching/types/packages/core/src/enhancers/memoization/test-setup.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/middleware/index.d.ts +0 -3
- package/dist/enhancers/batching/types/packages/core/src/enhancers/middleware/index.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/middleware/jest.config.d.ts +0 -16
- package/dist/enhancers/batching/types/packages/core/src/enhancers/middleware/jest.config.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/middleware/lib/async-helpers.d.ts +0 -16
- package/dist/enhancers/batching/types/packages/core/src/enhancers/middleware/lib/async-helpers.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/middleware/lib/middleware.d.ts +0 -43
- package/dist/enhancers/batching/types/packages/core/src/enhancers/middleware/lib/middleware.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/middleware/test-setup.d.ts +0 -2
- package/dist/enhancers/batching/types/packages/core/src/enhancers/middleware/test-setup.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/presets/index.d.ts +0 -2
- package/dist/enhancers/batching/types/packages/core/src/enhancers/presets/index.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/presets/jest.config.d.ts +0 -16
- package/dist/enhancers/batching/types/packages/core/src/enhancers/presets/jest.config.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/presets/lib/presets.d.ts +0 -69
- package/dist/enhancers/batching/types/packages/core/src/enhancers/presets/lib/presets.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/presets/test-setup.d.ts +0 -2
- package/dist/enhancers/batching/types/packages/core/src/enhancers/presets/test-setup.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/serialization/constants.d.ts +0 -19
- package/dist/enhancers/batching/types/packages/core/src/enhancers/serialization/constants.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/serialization/index.d.ts +0 -3
- package/dist/enhancers/batching/types/packages/core/src/enhancers/serialization/index.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/serialization/jest.config.d.ts +0 -16
- package/dist/enhancers/batching/types/packages/core/src/enhancers/serialization/jest.config.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/serialization/lib/serialization.d.ts +0 -186
- package/dist/enhancers/batching/types/packages/core/src/enhancers/serialization/lib/serialization.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/serialization/test-setup.d.ts +0 -2
- package/dist/enhancers/batching/types/packages/core/src/enhancers/serialization/test-setup.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/time-travel/index.d.ts +0 -2
- package/dist/enhancers/batching/types/packages/core/src/enhancers/time-travel/index.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/time-travel/jest.config.d.ts +0 -16
- package/dist/enhancers/batching/types/packages/core/src/enhancers/time-travel/jest.config.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/time-travel/lib/time-travel.d.ts +0 -145
- package/dist/enhancers/batching/types/packages/core/src/enhancers/time-travel/lib/time-travel.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/time-travel/lib/utils.d.ts +0 -3
- package/dist/enhancers/batching/types/packages/core/src/enhancers/time-travel/lib/utils.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/time-travel/test-setup.d.ts +0 -2
- package/dist/enhancers/batching/types/packages/core/src/enhancers/time-travel/test-setup.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/enhancers/types.d.ts +0 -112
- package/dist/enhancers/batching/types/packages/core/src/enhancers/types.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/index.d.ts +0 -119
- package/dist/enhancers/batching/types/packages/core/src/index.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/lib/constants.d.ts +0 -50
- package/dist/enhancers/batching/types/packages/core/src/lib/constants.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/lib/memory/memory-manager.d.ts +0 -145
- package/dist/enhancers/batching/types/packages/core/src/lib/memory/memory-manager.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/lib/performance/diff-engine.d.ts +0 -109
- package/dist/enhancers/batching/types/packages/core/src/lib/performance/diff-engine.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/lib/performance/path-index.d.ts +0 -120
- package/dist/enhancers/batching/types/packages/core/src/lib/performance/path-index.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/lib/performance/update-engine.d.ts +0 -116
- package/dist/enhancers/batching/types/packages/core/src/lib/performance/update-engine.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/lib/security/security-validator.d.ts +0 -145
- package/dist/enhancers/batching/types/packages/core/src/lib/security/security-validator.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/lib/signal-tree.d.ts +0 -17
- package/dist/enhancers/batching/types/packages/core/src/lib/signal-tree.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/lib/types.d.ts +0 -299
- package/dist/enhancers/batching/types/packages/core/src/lib/types.d.ts.map +0 -1
- package/dist/enhancers/batching/types/packages/core/src/lib/utils.d.ts +0 -53
- package/dist/enhancers/batching/types/packages/core/src/lib/utils.d.ts.map +0 -1
- package/dist/enhancers/computed/index.d.ts +0 -302
- package/dist/enhancers/computed/index.js +0 -165
- package/dist/enhancers/computed/index.js.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/batching/index.d.ts +0 -2
- package/dist/enhancers/computed/types/packages/core/src/enhancers/batching/index.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/batching/jest.config.d.ts +0 -16
- package/dist/enhancers/computed/types/packages/core/src/enhancers/batching/jest.config.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/batching/lib/batching.d.ts +0 -262
- package/dist/enhancers/computed/types/packages/core/src/enhancers/batching/lib/batching.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/batching/test-setup.d.ts +0 -2
- package/dist/enhancers/computed/types/packages/core/src/enhancers/batching/test-setup.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/computed/index.d.ts +0 -2
- package/dist/enhancers/computed/types/packages/core/src/enhancers/computed/index.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/computed/jest.config.d.ts +0 -16
- package/dist/enhancers/computed/types/packages/core/src/enhancers/computed/jest.config.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/computed/lib/computed.d.ts +0 -68
- package/dist/enhancers/computed/types/packages/core/src/enhancers/computed/lib/computed.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/devtools/index.d.ts +0 -2
- package/dist/enhancers/computed/types/packages/core/src/enhancers/devtools/index.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/devtools/jest.config.d.ts +0 -16
- package/dist/enhancers/computed/types/packages/core/src/enhancers/devtools/jest.config.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/devtools/lib/devtools.d.ts +0 -129
- package/dist/enhancers/computed/types/packages/core/src/enhancers/devtools/lib/devtools.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/devtools/test-setup.d.ts +0 -2
- package/dist/enhancers/computed/types/packages/core/src/enhancers/devtools/test-setup.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/entities/index.d.ts +0 -2
- package/dist/enhancers/computed/types/packages/core/src/enhancers/entities/index.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/entities/jest.config.d.ts +0 -16
- package/dist/enhancers/computed/types/packages/core/src/enhancers/entities/jest.config.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/entities/lib/entities.d.ts +0 -39
- package/dist/enhancers/computed/types/packages/core/src/enhancers/entities/lib/entities.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/entities/test-setup.d.ts +0 -2
- package/dist/enhancers/computed/types/packages/core/src/enhancers/entities/test-setup.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/index.d.ts +0 -38
- package/dist/enhancers/computed/types/packages/core/src/enhancers/index.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/memoization/index.d.ts +0 -2
- package/dist/enhancers/computed/types/packages/core/src/enhancers/memoization/index.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/memoization/jest.config.d.ts +0 -16
- package/dist/enhancers/computed/types/packages/core/src/enhancers/memoization/jest.config.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/memoization/lib/memoization.d.ts +0 -190
- package/dist/enhancers/computed/types/packages/core/src/enhancers/memoization/lib/memoization.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/memoization/test-setup.d.ts +0 -2
- package/dist/enhancers/computed/types/packages/core/src/enhancers/memoization/test-setup.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/middleware/index.d.ts +0 -3
- package/dist/enhancers/computed/types/packages/core/src/enhancers/middleware/index.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/middleware/jest.config.d.ts +0 -16
- package/dist/enhancers/computed/types/packages/core/src/enhancers/middleware/jest.config.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/middleware/lib/async-helpers.d.ts +0 -16
- package/dist/enhancers/computed/types/packages/core/src/enhancers/middleware/lib/async-helpers.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/middleware/lib/middleware.d.ts +0 -43
- package/dist/enhancers/computed/types/packages/core/src/enhancers/middleware/lib/middleware.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/middleware/test-setup.d.ts +0 -2
- package/dist/enhancers/computed/types/packages/core/src/enhancers/middleware/test-setup.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/presets/index.d.ts +0 -2
- package/dist/enhancers/computed/types/packages/core/src/enhancers/presets/index.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/presets/jest.config.d.ts +0 -16
- package/dist/enhancers/computed/types/packages/core/src/enhancers/presets/jest.config.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/presets/lib/presets.d.ts +0 -69
- package/dist/enhancers/computed/types/packages/core/src/enhancers/presets/lib/presets.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/presets/test-setup.d.ts +0 -2
- package/dist/enhancers/computed/types/packages/core/src/enhancers/presets/test-setup.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/serialization/constants.d.ts +0 -19
- package/dist/enhancers/computed/types/packages/core/src/enhancers/serialization/constants.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/serialization/index.d.ts +0 -3
- package/dist/enhancers/computed/types/packages/core/src/enhancers/serialization/index.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/serialization/jest.config.d.ts +0 -16
- package/dist/enhancers/computed/types/packages/core/src/enhancers/serialization/jest.config.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/serialization/lib/serialization.d.ts +0 -186
- package/dist/enhancers/computed/types/packages/core/src/enhancers/serialization/lib/serialization.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/serialization/test-setup.d.ts +0 -2
- package/dist/enhancers/computed/types/packages/core/src/enhancers/serialization/test-setup.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/time-travel/index.d.ts +0 -2
- package/dist/enhancers/computed/types/packages/core/src/enhancers/time-travel/index.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/time-travel/jest.config.d.ts +0 -16
- package/dist/enhancers/computed/types/packages/core/src/enhancers/time-travel/jest.config.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/time-travel/lib/time-travel.d.ts +0 -145
- package/dist/enhancers/computed/types/packages/core/src/enhancers/time-travel/lib/time-travel.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/time-travel/lib/utils.d.ts +0 -3
- package/dist/enhancers/computed/types/packages/core/src/enhancers/time-travel/lib/utils.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/time-travel/test-setup.d.ts +0 -2
- package/dist/enhancers/computed/types/packages/core/src/enhancers/time-travel/test-setup.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/enhancers/types.d.ts +0 -112
- package/dist/enhancers/computed/types/packages/core/src/enhancers/types.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/index.d.ts +0 -119
- package/dist/enhancers/computed/types/packages/core/src/index.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/lib/constants.d.ts +0 -50
- package/dist/enhancers/computed/types/packages/core/src/lib/constants.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/lib/memory/memory-manager.d.ts +0 -145
- package/dist/enhancers/computed/types/packages/core/src/lib/memory/memory-manager.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/lib/performance/diff-engine.d.ts +0 -109
- package/dist/enhancers/computed/types/packages/core/src/lib/performance/diff-engine.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/lib/performance/path-index.d.ts +0 -120
- package/dist/enhancers/computed/types/packages/core/src/lib/performance/path-index.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/lib/performance/update-engine.d.ts +0 -116
- package/dist/enhancers/computed/types/packages/core/src/lib/performance/update-engine.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/lib/security/security-validator.d.ts +0 -145
- package/dist/enhancers/computed/types/packages/core/src/lib/security/security-validator.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/lib/signal-tree.d.ts +0 -17
- package/dist/enhancers/computed/types/packages/core/src/lib/signal-tree.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/lib/types.d.ts +0 -299
- package/dist/enhancers/computed/types/packages/core/src/lib/types.d.ts.map +0 -1
- package/dist/enhancers/computed/types/packages/core/src/lib/utils.d.ts +0 -53
- package/dist/enhancers/computed/types/packages/core/src/lib/utils.d.ts.map +0 -1
- package/dist/enhancers/devtools/index.d.ts +0 -363
- package/dist/enhancers/devtools/index.js +0 -319
- package/dist/enhancers/devtools/index.js.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/batching/index.d.ts +0 -2
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/batching/index.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/batching/jest.config.d.ts +0 -16
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/batching/jest.config.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/batching/lib/batching.d.ts +0 -262
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/batching/lib/batching.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/batching/test-setup.d.ts +0 -2
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/batching/test-setup.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/computed/index.d.ts +0 -2
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/computed/index.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/computed/jest.config.d.ts +0 -16
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/computed/jest.config.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/computed/lib/computed.d.ts +0 -68
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/computed/lib/computed.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/devtools/index.d.ts +0 -2
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/devtools/index.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/devtools/jest.config.d.ts +0 -16
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/devtools/jest.config.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/devtools/lib/devtools.d.ts +0 -129
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/devtools/lib/devtools.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/devtools/test-setup.d.ts +0 -2
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/devtools/test-setup.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/entities/index.d.ts +0 -2
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/entities/index.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/entities/jest.config.d.ts +0 -16
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/entities/jest.config.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/entities/lib/entities.d.ts +0 -39
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/entities/lib/entities.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/entities/test-setup.d.ts +0 -2
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/entities/test-setup.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/index.d.ts +0 -38
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/index.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/memoization/index.d.ts +0 -2
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/memoization/index.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/memoization/jest.config.d.ts +0 -16
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/memoization/jest.config.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/memoization/lib/memoization.d.ts +0 -190
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/memoization/lib/memoization.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/memoization/test-setup.d.ts +0 -2
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/memoization/test-setup.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/middleware/index.d.ts +0 -3
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/middleware/index.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/middleware/jest.config.d.ts +0 -16
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/middleware/jest.config.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/middleware/lib/async-helpers.d.ts +0 -16
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/middleware/lib/async-helpers.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/middleware/lib/middleware.d.ts +0 -43
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/middleware/lib/middleware.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/middleware/test-setup.d.ts +0 -2
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/middleware/test-setup.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/presets/index.d.ts +0 -2
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/presets/index.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/presets/jest.config.d.ts +0 -16
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/presets/jest.config.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/presets/lib/presets.d.ts +0 -69
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/presets/lib/presets.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/presets/test-setup.d.ts +0 -2
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/presets/test-setup.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/serialization/constants.d.ts +0 -19
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/serialization/constants.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/serialization/index.d.ts +0 -3
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/serialization/index.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/serialization/jest.config.d.ts +0 -16
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/serialization/jest.config.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/serialization/lib/serialization.d.ts +0 -186
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/serialization/lib/serialization.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/serialization/test-setup.d.ts +0 -2
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/serialization/test-setup.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/time-travel/index.d.ts +0 -2
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/time-travel/index.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/time-travel/jest.config.d.ts +0 -16
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/time-travel/jest.config.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/time-travel/lib/time-travel.d.ts +0 -145
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/time-travel/lib/time-travel.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/time-travel/lib/utils.d.ts +0 -3
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/time-travel/lib/utils.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/time-travel/test-setup.d.ts +0 -2
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/time-travel/test-setup.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/types.d.ts +0 -112
- package/dist/enhancers/devtools/types/packages/core/src/enhancers/types.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/index.d.ts +0 -119
- package/dist/enhancers/devtools/types/packages/core/src/index.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/lib/constants.d.ts +0 -50
- package/dist/enhancers/devtools/types/packages/core/src/lib/constants.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/lib/memory/memory-manager.d.ts +0 -145
- package/dist/enhancers/devtools/types/packages/core/src/lib/memory/memory-manager.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/lib/performance/diff-engine.d.ts +0 -109
- package/dist/enhancers/devtools/types/packages/core/src/lib/performance/diff-engine.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/lib/performance/path-index.d.ts +0 -120
- package/dist/enhancers/devtools/types/packages/core/src/lib/performance/path-index.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/lib/performance/update-engine.d.ts +0 -116
- package/dist/enhancers/devtools/types/packages/core/src/lib/performance/update-engine.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/lib/security/security-validator.d.ts +0 -145
- package/dist/enhancers/devtools/types/packages/core/src/lib/security/security-validator.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/lib/signal-tree.d.ts +0 -17
- package/dist/enhancers/devtools/types/packages/core/src/lib/signal-tree.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/lib/types.d.ts +0 -299
- package/dist/enhancers/devtools/types/packages/core/src/lib/types.d.ts.map +0 -1
- package/dist/enhancers/devtools/types/packages/core/src/lib/utils.d.ts +0 -53
- package/dist/enhancers/devtools/types/packages/core/src/lib/utils.d.ts.map +0 -1
- package/dist/enhancers/entities/index.d.ts +0 -272
- package/dist/enhancers/entities/index.js +0 -164
- package/dist/enhancers/entities/index.js.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/batching/index.d.ts +0 -2
- package/dist/enhancers/entities/types/packages/core/src/enhancers/batching/index.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/batching/jest.config.d.ts +0 -16
- package/dist/enhancers/entities/types/packages/core/src/enhancers/batching/jest.config.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/batching/lib/batching.d.ts +0 -262
- package/dist/enhancers/entities/types/packages/core/src/enhancers/batching/lib/batching.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/batching/test-setup.d.ts +0 -2
- package/dist/enhancers/entities/types/packages/core/src/enhancers/batching/test-setup.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/computed/index.d.ts +0 -2
- package/dist/enhancers/entities/types/packages/core/src/enhancers/computed/index.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/computed/jest.config.d.ts +0 -16
- package/dist/enhancers/entities/types/packages/core/src/enhancers/computed/jest.config.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/computed/lib/computed.d.ts +0 -68
- package/dist/enhancers/entities/types/packages/core/src/enhancers/computed/lib/computed.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/devtools/index.d.ts +0 -2
- package/dist/enhancers/entities/types/packages/core/src/enhancers/devtools/index.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/devtools/jest.config.d.ts +0 -16
- package/dist/enhancers/entities/types/packages/core/src/enhancers/devtools/jest.config.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/devtools/lib/devtools.d.ts +0 -129
- package/dist/enhancers/entities/types/packages/core/src/enhancers/devtools/lib/devtools.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/devtools/test-setup.d.ts +0 -2
- package/dist/enhancers/entities/types/packages/core/src/enhancers/devtools/test-setup.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/entities/index.d.ts +0 -2
- package/dist/enhancers/entities/types/packages/core/src/enhancers/entities/index.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/entities/jest.config.d.ts +0 -16
- package/dist/enhancers/entities/types/packages/core/src/enhancers/entities/jest.config.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/entities/lib/entities.d.ts +0 -39
- package/dist/enhancers/entities/types/packages/core/src/enhancers/entities/lib/entities.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/entities/test-setup.d.ts +0 -2
- package/dist/enhancers/entities/types/packages/core/src/enhancers/entities/test-setup.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/index.d.ts +0 -38
- package/dist/enhancers/entities/types/packages/core/src/enhancers/index.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/memoization/index.d.ts +0 -2
- package/dist/enhancers/entities/types/packages/core/src/enhancers/memoization/index.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/memoization/jest.config.d.ts +0 -16
- package/dist/enhancers/entities/types/packages/core/src/enhancers/memoization/jest.config.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/memoization/lib/memoization.d.ts +0 -190
- package/dist/enhancers/entities/types/packages/core/src/enhancers/memoization/lib/memoization.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/memoization/test-setup.d.ts +0 -2
- package/dist/enhancers/entities/types/packages/core/src/enhancers/memoization/test-setup.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/middleware/index.d.ts +0 -3
- package/dist/enhancers/entities/types/packages/core/src/enhancers/middleware/index.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/middleware/jest.config.d.ts +0 -16
- package/dist/enhancers/entities/types/packages/core/src/enhancers/middleware/jest.config.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/middleware/lib/async-helpers.d.ts +0 -16
- package/dist/enhancers/entities/types/packages/core/src/enhancers/middleware/lib/async-helpers.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/middleware/lib/middleware.d.ts +0 -43
- package/dist/enhancers/entities/types/packages/core/src/enhancers/middleware/lib/middleware.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/middleware/test-setup.d.ts +0 -2
- package/dist/enhancers/entities/types/packages/core/src/enhancers/middleware/test-setup.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/presets/index.d.ts +0 -2
- package/dist/enhancers/entities/types/packages/core/src/enhancers/presets/index.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/presets/jest.config.d.ts +0 -16
- package/dist/enhancers/entities/types/packages/core/src/enhancers/presets/jest.config.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/presets/lib/presets.d.ts +0 -69
- package/dist/enhancers/entities/types/packages/core/src/enhancers/presets/lib/presets.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/presets/test-setup.d.ts +0 -2
- package/dist/enhancers/entities/types/packages/core/src/enhancers/presets/test-setup.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/serialization/constants.d.ts +0 -19
- package/dist/enhancers/entities/types/packages/core/src/enhancers/serialization/constants.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/serialization/index.d.ts +0 -3
- package/dist/enhancers/entities/types/packages/core/src/enhancers/serialization/index.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/serialization/jest.config.d.ts +0 -16
- package/dist/enhancers/entities/types/packages/core/src/enhancers/serialization/jest.config.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/serialization/lib/serialization.d.ts +0 -186
- package/dist/enhancers/entities/types/packages/core/src/enhancers/serialization/lib/serialization.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/serialization/test-setup.d.ts +0 -2
- package/dist/enhancers/entities/types/packages/core/src/enhancers/serialization/test-setup.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/time-travel/index.d.ts +0 -2
- package/dist/enhancers/entities/types/packages/core/src/enhancers/time-travel/index.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/time-travel/jest.config.d.ts +0 -16
- package/dist/enhancers/entities/types/packages/core/src/enhancers/time-travel/jest.config.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/time-travel/lib/time-travel.d.ts +0 -145
- package/dist/enhancers/entities/types/packages/core/src/enhancers/time-travel/lib/time-travel.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/time-travel/lib/utils.d.ts +0 -3
- package/dist/enhancers/entities/types/packages/core/src/enhancers/time-travel/lib/utils.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/time-travel/test-setup.d.ts +0 -2
- package/dist/enhancers/entities/types/packages/core/src/enhancers/time-travel/test-setup.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/enhancers/types.d.ts +0 -112
- package/dist/enhancers/entities/types/packages/core/src/enhancers/types.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/index.d.ts +0 -119
- package/dist/enhancers/entities/types/packages/core/src/index.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/lib/constants.d.ts +0 -50
- package/dist/enhancers/entities/types/packages/core/src/lib/constants.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/lib/memory/memory-manager.d.ts +0 -145
- package/dist/enhancers/entities/types/packages/core/src/lib/memory/memory-manager.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/lib/performance/diff-engine.d.ts +0 -109
- package/dist/enhancers/entities/types/packages/core/src/lib/performance/diff-engine.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/lib/performance/path-index.d.ts +0 -120
- package/dist/enhancers/entities/types/packages/core/src/lib/performance/path-index.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/lib/performance/update-engine.d.ts +0 -116
- package/dist/enhancers/entities/types/packages/core/src/lib/performance/update-engine.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/lib/security/security-validator.d.ts +0 -145
- package/dist/enhancers/entities/types/packages/core/src/lib/security/security-validator.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/lib/signal-tree.d.ts +0 -17
- package/dist/enhancers/entities/types/packages/core/src/lib/signal-tree.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/lib/types.d.ts +0 -299
- package/dist/enhancers/entities/types/packages/core/src/lib/types.d.ts.map +0 -1
- package/dist/enhancers/entities/types/packages/core/src/lib/utils.d.ts +0 -53
- package/dist/enhancers/entities/types/packages/core/src/lib/utils.d.ts.map +0 -1
- package/dist/enhancers/index.d.ts +0 -73
- package/dist/enhancers/index.js +0 -191
- package/dist/enhancers/index.js.map +0 -1
- package/dist/enhancers/memoization/index.d.ts +0 -425
- package/dist/enhancers/memoization/index.js +0 -570
- package/dist/enhancers/memoization/index.js.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/batching/index.d.ts +0 -2
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/batching/index.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/batching/jest.config.d.ts +0 -16
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/batching/jest.config.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/batching/lib/batching.d.ts +0 -262
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/batching/lib/batching.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/batching/test-setup.d.ts +0 -2
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/batching/test-setup.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/computed/index.d.ts +0 -2
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/computed/index.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/computed/jest.config.d.ts +0 -16
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/computed/jest.config.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/computed/lib/computed.d.ts +0 -68
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/computed/lib/computed.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/devtools/index.d.ts +0 -2
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/devtools/index.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/devtools/jest.config.d.ts +0 -16
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/devtools/jest.config.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/devtools/lib/devtools.d.ts +0 -129
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/devtools/lib/devtools.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/devtools/test-setup.d.ts +0 -2
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/devtools/test-setup.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/entities/index.d.ts +0 -2
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/entities/index.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/entities/jest.config.d.ts +0 -16
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/entities/jest.config.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/entities/lib/entities.d.ts +0 -39
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/entities/lib/entities.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/entities/test-setup.d.ts +0 -2
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/entities/test-setup.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/index.d.ts +0 -38
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/index.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/memoization/index.d.ts +0 -2
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/memoization/index.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/memoization/jest.config.d.ts +0 -16
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/memoization/jest.config.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/memoization/lib/memoization.d.ts +0 -190
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/memoization/lib/memoization.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/memoization/test-setup.d.ts +0 -2
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/memoization/test-setup.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/middleware/index.d.ts +0 -3
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/middleware/index.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/middleware/jest.config.d.ts +0 -16
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/middleware/jest.config.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/middleware/lib/async-helpers.d.ts +0 -16
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/middleware/lib/async-helpers.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/middleware/lib/middleware.d.ts +0 -43
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/middleware/lib/middleware.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/middleware/test-setup.d.ts +0 -2
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/middleware/test-setup.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/presets/index.d.ts +0 -2
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/presets/index.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/presets/jest.config.d.ts +0 -16
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/presets/jest.config.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/presets/lib/presets.d.ts +0 -69
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/presets/lib/presets.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/presets/test-setup.d.ts +0 -2
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/presets/test-setup.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/serialization/constants.d.ts +0 -19
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/serialization/constants.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/serialization/index.d.ts +0 -3
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/serialization/index.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/serialization/jest.config.d.ts +0 -16
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/serialization/jest.config.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/serialization/lib/serialization.d.ts +0 -186
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/serialization/lib/serialization.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/serialization/test-setup.d.ts +0 -2
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/serialization/test-setup.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/time-travel/index.d.ts +0 -2
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/time-travel/index.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/time-travel/jest.config.d.ts +0 -16
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/time-travel/jest.config.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/time-travel/lib/time-travel.d.ts +0 -145
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/time-travel/lib/time-travel.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/time-travel/lib/utils.d.ts +0 -3
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/time-travel/lib/utils.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/time-travel/test-setup.d.ts +0 -2
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/time-travel/test-setup.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/types.d.ts +0 -112
- package/dist/enhancers/memoization/types/packages/core/src/enhancers/types.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/index.d.ts +0 -119
- package/dist/enhancers/memoization/types/packages/core/src/index.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/lib/constants.d.ts +0 -50
- package/dist/enhancers/memoization/types/packages/core/src/lib/constants.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/lib/memory/memory-manager.d.ts +0 -145
- package/dist/enhancers/memoization/types/packages/core/src/lib/memory/memory-manager.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/lib/performance/diff-engine.d.ts +0 -109
- package/dist/enhancers/memoization/types/packages/core/src/lib/performance/diff-engine.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/lib/performance/path-index.d.ts +0 -120
- package/dist/enhancers/memoization/types/packages/core/src/lib/performance/path-index.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/lib/performance/update-engine.d.ts +0 -116
- package/dist/enhancers/memoization/types/packages/core/src/lib/performance/update-engine.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/lib/security/security-validator.d.ts +0 -145
- package/dist/enhancers/memoization/types/packages/core/src/lib/security/security-validator.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/lib/signal-tree.d.ts +0 -17
- package/dist/enhancers/memoization/types/packages/core/src/lib/signal-tree.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/lib/types.d.ts +0 -299
- package/dist/enhancers/memoization/types/packages/core/src/lib/types.d.ts.map +0 -1
- package/dist/enhancers/memoization/types/packages/core/src/lib/utils.d.ts +0 -53
- package/dist/enhancers/memoization/types/packages/core/src/lib/utils.d.ts.map +0 -1
- package/dist/enhancers/middleware/index.d.ts +0 -293
- package/dist/enhancers/middleware/index.js +0 -339
- package/dist/enhancers/middleware/index.js.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/batching/index.d.ts +0 -2
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/batching/index.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/batching/jest.config.d.ts +0 -16
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/batching/jest.config.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/batching/lib/batching.d.ts +0 -262
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/batching/lib/batching.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/batching/test-setup.d.ts +0 -2
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/batching/test-setup.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/computed/index.d.ts +0 -2
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/computed/index.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/computed/jest.config.d.ts +0 -16
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/computed/jest.config.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/computed/lib/computed.d.ts +0 -68
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/computed/lib/computed.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/devtools/index.d.ts +0 -2
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/devtools/index.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/devtools/jest.config.d.ts +0 -16
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/devtools/jest.config.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/devtools/lib/devtools.d.ts +0 -129
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/devtools/lib/devtools.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/devtools/test-setup.d.ts +0 -2
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/devtools/test-setup.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/entities/index.d.ts +0 -2
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/entities/index.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/entities/jest.config.d.ts +0 -16
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/entities/jest.config.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/entities/lib/entities.d.ts +0 -39
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/entities/lib/entities.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/entities/test-setup.d.ts +0 -2
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/entities/test-setup.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/index.d.ts +0 -38
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/index.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/memoization/index.d.ts +0 -2
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/memoization/index.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/memoization/jest.config.d.ts +0 -16
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/memoization/jest.config.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/memoization/lib/memoization.d.ts +0 -190
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/memoization/lib/memoization.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/memoization/test-setup.d.ts +0 -2
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/memoization/test-setup.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/middleware/index.d.ts +0 -3
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/middleware/index.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/middleware/jest.config.d.ts +0 -16
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/middleware/jest.config.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/middleware/lib/async-helpers.d.ts +0 -16
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/middleware/lib/async-helpers.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/middleware/lib/middleware.d.ts +0 -43
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/middleware/lib/middleware.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/middleware/test-setup.d.ts +0 -2
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/middleware/test-setup.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/presets/index.d.ts +0 -2
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/presets/index.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/presets/jest.config.d.ts +0 -16
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/presets/jest.config.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/presets/lib/presets.d.ts +0 -69
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/presets/lib/presets.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/presets/test-setup.d.ts +0 -2
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/presets/test-setup.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/serialization/constants.d.ts +0 -19
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/serialization/constants.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/serialization/index.d.ts +0 -3
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/serialization/index.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/serialization/jest.config.d.ts +0 -16
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/serialization/jest.config.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/serialization/lib/serialization.d.ts +0 -186
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/serialization/lib/serialization.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/serialization/test-setup.d.ts +0 -2
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/serialization/test-setup.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/time-travel/index.d.ts +0 -2
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/time-travel/index.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/time-travel/jest.config.d.ts +0 -16
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/time-travel/jest.config.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/time-travel/lib/time-travel.d.ts +0 -145
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/time-travel/lib/time-travel.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/time-travel/lib/utils.d.ts +0 -3
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/time-travel/lib/utils.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/time-travel/test-setup.d.ts +0 -2
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/time-travel/test-setup.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/types.d.ts +0 -112
- package/dist/enhancers/middleware/types/packages/core/src/enhancers/types.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/index.d.ts +0 -119
- package/dist/enhancers/middleware/types/packages/core/src/index.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/lib/constants.d.ts +0 -50
- package/dist/enhancers/middleware/types/packages/core/src/lib/constants.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/lib/memory/memory-manager.d.ts +0 -145
- package/dist/enhancers/middleware/types/packages/core/src/lib/memory/memory-manager.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/lib/performance/diff-engine.d.ts +0 -109
- package/dist/enhancers/middleware/types/packages/core/src/lib/performance/diff-engine.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/lib/performance/path-index.d.ts +0 -120
- package/dist/enhancers/middleware/types/packages/core/src/lib/performance/path-index.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/lib/performance/update-engine.d.ts +0 -116
- package/dist/enhancers/middleware/types/packages/core/src/lib/performance/update-engine.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/lib/security/security-validator.d.ts +0 -145
- package/dist/enhancers/middleware/types/packages/core/src/lib/security/security-validator.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/lib/signal-tree.d.ts +0 -17
- package/dist/enhancers/middleware/types/packages/core/src/lib/signal-tree.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/lib/types.d.ts +0 -299
- package/dist/enhancers/middleware/types/packages/core/src/lib/types.d.ts.map +0 -1
- package/dist/enhancers/middleware/types/packages/core/src/lib/utils.d.ts +0 -53
- package/dist/enhancers/middleware/types/packages/core/src/lib/utils.d.ts.map +0 -1
- package/dist/enhancers/presets/index.d.ts +0 -185
- package/dist/enhancers/presets/index.js +0 -170
- package/dist/enhancers/presets/index.js.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/batching/index.d.ts +0 -2
- package/dist/enhancers/presets/types/packages/core/src/enhancers/batching/index.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/batching/jest.config.d.ts +0 -16
- package/dist/enhancers/presets/types/packages/core/src/enhancers/batching/jest.config.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/batching/lib/batching.d.ts +0 -262
- package/dist/enhancers/presets/types/packages/core/src/enhancers/batching/lib/batching.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/batching/test-setup.d.ts +0 -2
- package/dist/enhancers/presets/types/packages/core/src/enhancers/batching/test-setup.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/computed/index.d.ts +0 -2
- package/dist/enhancers/presets/types/packages/core/src/enhancers/computed/index.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/computed/jest.config.d.ts +0 -16
- package/dist/enhancers/presets/types/packages/core/src/enhancers/computed/jest.config.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/computed/lib/computed.d.ts +0 -68
- package/dist/enhancers/presets/types/packages/core/src/enhancers/computed/lib/computed.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/devtools/index.d.ts +0 -2
- package/dist/enhancers/presets/types/packages/core/src/enhancers/devtools/index.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/devtools/jest.config.d.ts +0 -16
- package/dist/enhancers/presets/types/packages/core/src/enhancers/devtools/jest.config.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/devtools/lib/devtools.d.ts +0 -129
- package/dist/enhancers/presets/types/packages/core/src/enhancers/devtools/lib/devtools.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/devtools/test-setup.d.ts +0 -2
- package/dist/enhancers/presets/types/packages/core/src/enhancers/devtools/test-setup.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/entities/index.d.ts +0 -2
- package/dist/enhancers/presets/types/packages/core/src/enhancers/entities/index.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/entities/jest.config.d.ts +0 -16
- package/dist/enhancers/presets/types/packages/core/src/enhancers/entities/jest.config.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/entities/lib/entities.d.ts +0 -39
- package/dist/enhancers/presets/types/packages/core/src/enhancers/entities/lib/entities.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/entities/test-setup.d.ts +0 -2
- package/dist/enhancers/presets/types/packages/core/src/enhancers/entities/test-setup.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/index.d.ts +0 -38
- package/dist/enhancers/presets/types/packages/core/src/enhancers/index.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/memoization/index.d.ts +0 -2
- package/dist/enhancers/presets/types/packages/core/src/enhancers/memoization/index.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/memoization/jest.config.d.ts +0 -16
- package/dist/enhancers/presets/types/packages/core/src/enhancers/memoization/jest.config.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/memoization/lib/memoization.d.ts +0 -190
- package/dist/enhancers/presets/types/packages/core/src/enhancers/memoization/lib/memoization.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/memoization/test-setup.d.ts +0 -2
- package/dist/enhancers/presets/types/packages/core/src/enhancers/memoization/test-setup.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/middleware/index.d.ts +0 -3
- package/dist/enhancers/presets/types/packages/core/src/enhancers/middleware/index.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/middleware/jest.config.d.ts +0 -16
- package/dist/enhancers/presets/types/packages/core/src/enhancers/middleware/jest.config.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/middleware/lib/async-helpers.d.ts +0 -16
- package/dist/enhancers/presets/types/packages/core/src/enhancers/middleware/lib/async-helpers.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/middleware/lib/middleware.d.ts +0 -43
- package/dist/enhancers/presets/types/packages/core/src/enhancers/middleware/lib/middleware.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/middleware/test-setup.d.ts +0 -2
- package/dist/enhancers/presets/types/packages/core/src/enhancers/middleware/test-setup.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/presets/index.d.ts +0 -2
- package/dist/enhancers/presets/types/packages/core/src/enhancers/presets/index.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/presets/jest.config.d.ts +0 -16
- package/dist/enhancers/presets/types/packages/core/src/enhancers/presets/jest.config.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/presets/lib/presets.d.ts +0 -69
- package/dist/enhancers/presets/types/packages/core/src/enhancers/presets/lib/presets.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/presets/test-setup.d.ts +0 -2
- package/dist/enhancers/presets/types/packages/core/src/enhancers/presets/test-setup.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/serialization/constants.d.ts +0 -19
- package/dist/enhancers/presets/types/packages/core/src/enhancers/serialization/constants.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/serialization/index.d.ts +0 -3
- package/dist/enhancers/presets/types/packages/core/src/enhancers/serialization/index.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/serialization/jest.config.d.ts +0 -16
- package/dist/enhancers/presets/types/packages/core/src/enhancers/serialization/jest.config.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/serialization/lib/serialization.d.ts +0 -186
- package/dist/enhancers/presets/types/packages/core/src/enhancers/serialization/lib/serialization.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/serialization/test-setup.d.ts +0 -2
- package/dist/enhancers/presets/types/packages/core/src/enhancers/serialization/test-setup.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/time-travel/index.d.ts +0 -2
- package/dist/enhancers/presets/types/packages/core/src/enhancers/time-travel/index.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/time-travel/jest.config.d.ts +0 -16
- package/dist/enhancers/presets/types/packages/core/src/enhancers/time-travel/jest.config.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/time-travel/lib/time-travel.d.ts +0 -145
- package/dist/enhancers/presets/types/packages/core/src/enhancers/time-travel/lib/time-travel.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/time-travel/lib/utils.d.ts +0 -3
- package/dist/enhancers/presets/types/packages/core/src/enhancers/time-travel/lib/utils.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/time-travel/test-setup.d.ts +0 -2
- package/dist/enhancers/presets/types/packages/core/src/enhancers/time-travel/test-setup.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/enhancers/types.d.ts +0 -112
- package/dist/enhancers/presets/types/packages/core/src/enhancers/types.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/index.d.ts +0 -119
- package/dist/enhancers/presets/types/packages/core/src/index.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/lib/constants.d.ts +0 -50
- package/dist/enhancers/presets/types/packages/core/src/lib/constants.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/lib/memory/memory-manager.d.ts +0 -145
- package/dist/enhancers/presets/types/packages/core/src/lib/memory/memory-manager.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/lib/performance/diff-engine.d.ts +0 -109
- package/dist/enhancers/presets/types/packages/core/src/lib/performance/diff-engine.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/lib/performance/path-index.d.ts +0 -120
- package/dist/enhancers/presets/types/packages/core/src/lib/performance/path-index.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/lib/performance/update-engine.d.ts +0 -116
- package/dist/enhancers/presets/types/packages/core/src/lib/performance/update-engine.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/lib/security/security-validator.d.ts +0 -145
- package/dist/enhancers/presets/types/packages/core/src/lib/security/security-validator.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/lib/signal-tree.d.ts +0 -17
- package/dist/enhancers/presets/types/packages/core/src/lib/signal-tree.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/lib/types.d.ts +0 -299
- package/dist/enhancers/presets/types/packages/core/src/lib/types.d.ts.map +0 -1
- package/dist/enhancers/presets/types/packages/core/src/lib/utils.d.ts +0 -53
- package/dist/enhancers/presets/types/packages/core/src/lib/utils.d.ts.map +0 -1
- package/dist/enhancers/serialization/index.d.ts +0 -439
- package/dist/enhancers/serialization/index.js +0 -837
- package/dist/enhancers/serialization/index.js.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/batching/index.d.ts +0 -2
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/batching/index.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/batching/jest.config.d.ts +0 -16
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/batching/jest.config.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/batching/lib/batching.d.ts +0 -262
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/batching/lib/batching.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/batching/test-setup.d.ts +0 -2
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/batching/test-setup.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/computed/index.d.ts +0 -2
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/computed/index.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/computed/jest.config.d.ts +0 -16
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/computed/jest.config.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/computed/lib/computed.d.ts +0 -68
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/computed/lib/computed.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/devtools/index.d.ts +0 -2
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/devtools/index.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/devtools/jest.config.d.ts +0 -16
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/devtools/jest.config.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/devtools/lib/devtools.d.ts +0 -129
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/devtools/lib/devtools.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/devtools/test-setup.d.ts +0 -2
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/devtools/test-setup.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/entities/index.d.ts +0 -2
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/entities/index.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/entities/jest.config.d.ts +0 -16
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/entities/jest.config.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/entities/lib/entities.d.ts +0 -39
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/entities/lib/entities.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/entities/test-setup.d.ts +0 -2
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/entities/test-setup.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/index.d.ts +0 -38
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/index.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/memoization/index.d.ts +0 -2
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/memoization/index.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/memoization/jest.config.d.ts +0 -16
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/memoization/jest.config.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/memoization/lib/memoization.d.ts +0 -190
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/memoization/lib/memoization.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/memoization/test-setup.d.ts +0 -2
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/memoization/test-setup.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/middleware/index.d.ts +0 -3
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/middleware/index.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/middleware/jest.config.d.ts +0 -16
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/middleware/jest.config.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/middleware/lib/async-helpers.d.ts +0 -16
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/middleware/lib/async-helpers.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/middleware/lib/middleware.d.ts +0 -43
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/middleware/lib/middleware.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/middleware/test-setup.d.ts +0 -2
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/middleware/test-setup.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/presets/index.d.ts +0 -2
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/presets/index.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/presets/jest.config.d.ts +0 -16
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/presets/jest.config.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/presets/lib/presets.d.ts +0 -69
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/presets/lib/presets.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/presets/test-setup.d.ts +0 -2
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/presets/test-setup.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/serialization/constants.d.ts +0 -19
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/serialization/constants.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/serialization/index.d.ts +0 -3
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/serialization/index.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/serialization/jest.config.d.ts +0 -16
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/serialization/jest.config.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/serialization/lib/serialization.d.ts +0 -186
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/serialization/lib/serialization.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/serialization/test-setup.d.ts +0 -2
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/serialization/test-setup.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/time-travel/index.d.ts +0 -2
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/time-travel/index.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/time-travel/jest.config.d.ts +0 -16
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/time-travel/jest.config.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/time-travel/lib/time-travel.d.ts +0 -145
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/time-travel/lib/time-travel.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/time-travel/lib/utils.d.ts +0 -3
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/time-travel/lib/utils.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/time-travel/test-setup.d.ts +0 -2
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/time-travel/test-setup.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/types.d.ts +0 -112
- package/dist/enhancers/serialization/types/packages/core/src/enhancers/types.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/index.d.ts +0 -119
- package/dist/enhancers/serialization/types/packages/core/src/index.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/lib/constants.d.ts +0 -50
- package/dist/enhancers/serialization/types/packages/core/src/lib/constants.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/lib/memory/memory-manager.d.ts +0 -145
- package/dist/enhancers/serialization/types/packages/core/src/lib/memory/memory-manager.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/lib/performance/diff-engine.d.ts +0 -109
- package/dist/enhancers/serialization/types/packages/core/src/lib/performance/diff-engine.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/lib/performance/path-index.d.ts +0 -120
- package/dist/enhancers/serialization/types/packages/core/src/lib/performance/path-index.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/lib/performance/update-engine.d.ts +0 -116
- package/dist/enhancers/serialization/types/packages/core/src/lib/performance/update-engine.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/lib/security/security-validator.d.ts +0 -145
- package/dist/enhancers/serialization/types/packages/core/src/lib/security/security-validator.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/lib/signal-tree.d.ts +0 -17
- package/dist/enhancers/serialization/types/packages/core/src/lib/signal-tree.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/lib/types.d.ts +0 -299
- package/dist/enhancers/serialization/types/packages/core/src/lib/types.d.ts.map +0 -1
- package/dist/enhancers/serialization/types/packages/core/src/lib/utils.d.ts +0 -53
- package/dist/enhancers/serialization/types/packages/core/src/lib/utils.d.ts.map +0 -1
- package/dist/enhancers/time-travel/index.d.ts +0 -380
- package/dist/enhancers/time-travel/index.js +0 -289
- package/dist/enhancers/time-travel/index.js.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/batching/index.d.ts +0 -2
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/batching/index.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/batching/jest.config.d.ts +0 -16
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/batching/jest.config.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/batching/lib/batching.d.ts +0 -262
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/batching/lib/batching.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/batching/test-setup.d.ts +0 -2
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/batching/test-setup.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/computed/index.d.ts +0 -2
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/computed/index.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/computed/jest.config.d.ts +0 -16
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/computed/jest.config.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/computed/lib/computed.d.ts +0 -68
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/computed/lib/computed.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/devtools/index.d.ts +0 -2
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/devtools/index.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/devtools/jest.config.d.ts +0 -16
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/devtools/jest.config.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/devtools/lib/devtools.d.ts +0 -129
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/devtools/lib/devtools.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/devtools/test-setup.d.ts +0 -2
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/devtools/test-setup.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/entities/index.d.ts +0 -2
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/entities/index.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/entities/jest.config.d.ts +0 -16
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/entities/jest.config.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/entities/lib/entities.d.ts +0 -39
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/entities/lib/entities.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/entities/test-setup.d.ts +0 -2
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/entities/test-setup.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/index.d.ts +0 -38
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/index.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/memoization/index.d.ts +0 -2
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/memoization/index.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/memoization/jest.config.d.ts +0 -16
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/memoization/jest.config.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/memoization/lib/memoization.d.ts +0 -190
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/memoization/lib/memoization.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/memoization/test-setup.d.ts +0 -2
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/memoization/test-setup.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/middleware/index.d.ts +0 -3
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/middleware/index.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/middleware/jest.config.d.ts +0 -16
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/middleware/jest.config.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/middleware/lib/async-helpers.d.ts +0 -16
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/middleware/lib/async-helpers.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/middleware/lib/middleware.d.ts +0 -43
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/middleware/lib/middleware.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/middleware/test-setup.d.ts +0 -2
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/middleware/test-setup.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/presets/index.d.ts +0 -2
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/presets/index.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/presets/jest.config.d.ts +0 -16
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/presets/jest.config.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/presets/lib/presets.d.ts +0 -69
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/presets/lib/presets.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/presets/test-setup.d.ts +0 -2
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/presets/test-setup.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/serialization/constants.d.ts +0 -19
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/serialization/constants.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/serialization/index.d.ts +0 -3
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/serialization/index.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/serialization/jest.config.d.ts +0 -16
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/serialization/jest.config.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/serialization/lib/serialization.d.ts +0 -186
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/serialization/lib/serialization.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/serialization/test-setup.d.ts +0 -2
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/serialization/test-setup.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/time-travel/index.d.ts +0 -2
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/time-travel/index.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/time-travel/jest.config.d.ts +0 -16
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/time-travel/jest.config.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/time-travel/lib/time-travel.d.ts +0 -145
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/time-travel/lib/time-travel.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/time-travel/lib/utils.d.ts +0 -3
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/time-travel/lib/utils.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/time-travel/test-setup.d.ts +0 -2
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/time-travel/test-setup.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/types.d.ts +0 -112
- package/dist/enhancers/time-travel/types/packages/core/src/enhancers/types.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/index.d.ts +0 -119
- package/dist/enhancers/time-travel/types/packages/core/src/index.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/lib/constants.d.ts +0 -50
- package/dist/enhancers/time-travel/types/packages/core/src/lib/constants.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/lib/memory/memory-manager.d.ts +0 -145
- package/dist/enhancers/time-travel/types/packages/core/src/lib/memory/memory-manager.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/lib/performance/diff-engine.d.ts +0 -109
- package/dist/enhancers/time-travel/types/packages/core/src/lib/performance/diff-engine.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/lib/performance/path-index.d.ts +0 -120
- package/dist/enhancers/time-travel/types/packages/core/src/lib/performance/path-index.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/lib/performance/update-engine.d.ts +0 -116
- package/dist/enhancers/time-travel/types/packages/core/src/lib/performance/update-engine.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/lib/security/security-validator.d.ts +0 -145
- package/dist/enhancers/time-travel/types/packages/core/src/lib/security/security-validator.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/lib/signal-tree.d.ts +0 -17
- package/dist/enhancers/time-travel/types/packages/core/src/lib/signal-tree.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/lib/types.d.ts +0 -299
- package/dist/enhancers/time-travel/types/packages/core/src/lib/types.d.ts.map +0 -1
- package/dist/enhancers/time-travel/types/packages/core/src/lib/utils.d.ts +0 -53
- package/dist/enhancers/time-travel/types/packages/core/src/lib/utils.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/batching/index.d.ts +0 -2
- package/dist/enhancers/types/packages/core/src/enhancers/batching/index.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/batching/jest.config.d.ts +0 -16
- package/dist/enhancers/types/packages/core/src/enhancers/batching/jest.config.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/batching/lib/batching.d.ts +0 -262
- package/dist/enhancers/types/packages/core/src/enhancers/batching/lib/batching.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/batching/test-setup.d.ts +0 -2
- package/dist/enhancers/types/packages/core/src/enhancers/batching/test-setup.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/computed/index.d.ts +0 -2
- package/dist/enhancers/types/packages/core/src/enhancers/computed/index.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/computed/jest.config.d.ts +0 -16
- package/dist/enhancers/types/packages/core/src/enhancers/computed/jest.config.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/computed/lib/computed.d.ts +0 -68
- package/dist/enhancers/types/packages/core/src/enhancers/computed/lib/computed.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/devtools/index.d.ts +0 -2
- package/dist/enhancers/types/packages/core/src/enhancers/devtools/index.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/devtools/jest.config.d.ts +0 -16
- package/dist/enhancers/types/packages/core/src/enhancers/devtools/jest.config.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/devtools/lib/devtools.d.ts +0 -129
- package/dist/enhancers/types/packages/core/src/enhancers/devtools/lib/devtools.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/devtools/test-setup.d.ts +0 -2
- package/dist/enhancers/types/packages/core/src/enhancers/devtools/test-setup.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/entities/index.d.ts +0 -2
- package/dist/enhancers/types/packages/core/src/enhancers/entities/index.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/entities/jest.config.d.ts +0 -16
- package/dist/enhancers/types/packages/core/src/enhancers/entities/jest.config.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/entities/lib/entities.d.ts +0 -39
- package/dist/enhancers/types/packages/core/src/enhancers/entities/lib/entities.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/entities/test-setup.d.ts +0 -2
- package/dist/enhancers/types/packages/core/src/enhancers/entities/test-setup.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/index.d.ts +0 -38
- package/dist/enhancers/types/packages/core/src/enhancers/index.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/memoization/index.d.ts +0 -2
- package/dist/enhancers/types/packages/core/src/enhancers/memoization/index.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/memoization/jest.config.d.ts +0 -16
- package/dist/enhancers/types/packages/core/src/enhancers/memoization/jest.config.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/memoization/lib/memoization.d.ts +0 -190
- package/dist/enhancers/types/packages/core/src/enhancers/memoization/lib/memoization.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/memoization/test-setup.d.ts +0 -2
- package/dist/enhancers/types/packages/core/src/enhancers/memoization/test-setup.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/middleware/index.d.ts +0 -3
- package/dist/enhancers/types/packages/core/src/enhancers/middleware/index.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/middleware/jest.config.d.ts +0 -16
- package/dist/enhancers/types/packages/core/src/enhancers/middleware/jest.config.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/middleware/lib/async-helpers.d.ts +0 -16
- package/dist/enhancers/types/packages/core/src/enhancers/middleware/lib/async-helpers.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/middleware/lib/middleware.d.ts +0 -43
- package/dist/enhancers/types/packages/core/src/enhancers/middleware/lib/middleware.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/middleware/test-setup.d.ts +0 -2
- package/dist/enhancers/types/packages/core/src/enhancers/middleware/test-setup.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/presets/index.d.ts +0 -2
- package/dist/enhancers/types/packages/core/src/enhancers/presets/index.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/presets/jest.config.d.ts +0 -16
- package/dist/enhancers/types/packages/core/src/enhancers/presets/jest.config.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/presets/lib/presets.d.ts +0 -69
- package/dist/enhancers/types/packages/core/src/enhancers/presets/lib/presets.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/presets/test-setup.d.ts +0 -2
- package/dist/enhancers/types/packages/core/src/enhancers/presets/test-setup.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/serialization/constants.d.ts +0 -19
- package/dist/enhancers/types/packages/core/src/enhancers/serialization/constants.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/serialization/index.d.ts +0 -3
- package/dist/enhancers/types/packages/core/src/enhancers/serialization/index.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/serialization/jest.config.d.ts +0 -16
- package/dist/enhancers/types/packages/core/src/enhancers/serialization/jest.config.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/serialization/lib/serialization.d.ts +0 -186
- package/dist/enhancers/types/packages/core/src/enhancers/serialization/lib/serialization.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/serialization/test-setup.d.ts +0 -2
- package/dist/enhancers/types/packages/core/src/enhancers/serialization/test-setup.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/time-travel/index.d.ts +0 -2
- package/dist/enhancers/types/packages/core/src/enhancers/time-travel/index.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/time-travel/jest.config.d.ts +0 -16
- package/dist/enhancers/types/packages/core/src/enhancers/time-travel/jest.config.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/time-travel/lib/time-travel.d.ts +0 -145
- package/dist/enhancers/types/packages/core/src/enhancers/time-travel/lib/time-travel.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/time-travel/lib/utils.d.ts +0 -3
- package/dist/enhancers/types/packages/core/src/enhancers/time-travel/lib/utils.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/time-travel/test-setup.d.ts +0 -2
- package/dist/enhancers/types/packages/core/src/enhancers/time-travel/test-setup.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/enhancers/types.d.ts +0 -112
- package/dist/enhancers/types/packages/core/src/enhancers/types.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/index.d.ts +0 -119
- package/dist/enhancers/types/packages/core/src/index.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/lib/constants.d.ts +0 -50
- package/dist/enhancers/types/packages/core/src/lib/constants.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/lib/memory/memory-manager.d.ts +0 -145
- package/dist/enhancers/types/packages/core/src/lib/memory/memory-manager.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/lib/performance/diff-engine.d.ts +0 -109
- package/dist/enhancers/types/packages/core/src/lib/performance/diff-engine.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/lib/performance/path-index.d.ts +0 -120
- package/dist/enhancers/types/packages/core/src/lib/performance/path-index.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/lib/performance/update-engine.d.ts +0 -116
- package/dist/enhancers/types/packages/core/src/lib/performance/update-engine.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/lib/security/security-validator.d.ts +0 -145
- package/dist/enhancers/types/packages/core/src/lib/security/security-validator.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/lib/signal-tree.d.ts +0 -17
- package/dist/enhancers/types/packages/core/src/lib/signal-tree.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/lib/types.d.ts +0 -299
- package/dist/enhancers/types/packages/core/src/lib/types.d.ts.map +0 -1
- package/dist/enhancers/types/packages/core/src/lib/utils.d.ts +0 -53
- package/dist/enhancers/types/packages/core/src/lib/utils.d.ts.map +0 -1
- package/dist/index.cjs +0 -4966
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.ts +0 -1384
- package/dist/index.js +0 -4900
- package/dist/index.js.map +0 -1
- package/dist/types/packages/core/src/enhancers/batching/index.d.ts +0 -2
- package/dist/types/packages/core/src/enhancers/batching/index.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/batching/jest.config.d.ts +0 -16
- package/dist/types/packages/core/src/enhancers/batching/jest.config.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/batching/lib/batching.d.ts +0 -262
- package/dist/types/packages/core/src/enhancers/batching/lib/batching.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/batching/test-setup.d.ts +0 -2
- package/dist/types/packages/core/src/enhancers/batching/test-setup.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/computed/index.d.ts +0 -2
- package/dist/types/packages/core/src/enhancers/computed/index.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/computed/jest.config.d.ts +0 -16
- package/dist/types/packages/core/src/enhancers/computed/jest.config.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/computed/lib/computed.d.ts +0 -68
- package/dist/types/packages/core/src/enhancers/computed/lib/computed.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/devtools/index.d.ts +0 -2
- package/dist/types/packages/core/src/enhancers/devtools/index.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/devtools/jest.config.d.ts +0 -16
- package/dist/types/packages/core/src/enhancers/devtools/jest.config.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/devtools/lib/devtools.d.ts +0 -129
- package/dist/types/packages/core/src/enhancers/devtools/lib/devtools.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/devtools/test-setup.d.ts +0 -2
- package/dist/types/packages/core/src/enhancers/devtools/test-setup.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/entities/index.d.ts +0 -2
- package/dist/types/packages/core/src/enhancers/entities/index.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/entities/jest.config.d.ts +0 -16
- package/dist/types/packages/core/src/enhancers/entities/jest.config.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/entities/lib/entities.d.ts +0 -39
- package/dist/types/packages/core/src/enhancers/entities/lib/entities.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/entities/test-setup.d.ts +0 -2
- package/dist/types/packages/core/src/enhancers/entities/test-setup.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/index.d.ts +0 -38
- package/dist/types/packages/core/src/enhancers/index.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/memoization/index.d.ts +0 -2
- package/dist/types/packages/core/src/enhancers/memoization/index.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/memoization/jest.config.d.ts +0 -16
- package/dist/types/packages/core/src/enhancers/memoization/jest.config.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/memoization/lib/memoization.d.ts +0 -190
- package/dist/types/packages/core/src/enhancers/memoization/lib/memoization.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/memoization/test-setup.d.ts +0 -2
- package/dist/types/packages/core/src/enhancers/memoization/test-setup.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/middleware/index.d.ts +0 -3
- package/dist/types/packages/core/src/enhancers/middleware/index.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/middleware/jest.config.d.ts +0 -16
- package/dist/types/packages/core/src/enhancers/middleware/jest.config.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/middleware/lib/async-helpers.d.ts +0 -16
- package/dist/types/packages/core/src/enhancers/middleware/lib/async-helpers.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/middleware/lib/middleware.d.ts +0 -43
- package/dist/types/packages/core/src/enhancers/middleware/lib/middleware.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/middleware/test-setup.d.ts +0 -2
- package/dist/types/packages/core/src/enhancers/middleware/test-setup.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/presets/index.d.ts +0 -2
- package/dist/types/packages/core/src/enhancers/presets/index.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/presets/jest.config.d.ts +0 -16
- package/dist/types/packages/core/src/enhancers/presets/jest.config.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/presets/lib/presets.d.ts +0 -69
- package/dist/types/packages/core/src/enhancers/presets/lib/presets.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/presets/test-setup.d.ts +0 -2
- package/dist/types/packages/core/src/enhancers/presets/test-setup.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/serialization/constants.d.ts +0 -19
- package/dist/types/packages/core/src/enhancers/serialization/constants.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/serialization/index.d.ts +0 -3
- package/dist/types/packages/core/src/enhancers/serialization/index.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/serialization/jest.config.d.ts +0 -16
- package/dist/types/packages/core/src/enhancers/serialization/jest.config.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/serialization/lib/serialization.d.ts +0 -186
- package/dist/types/packages/core/src/enhancers/serialization/lib/serialization.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/serialization/test-setup.d.ts +0 -2
- package/dist/types/packages/core/src/enhancers/serialization/test-setup.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/time-travel/index.d.ts +0 -2
- package/dist/types/packages/core/src/enhancers/time-travel/index.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/time-travel/jest.config.d.ts +0 -16
- package/dist/types/packages/core/src/enhancers/time-travel/jest.config.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/time-travel/lib/time-travel.d.ts +0 -145
- package/dist/types/packages/core/src/enhancers/time-travel/lib/time-travel.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/time-travel/lib/utils.d.ts +0 -3
- package/dist/types/packages/core/src/enhancers/time-travel/lib/utils.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/time-travel/test-setup.d.ts +0 -2
- package/dist/types/packages/core/src/enhancers/time-travel/test-setup.d.ts.map +0 -1
- package/dist/types/packages/core/src/enhancers/types.d.ts +0 -112
- package/dist/types/packages/core/src/enhancers/types.d.ts.map +0 -1
- package/dist/types/packages/core/src/index.d.ts +0 -119
- package/dist/types/packages/core/src/index.d.ts.map +0 -1
- package/dist/types/packages/core/src/lib/constants.d.ts +0 -50
- package/dist/types/packages/core/src/lib/constants.d.ts.map +0 -1
- package/dist/types/packages/core/src/lib/memory/memory-manager.d.ts +0 -145
- package/dist/types/packages/core/src/lib/memory/memory-manager.d.ts.map +0 -1
- package/dist/types/packages/core/src/lib/performance/diff-engine.d.ts +0 -109
- package/dist/types/packages/core/src/lib/performance/diff-engine.d.ts.map +0 -1
- package/dist/types/packages/core/src/lib/performance/path-index.d.ts +0 -120
- package/dist/types/packages/core/src/lib/performance/path-index.d.ts.map +0 -1
- package/dist/types/packages/core/src/lib/performance/update-engine.d.ts +0 -116
- package/dist/types/packages/core/src/lib/performance/update-engine.d.ts.map +0 -1
- package/dist/types/packages/core/src/lib/security/security-validator.d.ts +0 -145
- package/dist/types/packages/core/src/lib/security/security-validator.d.ts.map +0 -1
- package/dist/types/packages/core/src/lib/signal-tree.d.ts +0 -17
- package/dist/types/packages/core/src/lib/signal-tree.d.ts.map +0 -1
- package/dist/types/packages/core/src/lib/types.d.ts +0 -299
- package/dist/types/packages/core/src/lib/types.d.ts.map +0 -1
- package/dist/types/packages/core/src/lib/utils.d.ts +0 -53
- package/dist/types/packages/core/src/lib/utils.d.ts.map +0 -1
package/dist/index.js
DELETED
|
@@ -1,4900 +0,0 @@
|
|
|
1
|
-
import { isSignal, signal, computed, effect, inject, DestroyRef } from '@angular/core';
|
|
2
|
-
import { DEFAULT_PATH_CACHE_SIZE, isBuiltInObject, deepEqual, LRUCache, deepClone } from '@signaltree/shared';
|
|
3
|
-
export { deepEqual, deepEqual as equal, isBuiltInObject, parsePath } from '@signaltree/shared';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* SignalTree Constants
|
|
7
|
-
* Centralized configuration values and messages
|
|
8
|
-
*/
|
|
9
|
-
const SIGNAL_TREE_CONSTANTS = {
|
|
10
|
-
/** Cache configuration */
|
|
11
|
-
MAX_PATH_CACHE_SIZE: DEFAULT_PATH_CACHE_SIZE,
|
|
12
|
-
/** Performance thresholds */
|
|
13
|
-
LAZY_THRESHOLD: 50,
|
|
14
|
-
ESTIMATE_MAX_DEPTH: 3,
|
|
15
|
-
ESTIMATE_SAMPLE_SIZE_ARRAY: 3,
|
|
16
|
-
ESTIMATE_SAMPLE_SIZE_OBJECT: 5,
|
|
17
|
-
/** Default values */
|
|
18
|
-
DEFAULT_CACHE_SIZE: 100,
|
|
19
|
-
DEFAULT_BATCH_SIZE: 10,
|
|
20
|
-
};
|
|
21
|
-
// Full developer-facing messages
|
|
22
|
-
const DEV_MESSAGES = {
|
|
23
|
-
NULL_OR_UNDEFINED: 'null/undefined',
|
|
24
|
-
CIRCULAR_REF: 'circular ref',
|
|
25
|
-
UPDATER_INVALID: 'updater invalid',
|
|
26
|
-
LAZY_FALLBACK: 'lazy fallback',
|
|
27
|
-
SIGNAL_CREATION_FAILED: 'signal creation failed',
|
|
28
|
-
UPDATE_PATH_NOT_FOUND: 'update path not found',
|
|
29
|
-
UPDATE_FAILED: 'update failed',
|
|
30
|
-
ROLLBACK_FAILED: 'rollback failed',
|
|
31
|
-
CLEANUP_ERROR: 'cleanup error',
|
|
32
|
-
PRESET_UNKNOWN: 'unknown preset',
|
|
33
|
-
STRATEGY_SELECTION: 'strategy select',
|
|
34
|
-
TREE_DESTROYED: 'destroyed',
|
|
35
|
-
UPDATE_TRANSACTION: 'update tx',
|
|
36
|
-
BATCH_NOT_ENABLED: 'batching disabled',
|
|
37
|
-
MEMOIZE_NOT_ENABLED: 'memoize disabled',
|
|
38
|
-
MIDDLEWARE_NOT_AVAILABLE: 'middleware missing',
|
|
39
|
-
ENTITY_HELPERS_NOT_AVAILABLE: 'entity helpers missing',
|
|
40
|
-
ASYNC_ACTIONS_NOT_AVAILABLE: 'async actions missing',
|
|
41
|
-
TIME_TRAVEL_NOT_AVAILABLE: 'time travel missing',
|
|
42
|
-
OPTIMIZE_NOT_AVAILABLE: 'optimize missing',
|
|
43
|
-
UPDATE_OPTIMIZED_NOT_AVAILABLE: 'update optimized missing',
|
|
44
|
-
CACHE_NOT_AVAILABLE: 'cache missing',
|
|
45
|
-
PERFORMANCE_NOT_ENABLED: 'performance disabled',
|
|
46
|
-
ENHANCER_ORDER_FAILED: 'enhancer order failed',
|
|
47
|
-
ENHANCER_CYCLE_DETECTED: 'enhancer cycle',
|
|
48
|
-
ENHANCER_REQUIREMENT_MISSING: 'enhancer req missing',
|
|
49
|
-
ENHANCER_PROVIDES_MISSING: 'enhancer provides missing',
|
|
50
|
-
ENHANCER_FAILED: 'enhancer failed',
|
|
51
|
-
ENHANCER_NOT_FUNCTION: 'enhancer not function',
|
|
52
|
-
EFFECT_NO_CONTEXT: 'no angular context',
|
|
53
|
-
SUBSCRIBE_NO_CONTEXT: 'no angular context',
|
|
54
|
-
};
|
|
55
|
-
// Compact production messages (very short numeric codes) to keep bundles minimal.
|
|
56
|
-
// We map each key to a short numeric string like '0','1','2' to minimize bytes.
|
|
57
|
-
const PROD_MESSAGES = (() => {
|
|
58
|
-
const out = {};
|
|
59
|
-
let i = 0;
|
|
60
|
-
for (const k of Object.keys(DEV_MESSAGES)) {
|
|
61
|
-
out[k] = String(i++);
|
|
62
|
-
}
|
|
63
|
-
return out;
|
|
64
|
-
})();
|
|
65
|
-
// Avoid referencing the bare `process` identifier to keep builds free of Node
|
|
66
|
-
// type assumptions; use globalThis to check env when available.
|
|
67
|
-
const _isProdByEnv = Boolean(typeof globalThis === 'object' &&
|
|
68
|
-
globalThis !== null &&
|
|
69
|
-
'process' in globalThis &&
|
|
70
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
71
|
-
typeof globalThis.process === 'object' &&
|
|
72
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
73
|
-
'env' in globalThis.process &&
|
|
74
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
75
|
-
globalThis.process.env.NODE_ENV === 'production');
|
|
76
|
-
const _isDev = typeof ngDevMode !== 'undefined' ? Boolean(ngDevMode) : !_isProdByEnv;
|
|
77
|
-
const SIGNAL_TREE_MESSAGES = Object.freeze(_isDev
|
|
78
|
-
? DEV_MESSAGES
|
|
79
|
-
: PROD_MESSAGES);
|
|
80
|
-
|
|
81
|
-
/** Symbol key for enhancer metadata */
|
|
82
|
-
const ENHANCER_META = Symbol('signaltree:enhancer:meta');
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Helper to create an enhancer with metadata attached
|
|
86
|
-
*
|
|
87
|
-
* @param meta - Metadata describing the enhancer
|
|
88
|
-
* @param enhancerFn - The enhancer function
|
|
89
|
-
* @returns Enhancer function with metadata attached
|
|
90
|
-
*
|
|
91
|
-
* @example
|
|
92
|
-
* ```typescript
|
|
93
|
-
* const myEnhancer = createEnhancer(
|
|
94
|
-
* {
|
|
95
|
-
* name: 'myEnhancer',
|
|
96
|
-
* provides: ['feature1'],
|
|
97
|
-
* requires: ['feature2']
|
|
98
|
-
* },
|
|
99
|
-
* (tree) => {
|
|
100
|
-
* // Enhance the tree
|
|
101
|
-
* return { ...tree, feature1: true };
|
|
102
|
-
* }
|
|
103
|
-
* );
|
|
104
|
-
* ```
|
|
105
|
-
*/
|
|
106
|
-
function createEnhancer(meta, enhancerFn) {
|
|
107
|
-
const fn = enhancerFn;
|
|
108
|
-
try {
|
|
109
|
-
fn.metadata = meta;
|
|
110
|
-
// Also attach under symbol for third-party compatibility
|
|
111
|
-
try {
|
|
112
|
-
fn[ENHANCER_META] = meta;
|
|
113
|
-
}
|
|
114
|
-
catch {
|
|
115
|
-
// Ignore if property can't be set
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
catch {
|
|
119
|
-
// Ignore errors
|
|
120
|
-
}
|
|
121
|
-
return fn;
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Resolve enhancer order using topological sort based on dependencies
|
|
125
|
-
*
|
|
126
|
-
* @param enhancers - Array of enhancers to order
|
|
127
|
-
* @param availableCapabilities - Set of already available capabilities
|
|
128
|
-
* @param debugMode - Whether to log debug information
|
|
129
|
-
* @returns Ordered array of enhancers
|
|
130
|
-
*/
|
|
131
|
-
function resolveEnhancerOrder(enhancers, availableCapabilities = new Set(), debugMode = false) {
|
|
132
|
-
// Build nodes with metadata
|
|
133
|
-
const nodes = enhancers.map((e, idx) => ({
|
|
134
|
-
fn: e,
|
|
135
|
-
name: e.metadata && e.metadata.name
|
|
136
|
-
? String(e.metadata.name)
|
|
137
|
-
: `enhancer#${idx}`,
|
|
138
|
-
requires: new Set(e.metadata?.requires ?? []),
|
|
139
|
-
provides: new Set(e.metadata?.provides ?? []),
|
|
140
|
-
}));
|
|
141
|
-
// Build dependency graph
|
|
142
|
-
const adj = new Map();
|
|
143
|
-
const nameToNode = new Map();
|
|
144
|
-
for (const n of nodes) {
|
|
145
|
-
nameToNode.set(n.name, n);
|
|
146
|
-
adj.set(n.name, new Set());
|
|
147
|
-
}
|
|
148
|
-
// Create edges based on requirements
|
|
149
|
-
for (const a of nodes) {
|
|
150
|
-
for (const b of nodes) {
|
|
151
|
-
if (a === b)
|
|
152
|
-
continue;
|
|
153
|
-
for (const req of b.requires) {
|
|
154
|
-
// Skip if requirement is already satisfied
|
|
155
|
-
if (availableCapabilities.has(req))
|
|
156
|
-
continue;
|
|
157
|
-
if (a.provides.has(req)) {
|
|
158
|
-
// a must come before b
|
|
159
|
-
const set = adj.get(a.name);
|
|
160
|
-
if (set)
|
|
161
|
-
set.add(b.name);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
// Kahn's algorithm for topological sort
|
|
167
|
-
const inDegree = new Map();
|
|
168
|
-
for (const entry of adj.keys())
|
|
169
|
-
inDegree.set(entry, 0);
|
|
170
|
-
for (const [, outs] of adj) {
|
|
171
|
-
for (const to of outs)
|
|
172
|
-
inDegree.set(to, (inDegree.get(to) || 0) + 1);
|
|
173
|
-
}
|
|
174
|
-
const queue = [];
|
|
175
|
-
for (const [name, deg] of inDegree.entries()) {
|
|
176
|
-
if (deg === 0)
|
|
177
|
-
queue.push(name);
|
|
178
|
-
}
|
|
179
|
-
const ordered = [];
|
|
180
|
-
while (queue.length > 0) {
|
|
181
|
-
const n = queue.shift();
|
|
182
|
-
if (!n)
|
|
183
|
-
break;
|
|
184
|
-
ordered.push(n);
|
|
185
|
-
const outs = adj.get(n);
|
|
186
|
-
if (!outs)
|
|
187
|
-
continue;
|
|
188
|
-
for (const m of outs) {
|
|
189
|
-
inDegree.set(m, (inDegree.get(m) || 0) - 1);
|
|
190
|
-
if (inDegree.get(m) === 0)
|
|
191
|
-
queue.push(m);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
// Check for cycles
|
|
195
|
-
if (ordered.length !== nodes.length) {
|
|
196
|
-
if (debugMode) {
|
|
197
|
-
console.warn(SIGNAL_TREE_MESSAGES.ENHANCER_CYCLE_DETECTED);
|
|
198
|
-
}
|
|
199
|
-
return enhancers;
|
|
200
|
-
}
|
|
201
|
-
// Map ordered names back to enhancer functions
|
|
202
|
-
return ordered.map((name) => {
|
|
203
|
-
const n = nameToNode.get(name);
|
|
204
|
-
return (n ? n.fn : enhancers[0]);
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Memory Manager for SignalTree
|
|
210
|
-
* Provides automatic cleanup and memory leak prevention for lazy-loaded signal trees
|
|
211
|
-
* @packageDocumentation
|
|
212
|
-
*/
|
|
213
|
-
/**
|
|
214
|
-
* SignalMemoryManager
|
|
215
|
-
*
|
|
216
|
-
* Manages memory for lazy-loaded signal trees using WeakRef and FinalizationRegistry.
|
|
217
|
-
* Provides automatic cleanup when signals are no longer referenced, preventing memory leaks.
|
|
218
|
-
*
|
|
219
|
-
* Features:
|
|
220
|
-
* - WeakRef caches allow garbage collection when signals are unused
|
|
221
|
-
* - FinalizationRegistry automatically cleans up after GC
|
|
222
|
-
* - Stats API for memory profiling and monitoring
|
|
223
|
-
* - Manual dispose() for explicit cleanup
|
|
224
|
-
*
|
|
225
|
-
* @example
|
|
226
|
-
* ```ts
|
|
227
|
-
* const manager = new SignalMemoryManager({
|
|
228
|
-
* enableAutoCleanup: true,
|
|
229
|
-
* onCleanup: (path, stats) => {
|
|
230
|
-
* console.log(`Cleaned up signal at ${path}`, stats);
|
|
231
|
-
* }
|
|
232
|
-
* });
|
|
233
|
-
*
|
|
234
|
-
* // Cache a signal
|
|
235
|
-
* manager.cacheSignal('user.name', nameSignal);
|
|
236
|
-
*
|
|
237
|
-
* // Get cached signal (returns undefined if GC'd)
|
|
238
|
-
* const signal = manager.getSignal('user.name');
|
|
239
|
-
*
|
|
240
|
-
* // Get memory stats
|
|
241
|
-
* const stats = manager.getStats();
|
|
242
|
-
* console.log(`Memory: ${stats.estimatedMemoryBytes} bytes`);
|
|
243
|
-
*
|
|
244
|
-
* // Dispose all cached signals
|
|
245
|
-
* manager.dispose();
|
|
246
|
-
* ```
|
|
247
|
-
*/
|
|
248
|
-
class SignalMemoryManager {
|
|
249
|
-
cache = new Map();
|
|
250
|
-
registry = null;
|
|
251
|
-
config;
|
|
252
|
-
// Statistics
|
|
253
|
-
stats = {
|
|
254
|
-
cleanedUpSignals: 0,
|
|
255
|
-
peakCachedSignals: 0,
|
|
256
|
-
manualDisposes: 0,
|
|
257
|
-
};
|
|
258
|
-
constructor(config = {}) {
|
|
259
|
-
this.config = {
|
|
260
|
-
enableAutoCleanup: config.enableAutoCleanup ?? true,
|
|
261
|
-
debugMode: config.debugMode ?? false,
|
|
262
|
-
onCleanup: config.onCleanup ??
|
|
263
|
-
(() => {
|
|
264
|
-
// Default no-op
|
|
265
|
-
}),
|
|
266
|
-
};
|
|
267
|
-
// Set up FinalizationRegistry for automatic cleanup
|
|
268
|
-
if (this.config.enableAutoCleanup &&
|
|
269
|
-
typeof FinalizationRegistry !== 'undefined') {
|
|
270
|
-
this.registry = new FinalizationRegistry((path) => {
|
|
271
|
-
this.handleCleanup(path);
|
|
272
|
-
});
|
|
273
|
-
}
|
|
274
|
-
if (this.config.debugMode) {
|
|
275
|
-
console.log('[SignalMemoryManager] Initialized', {
|
|
276
|
-
autoCleanup: this.config.enableAutoCleanup,
|
|
277
|
-
hasRegistry: !!this.registry,
|
|
278
|
-
});
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
/**
|
|
282
|
-
* Cache a signal with WeakRef for automatic garbage collection
|
|
283
|
-
*
|
|
284
|
-
* @param path - Dot-notation path to the signal
|
|
285
|
-
* @param signal - The signal to cache
|
|
286
|
-
*/
|
|
287
|
-
cacheSignal(path, signal) {
|
|
288
|
-
// Create WeakRef to allow GC
|
|
289
|
-
const ref = new WeakRef(signal);
|
|
290
|
-
// Store in cache
|
|
291
|
-
const entry = {
|
|
292
|
-
ref,
|
|
293
|
-
path,
|
|
294
|
-
cachedAt: Date.now(),
|
|
295
|
-
};
|
|
296
|
-
this.cache.set(path, entry);
|
|
297
|
-
// Register for automatic cleanup
|
|
298
|
-
if (this.registry) {
|
|
299
|
-
this.registry.register(signal, path, signal);
|
|
300
|
-
}
|
|
301
|
-
// Update peak stats
|
|
302
|
-
const currentSize = this.cache.size;
|
|
303
|
-
if (currentSize > this.stats.peakCachedSignals) {
|
|
304
|
-
this.stats.peakCachedSignals = currentSize;
|
|
305
|
-
}
|
|
306
|
-
if (this.config.debugMode) {
|
|
307
|
-
console.log(`[SignalMemoryManager] Cached signal: ${path}`, {
|
|
308
|
-
cacheSize: currentSize,
|
|
309
|
-
peak: this.stats.peakCachedSignals,
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
/**
|
|
314
|
-
* Get a cached signal
|
|
315
|
-
* Returns undefined if the signal has been garbage collected
|
|
316
|
-
*
|
|
317
|
-
* @param path - Dot-notation path to the signal
|
|
318
|
-
* @returns The signal or undefined if GC'd
|
|
319
|
-
*/
|
|
320
|
-
getSignal(path) {
|
|
321
|
-
const entry = this.cache.get(path);
|
|
322
|
-
if (!entry) {
|
|
323
|
-
return undefined;
|
|
324
|
-
}
|
|
325
|
-
// Try to dereference the WeakRef
|
|
326
|
-
const signal = entry.ref.deref();
|
|
327
|
-
if (!signal) {
|
|
328
|
-
// Signal was garbage collected, remove from cache
|
|
329
|
-
this.cache.delete(path);
|
|
330
|
-
if (this.config.debugMode) {
|
|
331
|
-
console.log(`[SignalMemoryManager] Signal GC'd: ${path}`);
|
|
332
|
-
}
|
|
333
|
-
return undefined;
|
|
334
|
-
}
|
|
335
|
-
return signal;
|
|
336
|
-
}
|
|
337
|
-
/**
|
|
338
|
-
* Check if a signal is cached (even if potentially GC'd)
|
|
339
|
-
*
|
|
340
|
-
* @param path - Dot-notation path to the signal
|
|
341
|
-
* @returns true if the path exists in cache
|
|
342
|
-
*/
|
|
343
|
-
hasSignal(path) {
|
|
344
|
-
return this.cache.has(path);
|
|
345
|
-
}
|
|
346
|
-
/**
|
|
347
|
-
* Remove a signal from the cache
|
|
348
|
-
*
|
|
349
|
-
* @param path - Dot-notation path to the signal
|
|
350
|
-
* @returns true if the signal was removed
|
|
351
|
-
*/
|
|
352
|
-
removeSignal(path) {
|
|
353
|
-
const entry = this.cache.get(path);
|
|
354
|
-
if (!entry) {
|
|
355
|
-
return false;
|
|
356
|
-
}
|
|
357
|
-
// Unregister from FinalizationRegistry
|
|
358
|
-
const signal = entry.ref.deref();
|
|
359
|
-
if (signal && this.registry) {
|
|
360
|
-
this.registry.unregister(signal);
|
|
361
|
-
}
|
|
362
|
-
this.cache.delete(path);
|
|
363
|
-
if (this.config.debugMode) {
|
|
364
|
-
console.log(`[SignalMemoryManager] Removed signal: ${path}`);
|
|
365
|
-
}
|
|
366
|
-
return true;
|
|
367
|
-
}
|
|
368
|
-
/**
|
|
369
|
-
* Handle automatic cleanup from FinalizationRegistry
|
|
370
|
-
* @private
|
|
371
|
-
*/
|
|
372
|
-
handleCleanup(path) {
|
|
373
|
-
this.cache.delete(path);
|
|
374
|
-
this.stats.cleanedUpSignals++;
|
|
375
|
-
const currentStats = this.getStats();
|
|
376
|
-
if (this.config.debugMode) {
|
|
377
|
-
console.log(`[SignalMemoryManager] Auto cleanup: ${path}`, currentStats);
|
|
378
|
-
}
|
|
379
|
-
this.config.onCleanup(path, currentStats);
|
|
380
|
-
}
|
|
381
|
-
/**
|
|
382
|
-
* Get current memory statistics
|
|
383
|
-
*
|
|
384
|
-
* @returns Current memory stats
|
|
385
|
-
*/
|
|
386
|
-
getStats() {
|
|
387
|
-
// Clean up stale entries (where WeakRef.deref() returns undefined)
|
|
388
|
-
let validSignals = 0;
|
|
389
|
-
for (const [path, entry] of this.cache.entries()) {
|
|
390
|
-
if (entry.ref.deref()) {
|
|
391
|
-
validSignals++;
|
|
392
|
-
}
|
|
393
|
-
else {
|
|
394
|
-
// Remove stale entry
|
|
395
|
-
this.cache.delete(path);
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
// Rough estimate: each signal ~100 bytes (very approximate)
|
|
399
|
-
const estimatedMemoryBytes = validSignals * 100;
|
|
400
|
-
return {
|
|
401
|
-
cachedSignals: validSignals,
|
|
402
|
-
cleanedUpSignals: this.stats.cleanedUpSignals,
|
|
403
|
-
peakCachedSignals: this.stats.peakCachedSignals,
|
|
404
|
-
manualDisposes: this.stats.manualDisposes,
|
|
405
|
-
estimatedMemoryBytes,
|
|
406
|
-
};
|
|
407
|
-
}
|
|
408
|
-
/**
|
|
409
|
-
* Dispose all cached signals and clean up resources
|
|
410
|
-
* Call this when destroying a SignalTree to prevent memory leaks
|
|
411
|
-
*/
|
|
412
|
-
dispose() {
|
|
413
|
-
if (this.config.debugMode) {
|
|
414
|
-
console.log('[SignalMemoryManager] Disposing', {
|
|
415
|
-
cachedSignals: this.cache.size,
|
|
416
|
-
});
|
|
417
|
-
}
|
|
418
|
-
// Unregister all signals from FinalizationRegistry
|
|
419
|
-
if (this.registry) {
|
|
420
|
-
for (const entry of this.cache.values()) {
|
|
421
|
-
const signal = entry.ref.deref();
|
|
422
|
-
if (signal) {
|
|
423
|
-
this.registry.unregister(signal);
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
// Clear cache
|
|
428
|
-
this.cache.clear();
|
|
429
|
-
this.stats.manualDisposes++;
|
|
430
|
-
if (this.config.debugMode) {
|
|
431
|
-
console.log('[SignalMemoryManager] Disposed', this.getStats());
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
/**
|
|
435
|
-
* Get all cached signal paths (for debugging)
|
|
436
|
-
*
|
|
437
|
-
* @returns Array of cached signal paths
|
|
438
|
-
*/
|
|
439
|
-
getCachedPaths() {
|
|
440
|
-
const paths = [];
|
|
441
|
-
for (const [path, entry] of this.cache.entries()) {
|
|
442
|
-
// Only include if signal is still alive
|
|
443
|
-
if (entry.ref.deref()) {
|
|
444
|
-
paths.push(path);
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
return paths;
|
|
448
|
-
}
|
|
449
|
-
/**
|
|
450
|
-
* Clear all stale entries (where signals have been GC'd)
|
|
451
|
-
* Useful for freeing up cache Map memory
|
|
452
|
-
*
|
|
453
|
-
* @returns Number of stale entries removed
|
|
454
|
-
*/
|
|
455
|
-
clearStale() {
|
|
456
|
-
let removed = 0;
|
|
457
|
-
for (const [path, entry] of this.cache.entries()) {
|
|
458
|
-
if (!entry.ref.deref()) {
|
|
459
|
-
this.cache.delete(path);
|
|
460
|
-
removed++;
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
if (this.config.debugMode && removed > 0) {
|
|
464
|
-
console.log(`[SignalMemoryManager] Cleared ${removed} stale entries`);
|
|
465
|
-
}
|
|
466
|
-
return removed;
|
|
467
|
-
}
|
|
468
|
-
/**
|
|
469
|
-
* Reset all statistics
|
|
470
|
-
*/
|
|
471
|
-
resetStats() {
|
|
472
|
-
this.stats = {
|
|
473
|
-
cleanedUpSignals: 0,
|
|
474
|
-
peakCachedSignals: 0,
|
|
475
|
-
manualDisposes: 0,
|
|
476
|
-
};
|
|
477
|
-
if (this.config.debugMode) {
|
|
478
|
-
console.log('[SignalMemoryManager] Stats reset');
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
/**
|
|
484
|
-
* DiffEngine - Efficient change detection for tree updates
|
|
485
|
-
* @packageDocumentation
|
|
486
|
-
*/
|
|
487
|
-
/**
|
|
488
|
-
* Type of change detected
|
|
489
|
-
*/
|
|
490
|
-
var ChangeType;
|
|
491
|
-
(function (ChangeType) {
|
|
492
|
-
ChangeType["ADD"] = "add";
|
|
493
|
-
ChangeType["UPDATE"] = "update";
|
|
494
|
-
ChangeType["DELETE"] = "delete";
|
|
495
|
-
ChangeType["REPLACE"] = "replace";
|
|
496
|
-
})(ChangeType || (ChangeType = {}));
|
|
497
|
-
/**
|
|
498
|
-
* DiffEngine
|
|
499
|
-
*
|
|
500
|
-
* Efficiently detects changes between two objects to minimize unnecessary updates.
|
|
501
|
-
*
|
|
502
|
-
* Features:
|
|
503
|
-
* - Deep object comparison
|
|
504
|
-
* - Circular reference detection
|
|
505
|
-
* - Configurable equality checking
|
|
506
|
-
* - Array diffing (ordered and unordered)
|
|
507
|
-
* - Path tracking for precise updates
|
|
508
|
-
*
|
|
509
|
-
* @example
|
|
510
|
-
* ```ts
|
|
511
|
-
* const engine = new DiffEngine();
|
|
512
|
-
*
|
|
513
|
-
* const current = { user: { name: 'Alice', age: 30 } };
|
|
514
|
-
* const updates = { user: { name: 'Alice', age: 31 } };
|
|
515
|
-
*
|
|
516
|
-
* const diff = engine.diff(current, updates);
|
|
517
|
-
*
|
|
518
|
-
* console.log(diff.changes);
|
|
519
|
-
* // [{ type: 'update', path: ['user', 'age'], value: 31, oldValue: 30 }]
|
|
520
|
-
* ```
|
|
521
|
-
*/
|
|
522
|
-
class DiffEngine {
|
|
523
|
-
defaultOptions = {
|
|
524
|
-
maxDepth: 100,
|
|
525
|
-
detectDeletions: false,
|
|
526
|
-
ignoreArrayOrder: false,
|
|
527
|
-
equalityFn: (a, b) => a === b,
|
|
528
|
-
keyValidator: undefined,
|
|
529
|
-
};
|
|
530
|
-
/**
|
|
531
|
-
* Diff two objects and return changes
|
|
532
|
-
*
|
|
533
|
-
* @param current - Current state
|
|
534
|
-
* @param updates - Updated state
|
|
535
|
-
* @param options - Diff options
|
|
536
|
-
* @returns Diff result with all changes
|
|
537
|
-
*/
|
|
538
|
-
diff(current, updates, options = {}) {
|
|
539
|
-
const opts = { ...this.defaultOptions, ...options };
|
|
540
|
-
const changes = [];
|
|
541
|
-
const visited = new WeakSet();
|
|
542
|
-
this.traverse(current, updates, [], changes, visited, opts, 0);
|
|
543
|
-
return {
|
|
544
|
-
changes,
|
|
545
|
-
hasChanges: changes.length > 0,
|
|
546
|
-
};
|
|
547
|
-
}
|
|
548
|
-
/**
|
|
549
|
-
* Traverse and compare objects recursively
|
|
550
|
-
*/
|
|
551
|
-
traverse(curr, upd, path, changes, visited, opts, depth) {
|
|
552
|
-
// Depth limit
|
|
553
|
-
if (depth > opts.maxDepth) {
|
|
554
|
-
return;
|
|
555
|
-
}
|
|
556
|
-
// Handle primitives
|
|
557
|
-
if (typeof upd !== 'object' || upd === null) {
|
|
558
|
-
if (!opts.equalityFn(curr, upd)) {
|
|
559
|
-
changes.push({
|
|
560
|
-
type: curr === undefined ? ChangeType.ADD : ChangeType.UPDATE,
|
|
561
|
-
path: [...path],
|
|
562
|
-
value: upd,
|
|
563
|
-
oldValue: curr,
|
|
564
|
-
});
|
|
565
|
-
}
|
|
566
|
-
return;
|
|
567
|
-
}
|
|
568
|
-
// Circular reference detection
|
|
569
|
-
if (visited.has(upd)) {
|
|
570
|
-
return;
|
|
571
|
-
}
|
|
572
|
-
visited.add(upd);
|
|
573
|
-
// Handle arrays
|
|
574
|
-
if (Array.isArray(upd)) {
|
|
575
|
-
this.diffArrays(curr, upd, path, changes, visited, opts, depth);
|
|
576
|
-
return;
|
|
577
|
-
}
|
|
578
|
-
// Handle objects
|
|
579
|
-
if (!curr || typeof curr !== 'object' || Array.isArray(curr)) {
|
|
580
|
-
// Type mismatch - replace entire subtree
|
|
581
|
-
changes.push({
|
|
582
|
-
type: ChangeType.REPLACE,
|
|
583
|
-
path: [...path],
|
|
584
|
-
value: upd,
|
|
585
|
-
oldValue: curr,
|
|
586
|
-
});
|
|
587
|
-
return;
|
|
588
|
-
}
|
|
589
|
-
// Diff object properties
|
|
590
|
-
const currObj = curr;
|
|
591
|
-
const updObj = upd;
|
|
592
|
-
for (const key in updObj) {
|
|
593
|
-
if (Object.prototype.hasOwnProperty.call(updObj, key)) {
|
|
594
|
-
// Validate key for security (e.g., prevent prototype pollution)
|
|
595
|
-
if (opts.keyValidator && !opts.keyValidator(key)) {
|
|
596
|
-
// Skip dangerous keys silently
|
|
597
|
-
continue;
|
|
598
|
-
}
|
|
599
|
-
this.traverse(currObj[key], updObj[key], [...path, key], changes, visited, opts, depth + 1);
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
// Check for deletions if enabled
|
|
603
|
-
if (opts.detectDeletions) {
|
|
604
|
-
for (const key in currObj) {
|
|
605
|
-
if (Object.prototype.hasOwnProperty.call(currObj, key) &&
|
|
606
|
-
!(key in updObj)) {
|
|
607
|
-
changes.push({
|
|
608
|
-
type: ChangeType.DELETE,
|
|
609
|
-
path: [...path, key],
|
|
610
|
-
oldValue: currObj[key],
|
|
611
|
-
});
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
/**
|
|
617
|
-
* Diff arrays
|
|
618
|
-
*/
|
|
619
|
-
diffArrays(curr, upd, path, changes, visited, opts, depth) {
|
|
620
|
-
if (!Array.isArray(curr)) {
|
|
621
|
-
// Not an array - replace
|
|
622
|
-
changes.push({
|
|
623
|
-
type: ChangeType.REPLACE,
|
|
624
|
-
path: [...path],
|
|
625
|
-
value: upd,
|
|
626
|
-
oldValue: curr,
|
|
627
|
-
});
|
|
628
|
-
return;
|
|
629
|
-
}
|
|
630
|
-
if (opts.ignoreArrayOrder) {
|
|
631
|
-
this.diffArraysUnordered(curr, upd, path, changes, opts);
|
|
632
|
-
}
|
|
633
|
-
else {
|
|
634
|
-
this.diffArraysOrdered(curr, upd, path, changes, visited, opts, depth);
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
/**
|
|
638
|
-
* Diff arrays in order (index-based)
|
|
639
|
-
*/
|
|
640
|
-
diffArraysOrdered(curr, upd, path, changes, visited, opts, depth) {
|
|
641
|
-
// Check each index
|
|
642
|
-
const maxLength = Math.max(curr.length, upd.length);
|
|
643
|
-
for (let i = 0; i < maxLength; i++) {
|
|
644
|
-
if (i >= upd.length) {
|
|
645
|
-
// Deletion (if enabled)
|
|
646
|
-
if (opts.detectDeletions) {
|
|
647
|
-
changes.push({
|
|
648
|
-
type: ChangeType.DELETE,
|
|
649
|
-
path: [...path, i],
|
|
650
|
-
oldValue: curr[i],
|
|
651
|
-
});
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
else if (i >= curr.length) {
|
|
655
|
-
// Addition
|
|
656
|
-
changes.push({
|
|
657
|
-
type: ChangeType.ADD,
|
|
658
|
-
path: [...path, i],
|
|
659
|
-
value: upd[i],
|
|
660
|
-
});
|
|
661
|
-
}
|
|
662
|
-
else {
|
|
663
|
-
// Potential update
|
|
664
|
-
this.traverse(curr[i], upd[i], [...path, i], changes, visited, opts, depth + 1);
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
/**
|
|
669
|
-
* Diff arrays ignoring order (value-based)
|
|
670
|
-
*/
|
|
671
|
-
diffArraysUnordered(curr, upd, path, changes, opts) {
|
|
672
|
-
// Build value sets
|
|
673
|
-
const currSet = new Set(curr.map((v) => this.stringify(v)));
|
|
674
|
-
const updSet = new Set(upd.map((v) => this.stringify(v)));
|
|
675
|
-
// Find additions
|
|
676
|
-
upd.forEach((value, index) => {
|
|
677
|
-
const str = this.stringify(value);
|
|
678
|
-
if (!currSet.has(str)) {
|
|
679
|
-
changes.push({
|
|
680
|
-
type: ChangeType.ADD,
|
|
681
|
-
path: [...path, index],
|
|
682
|
-
value,
|
|
683
|
-
});
|
|
684
|
-
}
|
|
685
|
-
});
|
|
686
|
-
// Find deletions (if enabled)
|
|
687
|
-
if (opts.detectDeletions) {
|
|
688
|
-
curr.forEach((value, index) => {
|
|
689
|
-
const str = this.stringify(value);
|
|
690
|
-
if (!updSet.has(str)) {
|
|
691
|
-
changes.push({
|
|
692
|
-
type: ChangeType.DELETE,
|
|
693
|
-
path: [...path, index],
|
|
694
|
-
oldValue: value,
|
|
695
|
-
});
|
|
696
|
-
}
|
|
697
|
-
});
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
/**
|
|
701
|
-
* Stringify value for set comparison
|
|
702
|
-
*/
|
|
703
|
-
stringify(value) {
|
|
704
|
-
try {
|
|
705
|
-
return JSON.stringify(value);
|
|
706
|
-
}
|
|
707
|
-
catch {
|
|
708
|
-
return String(value);
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
/**
|
|
714
|
-
* Node in the Trie structure
|
|
715
|
-
*/
|
|
716
|
-
class TrieNode {
|
|
717
|
-
value = null;
|
|
718
|
-
children = new Map();
|
|
719
|
-
}
|
|
720
|
-
/**
|
|
721
|
-
* PathIndex
|
|
722
|
-
*
|
|
723
|
-
* Fast signal lookup using a Trie (prefix tree) data structure.
|
|
724
|
-
* Provides O(k) lookup time where k is the path length, regardless of total signals.
|
|
725
|
-
*
|
|
726
|
-
* Features:
|
|
727
|
-
* - Trie-based indexing for O(k) lookup
|
|
728
|
-
* - WeakRef caching for memory efficiency
|
|
729
|
-
* - Automatic cleanup of stale references
|
|
730
|
-
* - Prefix matching for batch operations
|
|
731
|
-
* - Path normalization
|
|
732
|
-
*
|
|
733
|
-
* @example
|
|
734
|
-
* ```ts
|
|
735
|
-
* const index = new PathIndex();
|
|
736
|
-
*
|
|
737
|
-
* // Index signals
|
|
738
|
-
* index.set(['user', 'name'], nameSignal);
|
|
739
|
-
* index.set(['user', 'email'], emailSignal);
|
|
740
|
-
*
|
|
741
|
-
* // Fast lookup
|
|
742
|
-
* const signal = index.get(['user', 'name']);
|
|
743
|
-
*
|
|
744
|
-
* // Prefix matching
|
|
745
|
-
* const userSignals = index.getByPrefix(['user']);
|
|
746
|
-
* // Returns: { name: nameSignal, email: emailSignal }
|
|
747
|
-
*
|
|
748
|
-
* // Check if path exists
|
|
749
|
-
* if (index.has(['user', 'name'])) {
|
|
750
|
-
* // ...
|
|
751
|
-
* }
|
|
752
|
-
* ```
|
|
753
|
-
*/
|
|
754
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
755
|
-
class PathIndex {
|
|
756
|
-
root = new TrieNode();
|
|
757
|
-
pathCache = new Map();
|
|
758
|
-
stats = {
|
|
759
|
-
hits: 0,
|
|
760
|
-
misses: 0,
|
|
761
|
-
sets: 0,
|
|
762
|
-
cleanups: 0,
|
|
763
|
-
};
|
|
764
|
-
/**
|
|
765
|
-
* Set a value at the given path
|
|
766
|
-
*
|
|
767
|
-
* @param path - Path segments
|
|
768
|
-
* @param value - Value to store
|
|
769
|
-
*/
|
|
770
|
-
set(path, signal) {
|
|
771
|
-
const pathStr = this.pathToString(path);
|
|
772
|
-
const ref = new WeakRef(signal);
|
|
773
|
-
// Update trie
|
|
774
|
-
let node = this.root;
|
|
775
|
-
for (const segment of path) {
|
|
776
|
-
const key = String(segment);
|
|
777
|
-
if (!node.children.has(key)) {
|
|
778
|
-
node.children.set(key, new TrieNode());
|
|
779
|
-
}
|
|
780
|
-
const nextNode = node.children.get(key);
|
|
781
|
-
if (!nextNode) {
|
|
782
|
-
throw new Error(`Failed to get node for key: ${key}`);
|
|
783
|
-
}
|
|
784
|
-
node = nextNode;
|
|
785
|
-
}
|
|
786
|
-
node.value = ref;
|
|
787
|
-
// Update cache for fast string lookups
|
|
788
|
-
this.pathCache.set(pathStr, ref);
|
|
789
|
-
this.stats.sets++;
|
|
790
|
-
}
|
|
791
|
-
/**
|
|
792
|
-
* Get value at the given path
|
|
793
|
-
*
|
|
794
|
-
* @param path - Path segments
|
|
795
|
-
* @returns Value if found and not GC'd, null otherwise
|
|
796
|
-
*/
|
|
797
|
-
get(path) {
|
|
798
|
-
const pathStr = this.pathToString(path);
|
|
799
|
-
// Try cache first
|
|
800
|
-
const cached = this.pathCache.get(pathStr);
|
|
801
|
-
if (cached) {
|
|
802
|
-
const value = cached.deref();
|
|
803
|
-
if (value) {
|
|
804
|
-
this.stats.hits++;
|
|
805
|
-
return value;
|
|
806
|
-
}
|
|
807
|
-
// Clean up dead reference
|
|
808
|
-
this.pathCache.delete(pathStr);
|
|
809
|
-
this.stats.cleanups++;
|
|
810
|
-
}
|
|
811
|
-
// Try trie
|
|
812
|
-
let node = this.root;
|
|
813
|
-
for (const segment of path) {
|
|
814
|
-
const key = String(segment);
|
|
815
|
-
node = node.children.get(key);
|
|
816
|
-
if (!node) {
|
|
817
|
-
this.stats.misses++;
|
|
818
|
-
return null;
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
if (node.value) {
|
|
822
|
-
const value = node.value.deref();
|
|
823
|
-
if (value) {
|
|
824
|
-
// Re-cache for next time
|
|
825
|
-
this.pathCache.set(pathStr, node.value);
|
|
826
|
-
this.stats.hits++;
|
|
827
|
-
return value;
|
|
828
|
-
}
|
|
829
|
-
// Clean up dead reference
|
|
830
|
-
node.value = null;
|
|
831
|
-
this.stats.cleanups++;
|
|
832
|
-
}
|
|
833
|
-
this.stats.misses++;
|
|
834
|
-
return null;
|
|
835
|
-
}
|
|
836
|
-
/**
|
|
837
|
-
* Check if path exists in index
|
|
838
|
-
*
|
|
839
|
-
* @param path - Path segments
|
|
840
|
-
* @returns True if path exists and value is not GC'd
|
|
841
|
-
*/
|
|
842
|
-
has(path) {
|
|
843
|
-
return this.get(path) !== null;
|
|
844
|
-
}
|
|
845
|
-
/**
|
|
846
|
-
* Get all values matching a prefix
|
|
847
|
-
*
|
|
848
|
-
* @param prefix - Path prefix
|
|
849
|
-
* @returns Map of relative paths to values
|
|
850
|
-
*/
|
|
851
|
-
getByPrefix(prefix) {
|
|
852
|
-
const results = new Map();
|
|
853
|
-
// Find the node at prefix
|
|
854
|
-
let node = this.root;
|
|
855
|
-
for (const segment of prefix) {
|
|
856
|
-
const key = String(segment);
|
|
857
|
-
node = node.children.get(key);
|
|
858
|
-
if (!node) {
|
|
859
|
-
return results; // Empty map
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
// Collect all descendants
|
|
863
|
-
this.collectDescendants(node, [], results);
|
|
864
|
-
return results;
|
|
865
|
-
}
|
|
866
|
-
/**
|
|
867
|
-
* Delete value at path
|
|
868
|
-
*
|
|
869
|
-
* @param path - Path segments
|
|
870
|
-
* @returns True if deleted, false if not found
|
|
871
|
-
*/
|
|
872
|
-
delete(path) {
|
|
873
|
-
const pathStr = this.pathToString(path);
|
|
874
|
-
// Remove from cache
|
|
875
|
-
this.pathCache.delete(pathStr);
|
|
876
|
-
// Remove from trie
|
|
877
|
-
let node = this.root;
|
|
878
|
-
const nodes = [node];
|
|
879
|
-
for (const segment of path) {
|
|
880
|
-
const key = String(segment);
|
|
881
|
-
node = node.children.get(key);
|
|
882
|
-
if (!node) {
|
|
883
|
-
return false;
|
|
884
|
-
}
|
|
885
|
-
nodes.push(node);
|
|
886
|
-
}
|
|
887
|
-
// Clear value
|
|
888
|
-
const hadValue = node.value !== null;
|
|
889
|
-
node.value = null;
|
|
890
|
-
// Clean up empty nodes (from leaf to root)
|
|
891
|
-
for (let i = nodes.length - 1; i > 0; i--) {
|
|
892
|
-
const current = nodes[i];
|
|
893
|
-
if (current.value === null && current.children.size === 0) {
|
|
894
|
-
const parent = nodes[i - 1];
|
|
895
|
-
const segment = path[i - 1];
|
|
896
|
-
parent.children.delete(String(segment));
|
|
897
|
-
}
|
|
898
|
-
else {
|
|
899
|
-
break; // Stop if node has value or children
|
|
900
|
-
}
|
|
901
|
-
}
|
|
902
|
-
return hadValue;
|
|
903
|
-
}
|
|
904
|
-
/**
|
|
905
|
-
* Clear all entries
|
|
906
|
-
*/
|
|
907
|
-
clear() {
|
|
908
|
-
this.root = new TrieNode();
|
|
909
|
-
this.pathCache.clear();
|
|
910
|
-
}
|
|
911
|
-
/**
|
|
912
|
-
* Get statistics
|
|
913
|
-
*
|
|
914
|
-
* @returns Index statistics
|
|
915
|
-
*/
|
|
916
|
-
getStats() {
|
|
917
|
-
const total = this.stats.hits + this.stats.misses;
|
|
918
|
-
const hitRate = total > 0 ? this.stats.hits / total : 0;
|
|
919
|
-
return {
|
|
920
|
-
...this.stats,
|
|
921
|
-
hitRate,
|
|
922
|
-
cacheSize: this.pathCache.size,
|
|
923
|
-
};
|
|
924
|
-
}
|
|
925
|
-
/**
|
|
926
|
-
* Build index from a tree structure
|
|
927
|
-
*
|
|
928
|
-
* @param tree - Tree object to index
|
|
929
|
-
* @param path - Current path (for recursion)
|
|
930
|
-
*/
|
|
931
|
-
buildFromTree(tree, path = []) {
|
|
932
|
-
if (!tree) {
|
|
933
|
-
return;
|
|
934
|
-
}
|
|
935
|
-
// Check if it's a signal using Angular's isSignal
|
|
936
|
-
if (isSignal(tree)) {
|
|
937
|
-
this.set(path, tree);
|
|
938
|
-
return;
|
|
939
|
-
}
|
|
940
|
-
// Only continue if it's an object (not a signal or primitive)
|
|
941
|
-
if (typeof tree !== 'object') {
|
|
942
|
-
return;
|
|
943
|
-
}
|
|
944
|
-
// Recursively index children
|
|
945
|
-
for (const [key, value] of Object.entries(tree)) {
|
|
946
|
-
this.buildFromTree(value, [...path, key]);
|
|
947
|
-
}
|
|
948
|
-
}
|
|
949
|
-
/**
|
|
950
|
-
* Convert path to string for caching
|
|
951
|
-
*/
|
|
952
|
-
pathToString(path) {
|
|
953
|
-
return path.join('.');
|
|
954
|
-
}
|
|
955
|
-
/**
|
|
956
|
-
* Collect all descendant values recursively
|
|
957
|
-
*/
|
|
958
|
-
collectDescendants(node, currentPath, results) {
|
|
959
|
-
// Add current node's value if it exists
|
|
960
|
-
if (node.value) {
|
|
961
|
-
const value = node.value.deref();
|
|
962
|
-
if (value) {
|
|
963
|
-
results.set(this.pathToString(currentPath), value);
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
// Recursively collect children
|
|
967
|
-
for (const [key, child] of node.children) {
|
|
968
|
-
this.collectDescendants(child, [...currentPath, key], results);
|
|
969
|
-
}
|
|
970
|
-
}
|
|
971
|
-
}
|
|
972
|
-
|
|
973
|
-
/**
|
|
974
|
-
* OptimizedUpdateEngine
|
|
975
|
-
*
|
|
976
|
-
* High-performance update engine using path indexing and diffing to minimize
|
|
977
|
-
* unnecessary signal updates.
|
|
978
|
-
*
|
|
979
|
-
* Features:
|
|
980
|
-
* - Diff-based updates (only update what changed)
|
|
981
|
-
* - Path indexing for O(k) lookups
|
|
982
|
-
* - Automatic batching for large updates
|
|
983
|
-
* - Priority-based patch ordering
|
|
984
|
-
* - Skip unchanged values
|
|
985
|
-
*
|
|
986
|
-
* @example
|
|
987
|
-
* ```ts
|
|
988
|
-
* const tree = signalTree(data, { useLazySignals: true });
|
|
989
|
-
* const engine = new OptimizedUpdateEngine(tree);
|
|
990
|
-
*
|
|
991
|
-
* // Optimized update - only changes what's different
|
|
992
|
-
* const result = engine.update({
|
|
993
|
-
* user: { name: 'Alice' } // Only updates if name changed
|
|
994
|
-
* });
|
|
995
|
-
*
|
|
996
|
-
* console.log(result.changedPaths); // ['user.name']
|
|
997
|
-
* console.log(result.duration); // ~2ms
|
|
998
|
-
* ```
|
|
999
|
-
*/
|
|
1000
|
-
class OptimizedUpdateEngine {
|
|
1001
|
-
pathIndex;
|
|
1002
|
-
diffEngine;
|
|
1003
|
-
constructor(tree) {
|
|
1004
|
-
this.pathIndex = new PathIndex();
|
|
1005
|
-
this.diffEngine = new DiffEngine();
|
|
1006
|
-
// Build initial index
|
|
1007
|
-
this.pathIndex.buildFromTree(tree);
|
|
1008
|
-
}
|
|
1009
|
-
/**
|
|
1010
|
-
* Update tree with optimizations
|
|
1011
|
-
*
|
|
1012
|
-
* @param tree - Current tree state
|
|
1013
|
-
* @param updates - Updates to apply
|
|
1014
|
-
* @param options - Update options
|
|
1015
|
-
* @returns Update result
|
|
1016
|
-
*/
|
|
1017
|
-
update(tree, updates, options = {}) {
|
|
1018
|
-
const startTime = performance.now();
|
|
1019
|
-
// Step 1: Generate diff to find actual changes
|
|
1020
|
-
const diffOptions = {};
|
|
1021
|
-
if (options.maxDepth !== undefined)
|
|
1022
|
-
diffOptions.maxDepth = options.maxDepth;
|
|
1023
|
-
if (options.ignoreArrayOrder !== undefined)
|
|
1024
|
-
diffOptions.ignoreArrayOrder = options.ignoreArrayOrder;
|
|
1025
|
-
if (options.equalityFn !== undefined)
|
|
1026
|
-
diffOptions.equalityFn = options.equalityFn;
|
|
1027
|
-
const diff = this.diffEngine.diff(tree, updates, diffOptions);
|
|
1028
|
-
if (diff.changes.length === 0) {
|
|
1029
|
-
// No actual changes, skip update entirely
|
|
1030
|
-
return {
|
|
1031
|
-
changed: false,
|
|
1032
|
-
duration: performance.now() - startTime,
|
|
1033
|
-
changedPaths: [],
|
|
1034
|
-
};
|
|
1035
|
-
}
|
|
1036
|
-
// Step 2: Convert diff to optimized patches
|
|
1037
|
-
const patches = this.createPatches(diff.changes);
|
|
1038
|
-
// Step 3: Sort patches for optimal application order
|
|
1039
|
-
const sortedPatches = this.sortPatches(patches);
|
|
1040
|
-
// Step 4: Apply patches with optional batching
|
|
1041
|
-
const result = options.batch
|
|
1042
|
-
? this.batchApplyPatches(tree, sortedPatches, options.batchSize)
|
|
1043
|
-
: this.applyPatches(tree, sortedPatches);
|
|
1044
|
-
const duration = performance.now() - startTime;
|
|
1045
|
-
return {
|
|
1046
|
-
changed: true,
|
|
1047
|
-
duration,
|
|
1048
|
-
changedPaths: result.appliedPaths,
|
|
1049
|
-
stats: {
|
|
1050
|
-
totalPaths: diff.changes.length,
|
|
1051
|
-
optimizedPaths: patches.length,
|
|
1052
|
-
batchedUpdates: result.batchCount,
|
|
1053
|
-
},
|
|
1054
|
-
};
|
|
1055
|
-
}
|
|
1056
|
-
/**
|
|
1057
|
-
* Rebuild path index from current tree state
|
|
1058
|
-
*
|
|
1059
|
-
* @param tree - Current tree
|
|
1060
|
-
*/
|
|
1061
|
-
rebuildIndex(tree) {
|
|
1062
|
-
this.pathIndex.clear();
|
|
1063
|
-
this.pathIndex.buildFromTree(tree);
|
|
1064
|
-
}
|
|
1065
|
-
/**
|
|
1066
|
-
* Get path index statistics
|
|
1067
|
-
*/
|
|
1068
|
-
getIndexStats() {
|
|
1069
|
-
return this.pathIndex.getStats();
|
|
1070
|
-
}
|
|
1071
|
-
/**
|
|
1072
|
-
* Creates optimized patches from diff changes
|
|
1073
|
-
*/
|
|
1074
|
-
createPatches(changes) {
|
|
1075
|
-
const patches = [];
|
|
1076
|
-
const processedPaths = new Set();
|
|
1077
|
-
for (const change of changes) {
|
|
1078
|
-
const pathStr = change.path.join('.');
|
|
1079
|
-
// Skip if parent path already processed (optimization)
|
|
1080
|
-
let skipPath = false;
|
|
1081
|
-
for (const processed of processedPaths) {
|
|
1082
|
-
if (pathStr.startsWith(processed + '.')) {
|
|
1083
|
-
skipPath = true;
|
|
1084
|
-
break;
|
|
1085
|
-
}
|
|
1086
|
-
}
|
|
1087
|
-
if (skipPath) {
|
|
1088
|
-
continue;
|
|
1089
|
-
}
|
|
1090
|
-
// Create patch based on change type
|
|
1091
|
-
const patch = this.createPatch(change);
|
|
1092
|
-
patches.push(patch);
|
|
1093
|
-
// Mark path as processed
|
|
1094
|
-
processedPaths.add(pathStr);
|
|
1095
|
-
// If this is an object replacement, skip child paths
|
|
1096
|
-
if (change.type === ChangeType.REPLACE &&
|
|
1097
|
-
typeof change.value === 'object') {
|
|
1098
|
-
processedPaths.add(pathStr);
|
|
1099
|
-
}
|
|
1100
|
-
}
|
|
1101
|
-
return patches;
|
|
1102
|
-
}
|
|
1103
|
-
/**
|
|
1104
|
-
* Creates a single patch from a change
|
|
1105
|
-
*/
|
|
1106
|
-
createPatch(change) {
|
|
1107
|
-
return {
|
|
1108
|
-
type: change.type,
|
|
1109
|
-
path: change.path,
|
|
1110
|
-
value: change.value,
|
|
1111
|
-
oldValue: change.oldValue,
|
|
1112
|
-
priority: this.calculatePriority(change),
|
|
1113
|
-
signal: this.pathIndex.get(change.path),
|
|
1114
|
-
};
|
|
1115
|
-
}
|
|
1116
|
-
/**
|
|
1117
|
-
* Calculates update priority for optimal ordering
|
|
1118
|
-
*/
|
|
1119
|
-
calculatePriority(change) {
|
|
1120
|
-
let priority = 0;
|
|
1121
|
-
// Shallow updates have higher priority
|
|
1122
|
-
priority += (10 - change.path.length) * 10;
|
|
1123
|
-
// Array updates have lower priority (more expensive)
|
|
1124
|
-
if (change.path.some((p) => typeof p === 'number')) {
|
|
1125
|
-
priority -= 20;
|
|
1126
|
-
}
|
|
1127
|
-
// Replace operations have higher priority than nested updates
|
|
1128
|
-
if (change.type === ChangeType.REPLACE) {
|
|
1129
|
-
priority += 30;
|
|
1130
|
-
}
|
|
1131
|
-
return priority;
|
|
1132
|
-
}
|
|
1133
|
-
/**
|
|
1134
|
-
* Sorts patches for optimal application
|
|
1135
|
-
*/
|
|
1136
|
-
sortPatches(patches) {
|
|
1137
|
-
return patches.sort((a, b) => {
|
|
1138
|
-
// Sort by priority (higher first)
|
|
1139
|
-
if (a.priority !== b.priority) {
|
|
1140
|
-
return b.priority - a.priority;
|
|
1141
|
-
}
|
|
1142
|
-
// Then by path depth (shallow first)
|
|
1143
|
-
return a.path.length - b.path.length;
|
|
1144
|
-
});
|
|
1145
|
-
}
|
|
1146
|
-
/**
|
|
1147
|
-
* Applies patches directly (no batching)
|
|
1148
|
-
*/
|
|
1149
|
-
applyPatches(tree, patches) {
|
|
1150
|
-
const appliedPaths = [];
|
|
1151
|
-
let updateCount = 0;
|
|
1152
|
-
for (const patch of patches) {
|
|
1153
|
-
if (this.applyPatch(patch, tree)) {
|
|
1154
|
-
appliedPaths.push(patch.path.join('.'));
|
|
1155
|
-
updateCount++;
|
|
1156
|
-
}
|
|
1157
|
-
}
|
|
1158
|
-
return {
|
|
1159
|
-
appliedPaths,
|
|
1160
|
-
updateCount,
|
|
1161
|
-
batchCount: 1,
|
|
1162
|
-
};
|
|
1163
|
-
}
|
|
1164
|
-
/**
|
|
1165
|
-
* Applies patches with batching for better performance
|
|
1166
|
-
*/
|
|
1167
|
-
batchApplyPatches(tree, patches, batchSize = 50) {
|
|
1168
|
-
const batches = [];
|
|
1169
|
-
for (let i = 0; i < patches.length; i += batchSize) {
|
|
1170
|
-
batches.push(patches.slice(i, i + batchSize));
|
|
1171
|
-
}
|
|
1172
|
-
const appliedPaths = [];
|
|
1173
|
-
let updateCount = 0;
|
|
1174
|
-
// Process patches in batches
|
|
1175
|
-
for (const currentBatch of batches) {
|
|
1176
|
-
for (const patch of currentBatch) {
|
|
1177
|
-
if (this.applyPatch(patch, tree)) {
|
|
1178
|
-
appliedPaths.push(patch.path.join('.'));
|
|
1179
|
-
updateCount++;
|
|
1180
|
-
}
|
|
1181
|
-
}
|
|
1182
|
-
}
|
|
1183
|
-
return {
|
|
1184
|
-
appliedPaths,
|
|
1185
|
-
updateCount,
|
|
1186
|
-
batchCount: batches.length,
|
|
1187
|
-
};
|
|
1188
|
-
}
|
|
1189
|
-
/**
|
|
1190
|
-
* Applies a single patch to the tree object
|
|
1191
|
-
*/
|
|
1192
|
-
applyPatch(patch, tree) {
|
|
1193
|
-
try {
|
|
1194
|
-
// First, try to update via signal if available
|
|
1195
|
-
if (patch.signal && isSignal(patch.signal) && 'set' in patch.signal) {
|
|
1196
|
-
const currentValue = patch.signal();
|
|
1197
|
-
// Only update if value actually changed
|
|
1198
|
-
if (this.isEqual(currentValue, patch.value)) {
|
|
1199
|
-
return false;
|
|
1200
|
-
}
|
|
1201
|
-
// Update the signal - this will handle reactivity
|
|
1202
|
-
patch.signal.set(patch.value);
|
|
1203
|
-
// After successful ADD, update the index
|
|
1204
|
-
if (patch.type === ChangeType.ADD && patch.value !== undefined) {
|
|
1205
|
-
this.pathIndex.set(patch.path, patch.signal);
|
|
1206
|
-
}
|
|
1207
|
-
return true;
|
|
1208
|
-
} // Fallback: Navigate to parent object and update directly
|
|
1209
|
-
let current = tree;
|
|
1210
|
-
for (let i = 0; i < patch.path.length - 1; i++) {
|
|
1211
|
-
const key = patch.path[i];
|
|
1212
|
-
current = current[key];
|
|
1213
|
-
if (!current || typeof current !== 'object') {
|
|
1214
|
-
return false;
|
|
1215
|
-
}
|
|
1216
|
-
}
|
|
1217
|
-
const lastKey = patch.path[patch.path.length - 1];
|
|
1218
|
-
// Only update if value actually changed
|
|
1219
|
-
if (this.isEqual(current[lastKey], patch.value)) {
|
|
1220
|
-
return false;
|
|
1221
|
-
}
|
|
1222
|
-
// Apply update directly to object
|
|
1223
|
-
current[lastKey] = patch.value;
|
|
1224
|
-
return true;
|
|
1225
|
-
}
|
|
1226
|
-
catch (error) {
|
|
1227
|
-
console.error(`Failed to apply patch at ${patch.path.join('.')}:`, error);
|
|
1228
|
-
return false;
|
|
1229
|
-
}
|
|
1230
|
-
}
|
|
1231
|
-
/**
|
|
1232
|
-
* Check equality
|
|
1233
|
-
*/
|
|
1234
|
-
isEqual(a, b) {
|
|
1235
|
-
// Fast path for primitives
|
|
1236
|
-
if (a === b) {
|
|
1237
|
-
return true;
|
|
1238
|
-
}
|
|
1239
|
-
if (typeof a !== typeof b) {
|
|
1240
|
-
return false;
|
|
1241
|
-
}
|
|
1242
|
-
if (typeof a !== 'object' || a === null || b === null) {
|
|
1243
|
-
return false;
|
|
1244
|
-
}
|
|
1245
|
-
// Deep equality for objects (simple version)
|
|
1246
|
-
try {
|
|
1247
|
-
return JSON.stringify(a) === JSON.stringify(b);
|
|
1248
|
-
}
|
|
1249
|
-
catch {
|
|
1250
|
-
return false;
|
|
1251
|
-
}
|
|
1252
|
-
}
|
|
1253
|
-
}
|
|
1254
|
-
|
|
1255
|
-
/**
|
|
1256
|
-
* Security validator for SignalTree to prevent common vulnerabilities
|
|
1257
|
-
* @packageDocumentation
|
|
1258
|
-
*/
|
|
1259
|
-
/**
|
|
1260
|
-
* Built-in dangerous keys that can lead to prototype pollution
|
|
1261
|
-
*/
|
|
1262
|
-
const DANGEROUS_KEYS = ['__proto__', 'constructor', 'prototype'];
|
|
1263
|
-
/**
|
|
1264
|
-
* Basic HTML tag pattern for XSS detection
|
|
1265
|
-
*/
|
|
1266
|
-
const HTML_TAG_PATTERN = /<[^>]*>/g;
|
|
1267
|
-
/**
|
|
1268
|
-
* Dangerous HTML patterns that should always be blocked
|
|
1269
|
-
*/
|
|
1270
|
-
const DANGEROUS_HTML_PATTERNS = [
|
|
1271
|
-
/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
|
|
1272
|
-
/on\w+\s*=/gi, // Event handlers like onclick=
|
|
1273
|
-
/javascript:/gi,
|
|
1274
|
-
/<iframe\b/gi,
|
|
1275
|
-
/<object\b/gi,
|
|
1276
|
-
/<embed\b/gi,
|
|
1277
|
-
];
|
|
1278
|
-
/**
|
|
1279
|
-
* SecurityValidator prevents common security vulnerabilities in SignalTree
|
|
1280
|
-
*
|
|
1281
|
-
* Features:
|
|
1282
|
-
* - Prototype pollution prevention (blocks __proto__, constructor, prototype)
|
|
1283
|
-
* - XSS prevention (sanitizes string values)
|
|
1284
|
-
* - Security event callbacks for monitoring
|
|
1285
|
-
* - Configurable validation rules
|
|
1286
|
-
*
|
|
1287
|
-
* @example
|
|
1288
|
-
* ```ts
|
|
1289
|
-
* const validator = new SecurityValidator({
|
|
1290
|
-
* preventPrototypePollution: true,
|
|
1291
|
-
* preventXSS: true,
|
|
1292
|
-
* onSecurityEvent: (event) => console.warn('Security event:', event)
|
|
1293
|
-
* });
|
|
1294
|
-
*
|
|
1295
|
-
* // This will throw an error
|
|
1296
|
-
* validator.validateKey('__proto__');
|
|
1297
|
-
*
|
|
1298
|
-
* // This will sanitize the value
|
|
1299
|
-
* const safe = validator.validateValue('<script>alert("xss")</script>');
|
|
1300
|
-
* ```
|
|
1301
|
-
*/
|
|
1302
|
-
class SecurityValidator {
|
|
1303
|
-
config;
|
|
1304
|
-
dangerousKeys;
|
|
1305
|
-
constructor(config = {}) {
|
|
1306
|
-
this.config = {
|
|
1307
|
-
preventPrototypePollution: config.preventPrototypePollution ?? true,
|
|
1308
|
-
preventXSS: config.preventXSS ?? false,
|
|
1309
|
-
preventFunctions: config.preventFunctions ?? true,
|
|
1310
|
-
customDangerousKeys: config.customDangerousKeys ?? [],
|
|
1311
|
-
onSecurityEvent: config.onSecurityEvent ??
|
|
1312
|
-
(() => {
|
|
1313
|
-
// Default no-op callback
|
|
1314
|
-
}),
|
|
1315
|
-
sanitizationMode: config.sanitizationMode ?? 'strict',
|
|
1316
|
-
};
|
|
1317
|
-
// Build set of dangerous keys for O(1) lookup
|
|
1318
|
-
this.dangerousKeys = new Set([
|
|
1319
|
-
...DANGEROUS_KEYS,
|
|
1320
|
-
...this.config.customDangerousKeys,
|
|
1321
|
-
]);
|
|
1322
|
-
}
|
|
1323
|
-
/**
|
|
1324
|
-
* Validate a key to prevent prototype pollution
|
|
1325
|
-
*
|
|
1326
|
-
* @param key - The key to validate
|
|
1327
|
-
* @throws Error if the key is dangerous and validation is enabled
|
|
1328
|
-
*/
|
|
1329
|
-
validateKey(key) {
|
|
1330
|
-
if (!this.config.preventPrototypePollution) {
|
|
1331
|
-
return;
|
|
1332
|
-
}
|
|
1333
|
-
if (this.dangerousKeys.has(key)) {
|
|
1334
|
-
const event = {
|
|
1335
|
-
type: 'dangerous-key-blocked',
|
|
1336
|
-
key,
|
|
1337
|
-
reason: `Dangerous key "${key}" blocked to prevent prototype pollution`,
|
|
1338
|
-
timestamp: Date.now(),
|
|
1339
|
-
};
|
|
1340
|
-
this.config.onSecurityEvent(event);
|
|
1341
|
-
throw new Error(`[SignalTree Security] Dangerous key "${key}" is not allowed. ` +
|
|
1342
|
-
`This key can lead to prototype pollution attacks. ` +
|
|
1343
|
-
`Blocked keys: ${Array.from(this.dangerousKeys).join(', ')}`);
|
|
1344
|
-
}
|
|
1345
|
-
}
|
|
1346
|
-
/**
|
|
1347
|
-
* Validate and sanitize a value to prevent XSS and block functions
|
|
1348
|
-
*
|
|
1349
|
-
* @param value - The value to validate
|
|
1350
|
-
* @returns The sanitized value (or original if not a string or validation disabled)
|
|
1351
|
-
* @throws Error if value is a function and preventFunctions is enabled
|
|
1352
|
-
*/
|
|
1353
|
-
validateValue(value) {
|
|
1354
|
-
// Block function values to ensure serializable state
|
|
1355
|
-
if (this.config.preventFunctions && typeof value === 'function') {
|
|
1356
|
-
const event = {
|
|
1357
|
-
type: 'function-value-blocked',
|
|
1358
|
-
value,
|
|
1359
|
-
reason: 'Function values are not allowed - state must be serializable',
|
|
1360
|
-
timestamp: Date.now(),
|
|
1361
|
-
};
|
|
1362
|
-
this.config.onSecurityEvent(event);
|
|
1363
|
-
throw new Error(`[SignalTree Security] Function values are not allowed in state trees. ` +
|
|
1364
|
-
`Functions cannot be serialized, breaking features like time-travel, ` +
|
|
1365
|
-
`persistence, debugging, and SSR. ` +
|
|
1366
|
-
`\n\nTo fix this:` +
|
|
1367
|
-
`\n - Store function references outside the tree` +
|
|
1368
|
-
`\n - Use method names (strings) and a function registry` +
|
|
1369
|
-
`\n - Use computed signals for derived values` +
|
|
1370
|
-
`\n\nBlocked value: ${value.toString().substring(0, 100)}...`);
|
|
1371
|
-
}
|
|
1372
|
-
if (!this.config.preventXSS || typeof value !== 'string') {
|
|
1373
|
-
return value;
|
|
1374
|
-
}
|
|
1375
|
-
// Check for dangerous patterns first
|
|
1376
|
-
let hasDangerousPattern = false;
|
|
1377
|
-
for (const pattern of DANGEROUS_HTML_PATTERNS) {
|
|
1378
|
-
// Reset lastIndex for global regexes
|
|
1379
|
-
pattern.lastIndex = 0;
|
|
1380
|
-
if (pattern.test(value)) {
|
|
1381
|
-
hasDangerousPattern = true;
|
|
1382
|
-
break;
|
|
1383
|
-
}
|
|
1384
|
-
}
|
|
1385
|
-
if (hasDangerousPattern) {
|
|
1386
|
-
const event = {
|
|
1387
|
-
type: 'xss-attempt-blocked',
|
|
1388
|
-
value,
|
|
1389
|
-
reason: 'Dangerous HTML pattern detected and sanitized',
|
|
1390
|
-
timestamp: Date.now(),
|
|
1391
|
-
};
|
|
1392
|
-
this.config.onSecurityEvent(event);
|
|
1393
|
-
// In strict mode, remove all HTML
|
|
1394
|
-
// In permissive mode, we still block dangerous patterns
|
|
1395
|
-
return this.sanitize(value);
|
|
1396
|
-
}
|
|
1397
|
-
// Apply general sanitization based on mode
|
|
1398
|
-
return this.sanitize(value);
|
|
1399
|
-
}
|
|
1400
|
-
/**
|
|
1401
|
-
* Sanitize a string value based on the configured mode
|
|
1402
|
-
*
|
|
1403
|
-
* @param value - The string to sanitize
|
|
1404
|
-
* @returns The sanitized string
|
|
1405
|
-
*/
|
|
1406
|
-
sanitize(value) {
|
|
1407
|
-
if (this.config.sanitizationMode === 'strict') {
|
|
1408
|
-
// First remove dangerous patterns, then all HTML tags
|
|
1409
|
-
let sanitized = value;
|
|
1410
|
-
for (const pattern of DANGEROUS_HTML_PATTERNS) {
|
|
1411
|
-
// Reset lastIndex for global regexes
|
|
1412
|
-
pattern.lastIndex = 0;
|
|
1413
|
-
sanitized = sanitized.replace(pattern, '');
|
|
1414
|
-
}
|
|
1415
|
-
// Then remove all remaining HTML tags
|
|
1416
|
-
return sanitized.replace(HTML_TAG_PATTERN, '');
|
|
1417
|
-
}
|
|
1418
|
-
else {
|
|
1419
|
-
// Permissive mode: only remove dangerous patterns
|
|
1420
|
-
let sanitized = value;
|
|
1421
|
-
for (const pattern of DANGEROUS_HTML_PATTERNS) {
|
|
1422
|
-
// Reset lastIndex for global regexes
|
|
1423
|
-
pattern.lastIndex = 0;
|
|
1424
|
-
sanitized = sanitized.replace(pattern, '');
|
|
1425
|
-
}
|
|
1426
|
-
return sanitized;
|
|
1427
|
-
}
|
|
1428
|
-
}
|
|
1429
|
-
/**
|
|
1430
|
-
* Validate both key and value (convenience method)
|
|
1431
|
-
*
|
|
1432
|
-
* @param key - The key to validate
|
|
1433
|
-
* @param value - The value to validate
|
|
1434
|
-
* @returns The sanitized value
|
|
1435
|
-
*/
|
|
1436
|
-
validateKeyValue(key, value) {
|
|
1437
|
-
this.validateKey(key);
|
|
1438
|
-
return this.validateValue(value);
|
|
1439
|
-
}
|
|
1440
|
-
/**
|
|
1441
|
-
* Check if a key is dangerous without throwing
|
|
1442
|
-
*
|
|
1443
|
-
* @param key - The key to check
|
|
1444
|
-
* @returns true if the key is dangerous
|
|
1445
|
-
*/
|
|
1446
|
-
isDangerousKey(key) {
|
|
1447
|
-
return this.dangerousKeys.has(key);
|
|
1448
|
-
}
|
|
1449
|
-
/**
|
|
1450
|
-
* Get the current configuration
|
|
1451
|
-
*/
|
|
1452
|
-
getConfig() {
|
|
1453
|
-
return { ...this.config };
|
|
1454
|
-
}
|
|
1455
|
-
}
|
|
1456
|
-
/**
|
|
1457
|
-
* Create a SecurityValidator with common presets
|
|
1458
|
-
*/
|
|
1459
|
-
const SecurityPresets = {
|
|
1460
|
-
/**
|
|
1461
|
-
* Strict security: All protections enabled (recommended for production)
|
|
1462
|
-
*/
|
|
1463
|
-
strict: () => new SecurityValidator({
|
|
1464
|
-
preventPrototypePollution: true,
|
|
1465
|
-
preventXSS: true,
|
|
1466
|
-
preventFunctions: true,
|
|
1467
|
-
sanitizationMode: 'strict',
|
|
1468
|
-
}),
|
|
1469
|
-
/**
|
|
1470
|
-
* Standard security: Prototype pollution and function blocking (default)
|
|
1471
|
-
*/
|
|
1472
|
-
standard: () => new SecurityValidator({
|
|
1473
|
-
preventPrototypePollution: true,
|
|
1474
|
-
preventXSS: false,
|
|
1475
|
-
preventFunctions: true,
|
|
1476
|
-
}),
|
|
1477
|
-
/**
|
|
1478
|
-
* Permissive security: Only prototype pollution prevention
|
|
1479
|
-
* WARNING: Allows functions, breaking serialization features
|
|
1480
|
-
*/
|
|
1481
|
-
permissive: () => new SecurityValidator({
|
|
1482
|
-
preventPrototypePollution: true,
|
|
1483
|
-
preventXSS: false,
|
|
1484
|
-
preventFunctions: false,
|
|
1485
|
-
}),
|
|
1486
|
-
/**
|
|
1487
|
-
* Disabled: No security validations
|
|
1488
|
-
* DANGER: Not recommended - allows prototype pollution and functions
|
|
1489
|
-
*/
|
|
1490
|
-
disabled: () => new SecurityValidator({
|
|
1491
|
-
preventPrototypePollution: false,
|
|
1492
|
-
preventXSS: false,
|
|
1493
|
-
preventFunctions: false,
|
|
1494
|
-
}),
|
|
1495
|
-
};
|
|
1496
|
-
|
|
1497
|
-
/** Symbol to mark callable signals - using global symbol to match across files */
|
|
1498
|
-
const CALLABLE_SIGNAL_SYMBOL = Symbol.for('NodeAccessor');
|
|
1499
|
-
/**
|
|
1500
|
-
* Checks if a value is a node accessor created by makeNodeAccessor
|
|
1501
|
-
*/
|
|
1502
|
-
function isNodeAccessor$1(value) {
|
|
1503
|
-
return (typeof value === 'function' && value && CALLABLE_SIGNAL_SYMBOL in value);
|
|
1504
|
-
}
|
|
1505
|
-
/**
|
|
1506
|
-
* Checks if a value is either an Angular signal or a callable signal
|
|
1507
|
-
* This is useful for packages that need to work with both types
|
|
1508
|
-
*/
|
|
1509
|
-
function isAnySignal(value) {
|
|
1510
|
-
return isSignal(value) || isNodeAccessor$1(value);
|
|
1511
|
-
}
|
|
1512
|
-
function composeEnhancers(...enhancers) {
|
|
1513
|
-
return (tree) => enhancers.reduce((t, e) => e(t), tree);
|
|
1514
|
-
}
|
|
1515
|
-
/**
|
|
1516
|
-
* Creates a lazy signal tree using Proxy for on-demand signal creation
|
|
1517
|
-
*/
|
|
1518
|
-
function createLazySignalTree(obj, equalityFn, basePath = '', memoryManager) {
|
|
1519
|
-
const signalCache = new Map();
|
|
1520
|
-
const nestedProxies = new Map();
|
|
1521
|
-
const nestedCleanups = new Map();
|
|
1522
|
-
const cleanup = () => {
|
|
1523
|
-
nestedCleanups.forEach((fn) => {
|
|
1524
|
-
try {
|
|
1525
|
-
fn();
|
|
1526
|
-
}
|
|
1527
|
-
catch (error) {
|
|
1528
|
-
console.warn('Error during nested cleanup:', error);
|
|
1529
|
-
}
|
|
1530
|
-
});
|
|
1531
|
-
nestedCleanups.clear();
|
|
1532
|
-
signalCache.clear();
|
|
1533
|
-
nestedProxies.clear();
|
|
1534
|
-
// Clear from memory manager if provided
|
|
1535
|
-
if (memoryManager) {
|
|
1536
|
-
memoryManager.dispose();
|
|
1537
|
-
}
|
|
1538
|
-
};
|
|
1539
|
-
const proxy = new Proxy(obj, {
|
|
1540
|
-
get(target, prop) {
|
|
1541
|
-
if (prop === '__cleanup__')
|
|
1542
|
-
return cleanup;
|
|
1543
|
-
if (typeof prop === 'symbol') {
|
|
1544
|
-
return target[prop];
|
|
1545
|
-
}
|
|
1546
|
-
if (prop === 'valueOf' || prop === 'toString') {
|
|
1547
|
-
return target[prop];
|
|
1548
|
-
}
|
|
1549
|
-
const key = prop;
|
|
1550
|
-
const path = basePath ? `${basePath}.${key}` : key;
|
|
1551
|
-
if (!(key in target))
|
|
1552
|
-
return undefined;
|
|
1553
|
-
const value = target[key];
|
|
1554
|
-
if (isSignal(value))
|
|
1555
|
-
return value;
|
|
1556
|
-
// Check memory manager cache first
|
|
1557
|
-
if (memoryManager) {
|
|
1558
|
-
const cached = memoryManager.getSignal(path);
|
|
1559
|
-
if (cached)
|
|
1560
|
-
return cached;
|
|
1561
|
-
}
|
|
1562
|
-
if (signalCache.has(path))
|
|
1563
|
-
return signalCache.get(path);
|
|
1564
|
-
if (nestedProxies.has(path))
|
|
1565
|
-
return nestedProxies.get(path);
|
|
1566
|
-
if (value &&
|
|
1567
|
-
typeof value === 'object' &&
|
|
1568
|
-
!Array.isArray(value) &&
|
|
1569
|
-
!isSignal(value) &&
|
|
1570
|
-
!isBuiltInObject(value)) {
|
|
1571
|
-
try {
|
|
1572
|
-
const nestedProxy = createLazySignalTree(value, equalityFn, path, memoryManager);
|
|
1573
|
-
nestedProxies.set(path, nestedProxy);
|
|
1574
|
-
const proxyWithCleanup = nestedProxy;
|
|
1575
|
-
if (typeof proxyWithCleanup.__cleanup__ === 'function') {
|
|
1576
|
-
nestedCleanups.set(path, proxyWithCleanup.__cleanup__);
|
|
1577
|
-
}
|
|
1578
|
-
return nestedProxy;
|
|
1579
|
-
}
|
|
1580
|
-
catch (error) {
|
|
1581
|
-
console.warn(`Failed to create lazy proxy for path "${path}":`, error);
|
|
1582
|
-
const fallbackSignal = signal(value, { equal: equalityFn });
|
|
1583
|
-
signalCache.set(path, fallbackSignal);
|
|
1584
|
-
// Cache in memory manager
|
|
1585
|
-
if (memoryManager) {
|
|
1586
|
-
memoryManager.cacheSignal(path, fallbackSignal);
|
|
1587
|
-
}
|
|
1588
|
-
return fallbackSignal;
|
|
1589
|
-
}
|
|
1590
|
-
}
|
|
1591
|
-
try {
|
|
1592
|
-
const newSignal = signal(value, { equal: equalityFn });
|
|
1593
|
-
signalCache.set(path, newSignal);
|
|
1594
|
-
// Cache in memory manager
|
|
1595
|
-
if (memoryManager) {
|
|
1596
|
-
memoryManager.cacheSignal(path, newSignal);
|
|
1597
|
-
}
|
|
1598
|
-
return newSignal;
|
|
1599
|
-
}
|
|
1600
|
-
catch (error) {
|
|
1601
|
-
console.warn(`Failed to create signal for path "${path}":`, error);
|
|
1602
|
-
return value;
|
|
1603
|
-
}
|
|
1604
|
-
},
|
|
1605
|
-
set(target, prop, value) {
|
|
1606
|
-
if (typeof prop === 'symbol') {
|
|
1607
|
-
target[prop] = value;
|
|
1608
|
-
return true;
|
|
1609
|
-
}
|
|
1610
|
-
const key = prop;
|
|
1611
|
-
const path = basePath ? `${basePath}.${key}` : key;
|
|
1612
|
-
try {
|
|
1613
|
-
target[key] = value;
|
|
1614
|
-
const cachedSignal = signalCache.get(path);
|
|
1615
|
-
if (cachedSignal && 'set' in cachedSignal) {
|
|
1616
|
-
cachedSignal.set(value);
|
|
1617
|
-
}
|
|
1618
|
-
if (nestedProxies.has(path)) {
|
|
1619
|
-
const nestedCleanup = nestedCleanups.get(path);
|
|
1620
|
-
if (nestedCleanup) {
|
|
1621
|
-
nestedCleanup();
|
|
1622
|
-
nestedCleanups.delete(path);
|
|
1623
|
-
}
|
|
1624
|
-
nestedProxies.delete(path);
|
|
1625
|
-
}
|
|
1626
|
-
return true;
|
|
1627
|
-
}
|
|
1628
|
-
catch (error) {
|
|
1629
|
-
console.warn(`Failed to set value for path "${path}":`, error);
|
|
1630
|
-
return false;
|
|
1631
|
-
}
|
|
1632
|
-
},
|
|
1633
|
-
has(target, prop) {
|
|
1634
|
-
return prop in target;
|
|
1635
|
-
},
|
|
1636
|
-
ownKeys(target) {
|
|
1637
|
-
return Reflect.ownKeys(target);
|
|
1638
|
-
},
|
|
1639
|
-
getOwnPropertyDescriptor(target, prop) {
|
|
1640
|
-
return Reflect.getOwnPropertyDescriptor(target, prop);
|
|
1641
|
-
},
|
|
1642
|
-
});
|
|
1643
|
-
return proxy;
|
|
1644
|
-
}
|
|
1645
|
-
function unwrap(node) {
|
|
1646
|
-
if (node === null || node === undefined) {
|
|
1647
|
-
return node;
|
|
1648
|
-
}
|
|
1649
|
-
// Handle callable signals first
|
|
1650
|
-
if (isNodeAccessor$1(node)) {
|
|
1651
|
-
// For NodeAccessors, don't call them - read from their properties directly
|
|
1652
|
-
// This prevents infinite recursion when NodeAccessor calls unwrap(accessor)
|
|
1653
|
-
const result = {};
|
|
1654
|
-
for (const key in node) {
|
|
1655
|
-
if (!Object.prototype.hasOwnProperty.call(node, key))
|
|
1656
|
-
continue;
|
|
1657
|
-
// Skip function prototype properties only, not user properties
|
|
1658
|
-
if (key === 'length' || key === 'prototype')
|
|
1659
|
-
continue;
|
|
1660
|
-
// Special handling for 'name' - if it's a signal or NodeAccessor, include it
|
|
1661
|
-
if (key === 'name') {
|
|
1662
|
-
const value = node[key];
|
|
1663
|
-
if (!isSignal(value) && !isNodeAccessor$1(value)) {
|
|
1664
|
-
// Skip if it's just the function name property
|
|
1665
|
-
continue;
|
|
1666
|
-
}
|
|
1667
|
-
}
|
|
1668
|
-
const value = node[key];
|
|
1669
|
-
if (isNodeAccessor$1(value)) {
|
|
1670
|
-
result[key] = unwrap(value);
|
|
1671
|
-
}
|
|
1672
|
-
else if (isSignal(value)) {
|
|
1673
|
-
const unwrappedValue = value();
|
|
1674
|
-
if (typeof unwrappedValue === 'object' &&
|
|
1675
|
-
unwrappedValue !== null &&
|
|
1676
|
-
!Array.isArray(unwrappedValue) &&
|
|
1677
|
-
!isBuiltInObject(unwrappedValue)) {
|
|
1678
|
-
result[key] = unwrap(unwrappedValue);
|
|
1679
|
-
}
|
|
1680
|
-
else {
|
|
1681
|
-
result[key] = unwrappedValue;
|
|
1682
|
-
}
|
|
1683
|
-
}
|
|
1684
|
-
else if (typeof value === 'object' &&
|
|
1685
|
-
value !== null &&
|
|
1686
|
-
!Array.isArray(value) &&
|
|
1687
|
-
!isBuiltInObject(value)) {
|
|
1688
|
-
result[key] = unwrap(value);
|
|
1689
|
-
}
|
|
1690
|
-
else {
|
|
1691
|
-
result[key] = value;
|
|
1692
|
-
}
|
|
1693
|
-
}
|
|
1694
|
-
return result;
|
|
1695
|
-
}
|
|
1696
|
-
if (isSignal(node)) {
|
|
1697
|
-
const value = node();
|
|
1698
|
-
if (typeof value === 'object' &&
|
|
1699
|
-
value !== null &&
|
|
1700
|
-
!Array.isArray(value) &&
|
|
1701
|
-
!isBuiltInObject(value)) {
|
|
1702
|
-
return unwrap(value);
|
|
1703
|
-
}
|
|
1704
|
-
return value;
|
|
1705
|
-
}
|
|
1706
|
-
if (typeof node !== 'object') {
|
|
1707
|
-
return node;
|
|
1708
|
-
}
|
|
1709
|
-
if (Array.isArray(node)) {
|
|
1710
|
-
return node;
|
|
1711
|
-
}
|
|
1712
|
-
if (isBuiltInObject(node)) {
|
|
1713
|
-
return node;
|
|
1714
|
-
}
|
|
1715
|
-
const result = {};
|
|
1716
|
-
for (const key in node) {
|
|
1717
|
-
if (!Object.prototype.hasOwnProperty.call(node, key))
|
|
1718
|
-
continue;
|
|
1719
|
-
if (key === 'set' || key === 'update') {
|
|
1720
|
-
const v = node[key];
|
|
1721
|
-
if (typeof v === 'function')
|
|
1722
|
-
continue;
|
|
1723
|
-
}
|
|
1724
|
-
const value = node[key];
|
|
1725
|
-
if (isNodeAccessor$1(value)) {
|
|
1726
|
-
const unwrappedValue = value();
|
|
1727
|
-
if (typeof unwrappedValue === 'object' &&
|
|
1728
|
-
unwrappedValue !== null &&
|
|
1729
|
-
!Array.isArray(unwrappedValue) &&
|
|
1730
|
-
!isBuiltInObject(unwrappedValue)) {
|
|
1731
|
-
result[key] = unwrap(unwrappedValue);
|
|
1732
|
-
}
|
|
1733
|
-
else {
|
|
1734
|
-
result[key] = unwrappedValue;
|
|
1735
|
-
}
|
|
1736
|
-
}
|
|
1737
|
-
else if (isSignal(value)) {
|
|
1738
|
-
const unwrappedValue = value();
|
|
1739
|
-
if (typeof unwrappedValue === 'object' &&
|
|
1740
|
-
unwrappedValue !== null &&
|
|
1741
|
-
!Array.isArray(unwrappedValue) &&
|
|
1742
|
-
!isBuiltInObject(unwrappedValue)) {
|
|
1743
|
-
result[key] = unwrap(unwrappedValue);
|
|
1744
|
-
}
|
|
1745
|
-
else {
|
|
1746
|
-
result[key] = unwrappedValue;
|
|
1747
|
-
}
|
|
1748
|
-
}
|
|
1749
|
-
else if (typeof value === 'object' &&
|
|
1750
|
-
value !== null &&
|
|
1751
|
-
!Array.isArray(value) &&
|
|
1752
|
-
!isBuiltInObject(value)) {
|
|
1753
|
-
result[key] = unwrap(value);
|
|
1754
|
-
}
|
|
1755
|
-
else {
|
|
1756
|
-
result[key] = value;
|
|
1757
|
-
}
|
|
1758
|
-
}
|
|
1759
|
-
const symbols = Object.getOwnPropertySymbols(node);
|
|
1760
|
-
for (const sym of symbols) {
|
|
1761
|
-
const value = node[sym];
|
|
1762
|
-
if (isNodeAccessor$1(value)) {
|
|
1763
|
-
const unwrappedValue = value();
|
|
1764
|
-
if (typeof unwrappedValue === 'object' &&
|
|
1765
|
-
unwrappedValue !== null &&
|
|
1766
|
-
!Array.isArray(unwrappedValue) &&
|
|
1767
|
-
!isBuiltInObject(unwrappedValue)) {
|
|
1768
|
-
result[sym] = unwrap(unwrappedValue);
|
|
1769
|
-
}
|
|
1770
|
-
else {
|
|
1771
|
-
result[sym] = unwrappedValue;
|
|
1772
|
-
}
|
|
1773
|
-
}
|
|
1774
|
-
else if (isSignal(value)) {
|
|
1775
|
-
const unwrappedValue = value();
|
|
1776
|
-
if (typeof unwrappedValue === 'object' &&
|
|
1777
|
-
unwrappedValue !== null &&
|
|
1778
|
-
!Array.isArray(unwrappedValue) &&
|
|
1779
|
-
!isBuiltInObject(unwrappedValue)) {
|
|
1780
|
-
result[sym] = unwrap(unwrappedValue);
|
|
1781
|
-
}
|
|
1782
|
-
else {
|
|
1783
|
-
result[sym] = unwrappedValue;
|
|
1784
|
-
}
|
|
1785
|
-
}
|
|
1786
|
-
else if (typeof value === 'object' &&
|
|
1787
|
-
value !== null &&
|
|
1788
|
-
!Array.isArray(value) &&
|
|
1789
|
-
!isBuiltInObject(value)) {
|
|
1790
|
-
result[sym] = unwrap(value);
|
|
1791
|
-
}
|
|
1792
|
-
else {
|
|
1793
|
-
result[sym] = value;
|
|
1794
|
-
}
|
|
1795
|
-
}
|
|
1796
|
-
return result;
|
|
1797
|
-
}
|
|
1798
|
-
|
|
1799
|
-
// Global symbol for NodeAccessor identification
|
|
1800
|
-
const NODE_ACCESSOR_SYMBOL = Symbol.for('NodeAccessor');
|
|
1801
|
-
// Note: Callable syntax is supported via optional build-time transform only.
|
|
1802
|
-
// No runtime Proxy wrapping is applied to writable signals to keep zero-cost semantics.
|
|
1803
|
-
/**
|
|
1804
|
-
* Creates a callable NodeAccessor for nested objects WITHOUT a backing signal
|
|
1805
|
-
* This accessor reads from and writes to child signals directly
|
|
1806
|
-
*/
|
|
1807
|
-
function makeNodeAccessor() {
|
|
1808
|
-
const accessor = function (arg) {
|
|
1809
|
-
if (arguments.length === 0) {
|
|
1810
|
-
// Read from child signals - use the accessor itself as the context
|
|
1811
|
-
return unwrap(accessor);
|
|
1812
|
-
}
|
|
1813
|
-
if (typeof arg === 'function') {
|
|
1814
|
-
const updater = arg;
|
|
1815
|
-
const currentValue = unwrap(accessor);
|
|
1816
|
-
const newValue = updater(currentValue);
|
|
1817
|
-
recursiveUpdate(accessor, newValue);
|
|
1818
|
-
}
|
|
1819
|
-
else {
|
|
1820
|
-
// Direct set
|
|
1821
|
-
recursiveUpdate(accessor, arg);
|
|
1822
|
-
}
|
|
1823
|
-
};
|
|
1824
|
-
accessor[NODE_ACCESSOR_SYMBOL] = true;
|
|
1825
|
-
return accessor;
|
|
1826
|
-
}
|
|
1827
|
-
/**
|
|
1828
|
-
* Creates a NodeAccessor for the root tree that manages a backing signal
|
|
1829
|
-
*/
|
|
1830
|
-
function makeRootNodeAccessor(readSignal, writeSignal) {
|
|
1831
|
-
const accessor = function (arg) {
|
|
1832
|
-
if (arguments.length === 0) {
|
|
1833
|
-
return readSignal();
|
|
1834
|
-
}
|
|
1835
|
-
if (typeof arg === 'function') {
|
|
1836
|
-
const updater = arg;
|
|
1837
|
-
writeSignal.set(updater(readSignal()));
|
|
1838
|
-
}
|
|
1839
|
-
else {
|
|
1840
|
-
writeSignal.set(arg);
|
|
1841
|
-
}
|
|
1842
|
-
};
|
|
1843
|
-
accessor[NODE_ACCESSOR_SYMBOL] = true;
|
|
1844
|
-
return accessor;
|
|
1845
|
-
}
|
|
1846
|
-
function recursiveUpdate(target, updates) {
|
|
1847
|
-
if (!updates || typeof updates !== 'object') {
|
|
1848
|
-
return;
|
|
1849
|
-
}
|
|
1850
|
-
let targetObj;
|
|
1851
|
-
// Handle NodeAccessor (function) as target
|
|
1852
|
-
if (isNodeAccessor(target)) {
|
|
1853
|
-
targetObj = target;
|
|
1854
|
-
}
|
|
1855
|
-
else if (target && typeof target === 'object') {
|
|
1856
|
-
targetObj = target;
|
|
1857
|
-
}
|
|
1858
|
-
else {
|
|
1859
|
-
return;
|
|
1860
|
-
}
|
|
1861
|
-
const updatesObj = updates;
|
|
1862
|
-
for (const key in updatesObj) {
|
|
1863
|
-
if (!(key in targetObj)) {
|
|
1864
|
-
continue;
|
|
1865
|
-
}
|
|
1866
|
-
const targetProp = targetObj[key];
|
|
1867
|
-
const updateValue = updatesObj[key];
|
|
1868
|
-
if (isSignal(targetProp)) {
|
|
1869
|
-
// Leaf signal - check if it's writable
|
|
1870
|
-
if ('set' in targetProp && typeof targetProp.set === 'function') {
|
|
1871
|
-
targetProp.set(updateValue);
|
|
1872
|
-
}
|
|
1873
|
-
}
|
|
1874
|
-
else if (isNodeAccessor(targetProp)) {
|
|
1875
|
-
// For nested objects, check if updateValue is an object for recursive update
|
|
1876
|
-
if (updateValue && typeof updateValue === 'object') {
|
|
1877
|
-
recursiveUpdate(targetProp, updateValue);
|
|
1878
|
-
}
|
|
1879
|
-
else {
|
|
1880
|
-
// Direct value assignment
|
|
1881
|
-
targetProp(updateValue);
|
|
1882
|
-
}
|
|
1883
|
-
}
|
|
1884
|
-
}
|
|
1885
|
-
}
|
|
1886
|
-
/**
|
|
1887
|
-
* Checks if a value is a NodeAccessor
|
|
1888
|
-
*/
|
|
1889
|
-
function isNodeAccessor(value) {
|
|
1890
|
-
return (typeof value === 'function' &&
|
|
1891
|
-
value &&
|
|
1892
|
-
value[NODE_ACCESSOR_SYMBOL] === true);
|
|
1893
|
-
}
|
|
1894
|
-
// ============================================
|
|
1895
|
-
// PERFORMANCE HEURISTICS
|
|
1896
|
-
// ============================================
|
|
1897
|
-
function estimateObjectSize(obj, maxDepth = SIGNAL_TREE_CONSTANTS.ESTIMATE_MAX_DEPTH, currentDepth = 0) {
|
|
1898
|
-
if (currentDepth >= maxDepth)
|
|
1899
|
-
return 1;
|
|
1900
|
-
if (obj === null || obj === undefined)
|
|
1901
|
-
return 0;
|
|
1902
|
-
if (typeof obj !== 'object')
|
|
1903
|
-
return 1;
|
|
1904
|
-
let size = 0;
|
|
1905
|
-
try {
|
|
1906
|
-
if (Array.isArray(obj)) {
|
|
1907
|
-
size = obj.length;
|
|
1908
|
-
const sampleSize = Math.min(SIGNAL_TREE_CONSTANTS.ESTIMATE_SAMPLE_SIZE_ARRAY, obj.length);
|
|
1909
|
-
for (let i = 0; i < sampleSize; i++) {
|
|
1910
|
-
size += estimateObjectSize(obj[i], maxDepth, currentDepth + 1) * 0.1;
|
|
1911
|
-
}
|
|
1912
|
-
}
|
|
1913
|
-
else {
|
|
1914
|
-
const keys = Object.keys(obj);
|
|
1915
|
-
size = keys.length;
|
|
1916
|
-
const sampleSize = Math.min(SIGNAL_TREE_CONSTANTS.ESTIMATE_SAMPLE_SIZE_OBJECT, keys.length);
|
|
1917
|
-
for (let i = 0; i < sampleSize; i++) {
|
|
1918
|
-
const value = obj[keys[i]];
|
|
1919
|
-
size += estimateObjectSize(value, maxDepth, currentDepth + 1) * 0.5;
|
|
1920
|
-
}
|
|
1921
|
-
}
|
|
1922
|
-
}
|
|
1923
|
-
catch {
|
|
1924
|
-
return 1;
|
|
1925
|
-
}
|
|
1926
|
-
return Math.floor(size);
|
|
1927
|
-
}
|
|
1928
|
-
function shouldUseLazy(obj, config, precomputedSize) {
|
|
1929
|
-
if (config.useLazySignals !== undefined)
|
|
1930
|
-
return config.useLazySignals;
|
|
1931
|
-
if (config.debugMode || config.enableDevTools)
|
|
1932
|
-
return false;
|
|
1933
|
-
if (config.batchUpdates && config.useMemoization)
|
|
1934
|
-
return true;
|
|
1935
|
-
const estimatedSize = precomputedSize ?? estimateObjectSize(obj);
|
|
1936
|
-
return estimatedSize > SIGNAL_TREE_CONSTANTS.LAZY_THRESHOLD;
|
|
1937
|
-
}
|
|
1938
|
-
// ============================================
|
|
1939
|
-
// SECURITY VALIDATION
|
|
1940
|
-
// ============================================
|
|
1941
|
-
/**
|
|
1942
|
-
* Validates an object tree using SecurityValidator if configured
|
|
1943
|
-
* Throws if validation fails
|
|
1944
|
-
*/
|
|
1945
|
-
function validateTree(obj, config, path = []) {
|
|
1946
|
-
if (!config.security) {
|
|
1947
|
-
return; // No validation needed
|
|
1948
|
-
}
|
|
1949
|
-
const validator = new SecurityValidator(config.security);
|
|
1950
|
-
function validate(value, currentPath) {
|
|
1951
|
-
// Validate primitives and null/undefined
|
|
1952
|
-
if (value === null || value === undefined) {
|
|
1953
|
-
return;
|
|
1954
|
-
}
|
|
1955
|
-
if (typeof value !== 'object') {
|
|
1956
|
-
// Validate the value (this will catch functions)
|
|
1957
|
-
validator.validateValue(value);
|
|
1958
|
-
return;
|
|
1959
|
-
}
|
|
1960
|
-
// Skip built-in objects
|
|
1961
|
-
if (isBuiltInObject(value)) {
|
|
1962
|
-
return;
|
|
1963
|
-
}
|
|
1964
|
-
// Validate arrays
|
|
1965
|
-
if (Array.isArray(value)) {
|
|
1966
|
-
value.forEach((item, index) => {
|
|
1967
|
-
validate(item, [...currentPath, String(index)]);
|
|
1968
|
-
});
|
|
1969
|
-
return;
|
|
1970
|
-
}
|
|
1971
|
-
// Validate object keys and values
|
|
1972
|
-
// Use Reflect.ownKeys to catch all keys including __proto__
|
|
1973
|
-
const keys = [
|
|
1974
|
-
...Object.keys(value),
|
|
1975
|
-
...Object.getOwnPropertyNames(value),
|
|
1976
|
-
];
|
|
1977
|
-
const uniqueKeys = [...new Set(keys)];
|
|
1978
|
-
for (const key of uniqueKeys) {
|
|
1979
|
-
if (typeof key === 'symbol')
|
|
1980
|
-
continue;
|
|
1981
|
-
// Validate the key
|
|
1982
|
-
try {
|
|
1983
|
-
validator.validateKey(key);
|
|
1984
|
-
}
|
|
1985
|
-
catch (error) {
|
|
1986
|
-
const err = error;
|
|
1987
|
-
throw new Error(`${err.message}\nPath: ${[...currentPath, key].join('.')}`);
|
|
1988
|
-
}
|
|
1989
|
-
// Get the value
|
|
1990
|
-
const val = value[key];
|
|
1991
|
-
// Validate the value
|
|
1992
|
-
try {
|
|
1993
|
-
validator.validateValue(val);
|
|
1994
|
-
}
|
|
1995
|
-
catch (error) {
|
|
1996
|
-
const err = error;
|
|
1997
|
-
throw new Error(`${err.message}\nPath: ${[...currentPath, key].join('.')}`);
|
|
1998
|
-
}
|
|
1999
|
-
// Recursively validate nested objects
|
|
2000
|
-
validate(val, [...currentPath, key]);
|
|
2001
|
-
}
|
|
2002
|
-
}
|
|
2003
|
-
validate(obj, path);
|
|
2004
|
-
}
|
|
2005
|
-
function createEqualityFn(useShallowComparison) {
|
|
2006
|
-
return useShallowComparison ? Object.is : deepEqual;
|
|
2007
|
-
}
|
|
2008
|
-
// ============================================
|
|
2009
|
-
// SIGNAL CREATION
|
|
2010
|
-
// ============================================
|
|
2011
|
-
function createSignalStore(obj, equalityFn) {
|
|
2012
|
-
if (obj === null || obj === undefined || typeof obj !== 'object') {
|
|
2013
|
-
return signal(obj, { equal: equalityFn });
|
|
2014
|
-
}
|
|
2015
|
-
if (Array.isArray(obj)) {
|
|
2016
|
-
return signal(obj, { equal: equalityFn });
|
|
2017
|
-
}
|
|
2018
|
-
if (isBuiltInObject(obj)) {
|
|
2019
|
-
return signal(obj, { equal: equalityFn });
|
|
2020
|
-
}
|
|
2021
|
-
const store = {};
|
|
2022
|
-
const processedObjects = new WeakSet();
|
|
2023
|
-
if (processedObjects.has(obj)) {
|
|
2024
|
-
console.warn(SIGNAL_TREE_MESSAGES.CIRCULAR_REF);
|
|
2025
|
-
return signal(obj, { equal: equalityFn });
|
|
2026
|
-
}
|
|
2027
|
-
processedObjects.add(obj);
|
|
2028
|
-
try {
|
|
2029
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
2030
|
-
try {
|
|
2031
|
-
if (typeof key === 'symbol')
|
|
2032
|
-
continue;
|
|
2033
|
-
if (isSignal(value)) {
|
|
2034
|
-
// Preserve existing signals as-is
|
|
2035
|
-
store[key] = value;
|
|
2036
|
-
continue;
|
|
2037
|
-
}
|
|
2038
|
-
if (value === null || value === undefined) {
|
|
2039
|
-
store[key] = signal(value, {
|
|
2040
|
-
equal: equalityFn,
|
|
2041
|
-
});
|
|
2042
|
-
}
|
|
2043
|
-
else if (typeof value !== 'object') {
|
|
2044
|
-
store[key] = signal(value, {
|
|
2045
|
-
equal: equalityFn,
|
|
2046
|
-
});
|
|
2047
|
-
}
|
|
2048
|
-
else if (Array.isArray(value) || isBuiltInObject(value)) {
|
|
2049
|
-
store[key] = signal(value, {
|
|
2050
|
-
equal: equalityFn,
|
|
2051
|
-
});
|
|
2052
|
-
}
|
|
2053
|
-
else {
|
|
2054
|
-
// Nested object - create recursive structure
|
|
2055
|
-
const branch = createSignalStore(value, equalityFn);
|
|
2056
|
-
// Create a NodeAccessor for this nested object (no backing signal)
|
|
2057
|
-
const callableBranch = makeNodeAccessor();
|
|
2058
|
-
// Copy all the nested signal properties onto the callable branch
|
|
2059
|
-
for (const branchKey in branch) {
|
|
2060
|
-
if (Object.prototype.hasOwnProperty.call(branch, branchKey)) {
|
|
2061
|
-
try {
|
|
2062
|
-
Object.defineProperty(callableBranch, branchKey, {
|
|
2063
|
-
value: branch[branchKey],
|
|
2064
|
-
enumerable: true,
|
|
2065
|
-
configurable: true,
|
|
2066
|
-
});
|
|
2067
|
-
}
|
|
2068
|
-
catch {
|
|
2069
|
-
// Skip if property can't be defined
|
|
2070
|
-
}
|
|
2071
|
-
}
|
|
2072
|
-
}
|
|
2073
|
-
store[key] = callableBranch;
|
|
2074
|
-
}
|
|
2075
|
-
}
|
|
2076
|
-
catch (error) {
|
|
2077
|
-
console.warn(`${SIGNAL_TREE_MESSAGES.SIGNAL_CREATION_FAILED} "${key}":`, error);
|
|
2078
|
-
store[key] = signal(value, {
|
|
2079
|
-
equal: equalityFn,
|
|
2080
|
-
});
|
|
2081
|
-
}
|
|
2082
|
-
}
|
|
2083
|
-
const symbols = Object.getOwnPropertySymbols(obj);
|
|
2084
|
-
for (const sym of symbols) {
|
|
2085
|
-
const value = obj[sym];
|
|
2086
|
-
try {
|
|
2087
|
-
if (isSignal(value)) {
|
|
2088
|
-
store[sym] = value;
|
|
2089
|
-
}
|
|
2090
|
-
else {
|
|
2091
|
-
store[sym] = signal(value, {
|
|
2092
|
-
equal: equalityFn,
|
|
2093
|
-
});
|
|
2094
|
-
}
|
|
2095
|
-
}
|
|
2096
|
-
catch (error) {
|
|
2097
|
-
console.warn(SIGNAL_TREE_MESSAGES.SIGNAL_CREATION_FAILED, error);
|
|
2098
|
-
}
|
|
2099
|
-
}
|
|
2100
|
-
}
|
|
2101
|
-
catch (error) {
|
|
2102
|
-
throw new Error(`Failed to create signal store: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
2103
|
-
}
|
|
2104
|
-
return store;
|
|
2105
|
-
}
|
|
2106
|
-
// ============================================
|
|
2107
|
-
// TREE ENHANCEMENT
|
|
2108
|
-
// ============================================
|
|
2109
|
-
function enhanceTree(tree, config = {}) {
|
|
2110
|
-
const isLazy = config.useLazySignals ?? shouldUseLazy(tree.state, config);
|
|
2111
|
-
// with() enhancer composition
|
|
2112
|
-
tree.with = ((...enhancers) => {
|
|
2113
|
-
if (enhancers.length === 0) {
|
|
2114
|
-
return tree;
|
|
2115
|
-
}
|
|
2116
|
-
const coreCapabilities = new Set();
|
|
2117
|
-
if (config.batchUpdates)
|
|
2118
|
-
coreCapabilities.add('batchUpdate');
|
|
2119
|
-
if (config.useMemoization)
|
|
2120
|
-
coreCapabilities.add('memoize');
|
|
2121
|
-
if (config.enableTimeTravel)
|
|
2122
|
-
coreCapabilities.add('undo');
|
|
2123
|
-
if (config.enableDevTools)
|
|
2124
|
-
coreCapabilities.add('connectDevTools');
|
|
2125
|
-
try {
|
|
2126
|
-
for (const key of Object.keys(tree))
|
|
2127
|
-
coreCapabilities.add(String(key));
|
|
2128
|
-
}
|
|
2129
|
-
catch {
|
|
2130
|
-
// Ignore reflection issues
|
|
2131
|
-
}
|
|
2132
|
-
const hasMetadata = enhancers.some((e) => Boolean(e.metadata && (e.metadata.requires || e.metadata.provides)));
|
|
2133
|
-
let orderedEnhancers = enhancers;
|
|
2134
|
-
if (hasMetadata) {
|
|
2135
|
-
try {
|
|
2136
|
-
orderedEnhancers = resolveEnhancerOrder(enhancers, coreCapabilities, config.debugMode);
|
|
2137
|
-
}
|
|
2138
|
-
catch (err) {
|
|
2139
|
-
console.warn(SIGNAL_TREE_MESSAGES.ENHANCER_ORDER_FAILED, err);
|
|
2140
|
-
}
|
|
2141
|
-
}
|
|
2142
|
-
const provided = new Set(coreCapabilities);
|
|
2143
|
-
let currentTree = tree;
|
|
2144
|
-
for (let i = 0; i < orderedEnhancers.length; i++) {
|
|
2145
|
-
const enhancer = orderedEnhancers[i];
|
|
2146
|
-
if (typeof enhancer !== 'function') {
|
|
2147
|
-
throw new Error(SIGNAL_TREE_MESSAGES.ENHANCER_NOT_FUNCTION.replace('%d', String(i)));
|
|
2148
|
-
}
|
|
2149
|
-
const reqs = enhancer.metadata?.requires ?? [];
|
|
2150
|
-
for (const r of reqs) {
|
|
2151
|
-
if (!(r in currentTree) && !provided.has(r)) {
|
|
2152
|
-
const name = enhancer.metadata?.name ?? `enhancer#${i}`;
|
|
2153
|
-
const msg = SIGNAL_TREE_MESSAGES.ENHANCER_REQUIREMENT_MISSING.replace('%s', name).replace('%s', r);
|
|
2154
|
-
if (config.debugMode) {
|
|
2155
|
-
throw new Error(msg);
|
|
2156
|
-
}
|
|
2157
|
-
else {
|
|
2158
|
-
console.warn(msg);
|
|
2159
|
-
}
|
|
2160
|
-
}
|
|
2161
|
-
}
|
|
2162
|
-
try {
|
|
2163
|
-
const result = enhancer(currentTree);
|
|
2164
|
-
if (result !== currentTree)
|
|
2165
|
-
currentTree = result;
|
|
2166
|
-
const provs = enhancer.metadata?.provides ?? [];
|
|
2167
|
-
for (const p of provs)
|
|
2168
|
-
provided.add(p);
|
|
2169
|
-
if (config.debugMode && provs.length > 0) {
|
|
2170
|
-
for (const p of provs) {
|
|
2171
|
-
if (!(p in currentTree)) {
|
|
2172
|
-
console.warn(SIGNAL_TREE_MESSAGES.ENHANCER_PROVIDES_MISSING.replace('%s', enhancer.metadata?.name ?? String(i)).replace('%s', p));
|
|
2173
|
-
}
|
|
2174
|
-
}
|
|
2175
|
-
}
|
|
2176
|
-
}
|
|
2177
|
-
catch (error) {
|
|
2178
|
-
const name = enhancer.metadata?.name || `enhancer at index ${i}`;
|
|
2179
|
-
console.error(SIGNAL_TREE_MESSAGES.ENHANCER_FAILED.replace('%s', name), error);
|
|
2180
|
-
if (config.debugMode) {
|
|
2181
|
-
console.error('[SignalTree] Enhancer stack trace:', enhancer);
|
|
2182
|
-
console.error('[SignalTree] Tree state at failure:', currentTree);
|
|
2183
|
-
}
|
|
2184
|
-
throw error;
|
|
2185
|
-
}
|
|
2186
|
-
}
|
|
2187
|
-
return currentTree;
|
|
2188
|
-
});
|
|
2189
|
-
// destroy unchanged
|
|
2190
|
-
tree.destroy = () => {
|
|
2191
|
-
try {
|
|
2192
|
-
if (isLazy) {
|
|
2193
|
-
const state = tree.state;
|
|
2194
|
-
if (state && typeof state === 'object' && '__cleanup__' in state) {
|
|
2195
|
-
const cleanup = state.__cleanup__;
|
|
2196
|
-
if (typeof cleanup === 'function') {
|
|
2197
|
-
cleanup();
|
|
2198
|
-
}
|
|
2199
|
-
}
|
|
2200
|
-
}
|
|
2201
|
-
if (config.debugMode) {
|
|
2202
|
-
console.log(SIGNAL_TREE_MESSAGES.TREE_DESTROYED);
|
|
2203
|
-
}
|
|
2204
|
-
}
|
|
2205
|
-
catch (error) {
|
|
2206
|
-
console.error(SIGNAL_TREE_MESSAGES.CLEANUP_ERROR, error);
|
|
2207
|
-
}
|
|
2208
|
-
};
|
|
2209
|
-
// Add stub implementations for advanced features
|
|
2210
|
-
addStubMethods(tree, config);
|
|
2211
|
-
return tree;
|
|
2212
|
-
}
|
|
2213
|
-
function addStubMethods(tree, config) {
|
|
2214
|
-
tree.batchUpdate = (updater) => {
|
|
2215
|
-
console.warn(SIGNAL_TREE_MESSAGES.BATCH_NOT_ENABLED);
|
|
2216
|
-
tree((current) => {
|
|
2217
|
-
const partial = updater(current);
|
|
2218
|
-
return { ...current, ...partial };
|
|
2219
|
-
});
|
|
2220
|
-
};
|
|
2221
|
-
tree.memoize = (fn, cacheKey) => {
|
|
2222
|
-
console.warn(SIGNAL_TREE_MESSAGES.MEMOIZE_NOT_ENABLED);
|
|
2223
|
-
return computed(() => fn(tree()));
|
|
2224
|
-
};
|
|
2225
|
-
// Memoization helper stubs (overridden by withMemoization)
|
|
2226
|
-
tree.memoizedUpdate = (updater) => {
|
|
2227
|
-
if (config.debugMode) {
|
|
2228
|
-
console.warn(SIGNAL_TREE_MESSAGES.MEMOIZE_NOT_ENABLED);
|
|
2229
|
-
}
|
|
2230
|
-
// Fallback: apply the update without caching
|
|
2231
|
-
tree((current) => ({ ...current, ...updater(current) }));
|
|
2232
|
-
};
|
|
2233
|
-
tree.clearMemoCache = () => {
|
|
2234
|
-
if (config.debugMode) {
|
|
2235
|
-
console.warn(SIGNAL_TREE_MESSAGES.MEMOIZE_NOT_ENABLED);
|
|
2236
|
-
}
|
|
2237
|
-
// no-op
|
|
2238
|
-
};
|
|
2239
|
-
tree.getCacheStats = () => ({
|
|
2240
|
-
size: 0,
|
|
2241
|
-
hitRate: 0,
|
|
2242
|
-
totalHits: 0,
|
|
2243
|
-
totalMisses: 0,
|
|
2244
|
-
keys: [],
|
|
2245
|
-
});
|
|
2246
|
-
// Memoization helper methods are only present when withMemoization is applied
|
|
2247
|
-
tree.effect = (fn) => {
|
|
2248
|
-
try {
|
|
2249
|
-
effect(() => fn(tree()));
|
|
2250
|
-
}
|
|
2251
|
-
catch (error) {
|
|
2252
|
-
if (config.debugMode) {
|
|
2253
|
-
console.warn(SIGNAL_TREE_MESSAGES.EFFECT_NO_CONTEXT, error);
|
|
2254
|
-
}
|
|
2255
|
-
}
|
|
2256
|
-
};
|
|
2257
|
-
tree.subscribe = (fn) => {
|
|
2258
|
-
try {
|
|
2259
|
-
const destroyRef = inject(DestroyRef);
|
|
2260
|
-
let isDestroyed = false;
|
|
2261
|
-
const effectRef = effect(() => {
|
|
2262
|
-
if (!isDestroyed) {
|
|
2263
|
-
fn(tree());
|
|
2264
|
-
}
|
|
2265
|
-
});
|
|
2266
|
-
const unsubscribe = () => {
|
|
2267
|
-
isDestroyed = true;
|
|
2268
|
-
effectRef.destroy();
|
|
2269
|
-
};
|
|
2270
|
-
destroyRef.onDestroy(unsubscribe);
|
|
2271
|
-
return unsubscribe;
|
|
2272
|
-
}
|
|
2273
|
-
catch (error) {
|
|
2274
|
-
if (config.debugMode) {
|
|
2275
|
-
console.warn(SIGNAL_TREE_MESSAGES.SUBSCRIBE_NO_CONTEXT, error);
|
|
2276
|
-
}
|
|
2277
|
-
fn(tree());
|
|
2278
|
-
return () => {
|
|
2279
|
-
// No-op
|
|
2280
|
-
};
|
|
2281
|
-
}
|
|
2282
|
-
};
|
|
2283
|
-
// Performance stubs
|
|
2284
|
-
tree.optimize = () => {
|
|
2285
|
-
if (config.debugMode) {
|
|
2286
|
-
console.warn(SIGNAL_TREE_MESSAGES.OPTIMIZE_NOT_AVAILABLE);
|
|
2287
|
-
}
|
|
2288
|
-
};
|
|
2289
|
-
tree.clearCache = () => {
|
|
2290
|
-
if (config.debugMode) {
|
|
2291
|
-
console.warn(SIGNAL_TREE_MESSAGES.CACHE_NOT_AVAILABLE);
|
|
2292
|
-
}
|
|
2293
|
-
};
|
|
2294
|
-
tree.invalidatePattern = () => {
|
|
2295
|
-
if (config.debugMode) {
|
|
2296
|
-
console.warn(SIGNAL_TREE_MESSAGES.PERFORMANCE_NOT_ENABLED);
|
|
2297
|
-
}
|
|
2298
|
-
return 0;
|
|
2299
|
-
};
|
|
2300
|
-
// Initialize optimized update engine
|
|
2301
|
-
const treeWithEngine = tree;
|
|
2302
|
-
if (!treeWithEngine.updateEngine) {
|
|
2303
|
-
treeWithEngine.updateEngine = new OptimizedUpdateEngine(tree);
|
|
2304
|
-
}
|
|
2305
|
-
tree.updateOptimized = (updates, options = {}) => {
|
|
2306
|
-
const treeWithEngine = tree;
|
|
2307
|
-
const engine = treeWithEngine.updateEngine;
|
|
2308
|
-
if (!engine) {
|
|
2309
|
-
// Fallback to basic update
|
|
2310
|
-
if (config.debugMode) {
|
|
2311
|
-
console.warn(SIGNAL_TREE_MESSAGES.UPDATE_OPTIMIZED_NOT_AVAILABLE);
|
|
2312
|
-
}
|
|
2313
|
-
tree((current) => ({ ...current, ...updates }));
|
|
2314
|
-
return {
|
|
2315
|
-
changed: true,
|
|
2316
|
-
duration: 0,
|
|
2317
|
-
changedPaths: Object.keys(updates),
|
|
2318
|
-
stats: undefined,
|
|
2319
|
-
};
|
|
2320
|
-
}
|
|
2321
|
-
return engine.update(tree(), updates, options);
|
|
2322
|
-
};
|
|
2323
|
-
tree.getMetrics = () => {
|
|
2324
|
-
return {
|
|
2325
|
-
updates: 0,
|
|
2326
|
-
computations: 0,
|
|
2327
|
-
cacheHits: 0,
|
|
2328
|
-
cacheMisses: 0,
|
|
2329
|
-
averageUpdateTime: 0,
|
|
2330
|
-
};
|
|
2331
|
-
};
|
|
2332
|
-
// Middleware stubs
|
|
2333
|
-
tree.addTap = (middleware) => {
|
|
2334
|
-
if (config.debugMode) {
|
|
2335
|
-
console.warn(SIGNAL_TREE_MESSAGES.MIDDLEWARE_NOT_AVAILABLE);
|
|
2336
|
-
}
|
|
2337
|
-
};
|
|
2338
|
-
tree.removeTap = (id) => {
|
|
2339
|
-
if (config.debugMode) {
|
|
2340
|
-
console.warn(SIGNAL_TREE_MESSAGES.MIDDLEWARE_NOT_AVAILABLE);
|
|
2341
|
-
}
|
|
2342
|
-
};
|
|
2343
|
-
// Entity helpers stub
|
|
2344
|
-
tree.entities = () => {
|
|
2345
|
-
if (config.debugMode) {
|
|
2346
|
-
console.warn(SIGNAL_TREE_MESSAGES.ENTITY_HELPERS_NOT_AVAILABLE);
|
|
2347
|
-
}
|
|
2348
|
-
return {};
|
|
2349
|
-
};
|
|
2350
|
-
// Async action stub
|
|
2351
|
-
tree.asyncAction = (operation, asyncConfig = {}) => {
|
|
2352
|
-
if (config.debugMode) {
|
|
2353
|
-
console.warn(SIGNAL_TREE_MESSAGES.ASYNC_ACTIONS_NOT_AVAILABLE);
|
|
2354
|
-
}
|
|
2355
|
-
return {};
|
|
2356
|
-
};
|
|
2357
|
-
// Time travel stubs
|
|
2358
|
-
tree.undo = () => {
|
|
2359
|
-
if (config.debugMode) {
|
|
2360
|
-
console.warn(SIGNAL_TREE_MESSAGES.TIME_TRAVEL_NOT_AVAILABLE);
|
|
2361
|
-
}
|
|
2362
|
-
};
|
|
2363
|
-
tree.redo = () => {
|
|
2364
|
-
if (config.debugMode) {
|
|
2365
|
-
console.warn(SIGNAL_TREE_MESSAGES.TIME_TRAVEL_NOT_AVAILABLE);
|
|
2366
|
-
}
|
|
2367
|
-
};
|
|
2368
|
-
tree.getHistory = () => {
|
|
2369
|
-
if (config.debugMode) {
|
|
2370
|
-
console.warn(SIGNAL_TREE_MESSAGES.TIME_TRAVEL_NOT_AVAILABLE);
|
|
2371
|
-
}
|
|
2372
|
-
return [];
|
|
2373
|
-
};
|
|
2374
|
-
tree.resetHistory = () => {
|
|
2375
|
-
if (config.debugMode) {
|
|
2376
|
-
console.warn(SIGNAL_TREE_MESSAGES.TIME_TRAVEL_NOT_AVAILABLE);
|
|
2377
|
-
}
|
|
2378
|
-
};
|
|
2379
|
-
}
|
|
2380
|
-
// ============================================
|
|
2381
|
-
// CORE CREATION FUNCTION
|
|
2382
|
-
// ============================================
|
|
2383
|
-
function create(obj, config = {}) {
|
|
2384
|
-
if (obj === null || obj === undefined) {
|
|
2385
|
-
throw new Error(SIGNAL_TREE_MESSAGES.NULL_OR_UNDEFINED);
|
|
2386
|
-
}
|
|
2387
|
-
// Validate the tree if security is configured
|
|
2388
|
-
validateTree(obj, config);
|
|
2389
|
-
const estimatedSize = estimateObjectSize(obj);
|
|
2390
|
-
const equalityFn = createEqualityFn(config.useShallowComparison ?? false);
|
|
2391
|
-
// ARRAY ROOT MODE: arrays are treated as single signals
|
|
2392
|
-
if (Array.isArray(obj)) {
|
|
2393
|
-
const signalState = signal(obj, {
|
|
2394
|
-
equal: equalityFn,
|
|
2395
|
-
});
|
|
2396
|
-
const tree = makeRootNodeAccessor(signalState, signalState);
|
|
2397
|
-
// Add state and $ properties that reference the signal itself
|
|
2398
|
-
Object.defineProperty(tree, 'state', {
|
|
2399
|
-
value: signalState,
|
|
2400
|
-
enumerable: false,
|
|
2401
|
-
});
|
|
2402
|
-
Object.defineProperty(tree, '$', { value: signalState, enumerable: false });
|
|
2403
|
-
enhanceTree(tree, config);
|
|
2404
|
-
return tree;
|
|
2405
|
-
}
|
|
2406
|
-
const useLazy = shouldUseLazy(obj, config, estimatedSize);
|
|
2407
|
-
if (config.debugMode) {
|
|
2408
|
-
console.log(SIGNAL_TREE_MESSAGES.STRATEGY_SELECTION.replace('%s', useLazy ? 'lazy' : 'eager').replace('%d', String(estimatedSize)));
|
|
2409
|
-
}
|
|
2410
|
-
let signalState;
|
|
2411
|
-
let memoryManager;
|
|
2412
|
-
try {
|
|
2413
|
-
if (useLazy && typeof obj === 'object') {
|
|
2414
|
-
memoryManager = new SignalMemoryManager();
|
|
2415
|
-
signalState = createLazySignalTree(obj, equalityFn, '', // basePath
|
|
2416
|
-
memoryManager);
|
|
2417
|
-
}
|
|
2418
|
-
else {
|
|
2419
|
-
signalState = createSignalStore(obj, equalityFn);
|
|
2420
|
-
}
|
|
2421
|
-
}
|
|
2422
|
-
catch (error) {
|
|
2423
|
-
if (useLazy) {
|
|
2424
|
-
console.warn(SIGNAL_TREE_MESSAGES.LAZY_FALLBACK, error);
|
|
2425
|
-
signalState = createSignalStore(obj, equalityFn);
|
|
2426
|
-
memoryManager = undefined; // Reset memory manager on fallback
|
|
2427
|
-
}
|
|
2428
|
-
else {
|
|
2429
|
-
throw error;
|
|
2430
|
-
}
|
|
2431
|
-
}
|
|
2432
|
-
// Create callable tree function for the root
|
|
2433
|
-
const tree = function (arg) {
|
|
2434
|
-
if (arguments.length === 0) {
|
|
2435
|
-
return unwrap(signalState);
|
|
2436
|
-
}
|
|
2437
|
-
if (typeof arg === 'function') {
|
|
2438
|
-
const updater = arg;
|
|
2439
|
-
const currentValue = unwrap(signalState);
|
|
2440
|
-
const newValue = updater(currentValue);
|
|
2441
|
-
// Use recursive update to preserve signals
|
|
2442
|
-
recursiveUpdate(signalState, newValue);
|
|
2443
|
-
}
|
|
2444
|
-
else {
|
|
2445
|
-
// Direct set - use recursive update
|
|
2446
|
-
recursiveUpdate(signalState, arg);
|
|
2447
|
-
}
|
|
2448
|
-
};
|
|
2449
|
-
// Mark as NodeAccessor
|
|
2450
|
-
Object.defineProperty(tree, NODE_ACCESSOR_SYMBOL, {
|
|
2451
|
-
value: true,
|
|
2452
|
-
enumerable: false,
|
|
2453
|
-
});
|
|
2454
|
-
// Add state and $ properties first (these are safe)
|
|
2455
|
-
Object.defineProperty(tree, 'state', {
|
|
2456
|
-
value: signalState,
|
|
2457
|
-
enumerable: false,
|
|
2458
|
-
});
|
|
2459
|
-
Object.defineProperty(tree, '$', { value: signalState, enumerable: false });
|
|
2460
|
-
// Add dispose() method for manual cleanup when using lazy signals (stub)
|
|
2461
|
-
if (memoryManager) {
|
|
2462
|
-
Object.defineProperty(tree, 'dispose', {
|
|
2463
|
-
value: () => {
|
|
2464
|
-
memoryManager?.dispose();
|
|
2465
|
-
const cleanup = signalState.__cleanup__;
|
|
2466
|
-
if (typeof cleanup === 'function') {
|
|
2467
|
-
cleanup();
|
|
2468
|
-
}
|
|
2469
|
-
},
|
|
2470
|
-
enumerable: false,
|
|
2471
|
-
writable: false,
|
|
2472
|
-
});
|
|
2473
|
-
}
|
|
2474
|
-
// Enhance tree with methods
|
|
2475
|
-
enhanceTree(tree, config);
|
|
2476
|
-
// Attach signal state properties to the tree AFTER enhancement
|
|
2477
|
-
// This prevents conflicts with built-in methods
|
|
2478
|
-
for (const key in signalState) {
|
|
2479
|
-
if (Object.prototype.hasOwnProperty.call(signalState, key)) {
|
|
2480
|
-
// Skip if the property already exists (from enhancement)
|
|
2481
|
-
if (!(key in tree)) {
|
|
2482
|
-
try {
|
|
2483
|
-
Object.defineProperty(tree, key, {
|
|
2484
|
-
value: signalState[key],
|
|
2485
|
-
enumerable: true,
|
|
2486
|
-
configurable: true,
|
|
2487
|
-
});
|
|
2488
|
-
}
|
|
2489
|
-
catch {
|
|
2490
|
-
// Skip if property can't be defined
|
|
2491
|
-
}
|
|
2492
|
-
}
|
|
2493
|
-
}
|
|
2494
|
-
}
|
|
2495
|
-
return tree;
|
|
2496
|
-
}
|
|
2497
|
-
// ============================================
|
|
2498
|
-
// PRESET CONFIGURATIONS
|
|
2499
|
-
// ============================================
|
|
2500
|
-
const presetConfigs = {
|
|
2501
|
-
basic: {
|
|
2502
|
-
useLazySignals: false,
|
|
2503
|
-
debugMode: false,
|
|
2504
|
-
},
|
|
2505
|
-
performance: {
|
|
2506
|
-
useLazySignals: true,
|
|
2507
|
-
batchUpdates: true,
|
|
2508
|
-
useMemoization: true,
|
|
2509
|
-
useShallowComparison: true,
|
|
2510
|
-
},
|
|
2511
|
-
development: {
|
|
2512
|
-
useLazySignals: false,
|
|
2513
|
-
debugMode: true,
|
|
2514
|
-
enableDevTools: true,
|
|
2515
|
-
trackPerformance: true,
|
|
2516
|
-
},
|
|
2517
|
-
production: {
|
|
2518
|
-
useLazySignals: true,
|
|
2519
|
-
batchUpdates: true,
|
|
2520
|
-
useMemoization: true,
|
|
2521
|
-
debugMode: false,
|
|
2522
|
-
},
|
|
2523
|
-
};
|
|
2524
|
-
function signalTree(obj, configOrPreset) {
|
|
2525
|
-
if (typeof configOrPreset === 'string') {
|
|
2526
|
-
const config = presetConfigs[configOrPreset];
|
|
2527
|
-
if (!config) {
|
|
2528
|
-
console.warn(SIGNAL_TREE_MESSAGES.PRESET_UNKNOWN.replace('%s', configOrPreset));
|
|
2529
|
-
return create(obj, {});
|
|
2530
|
-
}
|
|
2531
|
-
return create(obj, config);
|
|
2532
|
-
}
|
|
2533
|
-
const config = configOrPreset || {};
|
|
2534
|
-
return create(obj, config);
|
|
2535
|
-
}
|
|
2536
|
-
|
|
2537
|
-
/** Global queue for batched updates awaiting processing */
|
|
2538
|
-
let updateQueue = [];
|
|
2539
|
-
/** Flag to prevent recursive batch processing */
|
|
2540
|
-
let isUpdating = false;
|
|
2541
|
-
/** Timeout ID for scheduled flush operations */
|
|
2542
|
-
let flushTimeoutId;
|
|
2543
|
-
/** Current batching configuration */
|
|
2544
|
-
let currentBatchingConfig = {};
|
|
2545
|
-
/**
|
|
2546
|
-
* Enhanced queue management with priority and deduplication
|
|
2547
|
-
* Returns true if queue was flushed immediately, false if scheduled for later
|
|
2548
|
-
*/
|
|
2549
|
-
function addToQueue(update, config = currentBatchingConfig) {
|
|
2550
|
-
const maxSize = config.maxBatchSize ?? 100;
|
|
2551
|
-
// Remove duplicates based on path if available
|
|
2552
|
-
if (update.path) {
|
|
2553
|
-
updateQueue = updateQueue.filter((existing) => existing.path !== update.path);
|
|
2554
|
-
}
|
|
2555
|
-
updateQueue.push(update);
|
|
2556
|
-
// Check if we should flush immediately due to maxBatchSize
|
|
2557
|
-
// Flush when we exceed maxBatchSize, not when we reach it
|
|
2558
|
-
if (updateQueue.length > maxSize) {
|
|
2559
|
-
// Flush immediately when max batch size is exceeded
|
|
2560
|
-
flushUpdates();
|
|
2561
|
-
return true; // Indicate that queue was flushed
|
|
2562
|
-
}
|
|
2563
|
-
// Schedule auto-flush if not already scheduled
|
|
2564
|
-
scheduleFlush(config);
|
|
2565
|
-
return false; // Indicate that queue was scheduled for later
|
|
2566
|
-
}
|
|
2567
|
-
/**
|
|
2568
|
-
* Schedules automatic queue flushing with configurable timing
|
|
2569
|
-
*/
|
|
2570
|
-
function scheduleFlush(config) {
|
|
2571
|
-
if (flushTimeoutId !== undefined) {
|
|
2572
|
-
clearTimeout(flushTimeoutId);
|
|
2573
|
-
}
|
|
2574
|
-
const delay = config.autoFlushDelay ?? 16; // Default to 60fps
|
|
2575
|
-
flushTimeoutId = setTimeout(() => {
|
|
2576
|
-
flushUpdates();
|
|
2577
|
-
}, delay);
|
|
2578
|
-
}
|
|
2579
|
-
/**
|
|
2580
|
-
* Processes the update queue immediately with race condition protection.
|
|
2581
|
-
* Handles updates that arrive during flush execution.
|
|
2582
|
-
*/
|
|
2583
|
-
function flushUpdates() {
|
|
2584
|
-
if (isUpdating)
|
|
2585
|
-
return;
|
|
2586
|
-
let queue;
|
|
2587
|
-
do {
|
|
2588
|
-
if (updateQueue.length === 0)
|
|
2589
|
-
return;
|
|
2590
|
-
isUpdating = true;
|
|
2591
|
-
queue = updateQueue;
|
|
2592
|
-
updateQueue = []; // Clear queue atomically
|
|
2593
|
-
// Clear any pending flush timeout
|
|
2594
|
-
if (flushTimeoutId !== undefined) {
|
|
2595
|
-
clearTimeout(flushTimeoutId);
|
|
2596
|
-
flushTimeoutId = undefined;
|
|
2597
|
-
}
|
|
2598
|
-
// Sort by depth (deepest first) for optimal update propagation
|
|
2599
|
-
queue.sort((a, b) => (b.depth ?? 0) - (a.depth ?? 0));
|
|
2600
|
-
try {
|
|
2601
|
-
queue.forEach(({ fn }) => fn());
|
|
2602
|
-
}
|
|
2603
|
-
finally {
|
|
2604
|
-
isUpdating = false;
|
|
2605
|
-
}
|
|
2606
|
-
// Process any updates that were added during flush
|
|
2607
|
-
} while (updateQueue.length > 0);
|
|
2608
|
-
}
|
|
2609
|
-
/**
|
|
2610
|
-
* Core batching function that intelligently queues updates and processes them in optimized microtasks.
|
|
2611
|
-
* Updates are sorted by depth (deepest first) for optimal update propagation and minimal re-computations.
|
|
2612
|
-
*
|
|
2613
|
-
* @param fn - The update function to batch
|
|
2614
|
-
* @param path - Optional state path for update grouping and optimization
|
|
2615
|
-
*
|
|
2616
|
-
* @example
|
|
2617
|
-
* ```typescript
|
|
2618
|
-
* // Simple batched update
|
|
2619
|
-
* batchUpdates(() => tree.update(() => ({ count: 1 })));
|
|
2620
|
-
*
|
|
2621
|
-
* // Path-aware batching for nested updates
|
|
2622
|
-
* batchUpdates(() => tree.update(() => ({ user: { name: 'John' } })), 'user.name');
|
|
2623
|
-
*
|
|
2624
|
-
* // Multiple updates get automatically batched
|
|
2625
|
-
* batchUpdates(() => tree.update(() => ({ loading: true })));
|
|
2626
|
-
* batchUpdates(() => tree.update(() => ({ error: null })));
|
|
2627
|
-
* // Both execute in single microtask
|
|
2628
|
-
* ```
|
|
2629
|
-
*/
|
|
2630
|
-
function batchUpdates(fn, path) {
|
|
2631
|
-
const startTime = performance.now();
|
|
2632
|
-
const depth = 0;
|
|
2633
|
-
const update = { fn, startTime, depth, path };
|
|
2634
|
-
// Use enhanced queue management
|
|
2635
|
-
const wasFlushed = addToQueue(update, currentBatchingConfig);
|
|
2636
|
-
// Only schedule additional flush if queue wasn't already flushed
|
|
2637
|
-
if (!wasFlushed) {
|
|
2638
|
-
// Check if we need to process immediately due to timeout
|
|
2639
|
-
const isTimedOut = currentBatchingConfig.batchTimeoutMs &&
|
|
2640
|
-
updateQueue.length > 0 &&
|
|
2641
|
-
startTime - updateQueue[0].startTime >=
|
|
2642
|
-
currentBatchingConfig.batchTimeoutMs;
|
|
2643
|
-
if (isTimedOut) {
|
|
2644
|
-
flushUpdates();
|
|
2645
|
-
}
|
|
2646
|
-
else if (!isUpdating && updateQueue.length > 0) {
|
|
2647
|
-
// Schedule flush but don't set isUpdating until the microtask runs
|
|
2648
|
-
queueMicrotask(() => {
|
|
2649
|
-
flushUpdates();
|
|
2650
|
-
});
|
|
2651
|
-
}
|
|
2652
|
-
}
|
|
2653
|
-
}
|
|
2654
|
-
/**
|
|
2655
|
-
* Enhances a SignalTree with intelligent batching capabilities for optimal performance.
|
|
2656
|
-
* Automatically groups rapid state updates into efficient batch cycles to eliminate UI thrashing.
|
|
2657
|
-
*
|
|
2658
|
-
* @template T - The state object type extending StateObject
|
|
2659
|
-
* @param config - Configuration options for batching behavior
|
|
2660
|
-
* @returns Function that enhances a SignalTree with batching capabilities
|
|
2661
|
-
*
|
|
2662
|
-
* @example
|
|
2663
|
-
* ```typescript
|
|
2664
|
-
* // Basic batching with default settings
|
|
2665
|
-
* const tree = create(initialState).with(withBatching());
|
|
2666
|
-
*
|
|
2667
|
-
* // High-performance batching for demanding applications
|
|
2668
|
-
* const tree = create(initialState).with(withBatching({
|
|
2669
|
-
* maxBatchSize: 50,
|
|
2670
|
-
* autoFlushDelay: 8, // ~120fps
|
|
2671
|
-
* batchTimeoutMs: 50
|
|
2672
|
-
* }));
|
|
2673
|
-
*
|
|
2674
|
-
* // Conservative batching for stable UIs
|
|
2675
|
-
* const tree = create(initialState).with(withBatching({
|
|
2676
|
-
* maxBatchSize: 10,
|
|
2677
|
-
* autoFlushDelay: 100,
|
|
2678
|
-
* batchTimeoutMs: 200
|
|
2679
|
-
* }));
|
|
2680
|
-
*
|
|
2681
|
-
* // Use batching methods
|
|
2682
|
-
* tree.batchUpdate((state) => ({
|
|
2683
|
-
* users: [...state.users, newUser],
|
|
2684
|
-
* loading: false,
|
|
2685
|
-
* error: null
|
|
2686
|
-
* }));
|
|
2687
|
-
* Uses unconstrained recursive typing - no limitations on T
|
|
2688
|
-
* ```
|
|
2689
|
-
*/
|
|
2690
|
-
function withBatching(config = {}) {
|
|
2691
|
-
const { enabled = true } = config;
|
|
2692
|
-
// Update global config for this batching instance
|
|
2693
|
-
currentBatchingConfig = { ...currentBatchingConfig, ...config };
|
|
2694
|
-
return (tree) => {
|
|
2695
|
-
if (!enabled) {
|
|
2696
|
-
return tree;
|
|
2697
|
-
}
|
|
2698
|
-
// Store the original callable tree function
|
|
2699
|
-
const originalTreeCall = tree.bind(tree);
|
|
2700
|
-
// Create enhanced tree function that batches update operations
|
|
2701
|
-
const enhancedTree = function (...args) {
|
|
2702
|
-
if (args.length === 0) {
|
|
2703
|
-
// Get operation - call original directly
|
|
2704
|
-
return originalTreeCall();
|
|
2705
|
-
}
|
|
2706
|
-
else {
|
|
2707
|
-
// Set or update operation - batch it
|
|
2708
|
-
batchUpdates(() => {
|
|
2709
|
-
if (args.length === 1) {
|
|
2710
|
-
const arg = args[0];
|
|
2711
|
-
if (typeof arg === 'function') {
|
|
2712
|
-
originalTreeCall(arg);
|
|
2713
|
-
}
|
|
2714
|
-
else {
|
|
2715
|
-
originalTreeCall(arg);
|
|
2716
|
-
}
|
|
2717
|
-
}
|
|
2718
|
-
});
|
|
2719
|
-
}
|
|
2720
|
-
};
|
|
2721
|
-
// Copy all properties and methods from original tree
|
|
2722
|
-
Object.setPrototypeOf(enhancedTree, Object.getPrototypeOf(tree));
|
|
2723
|
-
Object.assign(enhancedTree, tree);
|
|
2724
|
-
// Ensure state and $ properties are preserved
|
|
2725
|
-
if ('state' in tree) {
|
|
2726
|
-
Object.defineProperty(enhancedTree, 'state', {
|
|
2727
|
-
value: tree.state,
|
|
2728
|
-
enumerable: false,
|
|
2729
|
-
configurable: true,
|
|
2730
|
-
});
|
|
2731
|
-
}
|
|
2732
|
-
// Ensure $ alias is preserved
|
|
2733
|
-
if ('$' in tree) {
|
|
2734
|
-
Object.defineProperty(enhancedTree, '$', {
|
|
2735
|
-
value: tree['$'],
|
|
2736
|
-
enumerable: false,
|
|
2737
|
-
configurable: true,
|
|
2738
|
-
});
|
|
2739
|
-
}
|
|
2740
|
-
// Replace the stub batchUpdate method with actual batching logic
|
|
2741
|
-
enhancedTree.batchUpdate = (updater) => {
|
|
2742
|
-
batchUpdates(() => {
|
|
2743
|
-
const current = originalTreeCall();
|
|
2744
|
-
const updates = updater(current);
|
|
2745
|
-
// Apply updates to individual properties
|
|
2746
|
-
Object.entries(updates).forEach(([key, value]) => {
|
|
2747
|
-
const property = enhancedTree.state[key];
|
|
2748
|
-
if (property && 'set' in property) {
|
|
2749
|
-
// It's a WritableSignal - use .set()
|
|
2750
|
-
property.set(value);
|
|
2751
|
-
}
|
|
2752
|
-
else if (isNodeAccessor$1(property)) {
|
|
2753
|
-
// It's a NodeAccessor - use callable syntax
|
|
2754
|
-
property(value);
|
|
2755
|
-
}
|
|
2756
|
-
});
|
|
2757
|
-
});
|
|
2758
|
-
};
|
|
2759
|
-
return enhancedTree;
|
|
2760
|
-
};
|
|
2761
|
-
}
|
|
2762
|
-
/**
|
|
2763
|
-
* Convenience function to enable batching with default settings.
|
|
2764
|
-
* Equivalent to withBatching({ enabled: true }) but more concise for common usage.
|
|
2765
|
-
*
|
|
2766
|
-
* @template T - The state object type extending StateObject
|
|
2767
|
-
* @returns Function that enhances a SignalTree with default batching settings
|
|
2768
|
-
*
|
|
2769
|
-
* @example
|
|
2770
|
-
* ```typescript
|
|
2771
|
-
* // Simple batching enablement
|
|
2772
|
-
* const tree = create(initialState).with(enableBatching());
|
|
2773
|
-
*
|
|
2774
|
-
* // Equivalent to:
|
|
2775
|
-
* const tree = create(initialState).with(withBatching({ enabled: true }));
|
|
2776
|
-
* Uses unconstrained recursive typing - no limitations on T
|
|
2777
|
-
* ```
|
|
2778
|
-
*/
|
|
2779
|
-
/**
|
|
2780
|
-
* Creates high-performance batching configuration optimized for demanding applications.
|
|
2781
|
-
* Uses aggressive batching settings for maximum performance in high-frequency update scenarios.
|
|
2782
|
-
* Uses unconstrained recursive typing - no limitations on T
|
|
2783
|
-
*
|
|
2784
|
-
* @template T - The state object type extending StateObject
|
|
2785
|
-
* @returns Function that enhances a SignalTree with high-performance batching
|
|
2786
|
-
*
|
|
2787
|
-
* @example
|
|
2788
|
-
* ```typescript
|
|
2789
|
-
* // For performance-critical applications
|
|
2790
|
-
* const gameTree = create(gameState).with(withHighPerformanceBatching());
|
|
2791
|
-
*
|
|
2792
|
-
* // Perfect for:
|
|
2793
|
-
* // - Real-time games
|
|
2794
|
-
* // - High-frequency data updates
|
|
2795
|
-
* // - Animation-heavy UIs
|
|
2796
|
-
* // - Large dataset operations
|
|
2797
|
-
*
|
|
2798
|
-
* // Automatically includes:
|
|
2799
|
-
* // - Large batch sizes (200 updates)
|
|
2800
|
-
* // - Immediate processing (0ms timeout)
|
|
2801
|
-
* // - Aggressive optimization
|
|
2802
|
-
* Uses unconstrained recursive typing - no limitations on T
|
|
2803
|
-
* ```
|
|
2804
|
-
*/
|
|
2805
|
-
function withHighPerformanceBatching() {
|
|
2806
|
-
return withBatching({
|
|
2807
|
-
enabled: true,
|
|
2808
|
-
maxBatchSize: 200,
|
|
2809
|
-
batchTimeoutMs: 0,
|
|
2810
|
-
});
|
|
2811
|
-
}
|
|
2812
|
-
/**
|
|
2813
|
-
* Manually flushes all pending batched updates immediately.
|
|
2814
|
-
* Forces synchronous execution of queued updates, bypassing normal batching delays.
|
|
2815
|
-
* Useful for testing scenarios or when immediate state consistency is required.
|
|
2816
|
-
*
|
|
2817
|
-
* @example
|
|
2818
|
-
* ```typescript
|
|
2819
|
-
* // Queue some updates
|
|
2820
|
-
* tree.batchUpdate(() => ({ count: 1 }));
|
|
2821
|
-
* tree.batchUpdate(() => ({ name: 'test' }));
|
|
2822
|
-
*
|
|
2823
|
-
* // In tests, ensure updates are applied immediately
|
|
2824
|
-
* flushBatchedUpdates();
|
|
2825
|
-
* expect(tree().count).toBe(1);
|
|
2826
|
-
* expect(tree().name).toBe('test');
|
|
2827
|
-
*
|
|
2828
|
-
* // Before critical operations that need current state
|
|
2829
|
-
* flushBatchedUpdates();
|
|
2830
|
-
* const currentState = tree(); // Guaranteed to be up-to-date
|
|
2831
|
-
*
|
|
2832
|
-
* // In animation frames for precise timing
|
|
2833
|
-
* requestAnimationFrame(() => {
|
|
2834
|
-
* flushBatchedUpdates(); // Ensure updates are applied before render
|
|
2835
|
-
* updateUI();
|
|
2836
|
-
* });
|
|
2837
|
-
* ```
|
|
2838
|
-
*/
|
|
2839
|
-
function flushBatchedUpdates() {
|
|
2840
|
-
if (updateQueue.length > 0) {
|
|
2841
|
-
// Force flush regardless of isUpdating state
|
|
2842
|
-
const queue = updateQueue.slice();
|
|
2843
|
-
updateQueue = [];
|
|
2844
|
-
isUpdating = false; // Reset the updating flag
|
|
2845
|
-
// Sort by depth (deepest first) for optimal update propagation
|
|
2846
|
-
queue.sort((a, b) => (b.depth ?? 0) - (a.depth ?? 0));
|
|
2847
|
-
queue.forEach(({ fn }) => {
|
|
2848
|
-
fn();
|
|
2849
|
-
});
|
|
2850
|
-
}
|
|
2851
|
-
}
|
|
2852
|
-
/**
|
|
2853
|
-
* Checks if there are pending batched updates waiting to be processed.
|
|
2854
|
-
* Useful for testing, debugging, or conditional logic based on update queue state.
|
|
2855
|
-
*
|
|
2856
|
-
* @returns True if updates are queued, false if queue is empty
|
|
2857
|
-
*
|
|
2858
|
-
* @example
|
|
2859
|
-
* ```typescript
|
|
2860
|
-
* // Check before critical operations
|
|
2861
|
-
* tree.batchUpdate(() => ({ loading: true }));
|
|
2862
|
-
*
|
|
2863
|
-
* if (hasPendingUpdates()) {
|
|
2864
|
-
* console.log('Updates are queued for processing');
|
|
2865
|
-
* flushBatchedUpdates(); // Process them now if needed
|
|
2866
|
-
* }
|
|
2867
|
-
*
|
|
2868
|
-
* // In testing
|
|
2869
|
-
* tree.batchUpdate(() => ({ count: 1 }));
|
|
2870
|
-
* expect(hasPendingUpdates()).toBe(true);
|
|
2871
|
-
*
|
|
2872
|
-
* flushBatchedUpdates();
|
|
2873
|
-
* expect(hasPendingUpdates()).toBe(false);
|
|
2874
|
-
*
|
|
2875
|
-
* // Conditional behavior
|
|
2876
|
-
* function performCriticalOperation() {
|
|
2877
|
-
* if (hasPendingUpdates()) {
|
|
2878
|
-
* flushBatchedUpdates(); // Ensure consistent state
|
|
2879
|
-
* }
|
|
2880
|
-
* // Proceed with operation
|
|
2881
|
-
* }
|
|
2882
|
-
* ```
|
|
2883
|
-
*/
|
|
2884
|
-
function hasPendingUpdates() {
|
|
2885
|
-
return updateQueue.length > 0;
|
|
2886
|
-
}
|
|
2887
|
-
/**
|
|
2888
|
-
* Gets the current number of updates waiting in the batch queue.
|
|
2889
|
-
* Useful for performance monitoring, debugging, and batch size optimization.
|
|
2890
|
-
*
|
|
2891
|
-
* @returns Number of queued updates
|
|
2892
|
-
*
|
|
2893
|
-
* @example
|
|
2894
|
-
* ```typescript
|
|
2895
|
-
* // Performance monitoring
|
|
2896
|
-
* function monitorBatchPerformance() {
|
|
2897
|
-
* const queueSize = getBatchQueueSize();
|
|
2898
|
-
*
|
|
2899
|
-
* if (queueSize > 50) {
|
|
2900
|
-
* console.warn(`Large batch queue detected: ${queueSize} updates`);
|
|
2901
|
-
* }
|
|
2902
|
-
*
|
|
2903
|
-
* // Log metrics
|
|
2904
|
-
* console.log(`Current queue size: ${queueSize}`);
|
|
2905
|
-
* }
|
|
2906
|
-
*
|
|
2907
|
-
* // Debug batching behavior
|
|
2908
|
-
* tree.batchUpdate(() => ({ a: 1 }));
|
|
2909
|
-
* tree.batchUpdate(() => ({ b: 2 }));
|
|
2910
|
-
* tree.batchUpdate(() => ({ c: 3 }));
|
|
2911
|
-
*
|
|
2912
|
-
* console.log(`Queue size: ${getBatchQueueSize()}`); // 3
|
|
2913
|
-
*
|
|
2914
|
-
* flushBatchedUpdates();
|
|
2915
|
-
* console.log(`Queue size after flush: ${getBatchQueueSize()}`); // 0
|
|
2916
|
-
*
|
|
2917
|
-
* // Optimize batch configuration
|
|
2918
|
-
* const currentQueueSize = getBatchQueueSize();
|
|
2919
|
-
* if (currentQueueSize > 100) {
|
|
2920
|
-
* // Consider reducing maxBatchSize or autoFlushDelay
|
|
2921
|
-
* console.log('Consider optimizing batch configuration');
|
|
2922
|
-
* }
|
|
2923
|
-
* ```
|
|
2924
|
-
*/
|
|
2925
|
-
function getBatchQueueSize() {
|
|
2926
|
-
return updateQueue.length;
|
|
2927
|
-
}
|
|
2928
|
-
|
|
2929
|
-
// Global memoization cache with size limits and TTL
|
|
2930
|
-
const MAX_CACHE_SIZE = 1000;
|
|
2931
|
-
const DEFAULT_TTL = 5 * 60 * 1000; // 5 minutes
|
|
2932
|
-
// Use Map for global cache management (we keep iteration for diagnostics).
|
|
2933
|
-
// Note: we avoid starting any global timers at module import to prevent
|
|
2934
|
-
// background timer leaks in long-running processes; cleanup is performed
|
|
2935
|
-
// opportunistically inside hot paths (probabilistic) or via explicit APIs.
|
|
2936
|
-
const memoizationCache = new Map();
|
|
2937
|
-
function createMemoCacheStore(maxSize, enableLRU) {
|
|
2938
|
-
if (enableLRU) {
|
|
2939
|
-
const cache = new LRUCache(maxSize);
|
|
2940
|
-
const shadow = new Map();
|
|
2941
|
-
const pruneShadow = () => {
|
|
2942
|
-
while (shadow.size > cache.size()) {
|
|
2943
|
-
const oldestKey = shadow.keys().next().value;
|
|
2944
|
-
if (oldestKey === undefined) {
|
|
2945
|
-
break;
|
|
2946
|
-
}
|
|
2947
|
-
shadow.delete(oldestKey);
|
|
2948
|
-
}
|
|
2949
|
-
};
|
|
2950
|
-
return {
|
|
2951
|
-
get: (key) => {
|
|
2952
|
-
const value = cache.get(key);
|
|
2953
|
-
if (value !== undefined) {
|
|
2954
|
-
shadow.set(key, value);
|
|
2955
|
-
}
|
|
2956
|
-
else if (shadow.has(key)) {
|
|
2957
|
-
shadow.delete(key);
|
|
2958
|
-
}
|
|
2959
|
-
return value;
|
|
2960
|
-
},
|
|
2961
|
-
set: (key, value) => {
|
|
2962
|
-
cache.set(key, value);
|
|
2963
|
-
shadow.set(key, value);
|
|
2964
|
-
pruneShadow();
|
|
2965
|
-
},
|
|
2966
|
-
delete: (key) => {
|
|
2967
|
-
cache.delete(key);
|
|
2968
|
-
shadow.delete(key);
|
|
2969
|
-
},
|
|
2970
|
-
clear: () => {
|
|
2971
|
-
cache.clear();
|
|
2972
|
-
shadow.clear();
|
|
2973
|
-
},
|
|
2974
|
-
size: () => shadow.size,
|
|
2975
|
-
forEach: (callback) => {
|
|
2976
|
-
shadow.forEach((value, key) => callback(value, key));
|
|
2977
|
-
},
|
|
2978
|
-
keys: () => shadow.keys(),
|
|
2979
|
-
};
|
|
2980
|
-
}
|
|
2981
|
-
const store = new Map();
|
|
2982
|
-
return {
|
|
2983
|
-
get: (key) => store.get(key),
|
|
2984
|
-
set: (key, value) => {
|
|
2985
|
-
store.set(key, value);
|
|
2986
|
-
},
|
|
2987
|
-
delete: (key) => store.delete(key),
|
|
2988
|
-
clear: () => store.clear(),
|
|
2989
|
-
size: () => store.size,
|
|
2990
|
-
forEach: (callback) => {
|
|
2991
|
-
store.forEach((value, key) => callback(value, key));
|
|
2992
|
-
},
|
|
2993
|
-
keys: () => store.keys(),
|
|
2994
|
-
};
|
|
2995
|
-
}
|
|
2996
|
-
function getCleanupInterval(tree) {
|
|
2997
|
-
return tree._memoCleanupInterval;
|
|
2998
|
-
}
|
|
2999
|
-
function setCleanupInterval(tree, interval) {
|
|
3000
|
-
if (interval === undefined) {
|
|
3001
|
-
delete tree._memoCleanupInterval;
|
|
3002
|
-
return;
|
|
3003
|
-
}
|
|
3004
|
-
tree._memoCleanupInterval = interval;
|
|
3005
|
-
}
|
|
3006
|
-
function clearCleanupInterval(tree) {
|
|
3007
|
-
const interval = getCleanupInterval(tree);
|
|
3008
|
-
if (!interval) {
|
|
3009
|
-
return;
|
|
3010
|
-
}
|
|
3011
|
-
try {
|
|
3012
|
-
clearInterval(interval);
|
|
3013
|
-
}
|
|
3014
|
-
catch {
|
|
3015
|
-
/* best-effort cleanup */
|
|
3016
|
-
}
|
|
3017
|
-
setCleanupInterval(tree);
|
|
3018
|
-
}
|
|
3019
|
-
function resetMemoizationCaches() {
|
|
3020
|
-
memoizationCache.forEach((cache, tree) => {
|
|
3021
|
-
cache.clear();
|
|
3022
|
-
clearCleanupInterval(tree);
|
|
3023
|
-
});
|
|
3024
|
-
memoizationCache.clear();
|
|
3025
|
-
}
|
|
3026
|
-
/**
|
|
3027
|
-
* Cleanup the cache interval on app shutdown
|
|
3028
|
-
*/
|
|
3029
|
-
function cleanupMemoizationCache() {
|
|
3030
|
-
resetMemoizationCaches();
|
|
3031
|
-
}
|
|
3032
|
-
/**
|
|
3033
|
-
* Shallow equality check for dependency comparison
|
|
3034
|
-
* Much faster than deep equality for objects with primitive values
|
|
3035
|
-
* Optimized: Uses for...in instead of Object.keys() to avoid array allocations
|
|
3036
|
-
*/
|
|
3037
|
-
function shallowEqual(a, b) {
|
|
3038
|
-
if (a === b)
|
|
3039
|
-
return true;
|
|
3040
|
-
if (a == null || b == null)
|
|
3041
|
-
return false;
|
|
3042
|
-
if (typeof a !== typeof b)
|
|
3043
|
-
return false;
|
|
3044
|
-
if (typeof a === 'object' && typeof b === 'object') {
|
|
3045
|
-
const objA = a;
|
|
3046
|
-
const objB = b;
|
|
3047
|
-
// Count properties in objA and check equality
|
|
3048
|
-
let countA = 0;
|
|
3049
|
-
for (const key in objA) {
|
|
3050
|
-
if (!Object.prototype.hasOwnProperty.call(objA, key))
|
|
3051
|
-
continue;
|
|
3052
|
-
countA++;
|
|
3053
|
-
// Early exit if key missing or value different
|
|
3054
|
-
if (!(key in objB) || objA[key] !== objB[key])
|
|
3055
|
-
return false;
|
|
3056
|
-
}
|
|
3057
|
-
// Count properties in objB to ensure same number
|
|
3058
|
-
let countB = 0;
|
|
3059
|
-
for (const key in objB) {
|
|
3060
|
-
if (Object.prototype.hasOwnProperty.call(objB, key))
|
|
3061
|
-
countB++;
|
|
3062
|
-
}
|
|
3063
|
-
return countA === countB;
|
|
3064
|
-
}
|
|
3065
|
-
return false;
|
|
3066
|
-
}
|
|
3067
|
-
/**
|
|
3068
|
-
* Generate cache key for memoization
|
|
3069
|
-
*/
|
|
3070
|
-
function generateCacheKey(fn, args) {
|
|
3071
|
-
try {
|
|
3072
|
-
return `${fn.name || 'anonymous'}_${JSON.stringify(args)}`;
|
|
3073
|
-
}
|
|
3074
|
-
catch {
|
|
3075
|
-
// Fallback for cyclic or non-serializable args
|
|
3076
|
-
return `${fn.name || 'anonymous'}_${args.length}`;
|
|
3077
|
-
}
|
|
3078
|
-
}
|
|
3079
|
-
/**
|
|
3080
|
-
* Get equality function based on strategy
|
|
3081
|
-
*/
|
|
3082
|
-
function getEqualityFn(strategy) {
|
|
3083
|
-
switch (strategy) {
|
|
3084
|
-
case 'shallow':
|
|
3085
|
-
return shallowEqual;
|
|
3086
|
-
case 'reference':
|
|
3087
|
-
return (a, b) => a === b;
|
|
3088
|
-
case 'deep':
|
|
3089
|
-
default:
|
|
3090
|
-
return deepEqual;
|
|
3091
|
-
}
|
|
3092
|
-
}
|
|
3093
|
-
/**
|
|
3094
|
-
* Memoization function that caches expensive computations with enhanced cache management
|
|
3095
|
-
*/
|
|
3096
|
-
function memoize(fn, keyFn, config = {}) {
|
|
3097
|
-
const maxSize = config.maxCacheSize ?? MAX_CACHE_SIZE;
|
|
3098
|
-
const ttl = config.ttl ?? DEFAULT_TTL;
|
|
3099
|
-
// Use shallow equality by default to avoid expensive deep comparisons
|
|
3100
|
-
const equality = getEqualityFn(config.equality ?? 'shallow');
|
|
3101
|
-
// Disable LRU by default to avoid hidden CPU overhead
|
|
3102
|
-
const enableLRU = config.enableLRU ?? false;
|
|
3103
|
-
const cache = createMemoCacheStore(maxSize, enableLRU);
|
|
3104
|
-
const cleanExpiredEntries = () => {
|
|
3105
|
-
if (!ttl)
|
|
3106
|
-
return; // Skip if TTL is disabled
|
|
3107
|
-
const now = Date.now();
|
|
3108
|
-
cache.forEach((entry, key) => {
|
|
3109
|
-
if (entry.timestamp && now - entry.timestamp > ttl) {
|
|
3110
|
-
cache.delete(key);
|
|
3111
|
-
}
|
|
3112
|
-
});
|
|
3113
|
-
};
|
|
3114
|
-
return (...args) => {
|
|
3115
|
-
// Probabilistic cleanup to avoid paying cleanup cost on every hot call.
|
|
3116
|
-
// Runs ~1% of the time when TTL is enabled.
|
|
3117
|
-
if (ttl && Math.random() < 0.01) {
|
|
3118
|
-
cleanExpiredEntries();
|
|
3119
|
-
}
|
|
3120
|
-
const key = keyFn
|
|
3121
|
-
? keyFn(...args)
|
|
3122
|
-
: generateCacheKey(fn, args);
|
|
3123
|
-
const cached = cache.get(key);
|
|
3124
|
-
// If using custom key function, trust the key; otherwise check equality
|
|
3125
|
-
if (cached && (keyFn || equality(cached.deps, args))) {
|
|
3126
|
-
if (enableLRU) {
|
|
3127
|
-
cached.hitCount += 1;
|
|
3128
|
-
}
|
|
3129
|
-
return cached.value;
|
|
3130
|
-
}
|
|
3131
|
-
const result = fn(...args);
|
|
3132
|
-
cache.set(key, {
|
|
3133
|
-
value: result,
|
|
3134
|
-
deps: args,
|
|
3135
|
-
timestamp: Date.now(),
|
|
3136
|
-
hitCount: 1,
|
|
3137
|
-
});
|
|
3138
|
-
return result;
|
|
3139
|
-
};
|
|
3140
|
-
}
|
|
3141
|
-
/**
|
|
3142
|
-
* High-performance memoization function optimized for speed
|
|
3143
|
-
* Uses shallow equality and minimal cache management overhead
|
|
3144
|
-
*/
|
|
3145
|
-
function memoizeShallow(fn, keyFn) {
|
|
3146
|
-
return memoize(fn, keyFn, {
|
|
3147
|
-
equality: 'shallow',
|
|
3148
|
-
enableLRU: false,
|
|
3149
|
-
ttl: undefined,
|
|
3150
|
-
maxCacheSize: 100,
|
|
3151
|
-
});
|
|
3152
|
-
}
|
|
3153
|
-
/**
|
|
3154
|
-
* Lightweight memoization function with reference equality only
|
|
3155
|
-
* Maximum performance for scenarios where exact reference matches are sufficient
|
|
3156
|
-
*/
|
|
3157
|
-
function memoizeReference(fn, keyFn) {
|
|
3158
|
-
return memoize(fn, keyFn, {
|
|
3159
|
-
equality: 'reference',
|
|
3160
|
-
enableLRU: false,
|
|
3161
|
-
ttl: undefined,
|
|
3162
|
-
maxCacheSize: 50,
|
|
3163
|
-
});
|
|
3164
|
-
}
|
|
3165
|
-
/**
|
|
3166
|
-
* Preset memoization configurations optimized for common use cases
|
|
3167
|
-
* These presets are the same ones used in SignalTree's benchmarks
|
|
3168
|
-
*/
|
|
3169
|
-
const MEMOIZATION_PRESETS = {
|
|
3170
|
-
/**
|
|
3171
|
-
* Optimized for selectors and frequently-accessed computed values
|
|
3172
|
-
* - Fast reference-only equality checks (~0.3μs)
|
|
3173
|
-
* - Small cache (10 entries) for minimal overhead
|
|
3174
|
-
* - No LRU management (eliminates bookkeeping cost)
|
|
3175
|
-
* - Best for: Selectors, derived values, stable references
|
|
3176
|
-
*/
|
|
3177
|
-
selector: {
|
|
3178
|
-
equality: 'reference',
|
|
3179
|
-
maxCacheSize: 10,
|
|
3180
|
-
enableLRU: false,
|
|
3181
|
-
ttl: undefined,
|
|
3182
|
-
},
|
|
3183
|
-
/**
|
|
3184
|
-
* Balanced configuration for general computed values
|
|
3185
|
-
* - Shallow equality checks (~5-15μs) for object comparisons
|
|
3186
|
-
* - Medium cache (100 entries) for reasonable coverage
|
|
3187
|
-
* - No LRU (good performance/memory balance)
|
|
3188
|
-
* - Best for: General computations, objects with primitives
|
|
3189
|
-
*/
|
|
3190
|
-
computed: {
|
|
3191
|
-
equality: 'shallow',
|
|
3192
|
-
maxCacheSize: 100,
|
|
3193
|
-
enableLRU: false,
|
|
3194
|
-
ttl: undefined,
|
|
3195
|
-
},
|
|
3196
|
-
/**
|
|
3197
|
-
* Thorough configuration for complex nested state
|
|
3198
|
-
* - Deep equality checks (~50-200μs) for nested objects
|
|
3199
|
-
* - Large cache (1000 entries) for complex scenarios
|
|
3200
|
-
* - LRU enabled for intelligent cache management
|
|
3201
|
-
* - 5-minute TTL to prevent stale data
|
|
3202
|
-
* - Best for: Complex nested objects, thorough comparisons needed
|
|
3203
|
-
*/
|
|
3204
|
-
deepState: {
|
|
3205
|
-
equality: 'deep',
|
|
3206
|
-
maxCacheSize: 1000,
|
|
3207
|
-
enableLRU: true,
|
|
3208
|
-
ttl: 5 * 60 * 1000,
|
|
3209
|
-
},
|
|
3210
|
-
/**
|
|
3211
|
-
* Minimal overhead for high-frequency operations
|
|
3212
|
-
* - Reference-only equality (fastest possible)
|
|
3213
|
-
* - Tiny cache (5 entries) for minimal memory
|
|
3214
|
-
* - No bells and whistles
|
|
3215
|
-
* - Best for: Hot paths, microseconds matter, immutable data
|
|
3216
|
-
*/
|
|
3217
|
-
highFrequency: {
|
|
3218
|
-
equality: 'reference',
|
|
3219
|
-
maxCacheSize: 5,
|
|
3220
|
-
enableLRU: false,
|
|
3221
|
-
ttl: undefined,
|
|
3222
|
-
},
|
|
3223
|
-
};
|
|
3224
|
-
/**
|
|
3225
|
-
* Convenience function: Memoization optimized for selectors
|
|
3226
|
-
* Uses reference equality and small cache for maximum performance
|
|
3227
|
-
*
|
|
3228
|
-
* @example
|
|
3229
|
-
* ```typescript
|
|
3230
|
-
* const tree = signalTree(state).with(withSelectorMemoization());
|
|
3231
|
-
* const activeUsers = computed(() =>
|
|
3232
|
-
* tree.state.users().filter(u => u.active)
|
|
3233
|
-
* );
|
|
3234
|
-
* ```
|
|
3235
|
-
*/
|
|
3236
|
-
function withSelectorMemoization() {
|
|
3237
|
-
return withMemoization(MEMOIZATION_PRESETS.selector);
|
|
3238
|
-
}
|
|
3239
|
-
/**
|
|
3240
|
-
* Convenience function: Memoization optimized for computed values
|
|
3241
|
-
* Uses shallow equality for balanced performance
|
|
3242
|
-
*
|
|
3243
|
-
* @example
|
|
3244
|
-
* ```typescript
|
|
3245
|
-
* const tree = signalTree(state).with(withComputedMemoization());
|
|
3246
|
-
* const metrics = computed(() =>
|
|
3247
|
-
* calculateExpensiveMetrics(tree.state.data())
|
|
3248
|
-
* );
|
|
3249
|
-
* ```
|
|
3250
|
-
*/
|
|
3251
|
-
function withComputedMemoization() {
|
|
3252
|
-
return withMemoization(MEMOIZATION_PRESETS.computed);
|
|
3253
|
-
}
|
|
3254
|
-
/**
|
|
3255
|
-
* Convenience function: Memoization for complex nested state
|
|
3256
|
-
* Uses deep equality and LRU management
|
|
3257
|
-
*
|
|
3258
|
-
* @example
|
|
3259
|
-
* ```typescript
|
|
3260
|
-
* const tree = signalTree(state).with(withDeepStateMemoization());
|
|
3261
|
-
* // Handles complex nested object comparisons
|
|
3262
|
-
* ```
|
|
3263
|
-
*/
|
|
3264
|
-
function withDeepStateMemoization() {
|
|
3265
|
-
return withMemoization(MEMOIZATION_PRESETS.deepState);
|
|
3266
|
-
}
|
|
3267
|
-
/**
|
|
3268
|
-
* Convenience function: Minimal memoization for hot paths
|
|
3269
|
-
* Maximum performance with minimal overhead
|
|
3270
|
-
*
|
|
3271
|
-
* @example
|
|
3272
|
-
* ```typescript
|
|
3273
|
-
* const tree = signalTree(state).with(withHighFrequencyMemoization());
|
|
3274
|
-
* // For operations called thousands of times per second
|
|
3275
|
-
* ```
|
|
3276
|
-
*/
|
|
3277
|
-
function withHighFrequencyMemoization() {
|
|
3278
|
-
return withMemoization(MEMOIZATION_PRESETS.highFrequency);
|
|
3279
|
-
}
|
|
3280
|
-
/**
|
|
3281
|
-
* Enhances a SignalTree with memoization capabilities
|
|
3282
|
-
* Uses unconstrained recursive typing - no limitations on T
|
|
3283
|
-
*/
|
|
3284
|
-
function withMemoization(config = {}) {
|
|
3285
|
-
const { enabled = true, maxCacheSize = 1000, ttl,
|
|
3286
|
-
// Default behavior: deep equality and LRU enabled to preserve
|
|
3287
|
-
// memoization semantics expected by existing consumers/tests.
|
|
3288
|
-
equality = 'deep', enableLRU = true, } = config;
|
|
3289
|
-
return (tree) => {
|
|
3290
|
-
const originalTreeCall = tree.bind(tree);
|
|
3291
|
-
const applyUpdateResult = (result) => {
|
|
3292
|
-
Object.entries(result).forEach(([propKey, value]) => {
|
|
3293
|
-
const property = tree.state[propKey];
|
|
3294
|
-
if (property && 'set' in property) {
|
|
3295
|
-
property.set(value);
|
|
3296
|
-
}
|
|
3297
|
-
else if (isNodeAccessor$1(property)) {
|
|
3298
|
-
property(value);
|
|
3299
|
-
}
|
|
3300
|
-
});
|
|
3301
|
-
};
|
|
3302
|
-
if (!enabled) {
|
|
3303
|
-
const memoTree = tree;
|
|
3304
|
-
memoTree.memoizedUpdate = (updater) => {
|
|
3305
|
-
const currentState = originalTreeCall();
|
|
3306
|
-
const result = updater(currentState);
|
|
3307
|
-
applyUpdateResult(result);
|
|
3308
|
-
};
|
|
3309
|
-
memoTree.clearMemoCache = () => {
|
|
3310
|
-
/* no-op when memoization disabled */
|
|
3311
|
-
};
|
|
3312
|
-
memoTree.getCacheStats = () => ({
|
|
3313
|
-
size: 0,
|
|
3314
|
-
hitRate: 0,
|
|
3315
|
-
totalHits: 0,
|
|
3316
|
-
totalMisses: 0,
|
|
3317
|
-
keys: [],
|
|
3318
|
-
});
|
|
3319
|
-
return memoTree;
|
|
3320
|
-
}
|
|
3321
|
-
// Initialize cache for this tree
|
|
3322
|
-
const cache = createMemoCacheStore(maxCacheSize, enableLRU);
|
|
3323
|
-
memoizationCache.set(tree, cache);
|
|
3324
|
-
const equalityFn = getEqualityFn(equality);
|
|
3325
|
-
// Add memoized update method
|
|
3326
|
-
tree.memoizedUpdate = (updater, cacheKey) => {
|
|
3327
|
-
const currentState = originalTreeCall();
|
|
3328
|
-
// Determine cache key: prefer explicit keyFn-like behavior if not provided
|
|
3329
|
-
const key = cacheKey ||
|
|
3330
|
-
generateCacheKey(updater, [
|
|
3331
|
-
currentState,
|
|
3332
|
-
]);
|
|
3333
|
-
// Check cache
|
|
3334
|
-
const cached = cache.get(key);
|
|
3335
|
-
if (cached && equalityFn(cached.deps, [currentState])) {
|
|
3336
|
-
// Apply cached result - use callable interface to set the partial update
|
|
3337
|
-
const cachedUpdate = cached.value;
|
|
3338
|
-
applyUpdateResult(cachedUpdate);
|
|
3339
|
-
return;
|
|
3340
|
-
}
|
|
3341
|
-
// Compute new result
|
|
3342
|
-
const result = updater(currentState);
|
|
3343
|
-
// Cache the result
|
|
3344
|
-
cache.set(key, {
|
|
3345
|
-
value: result,
|
|
3346
|
-
deps: [currentState],
|
|
3347
|
-
timestamp: Date.now(),
|
|
3348
|
-
hitCount: 1,
|
|
3349
|
-
});
|
|
3350
|
-
// Apply update using callable interface
|
|
3351
|
-
applyUpdateResult(result);
|
|
3352
|
-
};
|
|
3353
|
-
// Add cache management methods
|
|
3354
|
-
tree.clearMemoCache = (key) => {
|
|
3355
|
-
if (key) {
|
|
3356
|
-
cache.delete(key);
|
|
3357
|
-
}
|
|
3358
|
-
else {
|
|
3359
|
-
cache.clear();
|
|
3360
|
-
}
|
|
3361
|
-
};
|
|
3362
|
-
tree.getCacheStats = () => {
|
|
3363
|
-
let totalHits = 0;
|
|
3364
|
-
let totalMisses = 0;
|
|
3365
|
-
cache.forEach((entry) => {
|
|
3366
|
-
totalHits += entry.hitCount || 0;
|
|
3367
|
-
// For simplicity, we'll estimate misses as half of hits
|
|
3368
|
-
totalMisses += Math.floor((entry.hitCount || 0) / 2);
|
|
3369
|
-
});
|
|
3370
|
-
const hitRate = totalHits + totalMisses > 0 ? totalHits / (totalHits + totalMisses) : 0;
|
|
3371
|
-
return {
|
|
3372
|
-
size: cache.size(),
|
|
3373
|
-
hitRate,
|
|
3374
|
-
totalHits,
|
|
3375
|
-
totalMisses,
|
|
3376
|
-
keys: Array.from(cache.keys()),
|
|
3377
|
-
};
|
|
3378
|
-
};
|
|
3379
|
-
// If we created a periodic cleanup for this tree, ensure callers can clear it
|
|
3380
|
-
const maybeInterval = getCleanupInterval(tree);
|
|
3381
|
-
if (maybeInterval) {
|
|
3382
|
-
// When the tree cache is cleared, also clear the interval
|
|
3383
|
-
const origClear = tree.clearMemoCache.bind(tree);
|
|
3384
|
-
tree.clearMemoCache = (key) => {
|
|
3385
|
-
origClear(key);
|
|
3386
|
-
clearCleanupInterval(tree);
|
|
3387
|
-
};
|
|
3388
|
-
}
|
|
3389
|
-
// Intentionally do NOT attach memoization helpers to `tree.$` to preserve
|
|
3390
|
-
// the "callable-only nodes" invariant for serialization safety.
|
|
3391
|
-
// Clean up expired entries if TTL is set
|
|
3392
|
-
if (ttl) {
|
|
3393
|
-
const cleanup = () => {
|
|
3394
|
-
const now = Date.now();
|
|
3395
|
-
cache.forEach((entry, key) => {
|
|
3396
|
-
if (entry.timestamp && now - entry.timestamp > ttl) {
|
|
3397
|
-
cache.delete(key);
|
|
3398
|
-
}
|
|
3399
|
-
});
|
|
3400
|
-
};
|
|
3401
|
-
// Run cleanup periodically
|
|
3402
|
-
const intervalId = setInterval(cleanup, ttl);
|
|
3403
|
-
// Store interval ID for cleanup (handle Node.js vs browser differences)
|
|
3404
|
-
setCleanupInterval(tree, intervalId);
|
|
3405
|
-
}
|
|
3406
|
-
return tree;
|
|
3407
|
-
};
|
|
3408
|
-
}
|
|
3409
|
-
/**
|
|
3410
|
-
* High-performance memoization with aggressive caching
|
|
3411
|
-
* Uses unconstrained recursive typing - no limitations on T
|
|
3412
|
-
*/
|
|
3413
|
-
function withHighPerformanceMemoization() {
|
|
3414
|
-
return withMemoization({
|
|
3415
|
-
enabled: true,
|
|
3416
|
-
maxCacheSize: 10000,
|
|
3417
|
-
ttl: 300000, // 5 minutes
|
|
3418
|
-
equality: 'shallow', // Faster than deep equality
|
|
3419
|
-
enableLRU: true,
|
|
3420
|
-
});
|
|
3421
|
-
}
|
|
3422
|
-
/**
|
|
3423
|
-
* Lightweight memoization optimized for performance-critical scenarios
|
|
3424
|
-
* Disables expensive cache management features for maximum speed
|
|
3425
|
-
*/
|
|
3426
|
-
function withLightweightMemoization() {
|
|
3427
|
-
return withMemoization({
|
|
3428
|
-
enabled: true,
|
|
3429
|
-
maxCacheSize: 100, // Smaller cache to reduce management overhead
|
|
3430
|
-
ttl: undefined, // No TTL to avoid timestamp checks
|
|
3431
|
-
equality: 'reference', // Fastest equality check
|
|
3432
|
-
enableLRU: false, // No LRU to avoid hit count tracking
|
|
3433
|
-
});
|
|
3434
|
-
}
|
|
3435
|
-
/**
|
|
3436
|
-
* Shallow equality memoization for objects with primitive values
|
|
3437
|
-
* Good balance between performance and correctness
|
|
3438
|
-
*/
|
|
3439
|
-
function withShallowMemoization() {
|
|
3440
|
-
return withMemoization({
|
|
3441
|
-
enabled: true,
|
|
3442
|
-
maxCacheSize: 1000,
|
|
3443
|
-
ttl: 60000, // 1 minute
|
|
3444
|
-
equality: 'shallow',
|
|
3445
|
-
enableLRU: true,
|
|
3446
|
-
});
|
|
3447
|
-
}
|
|
3448
|
-
/**
|
|
3449
|
-
* Clear all memoization caches
|
|
3450
|
-
*/
|
|
3451
|
-
function clearAllCaches() {
|
|
3452
|
-
resetMemoizationCaches();
|
|
3453
|
-
}
|
|
3454
|
-
/**
|
|
3455
|
-
* Get global cache statistics
|
|
3456
|
-
*/
|
|
3457
|
-
function getGlobalCacheStats() {
|
|
3458
|
-
// Note: We keep a Map keyed by tree objects to allow listing and diagnostics
|
|
3459
|
-
// (WeakMap would prevent traversal). This function summarizes those diagnostics.
|
|
3460
|
-
let totalSize = 0;
|
|
3461
|
-
let totalHits = 0;
|
|
3462
|
-
let treeCount = 0;
|
|
3463
|
-
memoizationCache.forEach((cache) => {
|
|
3464
|
-
treeCount++;
|
|
3465
|
-
totalSize += cache.size();
|
|
3466
|
-
cache.forEach((entry) => {
|
|
3467
|
-
totalHits += entry.hitCount || 0;
|
|
3468
|
-
});
|
|
3469
|
-
});
|
|
3470
|
-
return {
|
|
3471
|
-
treeCount,
|
|
3472
|
-
totalSize,
|
|
3473
|
-
totalHits,
|
|
3474
|
-
averageCacheSize: treeCount > 0 ? totalSize / treeCount : 0,
|
|
3475
|
-
};
|
|
3476
|
-
}
|
|
3477
|
-
|
|
3478
|
-
/**
|
|
3479
|
-
* Internal time travel state management
|
|
3480
|
-
*/
|
|
3481
|
-
class TimeTravelManager {
|
|
3482
|
-
tree;
|
|
3483
|
-
config;
|
|
3484
|
-
restoreStateFn;
|
|
3485
|
-
history = [];
|
|
3486
|
-
currentIndex = -1;
|
|
3487
|
-
maxHistorySize;
|
|
3488
|
-
includePayload;
|
|
3489
|
-
actionNames;
|
|
3490
|
-
constructor(tree, config = {}, restoreStateFn) {
|
|
3491
|
-
this.tree = tree;
|
|
3492
|
-
this.config = config;
|
|
3493
|
-
this.restoreStateFn = restoreStateFn;
|
|
3494
|
-
this.maxHistorySize = config.maxHistorySize ?? 50;
|
|
3495
|
-
this.includePayload = config.includePayload ?? true;
|
|
3496
|
-
this.actionNames = {
|
|
3497
|
-
update: 'UPDATE',
|
|
3498
|
-
set: 'SET',
|
|
3499
|
-
batch: 'BATCH',
|
|
3500
|
-
...config.actionNames,
|
|
3501
|
-
};
|
|
3502
|
-
// Add initial state to history
|
|
3503
|
-
this.addEntry('INIT', this.tree());
|
|
3504
|
-
}
|
|
3505
|
-
/**
|
|
3506
|
-
* Add a new entry to the history
|
|
3507
|
-
*/
|
|
3508
|
-
addEntry(action, state, payload) {
|
|
3509
|
-
// If we're not at the end of history, remove everything after current position
|
|
3510
|
-
if (this.currentIndex < this.history.length - 1) {
|
|
3511
|
-
this.history = this.history.slice(0, this.currentIndex + 1);
|
|
3512
|
-
}
|
|
3513
|
-
// Create new entry
|
|
3514
|
-
const entry = {
|
|
3515
|
-
state: deepClone(state),
|
|
3516
|
-
timestamp: Date.now(),
|
|
3517
|
-
action: this.actionNames[action] || action,
|
|
3518
|
-
...(this.includePayload && payload !== undefined && { payload }),
|
|
3519
|
-
};
|
|
3520
|
-
this.history.push(entry);
|
|
3521
|
-
this.currentIndex = this.history.length - 1;
|
|
3522
|
-
// Enforce max history size
|
|
3523
|
-
if (this.history.length > this.maxHistorySize) {
|
|
3524
|
-
this.history.shift();
|
|
3525
|
-
this.currentIndex--;
|
|
3526
|
-
}
|
|
3527
|
-
}
|
|
3528
|
-
undo() {
|
|
3529
|
-
if (!this.canUndo()) {
|
|
3530
|
-
return false;
|
|
3531
|
-
}
|
|
3532
|
-
this.currentIndex--;
|
|
3533
|
-
const entry = this.history[this.currentIndex];
|
|
3534
|
-
this.restoreState(entry.state);
|
|
3535
|
-
return true;
|
|
3536
|
-
}
|
|
3537
|
-
redo() {
|
|
3538
|
-
if (!this.canRedo()) {
|
|
3539
|
-
return false;
|
|
3540
|
-
}
|
|
3541
|
-
this.currentIndex++;
|
|
3542
|
-
const entry = this.history[this.currentIndex];
|
|
3543
|
-
this.restoreState(entry.state);
|
|
3544
|
-
return true;
|
|
3545
|
-
}
|
|
3546
|
-
getHistory() {
|
|
3547
|
-
return this.history.map((entry) => ({
|
|
3548
|
-
...entry,
|
|
3549
|
-
state: deepClone(entry.state),
|
|
3550
|
-
}));
|
|
3551
|
-
}
|
|
3552
|
-
resetHistory() {
|
|
3553
|
-
const currentState = this.tree();
|
|
3554
|
-
this.history = [];
|
|
3555
|
-
this.currentIndex = -1;
|
|
3556
|
-
this.addEntry('RESET', currentState);
|
|
3557
|
-
}
|
|
3558
|
-
jumpTo(index) {
|
|
3559
|
-
if (index < 0 || index >= this.history.length) {
|
|
3560
|
-
return false;
|
|
3561
|
-
}
|
|
3562
|
-
this.currentIndex = index;
|
|
3563
|
-
const entry = this.history[index];
|
|
3564
|
-
this.restoreState(entry.state);
|
|
3565
|
-
return true;
|
|
3566
|
-
}
|
|
3567
|
-
getCurrentIndex() {
|
|
3568
|
-
return this.currentIndex;
|
|
3569
|
-
}
|
|
3570
|
-
canUndo() {
|
|
3571
|
-
return this.currentIndex > 0;
|
|
3572
|
-
}
|
|
3573
|
-
canRedo() {
|
|
3574
|
-
return this.currentIndex < this.history.length - 1;
|
|
3575
|
-
}
|
|
3576
|
-
/**
|
|
3577
|
-
* Restore state without triggering time travel middleware
|
|
3578
|
-
*/
|
|
3579
|
-
restoreState(state) {
|
|
3580
|
-
if (this.restoreStateFn) {
|
|
3581
|
-
this.restoreStateFn(state);
|
|
3582
|
-
}
|
|
3583
|
-
else {
|
|
3584
|
-
// Fallback if no restoration function provided
|
|
3585
|
-
this.tree(state);
|
|
3586
|
-
}
|
|
3587
|
-
}
|
|
3588
|
-
}
|
|
3589
|
-
/**
|
|
3590
|
-
* Enhances a SignalTree with comprehensive time travel capabilities.
|
|
3591
|
-
*
|
|
3592
|
-
* Adds undo/redo functionality, state history management, and snapshot features.
|
|
3593
|
-
* Automatically tracks state changes and provides methods to navigate through
|
|
3594
|
-
* the application's state history with configurable limits and optimizations.
|
|
3595
|
-
*
|
|
3596
|
-
* @template T - The state object type
|
|
3597
|
-
* @param config - Configuration options for time travel behavior
|
|
3598
|
-
* @returns Function that enhances a SignalTree with time travel capabilities
|
|
3599
|
-
*
|
|
3600
|
-
* @example
|
|
3601
|
-
* ```typescript
|
|
3602
|
-
* // Basic time travel enhancement
|
|
3603
|
-
* const store = signalTree({ count: 0, text: '' }).with(withTimeTravel());
|
|
3604
|
-
*
|
|
3605
|
-
* // Make some changes
|
|
3606
|
-
* store.count.set(1);
|
|
3607
|
-
* store.text.set('hello');
|
|
3608
|
-
* store.count.set(2);
|
|
3609
|
-
*
|
|
3610
|
-
* // Access time travel interface
|
|
3611
|
-
* const timeTravel = store.__timeTravel;
|
|
3612
|
-
*
|
|
3613
|
-
* // Navigate history
|
|
3614
|
-
* console.log(timeTravel.canUndo()); // true
|
|
3615
|
-
* timeTravel.undo(); // count: 1, text: 'hello'
|
|
3616
|
-
* timeTravel.undo(); // count: 1, text: ''
|
|
3617
|
-
* timeTravel.undo(); // count: 0, text: ''
|
|
3618
|
-
*
|
|
3619
|
-
* timeTravel.redo(); // count: 1, text: ''
|
|
3620
|
-
* console.log(timeTravel.canRedo()); // true
|
|
3621
|
-
* ```
|
|
3622
|
-
*
|
|
3623
|
-
* @example
|
|
3624
|
-
* ```typescript
|
|
3625
|
-
* // Advanced configuration
|
|
3626
|
-
* const store = signalTree({
|
|
3627
|
-
* document: { title: '', content: '' },
|
|
3628
|
-
* settings: { theme: 'light' }
|
|
3629
|
-
* }).with(withTimeTravel({
|
|
3630
|
-
* maxHistorySize: 50, // Limit memory usage
|
|
3631
|
-
* includePayload: true, // Store action metadata
|
|
3632
|
-
* actionNames: { // Custom action names
|
|
3633
|
-
* 'update_title': 'Update Document Title',
|
|
3634
|
-
* 'change_theme': 'Change Theme'
|
|
3635
|
-
* }
|
|
3636
|
-
* }));
|
|
3637
|
-
*
|
|
3638
|
-
* // Named actions with metadata
|
|
3639
|
-
* store.update(() => ({ document: { title: 'New Title' } }), 'update_title');
|
|
3640
|
-
*
|
|
3641
|
-
* // View detailed history
|
|
3642
|
-
* const history = store.__timeTravel.getHistory();
|
|
3643
|
-
* console.log(history[0].action); // 'Update Document Title'
|
|
3644
|
-
* console.log(history[0].timestamp); // Date when change occurred
|
|
3645
|
-
* ```
|
|
3646
|
-
*/
|
|
3647
|
-
function withTimeTravel(config = {}) {
|
|
3648
|
-
return (tree) => {
|
|
3649
|
-
// Store the original callable tree function
|
|
3650
|
-
const originalTreeCall = tree.bind(tree);
|
|
3651
|
-
// Flag to prevent time travel during restoration
|
|
3652
|
-
let isRestoring = false;
|
|
3653
|
-
// Create time travel manager with restoration function
|
|
3654
|
-
const timeTravelManager = new TimeTravelManager(tree, config, (state) => {
|
|
3655
|
-
isRestoring = true;
|
|
3656
|
-
try {
|
|
3657
|
-
originalTreeCall(state);
|
|
3658
|
-
}
|
|
3659
|
-
finally {
|
|
3660
|
-
isRestoring = false;
|
|
3661
|
-
}
|
|
3662
|
-
});
|
|
3663
|
-
// Create enhanced tree function that includes time travel tracking
|
|
3664
|
-
const enhancedTree = function (...args) {
|
|
3665
|
-
if (args.length === 0) {
|
|
3666
|
-
// Get operation - call original directly
|
|
3667
|
-
return originalTreeCall();
|
|
3668
|
-
}
|
|
3669
|
-
else {
|
|
3670
|
-
// Set or update operation - track for time travel
|
|
3671
|
-
if (isRestoring) {
|
|
3672
|
-
// During restoration, just call original update
|
|
3673
|
-
if (args.length === 1) {
|
|
3674
|
-
const arg = args[0];
|
|
3675
|
-
if (typeof arg === 'function') {
|
|
3676
|
-
return originalTreeCall(arg);
|
|
3677
|
-
}
|
|
3678
|
-
else {
|
|
3679
|
-
return originalTreeCall(arg);
|
|
3680
|
-
}
|
|
3681
|
-
}
|
|
3682
|
-
return;
|
|
3683
|
-
}
|
|
3684
|
-
const beforeState = originalTreeCall();
|
|
3685
|
-
// Execute the actual update using the original callable interface
|
|
3686
|
-
let result;
|
|
3687
|
-
if (args.length === 1) {
|
|
3688
|
-
const arg = args[0];
|
|
3689
|
-
if (typeof arg === 'function') {
|
|
3690
|
-
result = originalTreeCall(arg);
|
|
3691
|
-
}
|
|
3692
|
-
else {
|
|
3693
|
-
result = originalTreeCall(arg);
|
|
3694
|
-
}
|
|
3695
|
-
}
|
|
3696
|
-
const afterState = originalTreeCall();
|
|
3697
|
-
// Only add to history if state actually changed
|
|
3698
|
-
const statesEqual = deepEqual(beforeState, afterState);
|
|
3699
|
-
if (!statesEqual) {
|
|
3700
|
-
timeTravelManager.addEntry('update', afterState);
|
|
3701
|
-
}
|
|
3702
|
-
return result;
|
|
3703
|
-
}
|
|
3704
|
-
};
|
|
3705
|
-
// Copy all properties and methods from original tree
|
|
3706
|
-
Object.setPrototypeOf(enhancedTree, Object.getPrototypeOf(tree));
|
|
3707
|
-
Object.assign(enhancedTree, tree);
|
|
3708
|
-
// Ensure state and $ properties are preserved
|
|
3709
|
-
if ('state' in tree) {
|
|
3710
|
-
Object.defineProperty(enhancedTree, 'state', {
|
|
3711
|
-
value: tree.state,
|
|
3712
|
-
enumerable: false,
|
|
3713
|
-
configurable: true,
|
|
3714
|
-
});
|
|
3715
|
-
}
|
|
3716
|
-
// Ensure $ alias is preserved
|
|
3717
|
-
if ('$' in tree) {
|
|
3718
|
-
Object.defineProperty(enhancedTree, '$', {
|
|
3719
|
-
value: tree['$'],
|
|
3720
|
-
enumerable: false,
|
|
3721
|
-
configurable: true,
|
|
3722
|
-
});
|
|
3723
|
-
}
|
|
3724
|
-
// Override DX-friendly methods to forward to the time travel manager
|
|
3725
|
-
// These shadow the core stubs when the enhancer is applied
|
|
3726
|
-
enhancedTree.undo = () => {
|
|
3727
|
-
timeTravelManager.undo();
|
|
3728
|
-
};
|
|
3729
|
-
enhancedTree.redo = () => {
|
|
3730
|
-
timeTravelManager.redo();
|
|
3731
|
-
};
|
|
3732
|
-
enhancedTree.getHistory = () => timeTravelManager.getHistory();
|
|
3733
|
-
enhancedTree.resetHistory =
|
|
3734
|
-
() => {
|
|
3735
|
-
timeTravelManager.resetHistory();
|
|
3736
|
-
};
|
|
3737
|
-
// Additional helpers exposed directly on the tree for better DX
|
|
3738
|
-
enhancedTree.jumpTo = (index) => {
|
|
3739
|
-
timeTravelManager.jumpTo(index);
|
|
3740
|
-
};
|
|
3741
|
-
enhancedTree.canUndo = () => timeTravelManager.canUndo();
|
|
3742
|
-
enhancedTree.canRedo = () => timeTravelManager.canRedo();
|
|
3743
|
-
enhancedTree.getCurrentIndex =
|
|
3744
|
-
() => timeTravelManager.getCurrentIndex();
|
|
3745
|
-
return Object.assign(enhancedTree, {
|
|
3746
|
-
__timeTravel: timeTravelManager,
|
|
3747
|
-
});
|
|
3748
|
-
};
|
|
3749
|
-
}
|
|
3750
|
-
/**
|
|
3751
|
-
* Convenience function to enable basic time travel
|
|
3752
|
-
*/
|
|
3753
|
-
function enableTimeTravel(maxHistorySize) {
|
|
3754
|
-
return withTimeTravel({ maxHistorySize });
|
|
3755
|
-
}
|
|
3756
|
-
/**
|
|
3757
|
-
* Get time travel interface from an enhanced tree
|
|
3758
|
-
*/
|
|
3759
|
-
function getTimeTravel(tree) {
|
|
3760
|
-
return tree.__timeTravel;
|
|
3761
|
-
}
|
|
3762
|
-
|
|
3763
|
-
/**
|
|
3764
|
-
* Creates entity helpers for a specific entity collection
|
|
3765
|
-
* This properly handles the SignalTree's TreeNode type structure
|
|
3766
|
-
*
|
|
3767
|
-
* CRITICAL: In SignalTree, arrays become WritableSignal<Array>
|
|
3768
|
-
* So `users: User[]` in the original state becomes `users: WritableSignal<User[]>` in tree.state
|
|
3769
|
-
*/
|
|
3770
|
-
function createEntityHelpers(tree, entityKey) {
|
|
3771
|
-
// Get the signal from the deeply signalified state
|
|
3772
|
-
// The state property is of type TreeNode<T>
|
|
3773
|
-
const getEntitySignal = () => {
|
|
3774
|
-
// Access the state property - it's already a signal due to TreeNode
|
|
3775
|
-
// We need to use type assertion here because TypeScript can't track the deep signalification
|
|
3776
|
-
const stateProperty = tree.state[entityKey];
|
|
3777
|
-
// Check if it exists
|
|
3778
|
-
if (!stateProperty) {
|
|
3779
|
-
throw new Error(`Entity key '${String(entityKey)}' does not exist in the state`);
|
|
3780
|
-
}
|
|
3781
|
-
// Due to TreeNode, if the original was an array, it's now WritableSignal<Array>
|
|
3782
|
-
if (!isAnySignal(stateProperty)) {
|
|
3783
|
-
throw new Error(`Entity key '${String(entityKey)}' is not a signal. This should not happen with SignalTree.`);
|
|
3784
|
-
}
|
|
3785
|
-
// Cast to WritableSignal and verify it contains an array
|
|
3786
|
-
const signal = stateProperty;
|
|
3787
|
-
const value = signal();
|
|
3788
|
-
if (!Array.isArray(value)) {
|
|
3789
|
-
throw new Error(`Entity key '${String(entityKey)}' does not contain an array. Current type: ${typeof value}`);
|
|
3790
|
-
}
|
|
3791
|
-
return signal;
|
|
3792
|
-
};
|
|
3793
|
-
// Helper function to set values on both WritableSignal and callable signals
|
|
3794
|
-
const setSignalValue = (signal, value) => {
|
|
3795
|
-
if (isNodeAccessor$1(signal)) {
|
|
3796
|
-
// Callable signal - use function call
|
|
3797
|
-
signal(value);
|
|
3798
|
-
}
|
|
3799
|
-
else {
|
|
3800
|
-
// WritableSignal - use .set() method
|
|
3801
|
-
signal.set(value);
|
|
3802
|
-
}
|
|
3803
|
-
};
|
|
3804
|
-
return {
|
|
3805
|
-
add: (entity) => {
|
|
3806
|
-
const entitySignal = getEntitySignal();
|
|
3807
|
-
const currentEntities = entitySignal();
|
|
3808
|
-
// Check for duplicate
|
|
3809
|
-
if (currentEntities.some((e) => e.id === entity.id)) {
|
|
3810
|
-
throw new Error(`Entity with id '${entity.id}' already exists`);
|
|
3811
|
-
}
|
|
3812
|
-
setSignalValue(entitySignal, [...currentEntities, entity]);
|
|
3813
|
-
},
|
|
3814
|
-
update: (id, updates) => {
|
|
3815
|
-
const entitySignal = getEntitySignal();
|
|
3816
|
-
const currentEntities = entitySignal();
|
|
3817
|
-
const updatedEntities = currentEntities.map((entity) => entity.id === id ? { ...entity, ...updates } : entity);
|
|
3818
|
-
setSignalValue(entitySignal, updatedEntities);
|
|
3819
|
-
},
|
|
3820
|
-
remove: (id) => {
|
|
3821
|
-
const entitySignal = getEntitySignal();
|
|
3822
|
-
const currentEntities = entitySignal();
|
|
3823
|
-
const filteredEntities = currentEntities.filter((entity) => entity.id !== id);
|
|
3824
|
-
setSignalValue(entitySignal, filteredEntities);
|
|
3825
|
-
},
|
|
3826
|
-
upsert: (entity) => {
|
|
3827
|
-
const entitySignal = getEntitySignal();
|
|
3828
|
-
const currentEntities = entitySignal();
|
|
3829
|
-
const index = currentEntities.findIndex((e) => e.id === entity.id);
|
|
3830
|
-
if (index >= 0) {
|
|
3831
|
-
// Update existing
|
|
3832
|
-
const updatedEntities = [...currentEntities];
|
|
3833
|
-
updatedEntities[index] = entity;
|
|
3834
|
-
setSignalValue(entitySignal, updatedEntities);
|
|
3835
|
-
}
|
|
3836
|
-
else {
|
|
3837
|
-
// Add new
|
|
3838
|
-
setSignalValue(entitySignal, [...currentEntities, entity]);
|
|
3839
|
-
}
|
|
3840
|
-
},
|
|
3841
|
-
selectById: (id) => {
|
|
3842
|
-
const entitySignal = getEntitySignal();
|
|
3843
|
-
return computed(() => entitySignal().find((entity) => entity.id === id));
|
|
3844
|
-
},
|
|
3845
|
-
selectBy: (predicate) => {
|
|
3846
|
-
const entitySignal = getEntitySignal();
|
|
3847
|
-
return computed(() => entitySignal().filter(predicate));
|
|
3848
|
-
},
|
|
3849
|
-
selectIds: () => {
|
|
3850
|
-
const entitySignal = getEntitySignal();
|
|
3851
|
-
return computed(() => entitySignal().map((entity) => entity.id));
|
|
3852
|
-
},
|
|
3853
|
-
selectAll: () => {
|
|
3854
|
-
const entitySignal = getEntitySignal();
|
|
3855
|
-
return entitySignal;
|
|
3856
|
-
},
|
|
3857
|
-
selectTotal: () => {
|
|
3858
|
-
const entitySignal = getEntitySignal();
|
|
3859
|
-
return computed(() => entitySignal().length);
|
|
3860
|
-
},
|
|
3861
|
-
clear: () => {
|
|
3862
|
-
const entitySignal = getEntitySignal();
|
|
3863
|
-
setSignalValue(entitySignal, []);
|
|
3864
|
-
},
|
|
3865
|
-
};
|
|
3866
|
-
}
|
|
3867
|
-
/**
|
|
3868
|
-
* Enhances a SignalTree with entity management capabilities
|
|
3869
|
-
* Works with SignalTree's TreeNode type structure
|
|
3870
|
-
*
|
|
3871
|
-
* The key insight: The state is already deeply signalified, so array properties
|
|
3872
|
-
* like `users: User[]` become `users: WritableSignal<User[]>` in tree.state
|
|
3873
|
-
*/
|
|
3874
|
-
function withEntities(config = {}) {
|
|
3875
|
-
const { enabled = true } = config;
|
|
3876
|
-
return function enhanceWithEntities(tree) {
|
|
3877
|
-
if (!enabled) {
|
|
3878
|
-
// When disabled, return the original tree object unchanged
|
|
3879
|
-
// Cast is safe here because we're not actually adding the method
|
|
3880
|
-
return tree;
|
|
3881
|
-
}
|
|
3882
|
-
// Type-safe enhancement that adds entities method using Object.assign
|
|
3883
|
-
// This approach preserves the generic method signature better than direct property assignment
|
|
3884
|
-
const enhancedTree = Object.assign(tree, {
|
|
3885
|
-
entities(entityKey) {
|
|
3886
|
-
return createEntityHelpers(tree, entityKey);
|
|
3887
|
-
},
|
|
3888
|
-
});
|
|
3889
|
-
return enhancedTree;
|
|
3890
|
-
};
|
|
3891
|
-
}
|
|
3892
|
-
/**
|
|
3893
|
-
* Convenience function to enable entities with default config
|
|
3894
|
-
*/
|
|
3895
|
-
function enableEntities() {
|
|
3896
|
-
return withEntities({ enabled: true });
|
|
3897
|
-
}
|
|
3898
|
-
/**
|
|
3899
|
-
* High-performance entity management configuration
|
|
3900
|
-
*/
|
|
3901
|
-
function withHighPerformanceEntities() {
|
|
3902
|
-
return withEntities({
|
|
3903
|
-
enabled: true});
|
|
3904
|
-
}
|
|
3905
|
-
|
|
3906
|
-
/**
|
|
3907
|
-
* Type markers for special object serialization
|
|
3908
|
-
* Using compact symbols to minimize serialized size
|
|
3909
|
-
*/
|
|
3910
|
-
const TYPE_MARKERS = {
|
|
3911
|
-
DATE: '§d',
|
|
3912
|
-
REGEXP: '§r',
|
|
3913
|
-
MAP: '§m',
|
|
3914
|
-
SET: '§s',
|
|
3915
|
-
UNDEFINED: '§u',
|
|
3916
|
-
NAN: '§n',
|
|
3917
|
-
INFINITY: '§i',
|
|
3918
|
-
NEG_INFINITY: '§-i',
|
|
3919
|
-
BIGINT: '§b',
|
|
3920
|
-
SYMBOL: '§y',
|
|
3921
|
-
CIRCULAR: '§c',
|
|
3922
|
-
};
|
|
3923
|
-
|
|
3924
|
-
/**
|
|
3925
|
-
* Default serialization config
|
|
3926
|
-
*/
|
|
3927
|
-
const DEFAULT_CONFIG = {
|
|
3928
|
-
includeMetadata: true,
|
|
3929
|
-
replacer: undefined,
|
|
3930
|
-
reviver: undefined,
|
|
3931
|
-
preserveTypes: true,
|
|
3932
|
-
maxDepth: 50,
|
|
3933
|
-
handleCircular: true,
|
|
3934
|
-
};
|
|
3935
|
-
/**
|
|
3936
|
-
* Safely unwrap object with circular reference detection
|
|
3937
|
-
*/
|
|
3938
|
-
function unwrapObjectSafely(obj, visited = new WeakSet(), depth = 0, maxDepth = 50, preserveTypes = true) {
|
|
3939
|
-
// Prevent infinite recursion
|
|
3940
|
-
if (depth > maxDepth)
|
|
3941
|
-
return '[Max Depth Exceeded]';
|
|
3942
|
-
// Primitives and non-objects
|
|
3943
|
-
if (obj === null || typeof obj !== 'object') {
|
|
3944
|
-
if (!preserveTypes)
|
|
3945
|
-
return obj;
|
|
3946
|
-
if (obj === undefined)
|
|
3947
|
-
return { [TYPE_MARKERS.UNDEFINED]: true };
|
|
3948
|
-
if (typeof obj === 'number') {
|
|
3949
|
-
if (Number.isNaN(obj))
|
|
3950
|
-
return { [TYPE_MARKERS.NAN]: true };
|
|
3951
|
-
if (obj === Infinity)
|
|
3952
|
-
return { [TYPE_MARKERS.INFINITY]: true };
|
|
3953
|
-
if (obj === -Infinity)
|
|
3954
|
-
return { [TYPE_MARKERS.NEG_INFINITY]: true };
|
|
3955
|
-
return obj;
|
|
3956
|
-
}
|
|
3957
|
-
if (typeof obj === 'bigint')
|
|
3958
|
-
return { [TYPE_MARKERS.BIGINT]: String(obj) };
|
|
3959
|
-
if (typeof obj === 'symbol')
|
|
3960
|
-
return { [TYPE_MARKERS.SYMBOL]: String(obj) };
|
|
3961
|
-
return obj;
|
|
3962
|
-
}
|
|
3963
|
-
// Handle callable signals (no longer need complex branch wrapper detection)
|
|
3964
|
-
if (typeof obj === 'function') {
|
|
3965
|
-
try {
|
|
3966
|
-
// Check if it's a callable signal by trying to invoke it
|
|
3967
|
-
const result = obj();
|
|
3968
|
-
return unwrapObjectSafely(result, visited, depth + 1, maxDepth, preserveTypes);
|
|
3969
|
-
}
|
|
3970
|
-
catch {
|
|
3971
|
-
// Not a callable signal, treat as regular function (non-serializable)
|
|
3972
|
-
return '[Function]';
|
|
3973
|
-
}
|
|
3974
|
-
}
|
|
3975
|
-
// If object already visited, mark as circular
|
|
3976
|
-
if (visited.has(obj))
|
|
3977
|
-
return '[Circular Reference]';
|
|
3978
|
-
// Unwrap signals
|
|
3979
|
-
if (isSignal(obj))
|
|
3980
|
-
return obj();
|
|
3981
|
-
// Preserve special types
|
|
3982
|
-
if (preserveTypes) {
|
|
3983
|
-
if (obj instanceof Date)
|
|
3984
|
-
return { [TYPE_MARKERS.DATE]: obj.toISOString() };
|
|
3985
|
-
if (obj instanceof RegExp)
|
|
3986
|
-
return {
|
|
3987
|
-
[TYPE_MARKERS.REGEXP]: { source: obj.source, flags: obj.flags },
|
|
3988
|
-
};
|
|
3989
|
-
if (obj instanceof Map) {
|
|
3990
|
-
return { [TYPE_MARKERS.MAP]: Array.from(obj.entries()) };
|
|
3991
|
-
}
|
|
3992
|
-
if (obj instanceof Set) {
|
|
3993
|
-
return { [TYPE_MARKERS.SET]: Array.from(obj.values()) };
|
|
3994
|
-
}
|
|
3995
|
-
}
|
|
3996
|
-
else {
|
|
3997
|
-
if (obj instanceof Date || obj instanceof RegExp)
|
|
3998
|
-
return obj;
|
|
3999
|
-
}
|
|
4000
|
-
visited.add(obj);
|
|
4001
|
-
try {
|
|
4002
|
-
if (Array.isArray(obj)) {
|
|
4003
|
-
const arr = obj.map((item) => unwrapObjectSafely(item, visited, depth + 1, maxDepth, preserveTypes));
|
|
4004
|
-
visited.delete(obj);
|
|
4005
|
-
return arr;
|
|
4006
|
-
}
|
|
4007
|
-
const out = {};
|
|
4008
|
-
for (const [k, v] of Object.entries(obj)) {
|
|
4009
|
-
// Skip runtime helpers when they are plain functions (not signals)
|
|
4010
|
-
if ((k === 'set' || k === 'update') &&
|
|
4011
|
-
typeof v === 'function' &&
|
|
4012
|
-
!isSignal(v))
|
|
4013
|
-
continue;
|
|
4014
|
-
if (isSignal(v)) {
|
|
4015
|
-
out[k] = unwrapObjectSafely(v(), visited, depth + 1, maxDepth, preserveTypes);
|
|
4016
|
-
}
|
|
4017
|
-
else if (typeof v === 'function' && k !== 'set' && k !== 'update') {
|
|
4018
|
-
// Handle callable signals - these are functions but not helper methods
|
|
4019
|
-
try {
|
|
4020
|
-
const callResult = v();
|
|
4021
|
-
out[k] = unwrapObjectSafely(callResult, visited, depth + 1, maxDepth, preserveTypes);
|
|
4022
|
-
}
|
|
4023
|
-
catch {
|
|
4024
|
-
// If calling fails, skip this property
|
|
4025
|
-
continue;
|
|
4026
|
-
}
|
|
4027
|
-
}
|
|
4028
|
-
else {
|
|
4029
|
-
out[k] = unwrapObjectSafely(v, visited, depth + 1, maxDepth, preserveTypes);
|
|
4030
|
-
}
|
|
4031
|
-
}
|
|
4032
|
-
visited.delete(obj);
|
|
4033
|
-
return out;
|
|
4034
|
-
}
|
|
4035
|
-
catch {
|
|
4036
|
-
visited.delete(obj);
|
|
4037
|
-
return '[Serialization Error]';
|
|
4038
|
-
}
|
|
4039
|
-
}
|
|
4040
|
-
/**
|
|
4041
|
-
* Detects circular references in an object
|
|
4042
|
-
*/
|
|
4043
|
-
function detectCircularReferences(obj, path = '', seen = new WeakSet(), paths = new Map()) {
|
|
4044
|
-
const circular = [];
|
|
4045
|
-
if (obj === null || typeof obj !== 'object') {
|
|
4046
|
-
return circular;
|
|
4047
|
-
}
|
|
4048
|
-
// Check if we've seen this object before
|
|
4049
|
-
if (seen.has(obj)) {
|
|
4050
|
-
// Found a circular reference
|
|
4051
|
-
const targetPath = paths.get(obj) || '';
|
|
4052
|
-
circular.push({ path, targetPath });
|
|
4053
|
-
return circular; // Don't recurse into circular references
|
|
4054
|
-
}
|
|
4055
|
-
// Mark this object as seen
|
|
4056
|
-
seen.add(obj);
|
|
4057
|
-
paths.set(obj, path);
|
|
4058
|
-
// Recursively check children
|
|
4059
|
-
if (Array.isArray(obj)) {
|
|
4060
|
-
const arrObj = obj;
|
|
4061
|
-
for (let i = 0; i < arrObj.length; i++) {
|
|
4062
|
-
const itemPath = path ? `${path}[${i}]` : `[${i}]`;
|
|
4063
|
-
const childCircular = detectCircularReferences(arrObj[i], itemPath, seen, paths);
|
|
4064
|
-
circular.push(...childCircular);
|
|
4065
|
-
}
|
|
4066
|
-
}
|
|
4067
|
-
else {
|
|
4068
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
4069
|
-
const propPath = path ? `${path}.${key}` : key;
|
|
4070
|
-
const childCircular = detectCircularReferences(value, propPath, seen, paths);
|
|
4071
|
-
circular.push(...childCircular);
|
|
4072
|
-
}
|
|
4073
|
-
}
|
|
4074
|
-
// Remove from seen set when backing out (allows siblings to reference same objects)
|
|
4075
|
-
seen.delete(obj);
|
|
4076
|
-
return circular;
|
|
4077
|
-
}
|
|
4078
|
-
/**
|
|
4079
|
-
* Custom replacer that handles circular references only
|
|
4080
|
-
*/
|
|
4081
|
-
function createReplacer(config) {
|
|
4082
|
-
const seen = new WeakSet();
|
|
4083
|
-
const circularPaths = new Map();
|
|
4084
|
-
return function replacer(key, value) {
|
|
4085
|
-
// Apply custom replacer first if provided
|
|
4086
|
-
if (config.replacer) {
|
|
4087
|
-
value = config.replacer.call(this, key, value);
|
|
4088
|
-
}
|
|
4089
|
-
// Skip signals - we already unwrapped them
|
|
4090
|
-
if (isSignal(value)) {
|
|
4091
|
-
return value();
|
|
4092
|
-
}
|
|
4093
|
-
// Handle circular references
|
|
4094
|
-
if (value && typeof value === 'object') {
|
|
4095
|
-
if (seen.has(value)) {
|
|
4096
|
-
if (config.handleCircular) {
|
|
4097
|
-
const targetPath = circularPaths.get(value) || '';
|
|
4098
|
-
return { [TYPE_MARKERS.CIRCULAR]: targetPath };
|
|
4099
|
-
}
|
|
4100
|
-
return undefined;
|
|
4101
|
-
}
|
|
4102
|
-
seen.add(value);
|
|
4103
|
-
const currentPath = key || '';
|
|
4104
|
-
circularPaths.set(value, currentPath);
|
|
4105
|
-
}
|
|
4106
|
-
// All special type handling is now done in unwrapObjectSafely
|
|
4107
|
-
return value;
|
|
4108
|
-
};
|
|
4109
|
-
}
|
|
4110
|
-
/**
|
|
4111
|
-
* Resolves circular references after parsing
|
|
4112
|
-
*/
|
|
4113
|
-
function resolveCircularReferences(obj, circularPaths) {
|
|
4114
|
-
for (const { path, targetPath } of circularPaths) {
|
|
4115
|
-
const pathParts = path.split(/\.|\[|\]/).filter(Boolean);
|
|
4116
|
-
const targetParts = targetPath.split(/\.|\[|\]/).filter(Boolean);
|
|
4117
|
-
// Navigate to the circular reference location
|
|
4118
|
-
let current = obj;
|
|
4119
|
-
for (let i = 0; i < pathParts.length - 1; i++) {
|
|
4120
|
-
current = current[pathParts[i]];
|
|
4121
|
-
if (!current)
|
|
4122
|
-
break;
|
|
4123
|
-
}
|
|
4124
|
-
// Navigate to the target
|
|
4125
|
-
let target = obj;
|
|
4126
|
-
for (const part of targetParts) {
|
|
4127
|
-
target = target[part];
|
|
4128
|
-
if (!target)
|
|
4129
|
-
break;
|
|
4130
|
-
}
|
|
4131
|
-
// Set the circular reference
|
|
4132
|
-
if (current && target) {
|
|
4133
|
-
current[pathParts[pathParts.length - 1]] = target;
|
|
4134
|
-
}
|
|
4135
|
-
}
|
|
4136
|
-
}
|
|
4137
|
-
/**
|
|
4138
|
-
* Enhances a SignalTree with serialization capabilities
|
|
4139
|
-
*/
|
|
4140
|
-
function withSerialization(defaultConfig = {}) {
|
|
4141
|
-
const enhancer = (tree) => {
|
|
4142
|
-
const enhanced = tree;
|
|
4143
|
-
/**
|
|
4144
|
-
* Get plain object representation
|
|
4145
|
-
*/
|
|
4146
|
-
enhanced.toJSON = () => {
|
|
4147
|
-
// Delegate to the tree's public unwrap() which already strips helper
|
|
4148
|
-
// methods like `set`/`update`. Keep unwrapObjectSafely for
|
|
4149
|
-
// serialize() where we need type-preserving markers.
|
|
4150
|
-
return tree();
|
|
4151
|
-
};
|
|
4152
|
-
/**
|
|
4153
|
-
* Restore from plain object
|
|
4154
|
-
*/
|
|
4155
|
-
enhanced.fromJSON = (data, metadata) => {
|
|
4156
|
-
// Convert special type markers back to their actual types
|
|
4157
|
-
const restoreSpecialTypes = (value) => {
|
|
4158
|
-
if (!value || typeof value !== 'object') {
|
|
4159
|
-
return value;
|
|
4160
|
-
}
|
|
4161
|
-
// Check for type markers
|
|
4162
|
-
if (TYPE_MARKERS.UNDEFINED in value) {
|
|
4163
|
-
return undefined;
|
|
4164
|
-
}
|
|
4165
|
-
if (TYPE_MARKERS.NAN in value) {
|
|
4166
|
-
return NaN;
|
|
4167
|
-
}
|
|
4168
|
-
if (TYPE_MARKERS.INFINITY in value) {
|
|
4169
|
-
return Infinity;
|
|
4170
|
-
}
|
|
4171
|
-
if (TYPE_MARKERS.NEG_INFINITY in value) {
|
|
4172
|
-
return -Infinity;
|
|
4173
|
-
}
|
|
4174
|
-
if (TYPE_MARKERS.BIGINT in value) {
|
|
4175
|
-
return BigInt(value[TYPE_MARKERS.BIGINT]);
|
|
4176
|
-
}
|
|
4177
|
-
if (TYPE_MARKERS.SYMBOL in value) {
|
|
4178
|
-
return Symbol.for(value[TYPE_MARKERS.SYMBOL]);
|
|
4179
|
-
}
|
|
4180
|
-
if (TYPE_MARKERS.DATE in value) {
|
|
4181
|
-
return new Date(value[TYPE_MARKERS.DATE]);
|
|
4182
|
-
}
|
|
4183
|
-
if (TYPE_MARKERS.REGEXP in value) {
|
|
4184
|
-
const regexpData = value[TYPE_MARKERS.REGEXP];
|
|
4185
|
-
return new RegExp(regexpData.source, regexpData.flags);
|
|
4186
|
-
}
|
|
4187
|
-
if (TYPE_MARKERS.MAP in value) {
|
|
4188
|
-
return new Map(value[TYPE_MARKERS.MAP]);
|
|
4189
|
-
}
|
|
4190
|
-
if (TYPE_MARKERS.SET in value) {
|
|
4191
|
-
return new Set(value[TYPE_MARKERS.SET]);
|
|
4192
|
-
}
|
|
4193
|
-
// Handle arrays
|
|
4194
|
-
if (Array.isArray(value)) {
|
|
4195
|
-
return value.map(restoreSpecialTypes);
|
|
4196
|
-
}
|
|
4197
|
-
// Handle objects
|
|
4198
|
-
const result = {};
|
|
4199
|
-
for (const [k, v] of Object.entries(value)) {
|
|
4200
|
-
result[k] = restoreSpecialTypes(v);
|
|
4201
|
-
}
|
|
4202
|
-
return result;
|
|
4203
|
-
};
|
|
4204
|
-
// Restore special types in the data
|
|
4205
|
-
const restoredData = restoreSpecialTypes(data);
|
|
4206
|
-
// Helper to resolve a signal from the root alias (`tree.$`) using the
|
|
4207
|
-
// accumulated path so keys that collide with branch methods (like "set")
|
|
4208
|
-
// still map to the child signals.
|
|
4209
|
-
function resolveAliasSignal(path, key) {
|
|
4210
|
-
let node = tree.$;
|
|
4211
|
-
if (path && node) {
|
|
4212
|
-
for (const part of path.split('.')) {
|
|
4213
|
-
if (!part)
|
|
4214
|
-
continue;
|
|
4215
|
-
const next = node[part];
|
|
4216
|
-
if (!next ||
|
|
4217
|
-
(typeof next !== 'object' && typeof next !== 'function')) {
|
|
4218
|
-
node = undefined;
|
|
4219
|
-
break;
|
|
4220
|
-
}
|
|
4221
|
-
node = next;
|
|
4222
|
-
}
|
|
4223
|
-
}
|
|
4224
|
-
const candidate = node?.[key];
|
|
4225
|
-
return isSignal(candidate)
|
|
4226
|
-
? candidate
|
|
4227
|
-
: undefined;
|
|
4228
|
-
}
|
|
4229
|
-
function updateSignals(target, source, path = '') {
|
|
4230
|
-
if (!target || !source)
|
|
4231
|
-
return;
|
|
4232
|
-
for (const key in source) {
|
|
4233
|
-
if (!Object.prototype.hasOwnProperty.call(source, key))
|
|
4234
|
-
continue;
|
|
4235
|
-
const sourceValue = source[key];
|
|
4236
|
-
const direct = target[key];
|
|
4237
|
-
// Prefer the real signal if present; otherwise resolve from root alias
|
|
4238
|
-
const targetSignal = isSignal(direct)
|
|
4239
|
-
? direct
|
|
4240
|
-
: // Check if it's a callable signal (function with set method)
|
|
4241
|
-
typeof direct === 'function' &&
|
|
4242
|
-
'set' in direct &&
|
|
4243
|
-
typeof direct.set === 'function'
|
|
4244
|
-
? direct
|
|
4245
|
-
: resolveAliasSignal(path, key);
|
|
4246
|
-
if (targetSignal) {
|
|
4247
|
-
targetSignal.set(sourceValue);
|
|
4248
|
-
continue;
|
|
4249
|
-
}
|
|
4250
|
-
if (sourceValue &&
|
|
4251
|
-
typeof sourceValue === 'object' &&
|
|
4252
|
-
!Array.isArray(sourceValue) &&
|
|
4253
|
-
direct &&
|
|
4254
|
-
(typeof direct === 'object' ||
|
|
4255
|
-
(typeof direct === 'function' && !('set' in direct))) &&
|
|
4256
|
-
!isSignal(direct)) {
|
|
4257
|
-
updateSignals(direct, sourceValue, path ? `${path}.${key}` : key);
|
|
4258
|
-
}
|
|
4259
|
-
}
|
|
4260
|
-
}
|
|
4261
|
-
// If the serialized data contains a compact nodeMap, use it to apply
|
|
4262
|
-
// updates deterministically: 'r' => root set, 'b' => set on branch
|
|
4263
|
-
const nodeMap = metadata?.nodeMap;
|
|
4264
|
-
if (nodeMap && Object.keys(nodeMap).length > 0) {
|
|
4265
|
-
// Root marker
|
|
4266
|
-
if (nodeMap[''] === 'r') {
|
|
4267
|
-
const rootAlias = tree.$;
|
|
4268
|
-
if (rootAlias && typeof rootAlias.set === 'function') {
|
|
4269
|
-
rootAlias.set(restoredData);
|
|
4270
|
-
// Don't return; still perform targeted updates below to ensure
|
|
4271
|
-
// type-preserving restoration for all branches.
|
|
4272
|
-
}
|
|
4273
|
-
}
|
|
4274
|
-
// For branch entries, apply child signal .set directly when possible
|
|
4275
|
-
for (const [path, kind] of Object.entries(nodeMap)) {
|
|
4276
|
-
if (path === '')
|
|
4277
|
-
continue; // root handled
|
|
4278
|
-
if (kind !== 'b')
|
|
4279
|
-
continue;
|
|
4280
|
-
// Navigate to path and set the node if a WritableSignal is found
|
|
4281
|
-
const parts = path.split(/\.|\[|\]/).filter(Boolean);
|
|
4282
|
-
let node = tree.$;
|
|
4283
|
-
for (const p of parts) {
|
|
4284
|
-
if (!node)
|
|
4285
|
-
break;
|
|
4286
|
-
node =
|
|
4287
|
-
node[p] ?? undefined;
|
|
4288
|
-
}
|
|
4289
|
-
if (node &&
|
|
4290
|
-
(isSignal(node) ||
|
|
4291
|
-
(typeof node === 'function' &&
|
|
4292
|
-
'set' in node &&
|
|
4293
|
-
typeof node.set === 'function'))) {
|
|
4294
|
-
// Extract the corresponding value from restoredData
|
|
4295
|
-
let current = restoredData;
|
|
4296
|
-
for (const p of parts) {
|
|
4297
|
-
if (current == null) {
|
|
4298
|
-
current = undefined;
|
|
4299
|
-
break;
|
|
4300
|
-
}
|
|
4301
|
-
if (typeof current === 'object') {
|
|
4302
|
-
current = current[p];
|
|
4303
|
-
}
|
|
4304
|
-
else {
|
|
4305
|
-
current = undefined;
|
|
4306
|
-
break;
|
|
4307
|
-
}
|
|
4308
|
-
}
|
|
4309
|
-
try {
|
|
4310
|
-
node.set(current);
|
|
4311
|
-
}
|
|
4312
|
-
catch {
|
|
4313
|
-
/* ignore per-path failures */
|
|
4314
|
-
}
|
|
4315
|
-
}
|
|
4316
|
-
}
|
|
4317
|
-
// After applying nodeMap-targeted sets, perform a best-effort deep update for remaining keys
|
|
4318
|
-
updateSignals(tree.state, restoredData);
|
|
4319
|
-
return;
|
|
4320
|
-
}
|
|
4321
|
-
updateSignals(tree.state, restoredData);
|
|
4322
|
-
};
|
|
4323
|
-
// Encode/decode helpers that work on already-unwrapped plain data
|
|
4324
|
-
function encodeSpecials(v, preserveTypes) {
|
|
4325
|
-
if (!preserveTypes)
|
|
4326
|
-
return v;
|
|
4327
|
-
if (v === undefined)
|
|
4328
|
-
return { [TYPE_MARKERS.UNDEFINED]: true };
|
|
4329
|
-
if (typeof v === 'number') {
|
|
4330
|
-
if (Number.isNaN(v))
|
|
4331
|
-
return { [TYPE_MARKERS.NAN]: true };
|
|
4332
|
-
if (v === Infinity)
|
|
4333
|
-
return { [TYPE_MARKERS.INFINITY]: true };
|
|
4334
|
-
if (v === -Infinity)
|
|
4335
|
-
return { [TYPE_MARKERS.NEG_INFINITY]: true };
|
|
4336
|
-
return v;
|
|
4337
|
-
}
|
|
4338
|
-
if (typeof v === 'bigint')
|
|
4339
|
-
return { [TYPE_MARKERS.BIGINT]: String(v) };
|
|
4340
|
-
if (typeof v === 'symbol')
|
|
4341
|
-
return { [TYPE_MARKERS.SYMBOL]: String(v) };
|
|
4342
|
-
if (v instanceof Date)
|
|
4343
|
-
return { [TYPE_MARKERS.DATE]: v.toISOString() };
|
|
4344
|
-
if (v instanceof RegExp)
|
|
4345
|
-
return {
|
|
4346
|
-
[TYPE_MARKERS.REGEXP]: { source: v.source, flags: v.flags },
|
|
4347
|
-
};
|
|
4348
|
-
if (v instanceof Map)
|
|
4349
|
-
return { [TYPE_MARKERS.MAP]: Array.from(v.entries()) };
|
|
4350
|
-
if (v instanceof Set)
|
|
4351
|
-
return { [TYPE_MARKERS.SET]: Array.from(v.values()) };
|
|
4352
|
-
if (Array.isArray(v))
|
|
4353
|
-
return v.map((x) => encodeSpecials(x, preserveTypes));
|
|
4354
|
-
if (v && typeof v === 'object') {
|
|
4355
|
-
const out = {};
|
|
4356
|
-
for (const [k, val] of Object.entries(v))
|
|
4357
|
-
out[k] = encodeSpecials(val, preserveTypes);
|
|
4358
|
-
return out;
|
|
4359
|
-
}
|
|
4360
|
-
return v;
|
|
4361
|
-
}
|
|
4362
|
-
/**
|
|
4363
|
-
* Serialize to JSON string
|
|
4364
|
-
*/
|
|
4365
|
-
enhanced.serialize = (config) => {
|
|
4366
|
-
const fullConfig = {
|
|
4367
|
-
...DEFAULT_CONFIG,
|
|
4368
|
-
...defaultConfig,
|
|
4369
|
-
...config,
|
|
4370
|
-
};
|
|
4371
|
-
// Use a safe local unwrap to avoid accidental dropping of keys like
|
|
4372
|
-
// 'set' which may collide with branch helpers; let encodeSpecials
|
|
4373
|
-
// handle special type markers.
|
|
4374
|
-
const raw = unwrapObjectSafely(tree.state, new WeakSet(), 0, fullConfig.maxDepth, fullConfig.preserveTypes);
|
|
4375
|
-
const state = encodeSpecials(raw, fullConfig.preserveTypes);
|
|
4376
|
-
// Detect circular references if needed
|
|
4377
|
-
const circularPaths = fullConfig.handleCircular
|
|
4378
|
-
? detectCircularReferences(state)
|
|
4379
|
-
: [];
|
|
4380
|
-
// Prepare data
|
|
4381
|
-
const data = {
|
|
4382
|
-
data: state,
|
|
4383
|
-
};
|
|
4384
|
-
// Build a compact nodeMap by traversing the callable proxy alias (tree.$)
|
|
4385
|
-
// and marking any signal-like branch node we encounter. Also mark a
|
|
4386
|
-
// root-as-signal marker ('r') if the root alias exposes a .set().
|
|
4387
|
-
const nodeMap = {};
|
|
4388
|
-
try {
|
|
4389
|
-
const rootAlias = tree.$;
|
|
4390
|
-
if (rootAlias && typeof rootAlias.set === 'function') {
|
|
4391
|
-
nodeMap[''] = 'r';
|
|
4392
|
-
}
|
|
4393
|
-
const visited = new WeakSet();
|
|
4394
|
-
const isBranch = (v) => isSignal(v) ||
|
|
4395
|
-
(typeof v === 'function' &&
|
|
4396
|
-
'set' in v &&
|
|
4397
|
-
typeof v.set === 'function');
|
|
4398
|
-
const walkAlias = (obj, path = '') => {
|
|
4399
|
-
if (!obj || (typeof obj !== 'object' && typeof obj !== 'function'))
|
|
4400
|
-
return;
|
|
4401
|
-
const ref = obj;
|
|
4402
|
-
if (visited.has(ref))
|
|
4403
|
-
return;
|
|
4404
|
-
visited.add(ref);
|
|
4405
|
-
if (path && isBranch(obj)) {
|
|
4406
|
-
nodeMap[path] = 'b';
|
|
4407
|
-
}
|
|
4408
|
-
// Traverse own enumerable properties (callable proxies expose children here)
|
|
4409
|
-
for (const [k, v] of Object.entries(obj)) {
|
|
4410
|
-
const childPath = path ? `${path}.${k}` : k;
|
|
4411
|
-
walkAlias(v, childPath);
|
|
4412
|
-
}
|
|
4413
|
-
};
|
|
4414
|
-
if (rootAlias)
|
|
4415
|
-
walkAlias(rootAlias);
|
|
4416
|
-
}
|
|
4417
|
-
catch {
|
|
4418
|
-
// Do not block serialization on nodeMap errors
|
|
4419
|
-
}
|
|
4420
|
-
// Add metadata if requested
|
|
4421
|
-
if (fullConfig.includeMetadata) {
|
|
4422
|
-
data.metadata = {
|
|
4423
|
-
timestamp: Date.now(),
|
|
4424
|
-
version: '1.0.0',
|
|
4425
|
-
...(circularPaths.length > 0 && { circularRefs: circularPaths }),
|
|
4426
|
-
...(Object.keys(nodeMap).length > 0 && { nodeMap }),
|
|
4427
|
-
};
|
|
4428
|
-
}
|
|
4429
|
-
// Serialize with custom replacer
|
|
4430
|
-
const replacer = createReplacer(fullConfig);
|
|
4431
|
-
const json = JSON.stringify(data, replacer, 2);
|
|
4432
|
-
// Extra debug: if JSON contains MAP or SET markers, print compact preview
|
|
4433
|
-
return json;
|
|
4434
|
-
};
|
|
4435
|
-
/**
|
|
4436
|
-
* Deserialize from JSON string
|
|
4437
|
-
*/
|
|
4438
|
-
enhanced.deserialize = (json, config) => {
|
|
4439
|
-
const fullConfig = {
|
|
4440
|
-
...DEFAULT_CONFIG,
|
|
4441
|
-
...defaultConfig,
|
|
4442
|
-
...config,
|
|
4443
|
-
};
|
|
4444
|
-
try {
|
|
4445
|
-
// Parse with simple JSON.parse (no custom reviver)
|
|
4446
|
-
const parsed = JSON.parse(json);
|
|
4447
|
-
// Extract data and metadata
|
|
4448
|
-
const { data, metadata } = parsed;
|
|
4449
|
-
// Resolve circular references if present
|
|
4450
|
-
if (metadata?.circularRefs && fullConfig.handleCircular) {
|
|
4451
|
-
resolveCircularReferences(data, metadata.circularRefs);
|
|
4452
|
-
}
|
|
4453
|
-
// Apply parsed data to the tree; fromJSON will handle type restoration
|
|
4454
|
-
enhanced.fromJSON(data, metadata);
|
|
4455
|
-
// Log restoration if in debug mode
|
|
4456
|
-
if (tree.__config?.debugMode) {
|
|
4457
|
-
console.log('[SignalTree] State restored from serialized data', {
|
|
4458
|
-
timestamp: metadata?.timestamp,
|
|
4459
|
-
version: metadata?.version,
|
|
4460
|
-
});
|
|
4461
|
-
}
|
|
4462
|
-
}
|
|
4463
|
-
catch (error) {
|
|
4464
|
-
console.error('[SignalTree] Failed to deserialize:', error);
|
|
4465
|
-
throw new Error(`Failed to deserialize SignalTree state: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
4466
|
-
}
|
|
4467
|
-
};
|
|
4468
|
-
/**
|
|
4469
|
-
* Create a snapshot
|
|
4470
|
-
*/
|
|
4471
|
-
enhanced.snapshot = () => {
|
|
4472
|
-
const state = enhanced.toJSON();
|
|
4473
|
-
const circularPaths = detectCircularReferences(state);
|
|
4474
|
-
return {
|
|
4475
|
-
data: JSON.parse(JSON.stringify(state)), // Deep clone
|
|
4476
|
-
metadata: {
|
|
4477
|
-
timestamp: Date.now(),
|
|
4478
|
-
version: '1.0.0',
|
|
4479
|
-
...(circularPaths.length > 0 && { circularRefs: circularPaths }),
|
|
4480
|
-
},
|
|
4481
|
-
};
|
|
4482
|
-
};
|
|
4483
|
-
/**
|
|
4484
|
-
* Restore from snapshot
|
|
4485
|
-
*/
|
|
4486
|
-
enhanced.restore = (snapshot) => {
|
|
4487
|
-
const { data, metadata } = snapshot;
|
|
4488
|
-
// Resolve circular references if present
|
|
4489
|
-
if (metadata?.circularRefs) {
|
|
4490
|
-
resolveCircularReferences(data, metadata.circularRefs);
|
|
4491
|
-
}
|
|
4492
|
-
enhanced.fromJSON(data, metadata);
|
|
4493
|
-
};
|
|
4494
|
-
return enhanced;
|
|
4495
|
-
};
|
|
4496
|
-
enhancer.metadata = {
|
|
4497
|
-
name: 'serialization',
|
|
4498
|
-
};
|
|
4499
|
-
return enhancer;
|
|
4500
|
-
}
|
|
4501
|
-
/**
|
|
4502
|
-
* Convenience function to enable serialization with defaults
|
|
4503
|
-
*/
|
|
4504
|
-
function enableSerialization() {
|
|
4505
|
-
return withSerialization({
|
|
4506
|
-
includeMetadata: true,
|
|
4507
|
-
preserveTypes: true,
|
|
4508
|
-
handleCircular: true,
|
|
4509
|
-
});
|
|
4510
|
-
}
|
|
4511
|
-
/**
|
|
4512
|
-
* Adds persistence capabilities to a SerializableSignalTree
|
|
4513
|
-
*/
|
|
4514
|
-
function withPersistence(config) {
|
|
4515
|
-
const { key, storage = typeof window !== 'undefined' ? window.localStorage : undefined, autoSave = true, debounceMs = 1000, autoLoad = true, ...serializationConfig } = config;
|
|
4516
|
-
if (!storage) {
|
|
4517
|
-
throw new Error('No storage adapter available. Provide a storage adapter in the config.');
|
|
4518
|
-
}
|
|
4519
|
-
// Narrow storage for TypeScript and linter: from here on it's defined.
|
|
4520
|
-
const storageAdapter = storage;
|
|
4521
|
-
function enhancer(tree) {
|
|
4522
|
-
// First enhance with serialization
|
|
4523
|
-
const serializable = withSerialization(serializationConfig)(tree);
|
|
4524
|
-
// Add persistence methods
|
|
4525
|
-
const enhanced = serializable;
|
|
4526
|
-
// Cache to avoid redundant storage writes. Use a metadata-free cache key
|
|
4527
|
-
// so timestamps in metadata don't cause false positives for changes.
|
|
4528
|
-
let lastCacheKey = null;
|
|
4529
|
-
/**
|
|
4530
|
-
* Save current state to storage
|
|
4531
|
-
*/
|
|
4532
|
-
enhanced.save = async () => {
|
|
4533
|
-
try {
|
|
4534
|
-
// Compute a deterministic cache key that excludes metadata (timestamps)
|
|
4535
|
-
const cacheKey = enhanced.serialize({
|
|
4536
|
-
...serializationConfig,
|
|
4537
|
-
includeMetadata: false,
|
|
4538
|
-
});
|
|
4539
|
-
// Only write to storage if the state has changed (by cacheKey), unless skipCache is true
|
|
4540
|
-
if (config.skipCache || cacheKey !== lastCacheKey) {
|
|
4541
|
-
// Persist the full payload (respecting includeMetadata from config)
|
|
4542
|
-
const serialized = enhanced.serialize(serializationConfig);
|
|
4543
|
-
await Promise.resolve(storageAdapter.setItem(key, serialized));
|
|
4544
|
-
lastCacheKey = cacheKey;
|
|
4545
|
-
if (tree.__config?.debugMode) {
|
|
4546
|
-
console.log(`[SignalTree] State saved to storage key: ${key}`);
|
|
4547
|
-
}
|
|
4548
|
-
}
|
|
4549
|
-
else if (tree.__config?.debugMode) {
|
|
4550
|
-
console.log(`[SignalTree] State unchanged, skipping storage write for key: ${key}`);
|
|
4551
|
-
}
|
|
4552
|
-
}
|
|
4553
|
-
catch (error) {
|
|
4554
|
-
console.error('[SignalTree] Failed to save state:', error);
|
|
4555
|
-
throw error; // Re-throw for tests to catch
|
|
4556
|
-
}
|
|
4557
|
-
};
|
|
4558
|
-
/**
|
|
4559
|
-
* Load state from storage
|
|
4560
|
-
*/
|
|
4561
|
-
enhanced.load = async () => {
|
|
4562
|
-
try {
|
|
4563
|
-
const data = await Promise.resolve(storageAdapter.getItem(key));
|
|
4564
|
-
if (data) {
|
|
4565
|
-
enhanced.deserialize(data, serializationConfig);
|
|
4566
|
-
// Reset cache after loading new data using a metadata-free key
|
|
4567
|
-
lastCacheKey = enhanced.serialize({
|
|
4568
|
-
...serializationConfig,
|
|
4569
|
-
includeMetadata: false,
|
|
4570
|
-
});
|
|
4571
|
-
if (tree.__config?.debugMode) {
|
|
4572
|
-
console.log(`[SignalTree] State loaded from storage key: ${key}`);
|
|
4573
|
-
}
|
|
4574
|
-
}
|
|
4575
|
-
}
|
|
4576
|
-
catch (error) {
|
|
4577
|
-
console.error('[SignalTree] Failed to load state:', error);
|
|
4578
|
-
throw error; // Re-throw for tests to catch
|
|
4579
|
-
}
|
|
4580
|
-
};
|
|
4581
|
-
/**
|
|
4582
|
-
* Clear state from storage
|
|
4583
|
-
*/
|
|
4584
|
-
enhanced.clear = async () => {
|
|
4585
|
-
try {
|
|
4586
|
-
await Promise.resolve(storageAdapter.removeItem(key));
|
|
4587
|
-
lastCacheKey = null;
|
|
4588
|
-
if (tree.__config?.debugMode) {
|
|
4589
|
-
console.log(`[SignalTree] State cleared from storage key: ${key}`);
|
|
4590
|
-
}
|
|
4591
|
-
}
|
|
4592
|
-
catch (error) {
|
|
4593
|
-
console.error('[SignalTree] Failed to clear state:', error);
|
|
4594
|
-
throw error; // Re-throw for tests to catch
|
|
4595
|
-
}
|
|
4596
|
-
};
|
|
4597
|
-
// Auto-load on creation if enabled
|
|
4598
|
-
if (autoLoad) {
|
|
4599
|
-
// Use setTimeout to avoid blocking initialization and timing issues
|
|
4600
|
-
setTimeout(() => {
|
|
4601
|
-
enhanced.load().catch((error) => {
|
|
4602
|
-
console.warn('[SignalTree] Auto-load failed:', error);
|
|
4603
|
-
});
|
|
4604
|
-
}, 0);
|
|
4605
|
-
}
|
|
4606
|
-
// Auto-save on updates if enabled
|
|
4607
|
-
if (autoSave) {
|
|
4608
|
-
let saveTimeout;
|
|
4609
|
-
// Hook into state changes to trigger auto-save
|
|
4610
|
-
const triggerAutoSave = () => {
|
|
4611
|
-
// Debounce saves
|
|
4612
|
-
if (saveTimeout) {
|
|
4613
|
-
clearTimeout(saveTimeout);
|
|
4614
|
-
}
|
|
4615
|
-
saveTimeout = setTimeout(() => {
|
|
4616
|
-
enhanced.save().catch((error) => {
|
|
4617
|
-
console.error('[SignalTree] Auto-save failed:', error);
|
|
4618
|
-
});
|
|
4619
|
-
}, debounceMs);
|
|
4620
|
-
};
|
|
4621
|
-
// Watch for any signal changes in the tree
|
|
4622
|
-
const watchSignals = (obj, path = '') => {
|
|
4623
|
-
if (!obj || typeof obj !== 'object')
|
|
4624
|
-
return;
|
|
4625
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
4626
|
-
if (isSignal(value)) {
|
|
4627
|
-
// Create an effect to watch this signal
|
|
4628
|
-
const signal = value;
|
|
4629
|
-
let previousValue = signal();
|
|
4630
|
-
// Periodically check for changes (this is a simplified approach)
|
|
4631
|
-
// In a real implementation, you'd want to use Angular's effect() or similar
|
|
4632
|
-
const checkForChanges = () => {
|
|
4633
|
-
const currentValue = signal();
|
|
4634
|
-
if (currentValue !== previousValue) {
|
|
4635
|
-
previousValue = currentValue;
|
|
4636
|
-
triggerAutoSave();
|
|
4637
|
-
}
|
|
4638
|
-
setTimeout(checkForChanges, 50); // Check every 50ms
|
|
4639
|
-
};
|
|
4640
|
-
setTimeout(checkForChanges, 0);
|
|
4641
|
-
}
|
|
4642
|
-
else if (value && typeof value === 'object') {
|
|
4643
|
-
watchSignals(value, path ? `${path}.${key}` : key);
|
|
4644
|
-
}
|
|
4645
|
-
}
|
|
4646
|
-
};
|
|
4647
|
-
// Start watching signals
|
|
4648
|
-
watchSignals(tree.state);
|
|
4649
|
-
// Store cleanup function for testing
|
|
4650
|
-
enhanced.__flushAutoSave = () => {
|
|
4651
|
-
if (saveTimeout) {
|
|
4652
|
-
clearTimeout(saveTimeout);
|
|
4653
|
-
saveTimeout = undefined;
|
|
4654
|
-
return enhanced.save();
|
|
4655
|
-
}
|
|
4656
|
-
return Promise.resolve();
|
|
4657
|
-
};
|
|
4658
|
-
}
|
|
4659
|
-
return enhanced;
|
|
4660
|
-
}
|
|
4661
|
-
enhancer.metadata = { name: 'persistence' };
|
|
4662
|
-
return enhancer;
|
|
4663
|
-
}
|
|
4664
|
-
/**
|
|
4665
|
-
* Create a custom storage adapter
|
|
4666
|
-
*/
|
|
4667
|
-
function createStorageAdapter(getItem, setItem, removeItem) {
|
|
4668
|
-
return { getItem, setItem, removeItem };
|
|
4669
|
-
}
|
|
4670
|
-
/**
|
|
4671
|
-
* IndexedDB storage adapter for large state trees
|
|
4672
|
-
*/
|
|
4673
|
-
function createIndexedDBAdapter(dbName = 'SignalTreeDB', storeName = 'states') {
|
|
4674
|
-
let db = null;
|
|
4675
|
-
const openDB = async () => {
|
|
4676
|
-
if (db)
|
|
4677
|
-
return db;
|
|
4678
|
-
return new Promise((resolve, reject) => {
|
|
4679
|
-
const request = indexedDB.open(dbName, 1);
|
|
4680
|
-
request.onerror = () => reject(request.error);
|
|
4681
|
-
request.onsuccess = () => {
|
|
4682
|
-
db = request.result;
|
|
4683
|
-
resolve(db);
|
|
4684
|
-
};
|
|
4685
|
-
request.onupgradeneeded = (event) => {
|
|
4686
|
-
const database = event.target.result;
|
|
4687
|
-
if (!database.objectStoreNames.contains(storeName)) {
|
|
4688
|
-
database.createObjectStore(storeName);
|
|
4689
|
-
}
|
|
4690
|
-
};
|
|
4691
|
-
});
|
|
4692
|
-
};
|
|
4693
|
-
return {
|
|
4694
|
-
async getItem(key) {
|
|
4695
|
-
const database = await openDB();
|
|
4696
|
-
return new Promise((resolve, reject) => {
|
|
4697
|
-
const transaction = database.transaction([storeName], 'readonly');
|
|
4698
|
-
const store = transaction.objectStore(storeName);
|
|
4699
|
-
const request = store.get(key);
|
|
4700
|
-
request.onerror = () => reject(request.error);
|
|
4701
|
-
request.onsuccess = () => resolve(request.result || null);
|
|
4702
|
-
});
|
|
4703
|
-
},
|
|
4704
|
-
async setItem(key, value) {
|
|
4705
|
-
const database = await openDB();
|
|
4706
|
-
return new Promise((resolve, reject) => {
|
|
4707
|
-
const transaction = database.transaction([storeName], 'readwrite');
|
|
4708
|
-
const store = transaction.objectStore(storeName);
|
|
4709
|
-
const request = store.put(value, key);
|
|
4710
|
-
request.onerror = () => reject(request.error);
|
|
4711
|
-
request.onsuccess = () => resolve();
|
|
4712
|
-
});
|
|
4713
|
-
},
|
|
4714
|
-
async removeItem(key) {
|
|
4715
|
-
const database = await openDB();
|
|
4716
|
-
return new Promise((resolve, reject) => {
|
|
4717
|
-
const transaction = database.transaction([storeName], 'readwrite');
|
|
4718
|
-
const store = transaction.objectStore(storeName);
|
|
4719
|
-
const request = store.delete(key);
|
|
4720
|
-
request.onerror = () => reject(request.error);
|
|
4721
|
-
request.onsuccess = () => resolve();
|
|
4722
|
-
});
|
|
4723
|
-
},
|
|
4724
|
-
};
|
|
4725
|
-
}
|
|
4726
|
-
// Type-only exports (none)
|
|
4727
|
-
/**
|
|
4728
|
-
* Helpers to apply enhancers with explicit typing to avoid depending on
|
|
4729
|
-
* complex `.with()` overload inference in tests and tooling.
|
|
4730
|
-
*/
|
|
4731
|
-
function applySerialization(tree) {
|
|
4732
|
-
return withSerialization()(tree);
|
|
4733
|
-
}
|
|
4734
|
-
function applyPersistence(tree, cfg) {
|
|
4735
|
-
return withPersistence(cfg)(tree);
|
|
4736
|
-
}
|
|
4737
|
-
|
|
4738
|
-
/**
|
|
4739
|
-
* Pre-configured SignalTree configurations for common use cases.
|
|
4740
|
-
*
|
|
4741
|
-
* - **basic**: Minimal configuration with no advanced features
|
|
4742
|
-
* - **performance**: Optimized for speed with batching and memoization
|
|
4743
|
-
* - **development**: Full debugging features including time-travel and devtools
|
|
4744
|
-
* - **production**: Optimized for production with performance features only
|
|
4745
|
-
*/
|
|
4746
|
-
const TREE_PRESETS = {
|
|
4747
|
-
basic: {
|
|
4748
|
-
batchUpdates: false,
|
|
4749
|
-
useMemoization: false,
|
|
4750
|
-
trackPerformance: false,
|
|
4751
|
-
enableTimeTravel: false,
|
|
4752
|
-
enableDevTools: false,
|
|
4753
|
-
debugMode: false,
|
|
4754
|
-
},
|
|
4755
|
-
performance: {
|
|
4756
|
-
batchUpdates: true,
|
|
4757
|
-
useMemoization: true,
|
|
4758
|
-
trackPerformance: false,
|
|
4759
|
-
enableTimeTravel: false,
|
|
4760
|
-
enableDevTools: false,
|
|
4761
|
-
debugMode: false,
|
|
4762
|
-
useShallowComparison: true,
|
|
4763
|
-
maxCacheSize: 200,
|
|
4764
|
-
},
|
|
4765
|
-
development: {
|
|
4766
|
-
batchUpdates: true,
|
|
4767
|
-
useMemoization: true,
|
|
4768
|
-
trackPerformance: true,
|
|
4769
|
-
enableTimeTravel: true,
|
|
4770
|
-
enableDevTools: true,
|
|
4771
|
-
debugMode: true,
|
|
4772
|
-
maxCacheSize: 100,
|
|
4773
|
-
},
|
|
4774
|
-
production: {
|
|
4775
|
-
batchUpdates: true,
|
|
4776
|
-
useMemoization: true,
|
|
4777
|
-
trackPerformance: false,
|
|
4778
|
-
enableTimeTravel: false,
|
|
4779
|
-
enableDevTools: false,
|
|
4780
|
-
debugMode: false,
|
|
4781
|
-
useShallowComparison: true,
|
|
4782
|
-
maxCacheSize: 200,
|
|
4783
|
-
},
|
|
4784
|
-
};
|
|
4785
|
-
/**
|
|
4786
|
-
* Helper function to create a tree configuration from a preset.
|
|
4787
|
-
* Can be used to start with a preset and then customize specific options.
|
|
4788
|
-
*
|
|
4789
|
-
* @param preset - The preset name to use as a base
|
|
4790
|
-
* @param overrides - Optional overrides to apply on top of the preset
|
|
4791
|
-
* @returns Complete tree configuration
|
|
4792
|
-
*
|
|
4793
|
-
* @example
|
|
4794
|
-
* ```typescript
|
|
4795
|
-
* // Use development preset with custom tree name
|
|
4796
|
-
* const config = createPresetConfig('development', { treeName: 'MyApp' });
|
|
4797
|
-
*
|
|
4798
|
-
* // Use performance preset but enable debug mode
|
|
4799
|
-
* const debugPerf = createPresetConfig('performance', { debugMode: true });
|
|
4800
|
-
* ```
|
|
4801
|
-
*/
|
|
4802
|
-
function createPresetConfig(preset, overrides = {}) {
|
|
4803
|
-
const baseConfig = TREE_PRESETS[preset];
|
|
4804
|
-
return {
|
|
4805
|
-
...baseConfig,
|
|
4806
|
-
...overrides,
|
|
4807
|
-
};
|
|
4808
|
-
}
|
|
4809
|
-
/**
|
|
4810
|
-
* Validates that a preset configuration is valid.
|
|
4811
|
-
* Useful for development-time checks.
|
|
4812
|
-
*
|
|
4813
|
-
* @param preset - The preset to validate
|
|
4814
|
-
* @returns True if valid, throws error if invalid
|
|
4815
|
-
*/
|
|
4816
|
-
function validatePreset(preset) {
|
|
4817
|
-
if (!TREE_PRESETS[preset]) {
|
|
4818
|
-
throw new Error(`Invalid preset: ${preset}. Valid presets are: ${Object.keys(TREE_PRESETS).join(', ')}`);
|
|
4819
|
-
}
|
|
4820
|
-
return true;
|
|
4821
|
-
}
|
|
4822
|
-
/**
|
|
4823
|
-
* Gets the list of available preset names.
|
|
4824
|
-
*
|
|
4825
|
-
* @returns Array of preset names
|
|
4826
|
-
*/
|
|
4827
|
-
function getAvailablePresets() {
|
|
4828
|
-
return Object.keys(TREE_PRESETS);
|
|
4829
|
-
}
|
|
4830
|
-
/**
|
|
4831
|
-
* Creates a custom preset by combining multiple existing presets.
|
|
4832
|
-
* Later presets in the array take precedence over earlier ones.
|
|
4833
|
-
*
|
|
4834
|
-
* @param presets - Array of presets to combine
|
|
4835
|
-
* @param overrides - Optional final overrides
|
|
4836
|
-
* @returns Combined configuration
|
|
4837
|
-
*
|
|
4838
|
-
* @example
|
|
4839
|
-
* ```typescript
|
|
4840
|
-
* // Combine basic preset with some performance features
|
|
4841
|
-
* const config = combinePresets(['basic', 'performance'], { enableDevTools: true });
|
|
4842
|
-
* ```
|
|
4843
|
-
*/
|
|
4844
|
-
function combinePresets(presets, overrides = {}) {
|
|
4845
|
-
let combined = {};
|
|
4846
|
-
for (const preset of presets) {
|
|
4847
|
-
validatePreset(preset);
|
|
4848
|
-
combined = { ...combined, ...TREE_PRESETS[preset] };
|
|
4849
|
-
}
|
|
4850
|
-
return { ...combined, ...overrides };
|
|
4851
|
-
}
|
|
4852
|
-
/**
|
|
4853
|
-
* Convenience helper for creating a development-ready SignalTree.
|
|
4854
|
-
* Composes dev-only enhancers (devtools, time-travel, async) into a single
|
|
4855
|
-
* enhancer function that can be applied to a tree. This keeps packages
|
|
4856
|
-
* independent while offering a one-line dev onboarding.
|
|
4857
|
-
*/
|
|
4858
|
-
function createDevTree(overrides = {}) {
|
|
4859
|
-
const config = createPresetConfig('development', overrides);
|
|
4860
|
-
// Compose enhancers in a predictable left-to-right order. We import the
|
|
4861
|
-
// enhancers lazily so consumers who don't install dev packages won't fail at
|
|
4862
|
-
// module-eval time.
|
|
4863
|
-
const enhancers = [];
|
|
4864
|
-
// Helper to access CommonJS-style require at runtime without forcing Node types
|
|
4865
|
-
function tryRequire(id) {
|
|
4866
|
-
const maybeReq = globalThis.require;
|
|
4867
|
-
if (typeof maybeReq !== 'function')
|
|
4868
|
-
return undefined;
|
|
4869
|
-
try {
|
|
4870
|
-
return maybeReq(id);
|
|
4871
|
-
}
|
|
4872
|
-
catch {
|
|
4873
|
-
return undefined;
|
|
4874
|
-
}
|
|
4875
|
-
}
|
|
4876
|
-
try {
|
|
4877
|
-
const mod = tryRequire('@signaltree/devtools');
|
|
4878
|
-
const withDevtools = mod && (mod.withDevtools ?? mod.withDevTools ?? mod.default ?? mod);
|
|
4879
|
-
if (typeof withDevtools === 'function')
|
|
4880
|
-
enhancers.push(withDevtools);
|
|
4881
|
-
}
|
|
4882
|
-
catch (e) {
|
|
4883
|
-
}
|
|
4884
|
-
try {
|
|
4885
|
-
const mod = tryRequire('@signaltree/time-travel');
|
|
4886
|
-
const withTimeTravel = mod && (mod.withTimeTravel ?? mod.default ?? mod);
|
|
4887
|
-
if (typeof withTimeTravel === 'function')
|
|
4888
|
-
enhancers.push(withTimeTravel);
|
|
4889
|
-
}
|
|
4890
|
-
catch (e) {
|
|
4891
|
-
}
|
|
4892
|
-
const composed = composeEnhancers(...enhancers);
|
|
4893
|
-
return {
|
|
4894
|
-
config,
|
|
4895
|
-
enhancer: composed,
|
|
4896
|
-
};
|
|
4897
|
-
}
|
|
4898
|
-
|
|
4899
|
-
export { ENHANCER_META, SIGNAL_TREE_CONSTANTS, SIGNAL_TREE_MESSAGES, SecurityPresets, SecurityValidator, TREE_PRESETS, applyPersistence, applySerialization, cleanupMemoizationCache, clearAllCaches, combinePresets, composeEnhancers, createDevTree, createEnhancer, createIndexedDBAdapter, createLazySignalTree, createPresetConfig, createStorageAdapter, enableEntities, enableSerialization, enableTimeTravel, flushBatchedUpdates, getAvailablePresets, getBatchQueueSize, getGlobalCacheStats, getTimeTravel, hasPendingUpdates, isAnySignal, isNodeAccessor$1 as isNodeAccessor, memoize, memoizeReference, memoizeShallow, resolveEnhancerOrder, signalTree, validatePreset, withBatching, withComputedMemoization, withDeepStateMemoization, withEntities, withHighFrequencyMemoization, withHighPerformanceBatching, withHighPerformanceEntities, withHighPerformanceMemoization, withLightweightMemoization, withMemoization, withPersistence, withSelectorMemoization, withSerialization, withShallowMemoization, withTimeTravel };
|
|
4900
|
-
//# sourceMappingURL=index.js.map
|