teamplay 0.5.0-alpha.5 → 0.5.0-alpha.7

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/index.d.ts CHANGED
@@ -52,8 +52,6 @@ export { defineModels, default as initModels, getModels, resetModelsForTests } f
52
52
  export { default as signal } from './orm/getSignal.js';
53
53
  export { GLOBAL_ROOT_ID } from './orm/Root.js';
54
54
  export declare const $: RootSignal;
55
- export declare const $root: RootSignal;
56
- export declare const model: RootSignal;
57
55
  export default $;
58
56
  export { default as sub } from './orm/sub.js';
59
57
  export { default as useSub, useAsyncSub, setUseDeferredValue as __setUseDeferredValue, setDefaultDefer as __setDefaultDefer } from './react/useSub.js';
package/dist/index.js CHANGED
@@ -13,8 +13,6 @@ export { default as signal } from "./orm/getSignal.js";
13
13
  export { GLOBAL_ROOT_ID } from "./orm/Root.js";
14
14
  const getRuntimeRootSignal = _getRootSignal;
15
15
  export const $ = getRuntimeRootSignal({ rootId: GLOBAL_ROOT_ID, rootFunction: universal$ });
16
- export const $root = $;
17
- export const model = $;
18
16
  export default $;
19
17
  export { default as sub } from "./orm/sub.js";
20
18
  export { default as useSub, useAsyncSub, setUseDeferredValue as __setUseDeferredValue, setDefaultDefer as __setDefaultDefer } from "./react/useSub.js";
@@ -21,27 +21,14 @@ import disposeRootContext from "../disposeRootContext.js";
21
21
  import { arrayInsertPrivateData, arrayMovePrivateData, arrayPopPrivateData, arrayPushPrivateData, arrayRemovePrivateData, arrayShiftPrivateData, arrayUnshiftPrivateData, delPrivateData, setReplacePrivateData, stringInsertPrivateData, stringRemovePrivateData } from '../privateData.js';
22
22
  class SignalCompat extends Signal {
23
23
  static ID_FIELDS = ['_id', 'id'];
24
- static [GETTERS] = [...DEFAULT_GETTERS, 'at', 'scope', 'getCopy', 'getDeepCopy'];
24
+ static [GETTERS] = [...DEFAULT_GETTERS, 'getCopy', 'getDeepCopy'];
25
25
  get root() {
26
- return this.scope();
26
+ return getRoot(this) || this;
27
27
  }
28
- path(subpath) {
29
- if (arguments.length > 1)
30
- throw Error('Signal.path() expects a single argument');
31
- if (arguments.length === 0)
32
- return super.path();
33
- const segments = parseAtSubpath(subpath, arguments.length, 'Signal.path()');
34
- if (segments.length === 0)
35
- return super.path();
36
- return [...this[SEGMENTS], ...segments].join('.');
37
- }
38
- at(subpath) {
39
- const segments = arguments.length > 1
40
- ? parseAtSegments(arguments, 'Signal.at()')
41
- : parseAtSubpath(subpath, arguments.length, 'Signal.at()');
42
- if (segments.length === 0)
43
- return this;
44
- return resolveRelativePathTarget(this, segments);
28
+ path() {
29
+ if (arguments.length > 0)
30
+ throw Error('Signal.path() does not accept any arguments');
31
+ return super.path();
45
32
  }
46
33
  getId() {
47
34
  const $target = resolveRefSignal(this);
@@ -55,19 +42,15 @@ class SignalCompat extends Signal {
55
42
  return $target.getCollection();
56
43
  return super.getCollection();
57
44
  }
58
- getCopy(subpath) {
59
- if (arguments.length > 1)
60
- throw Error('Signal.getCopy() expects a single argument');
61
- const segments = parseAtSubpath(subpath, arguments.length, 'Signal.getCopy()');
62
- const value = getSignalValueAt(this, segments);
63
- return shallowCopy(value);
45
+ getCopy() {
46
+ if (arguments.length > 0)
47
+ throw Error('Signal.getCopy() does not accept any arguments');
48
+ return shallowCopy(this.get());
64
49
  }
65
- getDeepCopy(subpath) {
66
- if (arguments.length > 1)
67
- throw Error('Signal.getDeepCopy() expects a single argument');
68
- const segments = parseAtSubpath(subpath, arguments.length, 'Signal.getDeepCopy()');
69
- const value = getSignalValueAt(this, segments);
70
- return deepCopy(value);
50
+ getDeepCopy() {
51
+ if (arguments.length > 0)
52
+ throw Error('Signal.getDeepCopy() does not accept any arguments');
53
+ return deepCopy(this.get());
71
54
  }
72
55
  query(collection, params, options) {
73
56
  if (arguments.length < 1 || arguments.length > 3)
@@ -136,60 +119,37 @@ class SignalCompat extends Signal {
136
119
  return createSilentSignalWrapper(this, enabled);
137
120
  }
138
121
  get() {
139
- if (arguments.length > 1) {
140
- const segments = parseAtSegments(arguments, 'Signal.get()');
141
- const $target = resolveRelativePathTarget(this, segments);
142
- return Signal.prototype.get.call($target);
143
- }
144
- if (arguments.length === 1) {
145
- if (arguments[0] == null) {
146
- return Signal.prototype.get.apply(this, []);
147
- }
148
- const segments = parseAtSubpath(arguments[0], 1, 'Signal.get()');
149
- const $target = resolveRelativePathTarget(this, segments);
150
- return Signal.prototype.get.call($target);
151
- }
122
+ if (arguments.length > 0)
123
+ throw Error('Signal.get() does not accept any arguments');
152
124
  return Signal.prototype.get.apply(this, arguments);
153
125
  }
154
126
  peek() {
155
- if (arguments.length > 1) {
156
- const segments = parseAtSegments(arguments, 'Signal.peek()');
157
- const $target = resolveRelativePathTarget(this, segments);
158
- return Signal.prototype.peek.call($target);
159
- }
160
- if (arguments.length === 1) {
161
- if (arguments[0] == null) {
162
- const $target = resolveRefSignal(this);
163
- if ($target !== this)
164
- return Signal.prototype.peek.apply($target, []);
165
- return Signal.prototype.peek.apply(this, []);
166
- }
167
- const segments = parseAtSubpath(arguments[0], 1, 'Signal.peek()');
168
- const $target = resolveRelativePathTarget(this, segments);
169
- return Signal.prototype.peek.call($target);
170
- }
127
+ if (arguments.length > 0)
128
+ throw Error('Signal.peek() does not accept any arguments');
171
129
  const $target = resolveRefSignal(this);
172
130
  if ($target !== this)
173
131
  return Signal.prototype.peek.apply($target, arguments);
174
132
  return Signal.prototype.peek.apply(this, arguments);
175
133
  }
176
- async set(path, value) {
134
+ async set(value) {
177
135
  const forwarded = forwardRef(this, 'set', arguments);
178
136
  if (forwarded)
179
137
  return forwarded;
180
- if (arguments.length > 2)
181
- throw Error('Signal.set() expects one or two arguments');
182
- let segments = [];
183
- if (arguments.length === 2) {
184
- segments = parseAtSubpath(path, 1, 'Signal.set()');
185
- }
186
- else if (arguments.length === 1) {
187
- value = path;
188
- }
189
- const $target = resolveRelativePathTarget(this, segments);
138
+ if (arguments.length > 1)
139
+ throw Error('Signal.set() expects a single argument');
140
+ if (value === undefined)
141
+ return Signal.prototype.set.call(this, value);
142
+ return setReplaceOnSignal(this, value);
143
+ }
144
+ async setReplace(value) {
145
+ const forwarded = forwardRef(this, 'setReplace', arguments);
146
+ if (forwarded)
147
+ return forwarded;
148
+ if (arguments.length > 1)
149
+ throw Error('Signal.setReplace() expects a single argument');
190
150
  if (value === undefined)
191
- return Signal.prototype.set.call($target, value);
192
- return setReplaceOnSignal($target, value);
151
+ return Signal.prototype.set.call(this, value);
152
+ return setReplaceOnSignal(this, value);
193
153
  }
194
154
  async add(collectionOrValue, value) {
195
155
  const isRoot = this[SEGMENTS].length === 0;
@@ -207,102 +167,56 @@ class SignalCompat extends Signal {
207
167
  throw Error('Signal.add() expects a single argument');
208
168
  return Signal.prototype.add.call(this, collectionOrValue);
209
169
  }
210
- async setNull(path, value) {
170
+ async setNull(value) {
211
171
  const forwarded = forwardRef(this, 'setNull', arguments);
212
172
  if (forwarded)
213
173
  return forwarded;
214
- if (arguments.length > 2)
215
- throw Error('Signal.setNull() expects one or two arguments');
216
- let segments = [];
217
- if (arguments.length === 2) {
218
- segments = parseAtSubpath(path, 1, 'Signal.setNull()');
219
- }
220
- else if (arguments.length === 1) {
221
- value = path;
222
- }
223
- const $target = resolveRelativePathTarget(this, segments);
224
- if ($target.get() != null)
174
+ if (arguments.length > 1)
175
+ throw Error('Signal.setNull() expects a single argument');
176
+ if (this.get() != null)
225
177
  return;
226
- return setReplaceOnSignal($target, value);
178
+ return setReplaceOnSignal(this, value);
227
179
  }
228
- async create(path, value) {
180
+ async create(value) {
229
181
  const forwarded = forwardRef(this, 'create', arguments);
230
182
  if (forwarded)
231
183
  return forwarded;
232
- if (arguments.length > 2)
233
- throw Error('Signal.create() expects zero to two arguments');
234
- let segments = [];
235
- if (arguments.length === 2) {
236
- segments = parseAtSubpath(path, 1, 'Signal.create()');
237
- }
238
- else if (arguments.length === 1) {
239
- if (typeof path === 'string' || typeof path === 'number') {
240
- segments = parseAtSubpath(path, 1, 'Signal.create()');
241
- value = {};
242
- }
243
- else {
244
- value = path;
245
- }
246
- }
247
- else {
184
+ if (arguments.length > 1)
185
+ throw Error('Signal.create() expects zero or one argument');
186
+ if (arguments.length === 0) {
248
187
  value = {};
249
188
  }
250
- const $target = resolveRelativePathTarget(this, segments);
251
- ensureCreateTarget($target, 'Signal.create()');
252
- if ($target.get() != null) {
253
- throw Error(`Signal.create() may only be used on a non-existing document path. Path: ${$target.path()}`);
189
+ ensureCreateTarget(this, 'Signal.create()');
190
+ if (this.get() != null) {
191
+ throw Error(`Signal.create() may only be used on a non-existing document path. Path: ${this.path()}`);
254
192
  }
255
- return setReplaceOnSignal($target, value);
193
+ return setReplaceOnSignal(this, value);
256
194
  }
257
- async setDiffDeep(path, value) {
195
+ async setDiffDeep(value) {
258
196
  const forwarded = forwardRef(this, 'setDiffDeep', arguments);
259
197
  if (forwarded)
260
198
  return forwarded;
261
- if (arguments.length > 2)
262
- throw Error('Signal.setDiffDeep() expects one or two arguments');
263
- let segments = [];
264
- if (arguments.length === 2) {
265
- segments = parseAtSubpath(path, 1, 'Signal.setDiffDeep()');
266
- }
267
- else if (arguments.length === 1) {
268
- value = path;
269
- }
270
- const $target = resolveRelativePathTarget(this, segments);
271
- return runInBatch(() => setDiffDeepOnSignal($target, value));
199
+ if (arguments.length > 1)
200
+ throw Error('Signal.setDiffDeep() expects a single argument');
201
+ return runInBatch(() => setDiffDeepOnSignal(this, value));
272
202
  }
273
- async setDiff(path, value) {
203
+ async setDiff(value) {
274
204
  const forwarded = forwardRef(this, 'setDiff', arguments);
275
205
  if (forwarded)
276
206
  return forwarded;
277
- if (arguments.length > 2)
278
- throw Error('Signal.setDiff() expects one or two arguments');
279
- let segments = [];
280
- if (arguments.length === 2) {
281
- segments = parseAtSubpath(path, 1, 'Signal.setDiff()');
282
- }
283
- else if (arguments.length === 1) {
284
- value = path;
285
- }
286
- const $target = resolveRelativePathTarget(this, segments);
287
- const before = $target.peek();
207
+ if (arguments.length > 1)
208
+ throw Error('Signal.setDiff() expects a single argument');
209
+ const before = this.peek();
288
210
  if (racerEqualCompat(before, value))
289
211
  return;
290
- return setReplaceOnSignal($target, value);
212
+ return setReplaceOnSignal(this, value);
291
213
  }
292
- async setEach(path, object) {
214
+ async setEach(object) {
293
215
  const forwarded = forwardRef(this, 'setEach', arguments);
294
216
  if (forwarded)
295
217
  return forwarded;
296
- if (arguments.length > 2)
297
- throw Error('Signal.setEach() expects one or two arguments');
298
- let segments = [];
299
- if (arguments.length === 2) {
300
- segments = parseAtSubpath(path, 1, 'Signal.setEach()');
301
- }
302
- else if (arguments.length === 1) {
303
- object = path;
304
- }
305
- const $target = resolveRelativePathTarget(this, segments);
218
+ if (arguments.length > 1)
219
+ throw Error('Signal.setEach() expects a single argument');
306
220
  if (!object)
307
221
  return;
308
222
  if (typeof object !== 'object') {
@@ -311,126 +225,83 @@ class SignalCompat extends Signal {
311
225
  return runInBatch(async () => {
312
226
  const promises = [];
313
227
  for (const key of Object.keys(object)) {
314
- promises.push(SignalCompat.prototype.set.call($target[key], object[key]));
228
+ promises.push(SignalCompat.prototype.set.call(this[key], object[key]));
315
229
  }
316
230
  await Promise.all(promises);
317
231
  });
318
232
  }
319
- async del(path) {
233
+ async del() {
320
234
  const forwarded = forwardRef(this, 'del', arguments);
321
235
  if (forwarded)
322
236
  return forwarded;
323
- if (arguments.length > 1)
324
- throw Error('Signal.del() expects a single argument');
325
- const segments = parseAtSubpath(path, arguments.length, 'Signal.del()');
326
- const $target = resolveRelativePathTarget(this, segments);
237
+ if (arguments.length > 0)
238
+ throw Error('Signal.del() does not accept any arguments');
327
239
  try {
328
- return await Signal.prototype.del.call($target);
240
+ return await Signal.prototype.del.call(this);
329
241
  }
330
242
  catch (error) {
331
- if (isMissingPublicDocDeleteError($target, error))
243
+ if (isMissingPublicDocDeleteError(this, error))
332
244
  return;
333
245
  throw error;
334
246
  }
335
247
  }
336
- async increment(path, byNumber) {
248
+ async increment(byNumber) {
337
249
  const forwarded = forwardRef(this, 'increment', arguments);
338
250
  if (forwarded)
339
251
  return forwarded;
340
- if (arguments.length > 2)
341
- throw Error('Signal.increment() expects one or two arguments');
342
- let segments = [];
343
- if (arguments.length === 2) {
344
- segments = parseAtSubpath(path, 1, 'Signal.increment()');
345
- }
346
- else if (arguments.length === 1) {
347
- if (typeof path === 'number') {
348
- byNumber = path;
349
- }
350
- else {
351
- segments = parseAtSubpath(path, 1, 'Signal.increment()');
352
- }
252
+ if (arguments.length > 1)
253
+ throw Error('Signal.increment() expects zero or one argument');
254
+ if (byNumber != null && (typeof byNumber !== 'number' || !Number.isFinite(byNumber))) {
255
+ throw Error('Signal.increment() expects a numeric argument');
353
256
  }
354
- const $target = resolveRelativePathTarget(this, segments);
355
- return incrementOnSignal($target, byNumber);
257
+ return incrementOnSignal(this, byNumber);
356
258
  }
357
- async push(path, value) {
259
+ async push(value) {
358
260
  const forwarded = forwardRef(this, 'push', arguments);
359
261
  if (forwarded)
360
262
  return forwarded;
361
- if (arguments.length > 2)
362
- throw Error('Signal.push() expects one or two arguments');
363
- let segments = [];
364
- if (arguments.length === 2) {
365
- segments = parseAtSubpath(path, 1, 'Signal.push()');
366
- }
367
- else {
368
- value = path;
369
- }
370
- const $target = resolveRelativePathTarget(this, segments);
371
- return arrayPushOnSignal($target, value);
263
+ if (arguments.length > 1)
264
+ throw Error('Signal.push() expects a single argument');
265
+ return arrayPushOnSignal(this, value);
372
266
  }
373
- async unshift(path, value) {
267
+ async unshift(value) {
374
268
  const forwarded = forwardRef(this, 'unshift', arguments);
375
269
  if (forwarded)
376
270
  return forwarded;
377
- if (arguments.length > 2)
378
- throw Error('Signal.unshift() expects one or two arguments');
379
- let segments = [];
380
- if (arguments.length === 2) {
381
- segments = parseAtSubpath(path, 1, 'Signal.unshift()');
382
- }
383
- else {
384
- value = path;
385
- }
386
- const $target = resolveRelativePathTarget(this, segments);
387
- return arrayUnshiftOnSignal($target, value);
271
+ if (arguments.length > 1)
272
+ throw Error('Signal.unshift() expects a single argument');
273
+ return arrayUnshiftOnSignal(this, value);
388
274
  }
389
- async insert(path, index, values) {
275
+ async insert(index, values) {
390
276
  const forwarded = forwardRef(this, 'insert', arguments);
391
277
  if (forwarded)
392
278
  return forwarded;
393
279
  if (arguments.length < 2)
394
280
  throw Error('Not enough arguments for insert');
395
- if (arguments.length > 3)
396
- throw Error('Signal.insert() expects two or three arguments');
397
- let segments = [];
398
- if (arguments.length === 2) {
399
- index = arguments[0];
400
- values = arguments[1];
401
- }
402
- else {
403
- segments = parseAtSubpath(path, 1, 'Signal.insert()');
404
- index = arguments[1];
405
- values = arguments[2];
406
- }
281
+ if (arguments.length > 2)
282
+ throw Error('Signal.insert() expects two arguments');
407
283
  if (typeof index !== 'number' || !Number.isFinite(index)) {
408
284
  throw Error('Signal.insert() expects a numeric index');
409
285
  }
410
- const $target = resolveRelativePathTarget(this, segments);
411
- return arrayInsertOnSignal($target, index, values);
286
+ return arrayInsertOnSignal(this, index, values);
412
287
  }
413
- async pop(path) {
288
+ async pop() {
414
289
  const forwarded = forwardRef(this, 'pop', arguments);
415
290
  if (forwarded)
416
291
  return forwarded;
417
- if (arguments.length > 1)
418
- throw Error('Signal.pop() expects a single argument');
419
- const segments = parseAtSubpath(path, arguments.length, 'Signal.pop()');
420
- const $target = resolveRelativePathTarget(this, segments);
421
- return arrayPopOnSignal($target);
292
+ if (arguments.length > 0)
293
+ throw Error('Signal.pop() does not accept any arguments');
294
+ return arrayPopOnSignal(this);
422
295
  }
423
- async shift(path) {
296
+ async shift() {
424
297
  const forwarded = forwardRef(this, 'shift', arguments);
425
298
  if (forwarded)
426
299
  return forwarded;
427
- if (arguments.length > 1)
428
- throw Error('Signal.shift() expects a single argument');
429
- const segments = parseAtSubpath(path, arguments.length, 'Signal.shift()');
430
- const $target = resolveRelativePathTarget(this, segments);
431
- return arrayShiftOnSignal($target);
300
+ if (arguments.length > 0)
301
+ throw Error('Signal.shift() does not accept any arguments');
302
+ return arrayShiftOnSignal(this);
432
303
  }
433
- async remove(path, index, howMany) {
304
+ async remove(index, howMany) {
434
305
  const forwarded = forwardRef(this, 'remove', arguments);
435
306
  if (forwarded)
436
307
  return forwarded;
@@ -444,129 +315,53 @@ class SignalCompat extends Signal {
444
315
  const $target = resolveSignal($root, segments);
445
316
  return arrayRemoveOnSignal($target, +index, howMany);
446
317
  }
447
- if (arguments.length < 1)
448
- throw Error('Not enough arguments for remove');
449
- if (arguments.length > 3)
450
- throw Error('Signal.remove() expects one to three arguments');
451
- let segments = [];
452
- if (arguments.length === 1) {
453
- if (typeof path === 'number') {
454
- index = path;
455
- }
456
- else {
457
- segments = parseAtSubpath(path, 1, 'Signal.remove()');
458
- }
459
- }
460
- else if (arguments.length === 2) {
461
- if (typeof path === 'number') {
462
- index = path;
463
- howMany = arguments[1];
464
- }
465
- else {
466
- segments = parseAtSubpath(path, 1, 'Signal.remove()');
467
- index = arguments[1];
468
- }
469
- }
470
- else {
471
- segments = parseAtSubpath(path, 1, 'Signal.remove()');
472
- index = arguments[1];
473
- howMany = arguments[2];
474
- }
475
- if (index == null && segments.length && typeof segments[segments.length - 1] === 'number') {
476
- index = segments.pop();
477
- }
318
+ if (arguments.length > 2)
319
+ throw Error('Signal.remove() expects zero to two arguments');
478
320
  if (typeof index !== 'number' || !Number.isFinite(index)) {
479
321
  throw Error('Signal.remove() expects a numeric index');
480
322
  }
481
- const $target = resolveRelativePathTarget(this, segments);
482
- return arrayRemoveOnSignal($target, index, howMany);
323
+ return arrayRemoveOnSignal(this, index, howMany);
483
324
  }
484
- async move(path, from, to, howMany) {
325
+ async move(from, to, howMany) {
485
326
  const forwarded = forwardRef(this, 'move', arguments);
486
327
  if (forwarded)
487
328
  return forwarded;
488
329
  if (arguments.length < 2)
489
330
  throw Error('Not enough arguments for move');
490
- if (arguments.length > 4)
491
- throw Error('Signal.move() expects two to four arguments');
492
- let segments = [];
493
- if (arguments.length === 2) {
494
- from = arguments[0];
495
- to = arguments[1];
496
- }
497
- else if (arguments.length === 3) {
498
- if (typeof path === 'number') {
499
- from = arguments[0];
500
- to = arguments[1];
501
- howMany = arguments[2];
502
- }
503
- else {
504
- segments = parseAtSubpath(path, 1, 'Signal.move()');
505
- from = arguments[1];
506
- to = arguments[2];
507
- }
508
- }
509
- else {
510
- segments = parseAtSubpath(path, 1, 'Signal.move()');
511
- from = arguments[1];
512
- to = arguments[2];
513
- howMany = arguments[3];
514
- }
331
+ if (arguments.length > 3)
332
+ throw Error('Signal.move() expects two or three arguments');
515
333
  if (typeof from !== 'number' || !Number.isFinite(from) || typeof to !== 'number' || !Number.isFinite(to)) {
516
334
  throw Error('Signal.move() expects numeric from/to');
517
335
  }
518
- const $target = resolveRelativePathTarget(this, segments);
519
- return arrayMoveOnSignal($target, from, to, howMany);
336
+ return arrayMoveOnSignal(this, from, to, howMany);
520
337
  }
521
- async stringInsert(path, index, text) {
338
+ async stringInsert(index, text) {
522
339
  const forwarded = forwardRef(this, 'stringInsert', arguments);
523
340
  if (forwarded)
524
341
  return forwarded;
525
342
  if (arguments.length < 2)
526
343
  throw Error('Not enough arguments for stringInsert');
527
- if (arguments.length > 3)
528
- throw Error('Signal.stringInsert() expects two or three arguments');
529
- let segments = [];
530
- if (arguments.length === 2) {
531
- index = arguments[0];
532
- text = arguments[1];
533
- }
534
- else {
535
- segments = parseAtSubpath(path, 1, 'Signal.stringInsert()');
536
- index = arguments[1];
537
- text = arguments[2];
538
- }
344
+ if (arguments.length > 2)
345
+ throw Error('Signal.stringInsert() expects two arguments');
539
346
  if (typeof index !== 'number' || !Number.isFinite(index)) {
540
347
  throw Error('Signal.stringInsert() expects a numeric index');
541
348
  }
542
- const $target = resolveRelativePathTarget(this, segments);
543
- return stringInsertOnSignal($target, index, text);
349
+ return stringInsertOnSignal(this, index, text);
544
350
  }
545
- async stringRemove(path, index, howMany) {
351
+ async stringRemove(index, howMany) {
546
352
  const forwarded = forwardRef(this, 'stringRemove', arguments);
547
353
  if (forwarded)
548
354
  return forwarded;
549
355
  if (arguments.length < 2)
550
356
  throw Error('Not enough arguments for stringRemove');
551
- if (arguments.length > 3)
552
- throw Error('Signal.stringRemove() expects two or three arguments');
553
- let segments = [];
554
- if (arguments.length === 2) {
555
- index = arguments[0];
556
- howMany = arguments[1];
557
- }
558
- else {
559
- segments = parseAtSubpath(path, 1, 'Signal.stringRemove()');
560
- index = arguments[1];
561
- howMany = arguments[2];
562
- }
357
+ if (arguments.length > 2)
358
+ throw Error('Signal.stringRemove() expects two arguments');
563
359
  if (typeof index !== 'number' || !Number.isFinite(index)) {
564
360
  throw Error('Signal.stringRemove() expects a numeric index');
565
361
  }
566
362
  if (howMany == null)
567
363
  howMany = 1;
568
- const $target = resolveRelativePathTarget(this, segments);
569
- return stringRemoveOnSignal($target, index, howMany);
364
+ return stringRemoveOnSignal(this, index, howMany);
570
365
  }
571
366
  async assign(value) {
572
367
  const forwarded = forwardRef(this, 'assign', arguments);
@@ -626,63 +421,50 @@ class SignalCompat extends Signal {
626
421
  return removeCustomEventListener(eventName, handler);
627
422
  }
628
423
  ref(path, target, options) {
629
- if (arguments.length > 3)
630
- throw Error('Signal.ref() expects one to three arguments');
631
- let $from = this;
424
+ if (arguments.length < 1 || arguments.length > 2)
425
+ throw Error('Signal.ref() expects one or two arguments');
632
426
  let $to;
633
427
  if (arguments.length === 1) {
634
428
  $to = resolveRefTarget(this, path, 'Signal.ref()');
635
429
  }
636
- else if (arguments.length === 2) {
637
- if (isSignalLike(target) || typeof target === 'string') {
638
- const segments = parseAtSubpath(path, 1, 'Signal.ref()');
639
- $from = resolveSignal(this, segments);
640
- $to = resolveRefTarget(this, target, 'Signal.ref()');
641
- }
642
- else {
643
- $to = resolveRefTarget(this, path, 'Signal.ref()');
644
- options = target;
645
- }
646
- }
647
430
  else {
648
- const segments = parseAtSubpath(path, 1, 'Signal.ref()');
649
- $from = resolveSignal(this, segments);
650
- $to = resolveRefTarget(this, target, 'Signal.ref()');
431
+ $to = resolveRefTarget(this, path, 'Signal.ref()');
432
+ options = target;
651
433
  }
652
434
  if (!$to)
653
435
  throw Error('Signal.ref() expects a target path or signal');
654
- if ($from === $to)
655
- return $from;
656
- ensurePrivateRefSource($from, 'Signal.ref()');
657
- const store = getRefStore($from);
658
- const fromPath = $from.path();
436
+ if (this === $to)
437
+ return this;
438
+ ensurePrivateRefSource(this, 'Signal.ref()');
439
+ const store = getRefStore(this);
440
+ const fromPath = this.path();
659
441
  const existing = store.get(fromPath);
660
442
  if (existing)
661
443
  existing.stop();
662
444
  const mirrorOnly = !!($to?.[IS_QUERY] || $to?.[IS_AGGREGATION]);
663
- const { stop, onChange } = createRefLink($from, $to, { mirrorOnly, options });
445
+ const { stop, onChange } = createRefLink(this, $to, { mirrorOnly, options });
664
446
  store.set(fromPath, { stop });
665
- const fromRootId = (getRoot($from) || $from)?.[ROOT_ID];
447
+ const fromRootId = (getRoot(this) || this)?.[ROOT_ID];
666
448
  const toRootId = (getRoot($to) || $to)?.[ROOT_ID];
667
449
  if (!mirrorOnly) {
668
- $from[REF_TARGET] = $to;
669
- setRefLink(fromRootId, fromPath, $to.path(), $from[SEGMENTS], $to[SEGMENTS], {
450
+ this[REF_TARGET] = $to;
451
+ setRefLink(fromRootId, fromPath, $to.path(), this[SEGMENTS], $to[SEGMENTS], {
670
452
  mirrorOnly: false,
671
453
  fromRootId,
672
454
  toRootId
673
455
  });
674
456
  }
675
457
  else {
676
- setRefLink(fromRootId, fromPath, $to.path(), $from[SEGMENTS], $to[SEGMENTS], {
458
+ setRefLink(fromRootId, fromPath, $to.path(), this[SEGMENTS], $to[SEGMENTS], {
677
459
  mirrorOnly: true,
678
460
  onChange,
679
461
  fromRootId,
680
462
  toRootId
681
463
  });
682
- if ($from[REF_TARGET])
683
- delete $from[REF_TARGET];
464
+ if (this[REF_TARGET])
465
+ delete this[REF_TARGET];
684
466
  }
685
- return $from;
467
+ return this;
686
468
  }
687
469
  refExtra(path) {
688
470
  if (arguments.length !== 1)
@@ -707,40 +489,24 @@ class SignalCompat extends Signal {
707
489
  const $target = resolveSignal($root, segments);
708
490
  return SignalCompat.prototype.ref.call($target, this.ids);
709
491
  }
710
- removeRef(path) {
711
- if (arguments.length > 1)
712
- throw Error('Signal.removeRef() expects a single argument');
713
- let $from = this;
714
- if (arguments.length === 1) {
715
- const segments = parseAtSubpath(path, 1, 'Signal.removeRef()');
716
- $from = resolveSignal(this, segments);
717
- }
718
- const store = getRefStore($from);
719
- const fromPath = $from.path();
492
+ removeRef() {
493
+ if (arguments.length > 0)
494
+ throw Error('Signal.removeRef() does not accept any arguments');
495
+ const store = getRefStore(this);
496
+ const fromPath = this.path();
720
497
  const existing = store.get(fromPath);
721
498
  if (existing) {
722
499
  existing.stop();
723
500
  store.delete(fromPath);
724
501
  }
725
- const fromRootId = (getRoot($from) || $from)?.[ROOT_ID];
502
+ const fromRootId = (getRoot(this) || this)?.[ROOT_ID];
726
503
  removeRefLink(fromRootId, fromPath);
727
- const $target = resolveRefSignal($from);
728
- if ($target !== $from) {
729
- setDiffDeepBypassRef($from, deepCopy($target.get()));
504
+ const $target = resolveRefSignal(this);
505
+ if ($target !== this) {
506
+ setDiffDeepBypassRef(this, deepCopy($target.get()));
730
507
  }
731
- if ($from[REF_TARGET])
732
- delete $from[REF_TARGET];
733
- }
734
- scope(path) {
735
- const $root = getRoot(this) || this;
736
- if (arguments.length === 0)
737
- return $root;
738
- const segments = arguments.length > 1
739
- ? parseAtSegments(arguments, 'Signal.scope()')
740
- : parseAtSubpath(path, arguments.length, 'Signal.scope()');
741
- if (segments.length === 0)
742
- return $root;
743
- return resolveRelativePathTarget($root, segments);
508
+ if (this[REF_TARGET])
509
+ delete this[REF_TARGET];
744
510
  }
745
511
  }
746
512
  const SILENT_WRAPPER = Symbol('compat silent wrapper');
@@ -935,22 +701,6 @@ function parseAtSubpath(subpath, argsLength, methodName) {
935
701
  return [subpath];
936
702
  throw Error(`${methodName} expects a string or integer argument`);
937
703
  }
938
- function parseAtSegments(args, methodName) {
939
- const segments = [];
940
- for (const arg of Array.from(args)) {
941
- if (typeof arg === 'string') {
942
- const parts = arg.split('.').filter(Boolean);
943
- segments.push(...parts);
944
- continue;
945
- }
946
- if (typeof arg === 'number' && Number.isFinite(arg) && Number.isInteger(arg)) {
947
- segments.push(arg);
948
- continue;
949
- }
950
- throw Error(`${methodName} expects string or integer path segments`);
951
- }
952
- return segments;
953
- }
954
704
  function resolveSignal($signal, segments) {
955
705
  let $cursor = $signal;
956
706
  for (const segment of segments) {
@@ -958,24 +708,6 @@ function resolveSignal($signal, segments) {
958
708
  }
959
709
  return $cursor;
960
710
  }
961
- function resolveSignalWithRefs($signal, relativeSegments) {
962
- const baseSegments = Array.isArray($signal?.[SEGMENTS]) ? $signal[SEGMENTS] : [];
963
- const absoluteSegments = baseSegments.concat(relativeSegments);
964
- const resolvedSegments = resolveRefSegmentsSafe(absoluteSegments, (getRoot($signal) || $signal)?.[ROOT_ID]);
965
- if (!resolvedSegments)
966
- return resolveSignal($signal, relativeSegments);
967
- // Signals created through root functions can carry a raw root in [ROOT].
968
- // For path-based ref writes we need proxy traversal semantics.
969
- const $root = getRoot($signal) || $signal;
970
- const $traversalRoot = getRoot($root) || $root;
971
- return resolveSignal($traversalRoot, resolvedSegments);
972
- }
973
- function resolveRelativePathTarget($signal, relativeSegments) {
974
- if (!Array.isArray(relativeSegments) || relativeSegments.length === 0) {
975
- return resolveSignal($signal, []);
976
- }
977
- return resolveSignalWithRefs($signal, relativeSegments);
978
- }
979
711
  function isMissingPublicDocDeleteError($signal, error) {
980
712
  const segments = $signal?.[SEGMENTS];
981
713
  if (!Array.isArray(segments) || segments.length < 2)
@@ -1175,10 +907,6 @@ function deepEqualCompat(left, right) {
1175
907
  function racerEqualCompat(left, right) {
1176
908
  return left === right || (Number.isNaN(left) && Number.isNaN(right));
1177
909
  }
1178
- function getSignalValueAt($signal, segments) {
1179
- const $target = resolveRelativePathTarget($signal, segments);
1180
- return $target.get();
1181
- }
1182
910
  async function setReplaceOnSignal($signal, value) {
1183
911
  const segments = $signal[SEGMENTS];
1184
912
  if (segments.length === 0)
@@ -98,6 +98,11 @@ export declare class Signal<TValue = unknown> extends Function {
98
98
  * @param value New value to store at this signal path.
99
99
  */
100
100
  set(value: TValue): Promise<void>;
101
+ /**
102
+ * Replace this signal's value without deep-diffing object/array branches.
103
+ * @param value New value to store at this signal path.
104
+ */
105
+ setReplace(value: TValue): Promise<void>;
101
106
  /**
102
107
  * Set multiple object fields at once. Fields set to `null` or `undefined` are deleted.
103
108
  * @param value Object containing fields to set or delete.
@@ -13,14 +13,14 @@
13
13
  * in the raw data tree which have the same name as signal's methods
14
14
  */
15
15
  import uuid from '@teamplay/utils/uuid';
16
- import { get as _get, setPublicDoc as _setPublicDoc, dataTreeRaw, getRaw, getLogicalRootSnapshot, incrementPublic as _incrementPublic, arrayPushPublic as _arrayPushPublic, arrayUnshiftPublic as _arrayUnshiftPublic, arrayInsertPublic as _arrayInsertPublic, arrayPopPublic as _arrayPopPublic, arrayShiftPublic as _arrayShiftPublic, arrayRemovePublic as _arrayRemovePublic, arrayMovePublic as _arrayMovePublic, stringInsertPublic as _stringInsertPublic, stringRemovePublic as _stringRemovePublic } from './dataTree.js';
16
+ import { get as _get, setPublicDoc as _setPublicDoc, setPublicDocReplace as _setPublicDocReplace, del as _del, dataTreeRaw, getRaw, getLogicalRootSnapshot, incrementPublic as _incrementPublic, arrayPushPublic as _arrayPushPublic, arrayUnshiftPublic as _arrayUnshiftPublic, arrayInsertPublic as _arrayInsertPublic, arrayPopPublic as _arrayPopPublic, arrayShiftPublic as _arrayShiftPublic, arrayRemovePublic as _arrayRemovePublic, arrayMovePublic as _arrayMovePublic, stringInsertPublic as _stringInsertPublic, stringRemovePublic as _stringRemovePublic } from './dataTree.js';
17
17
  import getSignal, { rawSignal } from "./getSignal.js";
18
18
  import { docSubscriptions } from './Doc.js';
19
19
  import { IS_QUERY, HASH, QUERIES } from './Query.js';
20
20
  import { AGGREGATIONS, getAggregationCollectionName, getAggregationDocId } from './Aggregation.js';
21
21
  import { ROOT_FUNCTION, ROOT_ID, getRoot } from "./Root.js";
22
22
  import { isPrivateMutationForbidden } from "./connection.js";
23
- import { DEFAULT_ID_FIELDS, getIdFieldsForSegments, prepareAddPayload, resolveAddDocId } from "./idFields.js";
23
+ import { DEFAULT_ID_FIELDS, getIdFieldsForSegments, isIdFieldPath, isPublicDocPath, normalizeIdFields, prepareAddPayload, resolveAddDocId } from "./idFields.js";
24
24
  import { isCompatEnv } from './compatEnv.js';
25
25
  import { resolveRefSegmentsSafe, resolveRefSignalSafe } from './Compat/refFallback.js';
26
26
  import { compatStartOnRoot, compatStopOnRoot, joinScopePath } from './Compat/startStopCompat.js';
@@ -250,6 +250,42 @@ export class Signal extends Function {
250
250
  throw Error('Signal.set() expects a single argument');
251
251
  await setSignalValue(this, SIGNAL_VALUE_MUTATION_CONTEXT, value);
252
252
  }
253
+ /**
254
+ * Replace this signal's value without deep-diffing object/array branches.
255
+ * @param value New value to store at this signal path.
256
+ */
257
+ async setReplace(value) {
258
+ if (arguments.length > 1)
259
+ throw Error('Signal.setReplace() expects a single argument');
260
+ const segments = this[SEGMENTS];
261
+ if (segments.length === 0)
262
+ throw Error('Can\'t set the root signal data');
263
+ const idFields = getIdFieldsForSegments(segments);
264
+ if (isIdFieldPath(segments, idFields))
265
+ return;
266
+ const nextValue = isPublicDocPath(segments)
267
+ ? normalizeIdFields(value, idFields, segments[1])
268
+ : value;
269
+ if (isPublicCollection(segments[0])) {
270
+ if (value === undefined) {
271
+ await _setPublicDoc(segments, nextValue);
272
+ if (segments.length === 2) {
273
+ _del(segments);
274
+ }
275
+ }
276
+ else {
277
+ await _setPublicDocReplace(segments, nextValue);
278
+ }
279
+ return;
280
+ }
281
+ if (isPrivateMutationForbidden()) {
282
+ throw Error(`
283
+ Can't modify private collections data when 'publicOnly' is enabled.
284
+ On the server you can only work with public collections.
285
+ `);
286
+ }
287
+ setReplacePrivateData(getSignalOwningRootId(this), segments, nextValue);
288
+ }
253
289
  /**
254
290
  * Set multiple object fields at once. Fields set to `null` or `undefined` are deleted.
255
291
  * @param value Object containing fields to set or delete.
@@ -513,8 +549,9 @@ export const extremelyLateBindings = {
513
549
  if (segments[0] === AGGREGATIONS) {
514
550
  const aggregationDocId = getAggregationDocId(segments, getRoot(signal)?.[ROOT_ID]);
515
551
  if (aggregationDocId) {
516
- if (segments.length === 3 && key === 'set')
552
+ if (segments.length === 3 && (key === 'set' || key === 'setReplace')) {
517
553
  throw Error(ERRORS.setAggregationDoc(segments, key));
554
+ }
518
555
  const collectionName = getAggregationCollectionName(segments);
519
556
  const subDocSegments = segments.slice(3);
520
557
  const $original = getSignal(getRoot(signal), [collectionName, aggregationDocId, ...subDocSegments]);
@@ -14,6 +14,7 @@ export interface SignalValueMethods<TValue> {
14
14
  get: () => TValue;
15
15
  peek: () => TValue;
16
16
  set: (value: TValue) => Promise<void>;
17
+ setReplace: (value: TValue) => Promise<void>;
17
18
  assign: (value: NonNullable<TValue> extends object ? Partial<NonNullable<TValue>> : never) => Promise<void>;
18
19
  del: () => Promise<void>;
19
20
  increment: (value?: number) => Promise<number>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "teamplay",
3
- "version": "0.5.0-alpha.5",
3
+ "version": "0.5.0-alpha.7",
4
4
  "description": "Full-stack signals ORM with multiplayer",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -69,13 +69,13 @@
69
69
  "dependencies": {
70
70
  "@nx-js/observer-util": "^4.1.3",
71
71
  "@startupjs/sharedb-mingo-memory": "^4.0.0-2",
72
- "@teamplay/backend": "^0.5.0-alpha.5",
73
- "@teamplay/cache": "^0.5.0-alpha.0",
74
- "@teamplay/channel": "^0.5.0-alpha.0",
75
- "@teamplay/debug": "^0.5.0-alpha.0",
76
- "@teamplay/schema": "^0.5.0-alpha.1",
77
- "@teamplay/utils": "^0.5.0-alpha.5",
78
- "babel-plugin-teamplay": "^0.5.0-alpha.5",
72
+ "@teamplay/backend": "^0.5.0-alpha.7",
73
+ "@teamplay/cache": "^0.5.0-alpha.7",
74
+ "@teamplay/channel": "^0.5.0-alpha.7",
75
+ "@teamplay/debug": "^0.5.0-alpha.7",
76
+ "@teamplay/schema": "^0.5.0-alpha.7",
77
+ "@teamplay/utils": "^0.5.0-alpha.7",
78
+ "babel-plugin-teamplay": "^0.5.0-alpha.7",
79
79
  "diff-match-patch": "^1.0.5",
80
80
  "events": "^3.3.0",
81
81
  "json0-ot-diff": "^1.1.2",
@@ -116,6 +116,12 @@
116
116
  "transform": {
117
117
  "^.+\\.ts$": "./test/ts-transform.cjs"
118
118
  },
119
+ "testEnvironmentOptions": {
120
+ "customExportConditions": [
121
+ "teamplay-ts",
122
+ "browser"
123
+ ]
124
+ },
119
125
  "extensionsToTreatAsEsm": [
120
126
  ".ts"
121
127
  ],
@@ -128,5 +134,5 @@
128
134
  ]
129
135
  },
130
136
  "license": "MIT",
131
- "gitHead": "4527ba386f4994295901c4b4e30c5eaf42739103"
137
+ "gitHead": "a854bf3447232cd732ec55e6a3faf57b094e99d1"
132
138
  }