@signaltree/core 6.2.2 → 6.2.4

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.
@@ -1,283 +1,534 @@
1
1
  import { signal, computed } from '@angular/core';
2
2
 
3
- class EntitySignalImpl {
4
- pathNotifier;
5
- basePath;
6
- storage = new Map();
7
- allSignal;
8
- countSignal;
9
- idsSignal;
10
- mapSignal;
11
- nodeCache = new Map();
12
- selectId;
13
- tapHandlers = [];
14
- interceptHandlers = [];
15
- constructor(config, pathNotifier, basePath) {
16
- this.pathNotifier = pathNotifier;
17
- this.basePath = basePath;
18
- this.selectId = config.selectId ?? (entity => entity['id']);
19
- this.allSignal = signal([]);
20
- this.countSignal = signal(0);
21
- this.idsSignal = signal([]);
22
- this.mapSignal = signal(new Map());
3
+ function createEntitySignal(config, pathNotifier, basePath) {
4
+ const storage = new Map();
5
+ const allSignal = signal([]);
6
+ const countSignal = signal(0);
7
+ const idsSignal = signal([]);
8
+ const mapSignal = signal(new Map());
9
+ const nodeCache = new Map();
10
+ const selectId = config.selectId ?? (entity => entity['id']);
11
+ const tapHandlers = [];
12
+ const interceptHandlers = [];
13
+ function updateSignals() {
14
+ const entities = Array.from(storage.values());
15
+ const ids = Array.from(storage.keys());
16
+ const map = new Map(storage);
17
+ allSignal.set(entities);
18
+ countSignal.set(entities.length);
19
+ idsSignal.set(ids);
20
+ mapSignal.set(map);
23
21
  }
24
- byId(id) {
25
- const entity = this.storage.get(id);
26
- if (!entity) return undefined;
27
- return this.getOrCreateNode(id, entity);
22
+ function createEntityNode(id, entity) {
23
+ const node = () => storage.get(id);
24
+ for (const key of Object.keys(entity)) {
25
+ Object.defineProperty(node, key, {
26
+ get: () => {
27
+ const current = storage.get(id);
28
+ const value = current?.[key];
29
+ return () => value;
30
+ },
31
+ enumerable: true,
32
+ configurable: true
33
+ });
34
+ }
35
+ return node;
28
36
  }
29
- byIdOrFail(id) {
30
- const node = this.byId(id);
37
+ function getOrCreateNode(id, entity) {
38
+ let node = nodeCache.get(id);
31
39
  if (!node) {
32
- throw new Error(`Entity with id ${String(id)} not found`);
40
+ node = createEntityNode(id, entity);
41
+ nodeCache.set(id, node);
33
42
  }
34
43
  return node;
35
44
  }
36
- get all() {
37
- return this.allSignal;
38
- }
39
- get count() {
40
- return this.countSignal;
41
- }
42
- get ids() {
43
- return this.idsSignal;
44
- }
45
- get map() {
46
- return this.mapSignal;
47
- }
48
- has(id) {
49
- return computed(() => this.storage.has(id));
50
- }
51
- get isEmpty() {
52
- return computed(() => this.storage.size === 0);
53
- }
54
- where(predicate) {
55
- return computed(() => {
56
- const result = [];
57
- for (const entity of this.storage.values()) {
45
+ const api = {
46
+ byId(id) {
47
+ const entity = storage.get(id);
48
+ if (!entity) return undefined;
49
+ return getOrCreateNode(id, entity);
50
+ },
51
+ byIdOrFail(id) {
52
+ const node = api.byId(id);
53
+ if (!node) {
54
+ throw new Error(`Entity with id ${String(id)} not found`);
55
+ }
56
+ return node;
57
+ },
58
+ get all() {
59
+ return allSignal;
60
+ },
61
+ get count() {
62
+ return countSignal;
63
+ },
64
+ get ids() {
65
+ return idsSignal;
66
+ },
67
+ get map() {
68
+ return mapSignal;
69
+ },
70
+ has(id) {
71
+ return computed(() => mapSignal().has(id));
72
+ },
73
+ get isEmpty() {
74
+ return computed(() => countSignal() === 0);
75
+ },
76
+ where(predicate) {
77
+ return computed(() => allSignal().filter(predicate));
78
+ },
79
+ find(predicate) {
80
+ return computed(() => allSignal().find(predicate));
81
+ },
82
+ addOne(entity, opts) {
83
+ const id = opts?.selectId?.(entity) ?? selectId(entity);
84
+ if (storage.has(id)) {
85
+ throw new Error(`Entity with id ${String(id)} already exists`);
86
+ }
87
+ let transformedEntity = entity;
88
+ for (const handler of interceptHandlers) {
89
+ const ctx = {
90
+ block: reason => {
91
+ throw new Error(`Cannot add entity: ${reason || 'blocked by interceptor'}`);
92
+ },
93
+ transform: value => {
94
+ transformedEntity = value;
95
+ },
96
+ blocked: false,
97
+ blockReason: undefined
98
+ };
99
+ handler.onAdd?.(entity, ctx);
100
+ }
101
+ storage.set(id, transformedEntity);
102
+ nodeCache.delete(id);
103
+ updateSignals();
104
+ pathNotifier.notify(`${basePath}.${String(id)}`, transformedEntity, undefined);
105
+ for (const handler of tapHandlers) {
106
+ handler.onAdd?.(transformedEntity, id);
107
+ }
108
+ return id;
109
+ },
110
+ addMany(entities, opts) {
111
+ const idsToAdd = [];
112
+ for (const entity of entities) {
113
+ const id = opts?.selectId?.(entity) ?? selectId(entity);
114
+ if (storage.has(id)) {
115
+ throw new Error(`Entity with id ${String(id)} already exists`);
116
+ }
117
+ idsToAdd.push(id);
118
+ }
119
+ const addedEntities = [];
120
+ for (let i = 0; i < entities.length; i++) {
121
+ const entity = entities[i];
122
+ const id = idsToAdd[i];
123
+ let transformedEntity = entity;
124
+ for (const handler of interceptHandlers) {
125
+ const ctx = {
126
+ block: reason => {
127
+ throw new Error(`Cannot add entity: ${reason || 'blocked by interceptor'}`);
128
+ },
129
+ transform: value => {
130
+ transformedEntity = value;
131
+ },
132
+ blocked: false,
133
+ blockReason: undefined
134
+ };
135
+ handler.onAdd?.(entity, ctx);
136
+ }
137
+ storage.set(id, transformedEntity);
138
+ nodeCache.delete(id);
139
+ addedEntities.push({
140
+ id,
141
+ entity: transformedEntity
142
+ });
143
+ }
144
+ updateSignals();
145
+ for (const {
146
+ id,
147
+ entity
148
+ } of addedEntities) {
149
+ pathNotifier.notify(`${basePath}.${String(id)}`, entity, undefined);
150
+ }
151
+ for (const {
152
+ id,
153
+ entity
154
+ } of addedEntities) {
155
+ for (const handler of tapHandlers) {
156
+ handler.onAdd?.(entity, id);
157
+ }
158
+ }
159
+ return idsToAdd;
160
+ },
161
+ updateOne(id, changes) {
162
+ const entity = storage.get(id);
163
+ if (!entity) {
164
+ throw new Error(`Entity with id ${String(id)} not found`);
165
+ }
166
+ const prev = entity;
167
+ let transformedChanges = changes;
168
+ for (const handler of interceptHandlers) {
169
+ const ctx = {
170
+ block: reason => {
171
+ throw new Error(`Cannot update entity: ${reason || 'blocked by interceptor'}`);
172
+ },
173
+ transform: value => {
174
+ transformedChanges = value;
175
+ },
176
+ blocked: false,
177
+ blockReason: undefined
178
+ };
179
+ handler.onUpdate?.(id, changes, ctx);
180
+ }
181
+ const finalUpdated = {
182
+ ...entity,
183
+ ...transformedChanges
184
+ };
185
+ storage.set(id, finalUpdated);
186
+ nodeCache.delete(id);
187
+ updateSignals();
188
+ pathNotifier.notify(`${basePath}.${String(id)}`, finalUpdated, prev);
189
+ for (const handler of tapHandlers) {
190
+ handler.onUpdate?.(id, transformedChanges, finalUpdated);
191
+ }
192
+ },
193
+ updateMany(ids, changes) {
194
+ if (ids.length === 0) return;
195
+ const updatedEntities = [];
196
+ for (const id of ids) {
197
+ const entity = storage.get(id);
198
+ if (!entity) {
199
+ throw new Error(`Entity with id ${String(id)} not found`);
200
+ }
201
+ const prev = entity;
202
+ let transformedChanges = changes;
203
+ for (const handler of interceptHandlers) {
204
+ const ctx = {
205
+ block: reason => {
206
+ throw new Error(`Cannot update entity: ${reason || 'blocked by interceptor'}`);
207
+ },
208
+ transform: value => {
209
+ transformedChanges = value;
210
+ },
211
+ blocked: false,
212
+ blockReason: undefined
213
+ };
214
+ handler.onUpdate?.(id, changes, ctx);
215
+ }
216
+ const finalUpdated = {
217
+ ...entity,
218
+ ...transformedChanges
219
+ };
220
+ storage.set(id, finalUpdated);
221
+ nodeCache.delete(id);
222
+ updatedEntities.push({
223
+ id,
224
+ prev,
225
+ finalUpdated,
226
+ transformedChanges
227
+ });
228
+ }
229
+ updateSignals();
230
+ for (const {
231
+ id,
232
+ prev,
233
+ finalUpdated
234
+ } of updatedEntities) {
235
+ pathNotifier.notify(`${basePath}.${String(id)}`, finalUpdated, prev);
236
+ }
237
+ for (const {
238
+ id,
239
+ transformedChanges,
240
+ finalUpdated
241
+ } of updatedEntities) {
242
+ for (const handler of tapHandlers) {
243
+ handler.onUpdate?.(id, transformedChanges, finalUpdated);
244
+ }
245
+ }
246
+ },
247
+ updateWhere(predicate, changes) {
248
+ const idsToUpdate = [];
249
+ for (const [id, entity] of storage) {
58
250
  if (predicate(entity)) {
59
- result.push(entity);
251
+ idsToUpdate.push(id);
60
252
  }
61
253
  }
62
- return result;
63
- });
64
- }
65
- find(predicate) {
66
- return computed(() => {
67
- for (const entity of this.storage.values()) {
254
+ if (idsToUpdate.length > 0) {
255
+ api.updateMany(idsToUpdate, changes);
256
+ }
257
+ return idsToUpdate.length;
258
+ },
259
+ removeOne(id) {
260
+ const entity = storage.get(id);
261
+ if (!entity) {
262
+ throw new Error(`Entity with id ${String(id)} not found`);
263
+ }
264
+ for (const handler of interceptHandlers) {
265
+ const ctx = {
266
+ block: reason => {
267
+ throw new Error(`Cannot remove entity: ${reason || 'blocked by interceptor'}`);
268
+ },
269
+ transform: () => {},
270
+ blocked: false,
271
+ blockReason: undefined
272
+ };
273
+ handler.onRemove?.(id, entity, ctx);
274
+ }
275
+ storage.delete(id);
276
+ nodeCache.delete(id);
277
+ updateSignals();
278
+ pathNotifier.notify(`${basePath}.${String(id)}`, undefined, entity);
279
+ for (const handler of tapHandlers) {
280
+ handler.onRemove?.(id, entity);
281
+ }
282
+ },
283
+ removeMany(ids) {
284
+ if (ids.length === 0) return;
285
+ const entitiesToRemove = [];
286
+ for (const id of ids) {
287
+ const entity = storage.get(id);
288
+ if (!entity) {
289
+ throw new Error(`Entity with id ${String(id)} not found`);
290
+ }
291
+ for (const handler of interceptHandlers) {
292
+ const ctx = {
293
+ block: reason => {
294
+ throw new Error(`Cannot remove entity: ${reason || 'blocked by interceptor'}`);
295
+ },
296
+ transform: () => {},
297
+ blocked: false,
298
+ blockReason: undefined
299
+ };
300
+ handler.onRemove?.(id, entity, ctx);
301
+ }
302
+ entitiesToRemove.push({
303
+ id,
304
+ entity
305
+ });
306
+ }
307
+ for (const {
308
+ id
309
+ } of entitiesToRemove) {
310
+ storage.delete(id);
311
+ nodeCache.delete(id);
312
+ }
313
+ updateSignals();
314
+ for (const {
315
+ id,
316
+ entity
317
+ } of entitiesToRemove) {
318
+ pathNotifier.notify(`${basePath}.${String(id)}`, undefined, entity);
319
+ }
320
+ for (const {
321
+ id,
322
+ entity
323
+ } of entitiesToRemove) {
324
+ for (const handler of tapHandlers) {
325
+ handler.onRemove?.(id, entity);
326
+ }
327
+ }
328
+ },
329
+ removeWhere(predicate) {
330
+ const idsToRemove = [];
331
+ for (const [id, entity] of storage) {
68
332
  if (predicate(entity)) {
69
- return entity;
333
+ idsToRemove.push(id);
70
334
  }
71
335
  }
72
- return undefined;
73
- });
74
- }
75
- addOne(entity, opts) {
76
- const id = opts?.selectId?.(entity) ?? this.selectId(entity);
77
- if (this.storage.has(id)) {
78
- throw new Error(`Entity with id ${String(id)} already exists`);
79
- }
80
- let transformedEntity = entity;
81
- for (const handler of this.interceptHandlers) {
82
- const ctx = {
83
- block: reason => {
84
- throw new Error(`Cannot add entity: ${reason || 'blocked by interceptor'}`);
85
- },
86
- transform: value => {
87
- transformedEntity = value;
88
- },
89
- blocked: false,
90
- blockReason: undefined
91
- };
92
- handler.onAdd?.(entity, ctx);
93
- }
94
- this.storage.set(id, transformedEntity);
95
- this.nodeCache.delete(id);
96
- this.updateSignals();
97
- this.pathNotifier.notify(`${this.basePath}.${String(id)}`, transformedEntity, undefined);
98
- for (const handler of this.tapHandlers) {
99
- handler.onAdd?.(transformedEntity, id);
100
- }
101
- return id;
102
- }
103
- addMany(entities, opts) {
104
- const ids = [];
105
- for (const entity of entities) {
106
- ids.push(this.addOne(entity, opts));
107
- }
108
- return ids;
109
- }
110
- updateOne(id, changes) {
111
- const entity = this.storage.get(id);
112
- if (!entity) {
113
- throw new Error(`Entity with id ${String(id)} not found`);
114
- }
115
- const prev = entity;
116
- let transformedChanges = changes;
117
- for (const handler of this.interceptHandlers) {
118
- const ctx = {
119
- block: reason => {
120
- throw new Error(`Cannot update entity: ${reason || 'blocked by interceptor'}`);
121
- },
122
- transform: value => {
123
- transformedChanges = value;
124
- },
125
- blocked: false,
126
- blockReason: undefined
127
- };
128
- handler.onUpdate?.(id, changes, ctx);
129
- }
130
- const finalUpdated = {
131
- ...entity,
132
- ...transformedChanges
133
- };
134
- this.storage.set(id, finalUpdated);
135
- this.nodeCache.delete(id);
136
- this.updateSignals();
137
- this.pathNotifier.notify(`${this.basePath}.${String(id)}`, finalUpdated, prev);
138
- for (const handler of this.tapHandlers) {
139
- handler.onUpdate?.(id, transformedChanges, finalUpdated);
140
- }
141
- }
142
- updateMany(ids, changes) {
143
- for (const id of ids) {
144
- this.updateOne(id, changes);
145
- }
146
- }
147
- updateWhere(predicate, changes) {
148
- let count = 0;
149
- for (const [id, entity] of this.storage) {
150
- if (predicate(entity)) {
151
- this.updateOne(id, changes);
152
- count++;
336
+ if (idsToRemove.length > 0) {
337
+ api.removeMany(idsToRemove);
153
338
  }
154
- }
155
- return count;
156
- }
157
- removeOne(id) {
158
- const entity = this.storage.get(id);
159
- if (!entity) {
160
- throw new Error(`Entity with id ${String(id)} not found`);
161
- }
162
- for (const handler of this.interceptHandlers) {
163
- const ctx = {
164
- block: reason => {
165
- throw new Error(`Cannot remove entity: ${reason || 'blocked by interceptor'}`);
166
- },
167
- transform: () => {},
168
- blocked: false,
169
- blockReason: undefined
170
- };
171
- handler.onRemove?.(id, entity, ctx);
172
- }
173
- this.storage.delete(id);
174
- this.nodeCache.delete(id);
175
- this.updateSignals();
176
- this.pathNotifier.notify(`${this.basePath}.${String(id)}`, undefined, entity);
177
- for (const handler of this.tapHandlers) {
178
- handler.onRemove?.(id, entity);
179
- }
180
- }
181
- removeMany(ids) {
182
- for (const id of ids) {
183
- this.removeOne(id);
184
- }
185
- }
186
- removeWhere(predicate) {
187
- const idsToRemove = [];
188
- for (const [id, entity] of this.storage) {
189
- if (predicate(entity)) {
190
- idsToRemove.push(id);
339
+ return idsToRemove.length;
340
+ },
341
+ upsertOne(entity, opts) {
342
+ const id = opts?.selectId?.(entity) ?? selectId(entity);
343
+ if (storage.has(id)) {
344
+ api.updateOne(id, entity);
345
+ } else {
346
+ api.addOne(entity, opts);
191
347
  }
348
+ return id;
349
+ },
350
+ upsertMany(entities, opts) {
351
+ if (entities.length === 0) return [];
352
+ const toAdd = [];
353
+ const toUpdate = [];
354
+ for (const entity of entities) {
355
+ const id = opts?.selectId?.(entity) ?? selectId(entity);
356
+ const existing = storage.get(id);
357
+ if (existing !== undefined) {
358
+ toUpdate.push({
359
+ entity,
360
+ id,
361
+ prev: existing
362
+ });
363
+ } else {
364
+ toAdd.push({
365
+ entity,
366
+ id
367
+ });
368
+ }
369
+ }
370
+ const addedEntities = [];
371
+ for (const {
372
+ entity,
373
+ id
374
+ } of toAdd) {
375
+ let transformedEntity = entity;
376
+ for (const handler of interceptHandlers) {
377
+ const ctx = {
378
+ block: reason => {
379
+ throw new Error(`Cannot add entity: ${reason || 'blocked by interceptor'}`);
380
+ },
381
+ transform: value => {
382
+ transformedEntity = value;
383
+ },
384
+ blocked: false,
385
+ blockReason: undefined
386
+ };
387
+ handler.onAdd?.(entity, ctx);
388
+ }
389
+ storage.set(id, transformedEntity);
390
+ nodeCache.delete(id);
391
+ addedEntities.push({
392
+ id,
393
+ entity: transformedEntity
394
+ });
395
+ }
396
+ const updatedEntities = [];
397
+ for (const {
398
+ entity,
399
+ id,
400
+ prev
401
+ } of toUpdate) {
402
+ let transformedChanges = entity;
403
+ for (const handler of interceptHandlers) {
404
+ const ctx = {
405
+ block: reason => {
406
+ throw new Error(`Cannot update entity: ${reason || 'blocked by interceptor'}`);
407
+ },
408
+ transform: value => {
409
+ transformedChanges = value;
410
+ },
411
+ blocked: false,
412
+ blockReason: undefined
413
+ };
414
+ handler.onUpdate?.(id, entity, ctx);
415
+ }
416
+ const finalUpdated = {
417
+ ...prev,
418
+ ...transformedChanges
419
+ };
420
+ storage.set(id, finalUpdated);
421
+ nodeCache.delete(id);
422
+ updatedEntities.push({
423
+ id,
424
+ prev,
425
+ finalUpdated,
426
+ transformedChanges
427
+ });
428
+ }
429
+ updateSignals();
430
+ for (const {
431
+ id,
432
+ entity
433
+ } of addedEntities) {
434
+ pathNotifier.notify(`${basePath}.${String(id)}`, entity, undefined);
435
+ }
436
+ for (const {
437
+ id,
438
+ prev,
439
+ finalUpdated
440
+ } of updatedEntities) {
441
+ pathNotifier.notify(`${basePath}.${String(id)}`, finalUpdated, prev);
442
+ }
443
+ for (const {
444
+ id,
445
+ entity
446
+ } of addedEntities) {
447
+ for (const handler of tapHandlers) {
448
+ handler.onAdd?.(entity, id);
449
+ }
450
+ }
451
+ for (const {
452
+ id,
453
+ transformedChanges,
454
+ finalUpdated
455
+ } of updatedEntities) {
456
+ for (const handler of tapHandlers) {
457
+ handler.onUpdate?.(id, transformedChanges, finalUpdated);
458
+ }
459
+ }
460
+ return [...toAdd.map(a => a.id), ...toUpdate.map(u => u.id)];
461
+ },
462
+ clear() {
463
+ storage.clear();
464
+ nodeCache.clear();
465
+ updateSignals();
466
+ },
467
+ removeAll() {
468
+ api.clear();
469
+ },
470
+ setAll(entities, opts) {
471
+ storage.clear();
472
+ nodeCache.clear();
473
+ const addedIds = [];
474
+ for (const entity of entities) {
475
+ const id = opts?.selectId?.(entity) ?? selectId(entity);
476
+ let transformedEntity = entity;
477
+ for (const handler of interceptHandlers) {
478
+ const ctx = {
479
+ block: reason => {
480
+ throw new Error(`Cannot add entity: ${reason || 'blocked by interceptor'}`);
481
+ },
482
+ transform: value => {
483
+ transformedEntity = value;
484
+ },
485
+ blocked: false,
486
+ blockReason: undefined
487
+ };
488
+ handler.onAdd?.(entity, ctx);
489
+ }
490
+ storage.set(id, transformedEntity);
491
+ addedIds.push(id);
492
+ }
493
+ updateSignals();
494
+ for (let i = 0; i < addedIds.length; i++) {
495
+ const id = addedIds[i];
496
+ const entity = storage.get(id);
497
+ pathNotifier.notify(`${basePath}.${String(id)}`, entity, undefined);
498
+ }
499
+ for (let i = 0; i < addedIds.length; i++) {
500
+ const id = addedIds[i];
501
+ const entity = storage.get(id);
502
+ if (entity) {
503
+ for (const handler of tapHandlers) {
504
+ handler.onAdd?.(entity, id);
505
+ }
506
+ }
507
+ }
508
+ },
509
+ tap(handlers) {
510
+ tapHandlers.push(handlers);
511
+ return () => {
512
+ const idx = tapHandlers.indexOf(handlers);
513
+ if (idx > -1) tapHandlers.splice(idx, 1);
514
+ };
515
+ },
516
+ intercept(handlers) {
517
+ interceptHandlers.push(handlers);
518
+ return () => {
519
+ const idx = interceptHandlers.indexOf(handlers);
520
+ if (idx > -1) interceptHandlers.splice(idx, 1);
521
+ };
192
522
  }
193
- let count = 0;
194
- for (const id of idsToRemove) {
195
- this.removeOne(id);
196
- count++;
197
- }
198
- return count;
199
- }
200
- upsertOne(entity, opts) {
201
- const id = opts?.selectId?.(entity) ?? this.selectId(entity);
202
- if (this.storage.has(id)) {
203
- this.updateOne(id, entity);
204
- } else {
205
- this.addOne(entity, opts);
206
- }
207
- return id;
208
- }
209
- upsertMany(entities, opts) {
210
- return entities.map(e => this.upsertOne(e, opts));
211
- }
212
- clear() {
213
- this.storage.clear();
214
- this.nodeCache.clear();
215
- this.updateSignals();
216
- }
217
- removeAll() {
218
- this.clear();
219
- }
220
- setAll(entities, opts) {
221
- this.clear();
222
- this.addMany(entities, opts);
223
- }
224
- tap(handlers) {
225
- this.tapHandlers.push(handlers);
226
- return () => {
227
- const idx = this.tapHandlers.indexOf(handlers);
228
- if (idx > -1) this.tapHandlers.splice(idx, 1);
229
- };
230
- }
231
- intercept(handlers) {
232
- this.interceptHandlers.push(handlers);
233
- return () => {
234
- const idx = this.interceptHandlers.indexOf(handlers);
235
- if (idx > -1) this.interceptHandlers.splice(idx, 1);
236
- };
237
- }
238
- updateSignals() {
239
- const entities = Array.from(this.storage.values());
240
- const ids = Array.from(this.storage.keys());
241
- const map = new Map(this.storage);
242
- this.allSignal.set(entities);
243
- this.countSignal.set(entities.length);
244
- this.idsSignal.set(ids);
245
- this.mapSignal.set(map);
246
- }
247
- getOrCreateNode(id, entity) {
248
- let node = this.nodeCache.get(id);
249
- if (!node) {
250
- node = this.createEntityNode(id, entity);
251
- this.nodeCache.set(id, node);
252
- }
253
- return node;
254
- }
255
- createEntityNode(id, entity) {
256
- const node = () => this.storage.get(id);
257
- for (const key of Object.keys(entity)) {
258
- Object.defineProperty(node, key, {
259
- get: () => {
260
- const current = this.storage.get(id);
261
- const value = current?.[key];
262
- return () => value;
263
- },
264
- enumerable: true,
265
- configurable: true
266
- });
267
- }
268
- return node;
269
- }
270
- }
271
- function createEntitySignal(config, pathNotifier, basePath) {
272
- const impl = new EntitySignalImpl(config, pathNotifier, basePath);
273
- return new Proxy(impl, {
523
+ };
524
+ return new Proxy(api, {
274
525
  get: (target, prop) => {
275
526
  if (typeof prop === 'string' && !isNaN(Number(prop))) {
276
- return target.byId(Number(prop));
527
+ return api.byId(Number(prop));
277
528
  }
278
529
  return target[prop];
279
530
  }
280
531
  });
281
532
  }
282
533
 
283
- export { EntitySignalImpl, createEntitySignal };
534
+ export { createEntitySignal };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signaltree/core",
3
- "version": "6.2.2",
3
+ "version": "6.2.4",
4
4
  "description": "Lightweight, type-safe signal-based state management for Angular. Core package providing hierarchical signal trees, basic entity management, and async actions.",
5
5
  "type": "module",
6
6
  "sideEffects": false,