teamplay 0.5.0-alpha.34 → 0.5.0-alpha.35
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/dist/orm/Compat/SignalCompat.js +4 -336
- package/dist/orm/Compat/modelEvents.js +4 -89
- package/dist/orm/SignalBase.js +1 -22
- package/dist/orm/disposeRootContext.js +0 -13
- package/dist/orm/getSignal.d.ts +1 -1
- package/dist/orm/getSignal.js +2 -12
- package/dist/orm/rootContext.d.ts +0 -7
- package/dist/orm/rootContext.js +0 -10
- package/package.json +1 -1
- package/dist/orm/Compat/refFallback.d.ts +0 -13
- package/dist/orm/Compat/refFallback.js +0 -65
- package/dist/orm/Compat/refRegistry.d.ts +0 -6
- package/dist/orm/Compat/refRegistry.js +0 -54
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { raw
|
|
1
|
+
import { raw } from '@nx-js/observer-util';
|
|
2
2
|
import arrayDiff from 'arraydiff';
|
|
3
3
|
import { Signal, GETTERS, DEFAULT_GETTERS, SEGMENTS, isPublicCollection, isPublicCollectionSignal, isPublicDocumentSignal } from "../SignalBase.js";
|
|
4
|
-
import { getRoot, ROOT, ROOT_ID
|
|
4
|
+
import { getRoot, ROOT, ROOT_ID } from "../Root.js";
|
|
5
5
|
import { docSubscriptions } from '../Doc.js';
|
|
6
6
|
import { IS_QUERY, querySubscriptions } from '../Query.js';
|
|
7
7
|
import { AGGREGATIONS, IS_AGGREGATION, aggregationSubscriptions } from '../Aggregation.js';
|
|
@@ -9,13 +9,7 @@ import { getIdFieldsForSegments, isIdFieldPath, isPublicDocPath, normalizeIdFiel
|
|
|
9
9
|
import { incrementPublic as _incrementPublic, arrayPushPublic as _arrayPushPublic, arrayUnshiftPublic as _arrayUnshiftPublic, arrayInsertPublic as _arrayInsertPublic, arrayPopPublic as _arrayPopPublic, arrayShiftPublic as _arrayShiftPublic, arrayRemovePublic as _arrayRemovePublic, arrayMovePublic as _arrayMovePublic, setPublicDocReplace as _setPublicDocReplace, stringInsertPublic as _stringInsertPublic, stringRemovePublic as _stringRemovePublic } from '../dataTree.js';
|
|
10
10
|
import { on as onCustomEvent, removeListener as removeCustomEventListener } from '../events.js';
|
|
11
11
|
import { waitForImperativeQueryReady } from '../queryReadiness.js';
|
|
12
|
-
import { isModelEventsEnabled } from './modelEvents.js';
|
|
13
|
-
import { setRefLink, removeRefLink, getAllRefLinks } from './refRegistry.js';
|
|
14
|
-
import { REF_TARGET, resolveRefSignalSafe, resolveRefSegmentsSafe } from './refFallback.js';
|
|
15
12
|
import { runInBatch } from '../batchScheduler.js';
|
|
16
|
-
import { runInModelEventsSilentContext, isSilentContextActive } from './silentContext.js';
|
|
17
|
-
import universal$ from "../../react/universal$.js";
|
|
18
|
-
import { getRootContext } from "../rootContext.js";
|
|
19
13
|
import { arrayInsertPrivateData, arrayMovePrivateData, arrayPopPrivateData, arrayPushPrivateData, arrayRemovePrivateData, arrayShiftPrivateData, arrayUnshiftPrivateData, delPrivateData, setReplacePrivateData, stringInsertPrivateData, stringRemovePrivateData } from '../privateData.js';
|
|
20
14
|
class SignalCompat extends Signal {
|
|
21
15
|
static [GETTERS] = DEFAULT_GETTERS;
|
|
@@ -27,15 +21,9 @@ class SignalCompat extends Signal {
|
|
|
27
21
|
getId() {
|
|
28
22
|
if (isAggregationValuePath(this[SEGMENTS]))
|
|
29
23
|
return super.getId();
|
|
30
|
-
const $target = resolveRefSignal(this);
|
|
31
|
-
if ($target !== this)
|
|
32
|
-
return $target.getId();
|
|
33
24
|
return super.getId();
|
|
34
25
|
}
|
|
35
26
|
getCollection() {
|
|
36
|
-
const $target = resolveRefSignal(this);
|
|
37
|
-
if ($target !== this)
|
|
38
|
-
return $target.getCollection();
|
|
39
27
|
return super.getCollection();
|
|
40
28
|
}
|
|
41
29
|
getCopy() {
|
|
@@ -75,15 +63,9 @@ class SignalCompat extends Signal {
|
|
|
75
63
|
peek() {
|
|
76
64
|
if (arguments.length > 0)
|
|
77
65
|
throw Error('Signal.peek() does not accept any arguments');
|
|
78
|
-
const $target = resolveRefSignal(this);
|
|
79
|
-
if ($target !== this)
|
|
80
|
-
return Signal.prototype.peek.apply($target, arguments);
|
|
81
66
|
return Signal.prototype.peek.apply(this, arguments);
|
|
82
67
|
}
|
|
83
68
|
async set(value) {
|
|
84
|
-
const forwarded = forwardRef(this, 'set', arguments);
|
|
85
|
-
if (forwarded)
|
|
86
|
-
return forwarded;
|
|
87
69
|
if (arguments.length > 1)
|
|
88
70
|
throw Error('Signal.set() expects a single argument');
|
|
89
71
|
if (value === undefined)
|
|
@@ -91,9 +73,6 @@ class SignalCompat extends Signal {
|
|
|
91
73
|
return setReplaceOnSignal(this, value);
|
|
92
74
|
}
|
|
93
75
|
async setReplace(value) {
|
|
94
|
-
const forwarded = forwardRef(this, 'setReplace', arguments);
|
|
95
|
-
if (forwarded)
|
|
96
|
-
return forwarded;
|
|
97
76
|
if (arguments.length > 1)
|
|
98
77
|
throw Error('Signal.setReplace() expects a single argument');
|
|
99
78
|
if (value === undefined)
|
|
@@ -101,9 +80,6 @@ class SignalCompat extends Signal {
|
|
|
101
80
|
return setReplaceOnSignal(this, value);
|
|
102
81
|
}
|
|
103
82
|
async setNull(value) {
|
|
104
|
-
const forwarded = forwardRef(this, 'setNull', arguments);
|
|
105
|
-
if (forwarded)
|
|
106
|
-
return forwarded;
|
|
107
83
|
if (arguments.length > 1)
|
|
108
84
|
throw Error('Signal.setNull() expects a single argument');
|
|
109
85
|
if (this.get() != null)
|
|
@@ -111,17 +87,11 @@ class SignalCompat extends Signal {
|
|
|
111
87
|
return setReplaceOnSignal(this, value);
|
|
112
88
|
}
|
|
113
89
|
async setDiffDeep(value) {
|
|
114
|
-
const forwarded = forwardRef(this, 'setDiffDeep', arguments);
|
|
115
|
-
if (forwarded)
|
|
116
|
-
return forwarded;
|
|
117
90
|
if (arguments.length > 1)
|
|
118
91
|
throw Error('Signal.setDiffDeep() expects a single argument');
|
|
119
92
|
return runInBatch(() => setDiffDeepOnSignal(this, value));
|
|
120
93
|
}
|
|
121
94
|
async setDiff(value) {
|
|
122
|
-
const forwarded = forwardRef(this, 'setDiff', arguments);
|
|
123
|
-
if (forwarded)
|
|
124
|
-
return forwarded;
|
|
125
95
|
if (arguments.length > 1)
|
|
126
96
|
throw Error('Signal.setDiff() expects a single argument');
|
|
127
97
|
const before = this.peek();
|
|
@@ -130,9 +100,6 @@ class SignalCompat extends Signal {
|
|
|
130
100
|
return setReplaceOnSignal(this, value);
|
|
131
101
|
}
|
|
132
102
|
async setEach(object) {
|
|
133
|
-
const forwarded = forwardRef(this, 'setEach', arguments);
|
|
134
|
-
if (forwarded)
|
|
135
|
-
return forwarded;
|
|
136
103
|
if (arguments.length > 1)
|
|
137
104
|
throw Error('Signal.setEach() expects a single argument');
|
|
138
105
|
if (!object)
|
|
@@ -149,9 +116,6 @@ class SignalCompat extends Signal {
|
|
|
149
116
|
});
|
|
150
117
|
}
|
|
151
118
|
async del() {
|
|
152
|
-
const forwarded = forwardRef(this, 'del', arguments);
|
|
153
|
-
if (forwarded)
|
|
154
|
-
return forwarded;
|
|
155
119
|
if (arguments.length > 0)
|
|
156
120
|
throw Error('Signal.del() does not accept any arguments');
|
|
157
121
|
try {
|
|
@@ -164,9 +128,6 @@ class SignalCompat extends Signal {
|
|
|
164
128
|
}
|
|
165
129
|
}
|
|
166
130
|
async increment(byNumber) {
|
|
167
|
-
const forwarded = forwardRef(this, 'increment', arguments);
|
|
168
|
-
if (forwarded)
|
|
169
|
-
return forwarded;
|
|
170
131
|
if (arguments.length > 1)
|
|
171
132
|
throw Error('Signal.increment() expects zero or one argument');
|
|
172
133
|
if (byNumber != null && (typeof byNumber !== 'number' || !Number.isFinite(byNumber))) {
|
|
@@ -175,25 +136,16 @@ class SignalCompat extends Signal {
|
|
|
175
136
|
return incrementOnSignal(this, byNumber);
|
|
176
137
|
}
|
|
177
138
|
async push(value) {
|
|
178
|
-
const forwarded = forwardRef(this, 'push', arguments);
|
|
179
|
-
if (forwarded)
|
|
180
|
-
return forwarded;
|
|
181
139
|
if (arguments.length > 1)
|
|
182
140
|
throw Error('Signal.push() expects a single argument');
|
|
183
141
|
return arrayPushOnSignal(this, value);
|
|
184
142
|
}
|
|
185
143
|
async unshift(value) {
|
|
186
|
-
const forwarded = forwardRef(this, 'unshift', arguments);
|
|
187
|
-
if (forwarded)
|
|
188
|
-
return forwarded;
|
|
189
144
|
if (arguments.length > 1)
|
|
190
145
|
throw Error('Signal.unshift() expects a single argument');
|
|
191
146
|
return arrayUnshiftOnSignal(this, value);
|
|
192
147
|
}
|
|
193
148
|
async insert(index, values) {
|
|
194
|
-
const forwarded = forwardRef(this, 'insert', arguments);
|
|
195
|
-
if (forwarded)
|
|
196
|
-
return forwarded;
|
|
197
149
|
if (arguments.length < 2)
|
|
198
150
|
throw Error('Not enough arguments for insert');
|
|
199
151
|
if (arguments.length > 2)
|
|
@@ -204,25 +156,16 @@ class SignalCompat extends Signal {
|
|
|
204
156
|
return arrayInsertOnSignal(this, index, values);
|
|
205
157
|
}
|
|
206
158
|
async pop() {
|
|
207
|
-
const forwarded = forwardRef(this, 'pop', arguments);
|
|
208
|
-
if (forwarded)
|
|
209
|
-
return forwarded;
|
|
210
159
|
if (arguments.length > 0)
|
|
211
160
|
throw Error('Signal.pop() does not accept any arguments');
|
|
212
161
|
return arrayPopOnSignal(this);
|
|
213
162
|
}
|
|
214
163
|
async shift() {
|
|
215
|
-
const forwarded = forwardRef(this, 'shift', arguments);
|
|
216
|
-
if (forwarded)
|
|
217
|
-
return forwarded;
|
|
218
164
|
if (arguments.length > 0)
|
|
219
165
|
throw Error('Signal.shift() does not accept any arguments');
|
|
220
166
|
return arrayShiftOnSignal(this);
|
|
221
167
|
}
|
|
222
168
|
async remove(index, howMany) {
|
|
223
|
-
const forwarded = forwardRef(this, 'remove', arguments);
|
|
224
|
-
if (forwarded)
|
|
225
|
-
return forwarded;
|
|
226
169
|
if (arguments.length === 0) {
|
|
227
170
|
const segments = this[SEGMENTS].slice();
|
|
228
171
|
if (!segments.length || typeof segments[segments.length - 1] !== 'number') {
|
|
@@ -241,9 +184,6 @@ class SignalCompat extends Signal {
|
|
|
241
184
|
return arrayRemoveOnSignal(this, index, howMany);
|
|
242
185
|
}
|
|
243
186
|
async move(from, to, howMany) {
|
|
244
|
-
const forwarded = forwardRef(this, 'move', arguments);
|
|
245
|
-
if (forwarded)
|
|
246
|
-
return forwarded;
|
|
247
187
|
if (arguments.length < 2)
|
|
248
188
|
throw Error('Not enough arguments for move');
|
|
249
189
|
if (arguments.length > 3)
|
|
@@ -254,9 +194,6 @@ class SignalCompat extends Signal {
|
|
|
254
194
|
return arrayMoveOnSignal(this, from, to, howMany);
|
|
255
195
|
}
|
|
256
196
|
async stringInsert(index, text) {
|
|
257
|
-
const forwarded = forwardRef(this, 'stringInsert', arguments);
|
|
258
|
-
if (forwarded)
|
|
259
|
-
return forwarded;
|
|
260
197
|
if (arguments.length < 2)
|
|
261
198
|
throw Error('Not enough arguments for stringInsert');
|
|
262
199
|
if (arguments.length > 2)
|
|
@@ -267,9 +204,6 @@ class SignalCompat extends Signal {
|
|
|
267
204
|
return stringInsertOnSignal(this, index, text);
|
|
268
205
|
}
|
|
269
206
|
async stringRemove(index, howMany) {
|
|
270
|
-
const forwarded = forwardRef(this, 'stringRemove', arguments);
|
|
271
|
-
if (forwarded)
|
|
272
|
-
return forwarded;
|
|
273
207
|
if (arguments.length < 2)
|
|
274
208
|
throw Error('Not enough arguments for stringRemove');
|
|
275
209
|
if (arguments.length > 2)
|
|
@@ -282,9 +216,6 @@ class SignalCompat extends Signal {
|
|
|
282
216
|
return stringRemoveOnSignal(this, index, howMany);
|
|
283
217
|
}
|
|
284
218
|
async assign(value) {
|
|
285
|
-
const forwarded = forwardRef(this, 'assign', arguments);
|
|
286
|
-
if (forwarded)
|
|
287
|
-
return forwarded;
|
|
288
219
|
if (arguments.length > 1)
|
|
289
220
|
throw Error('Signal.assign() expects a single argument');
|
|
290
221
|
return Signal.prototype.assign.call(this, value);
|
|
@@ -319,245 +250,15 @@ class SignalCompat extends Signal {
|
|
|
319
250
|
throw Error('Signal.removeListener() expects two arguments');
|
|
320
251
|
return removeCustomEventListener(eventName, handler);
|
|
321
252
|
}
|
|
322
|
-
ref(path, target, options) {
|
|
323
|
-
if (arguments.length < 1 || arguments.length > 2)
|
|
324
|
-
throw Error('Signal.ref() expects one or two arguments');
|
|
325
|
-
let $to;
|
|
326
|
-
if (arguments.length === 1) {
|
|
327
|
-
$to = resolveRefTarget(this, path, 'Signal.ref()');
|
|
328
|
-
}
|
|
329
|
-
else {
|
|
330
|
-
$to = resolveRefTarget(this, path, 'Signal.ref()');
|
|
331
|
-
options = target;
|
|
332
|
-
}
|
|
333
|
-
if (!$to)
|
|
334
|
-
throw Error('Signal.ref() expects a target path or signal');
|
|
335
|
-
if (this === $to)
|
|
336
|
-
return this;
|
|
337
|
-
ensurePrivateRefSource(this, 'Signal.ref()');
|
|
338
|
-
const store = getRefStore(this);
|
|
339
|
-
const fromPath = this.path();
|
|
340
|
-
const existing = store.get(fromPath);
|
|
341
|
-
if (existing)
|
|
342
|
-
existing.stop();
|
|
343
|
-
const mirrorOnly = !!($to?.[IS_QUERY] || $to?.[IS_AGGREGATION]);
|
|
344
|
-
const { stop, onChange } = createRefLink(this, $to, { mirrorOnly, options });
|
|
345
|
-
store.set(fromPath, { stop });
|
|
346
|
-
const fromRootId = (getRoot(this) || this)?.[ROOT_ID];
|
|
347
|
-
const toRootId = (getRoot($to) || $to)?.[ROOT_ID];
|
|
348
|
-
if (!mirrorOnly) {
|
|
349
|
-
this[REF_TARGET] = $to;
|
|
350
|
-
setRefLink(fromRootId, fromPath, $to.path(), this[SEGMENTS], $to[SEGMENTS], {
|
|
351
|
-
mirrorOnly: false,
|
|
352
|
-
fromRootId,
|
|
353
|
-
toRootId
|
|
354
|
-
});
|
|
355
|
-
}
|
|
356
|
-
else {
|
|
357
|
-
setRefLink(fromRootId, fromPath, $to.path(), this[SEGMENTS], $to[SEGMENTS], {
|
|
358
|
-
mirrorOnly: true,
|
|
359
|
-
onChange,
|
|
360
|
-
fromRootId,
|
|
361
|
-
toRootId
|
|
362
|
-
});
|
|
363
|
-
if (this[REF_TARGET])
|
|
364
|
-
delete this[REF_TARGET];
|
|
365
|
-
}
|
|
366
|
-
return this;
|
|
367
|
-
}
|
|
368
|
-
refExtra(path) {
|
|
369
|
-
if (arguments.length !== 1)
|
|
370
|
-
throw Error('Signal.refExtra() expects a single argument');
|
|
371
|
-
const segments = parseAtSubpath(path, 1, 'Signal.refExtra()');
|
|
372
|
-
const $root = getRoot(this) || this;
|
|
373
|
-
const $target = resolveSignal($root, segments);
|
|
374
|
-
let $source = this;
|
|
375
|
-
if (this[IS_QUERY]) {
|
|
376
|
-
$source = this.extra;
|
|
377
|
-
}
|
|
378
|
-
return SignalCompat.prototype.ref.call($target, $source);
|
|
379
|
-
}
|
|
380
|
-
refIds(path) {
|
|
381
|
-
if (arguments.length !== 1)
|
|
382
|
-
throw Error('Signal.refIds() expects a single argument');
|
|
383
|
-
if (!this[IS_QUERY]) {
|
|
384
|
-
throw Error('Signal.refIds() can only be used on query signals');
|
|
385
|
-
}
|
|
386
|
-
const segments = parseAtSubpath(path, 1, 'Signal.refIds()');
|
|
387
|
-
const $root = getRoot(this) || this;
|
|
388
|
-
const $target = resolveSignal($root, segments);
|
|
389
|
-
return SignalCompat.prototype.ref.call($target, this.ids);
|
|
390
|
-
}
|
|
391
|
-
removeRef() {
|
|
392
|
-
if (arguments.length > 0)
|
|
393
|
-
throw Error('Signal.removeRef() does not accept any arguments');
|
|
394
|
-
const store = getRefStore(this);
|
|
395
|
-
const fromPath = this.path();
|
|
396
|
-
const existing = store.get(fromPath);
|
|
397
|
-
if (existing) {
|
|
398
|
-
existing.stop();
|
|
399
|
-
store.delete(fromPath);
|
|
400
|
-
}
|
|
401
|
-
const fromRootId = (getRoot(this) || this)?.[ROOT_ID];
|
|
402
|
-
removeRefLink(fromRootId, fromPath);
|
|
403
|
-
const $target = resolveRefSignal(this);
|
|
404
|
-
if ($target !== this) {
|
|
405
|
-
setDiffDeepBypassRef(this, deepCopy($target.get()));
|
|
406
|
-
}
|
|
407
|
-
if (this[REF_TARGET])
|
|
408
|
-
delete this[REF_TARGET];
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
function getRefStore($signal) {
|
|
412
|
-
const $root = getRoot($signal) || $signal;
|
|
413
|
-
const rootId = $root?.[ROOT_ID];
|
|
414
|
-
return getRootContext(rootId, true).activeRefs;
|
|
415
|
-
}
|
|
416
|
-
function createRefLink($from, $to, { mirrorOnly = false } = {}) {
|
|
417
|
-
let disposed = false;
|
|
418
|
-
let pendingRead = null;
|
|
419
|
-
let mirrorObserver;
|
|
420
|
-
const syncFromTarget = () => {
|
|
421
|
-
const value = readRefValue($to);
|
|
422
|
-
if (isThenable(value)) {
|
|
423
|
-
pendingRead = value;
|
|
424
|
-
value.then(() => {
|
|
425
|
-
if (disposed || pendingRead !== value)
|
|
426
|
-
return;
|
|
427
|
-
pendingRead = null;
|
|
428
|
-
syncFromTarget();
|
|
429
|
-
}, () => {
|
|
430
|
-
if (pendingRead === value)
|
|
431
|
-
pendingRead = null;
|
|
432
|
-
});
|
|
433
|
-
return;
|
|
434
|
-
}
|
|
435
|
-
if (value === undefined)
|
|
436
|
-
return;
|
|
437
|
-
setDiffDeepBypassRef($from, deepCopy(value));
|
|
438
|
-
};
|
|
439
|
-
syncFromTarget();
|
|
440
|
-
if (mirrorOnly) {
|
|
441
|
-
mirrorObserver = observe(() => {
|
|
442
|
-
syncFromTarget();
|
|
443
|
-
return readRefValue($to);
|
|
444
|
-
}, {
|
|
445
|
-
scheduler: job => job()
|
|
446
|
-
});
|
|
447
|
-
// initialize dependency graph
|
|
448
|
-
mirrorObserver();
|
|
449
|
-
}
|
|
450
|
-
return {
|
|
451
|
-
onChange: syncFromTarget,
|
|
452
|
-
stop: () => {
|
|
453
|
-
disposed = true;
|
|
454
|
-
if (mirrorObserver)
|
|
455
|
-
unobserve(mirrorObserver);
|
|
456
|
-
// Subsequent sync happens directly at mutation time via mirrorRefMutationFromTarget().
|
|
457
|
-
}
|
|
458
|
-
};
|
|
459
|
-
}
|
|
460
|
-
function readRefValue($signal) {
|
|
461
|
-
try {
|
|
462
|
-
return $signal.get();
|
|
463
|
-
}
|
|
464
|
-
catch (err) {
|
|
465
|
-
if (isThenable(err))
|
|
466
|
-
return err;
|
|
467
|
-
throw err;
|
|
468
|
-
}
|
|
469
253
|
}
|
|
470
254
|
function isAggregationValuePath(segments) {
|
|
471
255
|
return Array.isArray(segments) &&
|
|
472
256
|
segments.length >= 3 &&
|
|
473
257
|
segments[0] === AGGREGATIONS;
|
|
474
258
|
}
|
|
475
|
-
function resolveRefSignal($signal) {
|
|
476
|
-
const directTarget = resolveRefSignalSafe($signal);
|
|
477
|
-
if (directTarget && directTarget !== $signal)
|
|
478
|
-
return directTarget;
|
|
479
|
-
const resolvedSegments = resolveRefSegmentsSafe($signal[SEGMENTS], (getRoot($signal) || $signal)?.[ROOT_ID]);
|
|
480
|
-
if (!resolvedSegments)
|
|
481
|
-
return $signal;
|
|
482
|
-
const $root = getRoot($signal) || $signal;
|
|
483
|
-
return resolveSignal($root, resolvedSegments);
|
|
484
|
-
}
|
|
485
|
-
function forwardRef($signal, methodName, args) {
|
|
486
|
-
const $target = resolveRefSignal($signal);
|
|
487
|
-
if ($target === $signal)
|
|
488
|
-
return null;
|
|
489
|
-
return SignalCompat.prototype[methodName].apply($target, args);
|
|
490
|
-
}
|
|
491
|
-
function setDiffDeepBypassRef($signal, value) {
|
|
492
|
-
const segments = $signal[SEGMENTS];
|
|
493
|
-
if (isPublicCollection(segments[0]))
|
|
494
|
-
return Signal.prototype.set.call($signal, value);
|
|
495
|
-
return setReplacePrivateData(getOwningRootId($signal), segments, value);
|
|
496
|
-
}
|
|
497
|
-
function mirrorRefMutationFromTarget(targetSegments, value) {
|
|
498
|
-
if (!Array.isArray(targetSegments) || targetSegments.length === 0)
|
|
499
|
-
return;
|
|
500
|
-
const updates = [];
|
|
501
|
-
for (const link of getAllRefLinks()) {
|
|
502
|
-
if (!isPathPrefix(link.toSegments, targetSegments))
|
|
503
|
-
continue;
|
|
504
|
-
const suffix = targetSegments.slice(link.toSegments.length);
|
|
505
|
-
updates.push({
|
|
506
|
-
fromRootId: link.fromRootId,
|
|
507
|
-
segments: link.fromSegments.concat(suffix),
|
|
508
|
-
value: deepCopy(value)
|
|
509
|
-
});
|
|
510
|
-
}
|
|
511
|
-
if (!updates.length)
|
|
512
|
-
return;
|
|
513
|
-
runInModelEventsSilentContext(() => {
|
|
514
|
-
for (const update of updates) {
|
|
515
|
-
const $root = getRootSignal({
|
|
516
|
-
rootId: update.fromRootId || GLOBAL_ROOT_ID,
|
|
517
|
-
rootFunction: universal$
|
|
518
|
-
});
|
|
519
|
-
const $target = resolveSignal($root, update.segments);
|
|
520
|
-
setDiffDeepBypassRef($target, update.value);
|
|
521
|
-
}
|
|
522
|
-
});
|
|
523
|
-
}
|
|
524
|
-
function isPathPrefix(prefixSegments, fullSegments) {
|
|
525
|
-
if (prefixSegments.length > fullSegments.length)
|
|
526
|
-
return false;
|
|
527
|
-
for (let i = 0; i < prefixSegments.length; i++) {
|
|
528
|
-
if (String(prefixSegments[i]) !== String(fullSegments[i]))
|
|
529
|
-
return false;
|
|
530
|
-
}
|
|
531
|
-
return true;
|
|
532
|
-
}
|
|
533
|
-
function isSignalLike(value) {
|
|
534
|
-
return value && typeof value.path === 'function' && typeof value.get === 'function';
|
|
535
|
-
}
|
|
536
259
|
function isReactLike(value) {
|
|
537
260
|
return !!(value && typeof value === 'object' && typeof value.$$typeof === 'symbol');
|
|
538
261
|
}
|
|
539
|
-
function isThenable(value) {
|
|
540
|
-
return !!value && typeof value.then === 'function';
|
|
541
|
-
}
|
|
542
|
-
function resolveRefTarget($signal, target, methodName) {
|
|
543
|
-
if (isSignalLike(target))
|
|
544
|
-
return target;
|
|
545
|
-
if (typeof target === 'string') {
|
|
546
|
-
const segments = parseAtSubpath(target, 1, methodName);
|
|
547
|
-
const $root = getRoot($signal) || $signal;
|
|
548
|
-
return resolveSignal($root, segments);
|
|
549
|
-
}
|
|
550
|
-
return undefined;
|
|
551
|
-
}
|
|
552
|
-
function parseAtSubpath(subpath, argsLength, methodName) {
|
|
553
|
-
if (argsLength === 0)
|
|
554
|
-
return [];
|
|
555
|
-
if (typeof subpath === 'string')
|
|
556
|
-
return subpath.split('.').filter(Boolean);
|
|
557
|
-
if (typeof subpath === 'number' && Number.isFinite(subpath) && Number.isInteger(subpath))
|
|
558
|
-
return [subpath];
|
|
559
|
-
throw Error(`${methodName} expects a string or integer argument`);
|
|
560
|
-
}
|
|
561
262
|
function resolveSignal($signal, segments) {
|
|
562
263
|
let $cursor = $signal;
|
|
563
264
|
for (const segment of segments) {
|
|
@@ -716,9 +417,6 @@ function setReplacePrivateCompatSync($signal, value) {
|
|
|
716
417
|
value = normalizeIdFields(value, idFields, segments[1]);
|
|
717
418
|
}
|
|
718
419
|
setReplacePrivateData(getOwningRootId($signal), segments, value);
|
|
719
|
-
if (shouldMirrorPrivateRefMutationLocally()) {
|
|
720
|
-
mirrorRefMutationFromTarget(segments, value);
|
|
721
|
-
}
|
|
722
420
|
}
|
|
723
421
|
function delPrivateCompatSync($signal, options) {
|
|
724
422
|
const segments = $signal[SEGMENTS];
|
|
@@ -775,17 +473,9 @@ async function setReplaceOnSignal($signal, value) {
|
|
|
775
473
|
value = normalizeIdFields(value, idFields, segments[1]);
|
|
776
474
|
}
|
|
777
475
|
if (isPublicCollection(segments[0])) {
|
|
778
|
-
|
|
779
|
-
if (shouldMirrorPublicRefMutationLocally(segments)) {
|
|
780
|
-
mirrorRefMutationFromTarget(segments, value);
|
|
781
|
-
}
|
|
782
|
-
return result;
|
|
476
|
+
return _setPublicDocReplace(segments, value);
|
|
783
477
|
}
|
|
784
|
-
|
|
785
|
-
if (shouldMirrorPrivateRefMutationLocally()) {
|
|
786
|
-
mirrorRefMutationFromTarget(segments, value);
|
|
787
|
-
}
|
|
788
|
-
return result;
|
|
478
|
+
return setReplacePrivateData(getOwningRootId($signal), segments, value);
|
|
789
479
|
}
|
|
790
480
|
async function incrementOnSignal($signal, byNumber) {
|
|
791
481
|
const segments = $signal[SEGMENTS];
|
|
@@ -911,28 +601,6 @@ function getOwningRootId($signal) {
|
|
|
911
601
|
const $root = getRoot($signal) || $signal;
|
|
912
602
|
return $root?.[ROOT_ID];
|
|
913
603
|
}
|
|
914
|
-
function ensurePrivateRefSource($signal, methodName) {
|
|
915
|
-
const segments = $signal?.[SEGMENTS];
|
|
916
|
-
const collection = segments?.[0];
|
|
917
|
-
if (typeof collection === 'string' && /^[_$]/.test(collection))
|
|
918
|
-
return;
|
|
919
|
-
throw Error(`${methodName} source path must be in a private collection`);
|
|
920
|
-
}
|
|
921
|
-
function shouldMirrorPublicRefMutationLocally(segments) {
|
|
922
|
-
if (isSilentContextActive())
|
|
923
|
-
return true;
|
|
924
|
-
if (!Array.isArray(segments) || segments.length < 2)
|
|
925
|
-
return true;
|
|
926
|
-
// Public doc ops emit compat model events only when there is an initialized
|
|
927
|
-
// Doc runtime (subscribed/fetched). Without runtime we must mirror immediately.
|
|
928
|
-
const transportHash = JSON.stringify([segments[0], segments[1]]);
|
|
929
|
-
return !docSubscriptions.hasRuntime(transportHash);
|
|
930
|
-
}
|
|
931
|
-
function shouldMirrorPrivateRefMutationLocally() {
|
|
932
|
-
if (isSilentContextActive())
|
|
933
|
-
return true;
|
|
934
|
-
return !isModelEventsEnabled();
|
|
935
|
-
}
|
|
936
604
|
function shallowCopy(value) {
|
|
937
605
|
const rawValue = raw(value);
|
|
938
606
|
if (Array.isArray(rawValue))
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
import { getRefLinks, getRefRootIds } from './refRegistry.js';
|
|
2
1
|
import { isCompatEnv } from '../compatEnv.js';
|
|
3
|
-
import { isSilentContextActive, isModelEventsSilentContextActive
|
|
2
|
+
import { isSilentContextActive, isModelEventsSilentContextActive } from './silentContext.js';
|
|
4
3
|
import { normalizeRootId } from "../rootScope.js";
|
|
5
4
|
import { getRootContext, getRootContexts } from "../rootContext.js";
|
|
6
|
-
import { setReplace as setReplaceInDataTree, del as delFromDataTree } from '../dataTree.js';
|
|
7
|
-
import { setReplacePrivateData, delPrivateData } from '../privateData.js';
|
|
8
5
|
const MODEL_EVENT_NAMES = ['change', 'all'];
|
|
9
6
|
export function isModelEventsEnabled() {
|
|
10
7
|
return isCompatEnv();
|
|
@@ -57,32 +54,8 @@ export function emitModelChange(path, value, prevValue, meta) {
|
|
|
57
54
|
const eventName = meta?.eventName || 'change';
|
|
58
55
|
const rootIds = getTargetRootIds(meta?.rootId);
|
|
59
56
|
for (const rootId of rootIds) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
while (queue.length) {
|
|
63
|
-
const segments = queue.shift();
|
|
64
|
-
const key = segments.join('.');
|
|
65
|
-
if (visited.has(key))
|
|
66
|
-
continue;
|
|
67
|
-
visited.add(key);
|
|
68
|
-
emitForEvent(rootId, 'change', segments, value, prevValue, meta);
|
|
69
|
-
emitForEvent(rootId, 'all', segments, value, prevValue, meta, eventName);
|
|
70
|
-
for (const link of getRefLinks(rootId).values()) {
|
|
71
|
-
if (!isPathPrefix(link.toSegments, segments))
|
|
72
|
-
continue;
|
|
73
|
-
if (link.mirrorOnly && typeof link.onChange === 'function') {
|
|
74
|
-
link.onChange();
|
|
75
|
-
}
|
|
76
|
-
else if (!link.mirrorOnly) {
|
|
77
|
-
mirrorRefAliasFromTargetSegments(rootId, link, segments, value, meta);
|
|
78
|
-
}
|
|
79
|
-
const suffix = segments.slice(link.toSegments.length);
|
|
80
|
-
const nextSegments = link.fromSegments.concat(suffix);
|
|
81
|
-
const nextKey = nextSegments.join('.');
|
|
82
|
-
if (!visited.has(nextKey))
|
|
83
|
-
queue.push(nextSegments);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
57
|
+
emitForEvent(rootId, 'change', initialSegments, value, prevValue, meta);
|
|
58
|
+
emitForEvent(rootId, 'all', initialSegments, value, prevValue, meta, eventName);
|
|
86
59
|
}
|
|
87
60
|
}
|
|
88
61
|
export function __resetModelEventsForTests() {
|
|
@@ -113,51 +86,6 @@ function splitPattern(pattern) {
|
|
|
113
86
|
return [];
|
|
114
87
|
return pattern.split('.').filter(Boolean);
|
|
115
88
|
}
|
|
116
|
-
function mirrorRefAliasFromTargetSegments(rootId, link, targetSegments, value, meta) {
|
|
117
|
-
const suffix = targetSegments.slice(link.toSegments.length);
|
|
118
|
-
const fromSegments = link.fromSegments.concat(suffix);
|
|
119
|
-
const fromRootId = normalizeRootId(link.fromRootId ?? rootId);
|
|
120
|
-
const shouldDelete = shouldDeleteMirroredPath(value, meta);
|
|
121
|
-
runInModelEventsSilentContext(() => {
|
|
122
|
-
if (isPrivateSegments(fromSegments)) {
|
|
123
|
-
if (shouldDelete) {
|
|
124
|
-
delPrivateData(fromRootId, fromSegments);
|
|
125
|
-
}
|
|
126
|
-
else {
|
|
127
|
-
setReplacePrivateData(fromRootId, fromSegments, cloneValue(value));
|
|
128
|
-
}
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
if (shouldDelete) {
|
|
132
|
-
delFromDataTree(fromSegments);
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
setReplaceInDataTree(fromSegments, cloneValue(value));
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
function isPrivateSegments(segments) {
|
|
139
|
-
if (!Array.isArray(segments) || !segments.length)
|
|
140
|
-
return false;
|
|
141
|
-
return /^[_$]/.test(String(segments[0]));
|
|
142
|
-
}
|
|
143
|
-
function shouldDeleteMirroredPath(value, meta) {
|
|
144
|
-
if (meta?.op === 'setReplace')
|
|
145
|
-
return false;
|
|
146
|
-
if (meta?.op === 'del')
|
|
147
|
-
return true;
|
|
148
|
-
return value === undefined;
|
|
149
|
-
}
|
|
150
|
-
function cloneValue(value) {
|
|
151
|
-
if (Array.isArray(value))
|
|
152
|
-
return value.map(cloneValue);
|
|
153
|
-
if (value && typeof value === 'object') {
|
|
154
|
-
const cloned = {};
|
|
155
|
-
for (const key of Object.keys(value))
|
|
156
|
-
cloned[key] = cloneValue(value[key]);
|
|
157
|
-
return cloned;
|
|
158
|
-
}
|
|
159
|
-
return value;
|
|
160
|
-
}
|
|
161
89
|
function getModelEventRootStore(eventName, rootId, create = false) {
|
|
162
90
|
return getRootContext(normalizeRootId(rootId), create)?.getModelEventStore(eventName, create);
|
|
163
91
|
}
|
|
@@ -174,11 +102,7 @@ function getModelEventRootIds() {
|
|
|
174
102
|
function getTargetRootIds(rootId) {
|
|
175
103
|
if (rootId != null)
|
|
176
104
|
return [normalizeRootId(rootId)];
|
|
177
|
-
|
|
178
|
-
...getModelEventRootIds(),
|
|
179
|
-
...getRefRootIds()
|
|
180
|
-
]);
|
|
181
|
-
return rootIds;
|
|
105
|
+
return getModelEventRootIds();
|
|
182
106
|
}
|
|
183
107
|
function splitPath(path) {
|
|
184
108
|
if (Array.isArray(path))
|
|
@@ -187,15 +111,6 @@ function splitPath(path) {
|
|
|
187
111
|
return [];
|
|
188
112
|
return String(path).split('.').filter(Boolean);
|
|
189
113
|
}
|
|
190
|
-
function isPathPrefix(prefixSegments, fullSegments) {
|
|
191
|
-
if (prefixSegments.length > fullSegments.length)
|
|
192
|
-
return false;
|
|
193
|
-
for (let i = 0; i < prefixSegments.length; i++) {
|
|
194
|
-
if (prefixSegments[i] !== fullSegments[i])
|
|
195
|
-
return false;
|
|
196
|
-
}
|
|
197
|
-
return true;
|
|
198
|
-
}
|
|
199
114
|
function matchPattern(patternSegments, pathSegments) {
|
|
200
115
|
function walk(patternIndex, pathIndex) {
|
|
201
116
|
if (patternIndex === patternSegments.length) {
|
package/dist/orm/SignalBase.js
CHANGED
|
@@ -22,8 +22,6 @@ import { IS_QUERY, HASH, QUERIES } from './Query.js';
|
|
|
22
22
|
import { AGGREGATIONS, IS_AGGREGATION, getAggregationCollectionName, getAggregationDocId } from './Aggregation.js';
|
|
23
23
|
import { ROOT_FUNCTION, ROOT_ID, closeRootSignal, getRoot } from "./Root.js";
|
|
24
24
|
import { getDefaultIdFields, getIdFieldsForSegments, isIdFieldPath, isPlainObject, isPublicDocPath, normalizeIdFields, prepareAddPayload, resolveAddDocId } from "./idFields.js";
|
|
25
|
-
import { isCompatEnv } from './compatEnv.js';
|
|
26
|
-
import { resolveRefSegmentsSafe, resolveRefSignalSafe } from './Compat/refFallback.js';
|
|
27
25
|
import { runInBatch } from './batchScheduler.js';
|
|
28
26
|
import { isPublicCollection } from "./signalPathKind.js";
|
|
29
27
|
import { ARRAY_METHOD, DEFAULT_GETTERS, GET, GETTERS, SEGMENTS } from "./signalSymbols.js";
|
|
@@ -781,7 +779,7 @@ export const regularBindings = {
|
|
|
781
779
|
}
|
|
782
780
|
};
|
|
783
781
|
const QUERY_METHODS = ['map', 'reduce', 'find', 'get', 'getIds', 'getExtra', 'fetch', 'unfetch'];
|
|
784
|
-
const AGGREGATION_ALLOWED_METHODS = ['fetch', 'unfetch'
|
|
782
|
+
const AGGREGATION_ALLOWED_METHODS = ['fetch', 'unfetch'];
|
|
785
783
|
// dot syntax always returns a child signal even if such method or property exists.
|
|
786
784
|
// The method is only called when the signal is explicitly called as a function,
|
|
787
785
|
// in which case we get the original method from the raw (non-proxied) parent signal
|
|
@@ -834,25 +832,6 @@ export const extremelyLateBindings = {
|
|
|
834
832
|
const rawParent = rawSignal($parent);
|
|
835
833
|
if (key in rawParent)
|
|
836
834
|
return Reflect.apply(rawParent[key], $parent, argumentsList);
|
|
837
|
-
if (isCompatEnv()) {
|
|
838
|
-
const $resolvedParent = resolveRefSignalSafe($parent);
|
|
839
|
-
if ($resolvedParent && $resolvedParent !== $parent) {
|
|
840
|
-
const rawResolvedParent = rawSignal($resolvedParent);
|
|
841
|
-
if (rawResolvedParent && key in rawResolvedParent) {
|
|
842
|
-
return Reflect.apply(rawResolvedParent[key], $resolvedParent, argumentsList);
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
else {
|
|
846
|
-
const resolvedSegments = resolveRefSegmentsSafe(segments, (getRoot(signal) || signal)?.[ROOT_ID]);
|
|
847
|
-
if (resolvedSegments) {
|
|
848
|
-
const $resolvedByPath = getSignal(getRoot(signal), resolvedSegments);
|
|
849
|
-
const rawResolvedByPath = rawSignal($resolvedByPath);
|
|
850
|
-
if (rawResolvedByPath && key in rawResolvedByPath) {
|
|
851
|
-
return Reflect.apply(rawResolvedByPath[key], $resolvedByPath, argumentsList);
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
835
|
throw Error(ERRORS.noSignalKey($parent, key));
|
|
857
836
|
},
|
|
858
837
|
get(signal, key, receiver) {
|
|
@@ -27,8 +27,6 @@ async function runDispose(rootId) {
|
|
|
27
27
|
const context = getRootContext(rootId, false);
|
|
28
28
|
if (!context)
|
|
29
29
|
return;
|
|
30
|
-
stopActiveRefs(context);
|
|
31
|
-
context.resetRefs();
|
|
32
30
|
context.resetModelListeners();
|
|
33
31
|
for (const transportHash of Array.from(context.queryRuntimeHashes)) {
|
|
34
32
|
await querySubscriptions.destroyByRuntimeHash(transportHash, { rootId, force: true });
|
|
@@ -43,17 +41,6 @@ async function runDispose(rootId) {
|
|
|
43
41
|
context.resetDirectDocSubscriptions();
|
|
44
42
|
deleteRootContext(rootId);
|
|
45
43
|
}
|
|
46
|
-
function stopActiveRefs(context) {
|
|
47
|
-
for (const entry of context.activeRefs.values()) {
|
|
48
|
-
try {
|
|
49
|
-
entry?.stop?.();
|
|
50
|
-
}
|
|
51
|
-
catch (err) {
|
|
52
|
-
console.error(err);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
context.resetActiveRefs();
|
|
56
|
-
}
|
|
57
44
|
export function __resetPendingRootDisposesForTests() {
|
|
58
45
|
PENDING_DISPOSES.clear();
|
|
59
46
|
}
|
package/dist/orm/getSignal.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export interface GetSignalOptions {
|
|
|
10
10
|
}
|
|
11
11
|
declare const PROXIES_CACHE: Cache<RootSignalRuntime>;
|
|
12
12
|
export default function getSignal($root?: RootSignalRuntime, segments?: PathSegment[], { useExtremelyLateBindings, rootId, signalHash, proxyHandlers }?: GetSignalOptions): RootSignalRuntime;
|
|
13
|
-
export declare function getSignalClass(segments: PathSegment[],
|
|
13
|
+
export declare function getSignalClass(segments: PathSegment[], _rootId?: string): SignalModelConstructor;
|
|
14
14
|
export declare function rawSignal(proxy: unknown): RootSignalRuntime | undefined;
|
|
15
15
|
export { PROXIES_CACHE as __DEBUG_SIGNALS_CACHE__ };
|
|
16
16
|
export declare function purgeSignalHashes(hashes: Iterable<string>): void;
|
package/dist/orm/getSignal.js
CHANGED
|
@@ -5,8 +5,6 @@ import { LOCAL } from './$.js';
|
|
|
5
5
|
import { ROOT, ROOT_ID, GLOBAL_ROOT_ID } from "./Root.js";
|
|
6
6
|
import { QUERIES } from './Query.js';
|
|
7
7
|
import { AGGREGATIONS } from './Aggregation.js';
|
|
8
|
-
import { isCompatEnv } from './compatEnv.js';
|
|
9
|
-
import { resolveRefSegmentsSafe } from './Compat/refFallback.js';
|
|
10
8
|
import { getSignalIdentityHash } from "./rootScope.js";
|
|
11
9
|
import { isRootContextClosed, registerRootOwnedSignalHash } from "./rootContext.js";
|
|
12
10
|
const PROXIES_CACHE = new Cache();
|
|
@@ -81,18 +79,10 @@ export default function getSignal($root, segments = [], { useExtremelyLateBindin
|
|
|
81
79
|
function getDefaultProxyHandlers({ useExtremelyLateBindings } = {}) {
|
|
82
80
|
return (useExtremelyLateBindings ? extremelyLateBindings : regularBindings);
|
|
83
81
|
}
|
|
84
|
-
export function getSignalClass(segments,
|
|
85
|
-
|
|
82
|
+
export function getSignalClass(segments, _rootId = GLOBAL_ROOT_ID) {
|
|
83
|
+
const Model = findModel(segments);
|
|
86
84
|
if (Model)
|
|
87
85
|
return Model;
|
|
88
|
-
if (!isCompatEnv())
|
|
89
|
-
return Signal;
|
|
90
|
-
const dereferencedSegments = resolveRefSegmentsSafe(segments, rootId);
|
|
91
|
-
if (dereferencedSegments) {
|
|
92
|
-
Model = findModel(dereferencedSegments);
|
|
93
|
-
if (Model)
|
|
94
|
-
return Model;
|
|
95
|
-
}
|
|
96
86
|
return Signal;
|
|
97
87
|
}
|
|
98
88
|
export function rawSignal(proxy) {
|
|
@@ -3,9 +3,6 @@ type RootId = string | null | undefined;
|
|
|
3
3
|
type DataTree = Record<string | number, unknown>;
|
|
4
4
|
type RuntimeKind = 'query' | 'aggregation';
|
|
5
5
|
type ModelEventStore = Map<string, unknown>;
|
|
6
|
-
type ActiveRefEntry = {
|
|
7
|
-
stop?: () => void;
|
|
8
|
-
};
|
|
9
6
|
interface RootContextOptions {
|
|
10
7
|
fetchOnly?: boolean;
|
|
11
8
|
}
|
|
@@ -24,8 +21,6 @@ export default class RootContext {
|
|
|
24
21
|
fetchOnly: boolean;
|
|
25
22
|
privateDataRaw: DataTree;
|
|
26
23
|
privateData: DataTree;
|
|
27
|
-
readonly refLinks: Map<string, unknown>;
|
|
28
|
-
readonly activeRefs: Map<string, ActiveRefEntry>;
|
|
29
24
|
readonly modelListeners: ModelListeners;
|
|
30
25
|
readonly queryRuntimeHashes: Set<string>;
|
|
31
26
|
readonly aggregationRuntimeHashes: Set<string>;
|
|
@@ -48,8 +43,6 @@ export default class RootContext {
|
|
|
48
43
|
unregisterSignalHash(signalHash: string | null | undefined): void;
|
|
49
44
|
registerDirectDocSubscription(hash: string | null | undefined, segments: readonly PathSegment[], token?: unknown): void;
|
|
50
45
|
unregisterDirectDocSubscription(hash: string | null | undefined, token?: unknown): void;
|
|
51
|
-
resetRefs(): void;
|
|
52
|
-
resetActiveRefs(): void;
|
|
53
46
|
resetModelListeners(): void;
|
|
54
47
|
resetRuntimeHashes(): void;
|
|
55
48
|
resetPrivateData(): void;
|
package/dist/orm/rootContext.js
CHANGED
|
@@ -12,8 +12,6 @@ export default class RootContext {
|
|
|
12
12
|
fetchOnly;
|
|
13
13
|
privateDataRaw;
|
|
14
14
|
privateData;
|
|
15
|
-
refLinks = new Map();
|
|
16
|
-
activeRefs = new Map();
|
|
17
15
|
modelListeners = {
|
|
18
16
|
change: new Map(),
|
|
19
17
|
all: new Map()
|
|
@@ -124,12 +122,6 @@ export default class RootContext {
|
|
|
124
122
|
if (entry.count === 0)
|
|
125
123
|
this.directDocSubscriptions.delete(hash);
|
|
126
124
|
}
|
|
127
|
-
resetRefs() {
|
|
128
|
-
this.refLinks.clear();
|
|
129
|
-
}
|
|
130
|
-
resetActiveRefs() {
|
|
131
|
-
this.activeRefs.clear();
|
|
132
|
-
}
|
|
133
125
|
resetModelListeners() {
|
|
134
126
|
for (const store of Object.values(this.modelListeners)) {
|
|
135
127
|
store.clear();
|
|
@@ -151,8 +143,6 @@ export default class RootContext {
|
|
|
151
143
|
}
|
|
152
144
|
isRuntimeEmpty() {
|
|
153
145
|
return (isPlainObjectEmpty(this.privateData) &&
|
|
154
|
-
this.refLinks.size === 0 &&
|
|
155
|
-
this.activeRefs.size === 0 &&
|
|
156
146
|
Object.values(this.modelListeners).every(store => store.size === 0) &&
|
|
157
147
|
this.queryRuntimeHashes.size === 0 &&
|
|
158
148
|
this.aggregationRuntimeHashes.size === 0 &&
|
package/package.json
CHANGED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { PathSegment } from '../types/path.js'
|
|
2
|
-
import type { SignalBaseInstance } from '../Signal.js'
|
|
3
|
-
|
|
4
|
-
export const REF_TARGET: unique symbol
|
|
5
|
-
export function resolveRefSignalSafe<TSignal extends SignalBaseInstance> (
|
|
6
|
-
$signal: TSignal | undefined,
|
|
7
|
-
maxDepth?: number
|
|
8
|
-
): TSignal | undefined
|
|
9
|
-
export function resolveRefSegmentsSafe (
|
|
10
|
-
segments: readonly PathSegment[],
|
|
11
|
-
rootId?: string,
|
|
12
|
-
maxDepth?: number
|
|
13
|
-
): PathSegment[] | undefined
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { getRefLinks } from './refRegistry.js';
|
|
2
|
-
import { GLOBAL_ROOT_ID } from "../Root.js";
|
|
3
|
-
export const REF_TARGET = Symbol.for('teamplay.compat.refTarget');
|
|
4
|
-
export function resolveRefSignalSafe($signal, maxDepth = 32) {
|
|
5
|
-
let current = $signal;
|
|
6
|
-
const seen = new Set();
|
|
7
|
-
for (let i = 0; i < maxDepth; i++) {
|
|
8
|
-
if (!current)
|
|
9
|
-
return undefined;
|
|
10
|
-
const next = current[REF_TARGET];
|
|
11
|
-
if (!next)
|
|
12
|
-
return current;
|
|
13
|
-
if (seen.has(current))
|
|
14
|
-
return undefined;
|
|
15
|
-
seen.add(current);
|
|
16
|
-
current = next;
|
|
17
|
-
}
|
|
18
|
-
return undefined;
|
|
19
|
-
}
|
|
20
|
-
export function resolveRefSegmentsSafe(segments, rootId = GLOBAL_ROOT_ID, maxDepth = 32) {
|
|
21
|
-
if (!Array.isArray(segments) || segments.length === 0)
|
|
22
|
-
return undefined;
|
|
23
|
-
let current = [...segments];
|
|
24
|
-
const visited = new Set([toPathKey(current)]);
|
|
25
|
-
let changed = false;
|
|
26
|
-
for (let i = 0; i < maxDepth; i++) {
|
|
27
|
-
const link = findBestMatchingLink(current, rootId);
|
|
28
|
-
if (!link)
|
|
29
|
-
return changed ? current : undefined;
|
|
30
|
-
const suffix = current.slice(link.fromSegments.length);
|
|
31
|
-
const next = link.toSegments.concat(suffix);
|
|
32
|
-
const key = toPathKey(next);
|
|
33
|
-
if (visited.has(key))
|
|
34
|
-
return undefined;
|
|
35
|
-
visited.add(key);
|
|
36
|
-
current = next;
|
|
37
|
-
changed = true;
|
|
38
|
-
}
|
|
39
|
-
return undefined;
|
|
40
|
-
}
|
|
41
|
-
function findBestMatchingLink(segments, rootId) {
|
|
42
|
-
let best;
|
|
43
|
-
for (const link of getRefLinks(rootId).values()) {
|
|
44
|
-
if (link.mirrorOnly)
|
|
45
|
-
continue;
|
|
46
|
-
if (!isPathPrefix(link.fromSegments, segments))
|
|
47
|
-
continue;
|
|
48
|
-
if (!best || link.fromSegments.length > best.fromSegments.length) {
|
|
49
|
-
best = link;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return best;
|
|
53
|
-
}
|
|
54
|
-
function isPathPrefix(prefixSegments, fullSegments) {
|
|
55
|
-
if (prefixSegments.length > fullSegments.length)
|
|
56
|
-
return false;
|
|
57
|
-
for (let i = 0; i < prefixSegments.length; i++) {
|
|
58
|
-
if (prefixSegments[i] !== String(fullSegments[i]))
|
|
59
|
-
return false;
|
|
60
|
-
}
|
|
61
|
-
return true;
|
|
62
|
-
}
|
|
63
|
-
function toPathKey(segments) {
|
|
64
|
-
return segments.map(segment => String(segment)).join('.');
|
|
65
|
-
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export function setRefLink(rootId: any, fromPath: any, toPath: any, fromSegments: any, toSegments: any, options?: {}): void;
|
|
2
|
-
export function removeRefLink(rootId: any, fromPath: any): void;
|
|
3
|
-
export function getRefLinks(rootId?: string): Map<string, unknown>;
|
|
4
|
-
export function getAllRefLinks(): Generator<unknown, void, unknown>;
|
|
5
|
-
export function getRefRootIds(): string[];
|
|
6
|
-
export function __resetRefLinksForTests(): void;
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { GLOBAL_ROOT_ID } from "../Root.js";
|
|
2
|
-
import { normalizeRootId } from "../rootScope.js";
|
|
3
|
-
import { getRootContext, getRootContexts } from "../rootContext.js";
|
|
4
|
-
const EMPTY_MAP = new Map();
|
|
5
|
-
export function setRefLink(rootId, fromPath, toPath, fromSegments, toSegments, options = {}) {
|
|
6
|
-
if (typeof fromPath !== 'string' || typeof toPath !== 'string')
|
|
7
|
-
return;
|
|
8
|
-
const normalizedFromSegments = Array.isArray(fromSegments)
|
|
9
|
-
? fromSegments.map(segment => String(segment))
|
|
10
|
-
: splitPath(fromPath);
|
|
11
|
-
const normalizedToSegments = Array.isArray(toSegments)
|
|
12
|
-
? toSegments.map(segment => String(segment))
|
|
13
|
-
: splitPath(toPath);
|
|
14
|
-
getRefStore(rootId, true).set(fromPath, {
|
|
15
|
-
fromPath,
|
|
16
|
-
toPath,
|
|
17
|
-
fromSegments: normalizedFromSegments,
|
|
18
|
-
toSegments: normalizedToSegments,
|
|
19
|
-
fromRootId: normalizeRootId(rootId),
|
|
20
|
-
toRootId: options.toRootId,
|
|
21
|
-
mirrorOnly: !!options.mirrorOnly,
|
|
22
|
-
onChange: typeof options.onChange === 'function' ? options.onChange : undefined
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
export function removeRefLink(rootId, fromPath) {
|
|
26
|
-
const store = getRefStore(rootId);
|
|
27
|
-
if (!store)
|
|
28
|
-
return;
|
|
29
|
-
store.delete(fromPath);
|
|
30
|
-
}
|
|
31
|
-
export function getRefLinks(rootId = GLOBAL_ROOT_ID) {
|
|
32
|
-
return getRefStore(rootId) || EMPTY_MAP;
|
|
33
|
-
}
|
|
34
|
-
export function* getAllRefLinks() {
|
|
35
|
-
for (const context of getRootContexts()) {
|
|
36
|
-
yield* context.refLinks.values();
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
export function getRefRootIds() {
|
|
40
|
-
return Array.from(getRootContexts())
|
|
41
|
-
.filter(context => context.refLinks.size > 0)
|
|
42
|
-
.map(context => context.rootId);
|
|
43
|
-
}
|
|
44
|
-
export function __resetRefLinksForTests() {
|
|
45
|
-
for (const context of getRootContexts()) {
|
|
46
|
-
context.resetRefs();
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
function splitPath(path) {
|
|
50
|
-
return path.split('.').filter(Boolean);
|
|
51
|
-
}
|
|
52
|
-
function getRefStore(rootId, create = false) {
|
|
53
|
-
return getRootContext(normalizeRootId(rootId), create)?.refLinks;
|
|
54
|
-
}
|