teamplay 0.5.0-alpha.5 → 0.5.0-alpha.8

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,11 @@ 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'];
25
- get root() {
26
- return this.scope();
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);
24
+ static [GETTERS] = [...DEFAULT_GETTERS, 'getCopy', 'getDeepCopy'];
25
+ path() {
26
+ if (arguments.length > 0)
27
+ throw Error('Signal.path() does not accept any arguments');
28
+ return super.path();
45
29
  }
46
30
  getId() {
47
31
  const $target = resolveRefSignal(this);
@@ -55,19 +39,15 @@ class SignalCompat extends Signal {
55
39
  return $target.getCollection();
56
40
  return super.getCollection();
57
41
  }
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);
42
+ getCopy() {
43
+ if (arguments.length > 0)
44
+ throw Error('Signal.getCopy() does not accept any arguments');
45
+ return shallowCopy(this.get());
64
46
  }
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);
47
+ getDeepCopy() {
48
+ if (arguments.length > 0)
49
+ throw Error('Signal.getDeepCopy() does not accept any arguments');
50
+ return deepCopy(this.get());
71
51
  }
72
52
  query(collection, params, options) {
73
53
  if (arguments.length < 1 || arguments.length > 3)
@@ -136,60 +116,37 @@ class SignalCompat extends Signal {
136
116
  return createSilentSignalWrapper(this, enabled);
137
117
  }
138
118
  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
- }
119
+ if (arguments.length > 0)
120
+ throw Error('Signal.get() does not accept any arguments');
152
121
  return Signal.prototype.get.apply(this, arguments);
153
122
  }
154
123
  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
- }
124
+ if (arguments.length > 0)
125
+ throw Error('Signal.peek() does not accept any arguments');
171
126
  const $target = resolveRefSignal(this);
172
127
  if ($target !== this)
173
128
  return Signal.prototype.peek.apply($target, arguments);
174
129
  return Signal.prototype.peek.apply(this, arguments);
175
130
  }
176
- async set(path, value) {
131
+ async set(value) {
177
132
  const forwarded = forwardRef(this, 'set', arguments);
178
133
  if (forwarded)
179
134
  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);
135
+ if (arguments.length > 1)
136
+ throw Error('Signal.set() expects a single argument');
190
137
  if (value === undefined)
191
- return Signal.prototype.set.call($target, value);
192
- return setReplaceOnSignal($target, value);
138
+ return Signal.prototype.set.call(this, value);
139
+ return setReplaceOnSignal(this, value);
140
+ }
141
+ async setReplace(value) {
142
+ const forwarded = forwardRef(this, 'setReplace', arguments);
143
+ if (forwarded)
144
+ return forwarded;
145
+ if (arguments.length > 1)
146
+ throw Error('Signal.setReplace() expects a single argument');
147
+ if (value === undefined)
148
+ return Signal.prototype.set.call(this, value);
149
+ return setReplaceOnSignal(this, value);
193
150
  }
194
151
  async add(collectionOrValue, value) {
195
152
  const isRoot = this[SEGMENTS].length === 0;
@@ -207,102 +164,56 @@ class SignalCompat extends Signal {
207
164
  throw Error('Signal.add() expects a single argument');
208
165
  return Signal.prototype.add.call(this, collectionOrValue);
209
166
  }
210
- async setNull(path, value) {
167
+ async setNull(value) {
211
168
  const forwarded = forwardRef(this, 'setNull', arguments);
212
169
  if (forwarded)
213
170
  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)
171
+ if (arguments.length > 1)
172
+ throw Error('Signal.setNull() expects a single argument');
173
+ if (this.get() != null)
225
174
  return;
226
- return setReplaceOnSignal($target, value);
175
+ return setReplaceOnSignal(this, value);
227
176
  }
228
- async create(path, value) {
177
+ async create(value) {
229
178
  const forwarded = forwardRef(this, 'create', arguments);
230
179
  if (forwarded)
231
180
  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 {
181
+ if (arguments.length > 1)
182
+ throw Error('Signal.create() expects zero or one argument');
183
+ if (arguments.length === 0) {
248
184
  value = {};
249
185
  }
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()}`);
186
+ ensureCreateTarget(this, 'Signal.create()');
187
+ if (this.get() != null) {
188
+ throw Error(`Signal.create() may only be used on a non-existing document path. Path: ${this.path()}`);
254
189
  }
255
- return setReplaceOnSignal($target, value);
190
+ return setReplaceOnSignal(this, value);
256
191
  }
257
- async setDiffDeep(path, value) {
192
+ async setDiffDeep(value) {
258
193
  const forwarded = forwardRef(this, 'setDiffDeep', arguments);
259
194
  if (forwarded)
260
195
  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));
196
+ if (arguments.length > 1)
197
+ throw Error('Signal.setDiffDeep() expects a single argument');
198
+ return runInBatch(() => setDiffDeepOnSignal(this, value));
272
199
  }
273
- async setDiff(path, value) {
200
+ async setDiff(value) {
274
201
  const forwarded = forwardRef(this, 'setDiff', arguments);
275
202
  if (forwarded)
276
203
  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();
204
+ if (arguments.length > 1)
205
+ throw Error('Signal.setDiff() expects a single argument');
206
+ const before = this.peek();
288
207
  if (racerEqualCompat(before, value))
289
208
  return;
290
- return setReplaceOnSignal($target, value);
209
+ return setReplaceOnSignal(this, value);
291
210
  }
292
- async setEach(path, object) {
211
+ async setEach(object) {
293
212
  const forwarded = forwardRef(this, 'setEach', arguments);
294
213
  if (forwarded)
295
214
  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);
215
+ if (arguments.length > 1)
216
+ throw Error('Signal.setEach() expects a single argument');
306
217
  if (!object)
307
218
  return;
308
219
  if (typeof object !== 'object') {
@@ -311,126 +222,83 @@ class SignalCompat extends Signal {
311
222
  return runInBatch(async () => {
312
223
  const promises = [];
313
224
  for (const key of Object.keys(object)) {
314
- promises.push(SignalCompat.prototype.set.call($target[key], object[key]));
225
+ promises.push(SignalCompat.prototype.set.call(this[key], object[key]));
315
226
  }
316
227
  await Promise.all(promises);
317
228
  });
318
229
  }
319
- async del(path) {
230
+ async del() {
320
231
  const forwarded = forwardRef(this, 'del', arguments);
321
232
  if (forwarded)
322
233
  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);
234
+ if (arguments.length > 0)
235
+ throw Error('Signal.del() does not accept any arguments');
327
236
  try {
328
- return await Signal.prototype.del.call($target);
237
+ return await Signal.prototype.del.call(this);
329
238
  }
330
239
  catch (error) {
331
- if (isMissingPublicDocDeleteError($target, error))
240
+ if (isMissingPublicDocDeleteError(this, error))
332
241
  return;
333
242
  throw error;
334
243
  }
335
244
  }
336
- async increment(path, byNumber) {
245
+ async increment(byNumber) {
337
246
  const forwarded = forwardRef(this, 'increment', arguments);
338
247
  if (forwarded)
339
248
  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
- }
249
+ if (arguments.length > 1)
250
+ throw Error('Signal.increment() expects zero or one argument');
251
+ if (byNumber != null && (typeof byNumber !== 'number' || !Number.isFinite(byNumber))) {
252
+ throw Error('Signal.increment() expects a numeric argument');
353
253
  }
354
- const $target = resolveRelativePathTarget(this, segments);
355
- return incrementOnSignal($target, byNumber);
254
+ return incrementOnSignal(this, byNumber);
356
255
  }
357
- async push(path, value) {
256
+ async push(value) {
358
257
  const forwarded = forwardRef(this, 'push', arguments);
359
258
  if (forwarded)
360
259
  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);
260
+ if (arguments.length > 1)
261
+ throw Error('Signal.push() expects a single argument');
262
+ return arrayPushOnSignal(this, value);
372
263
  }
373
- async unshift(path, value) {
264
+ async unshift(value) {
374
265
  const forwarded = forwardRef(this, 'unshift', arguments);
375
266
  if (forwarded)
376
267
  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);
268
+ if (arguments.length > 1)
269
+ throw Error('Signal.unshift() expects a single argument');
270
+ return arrayUnshiftOnSignal(this, value);
388
271
  }
389
- async insert(path, index, values) {
272
+ async insert(index, values) {
390
273
  const forwarded = forwardRef(this, 'insert', arguments);
391
274
  if (forwarded)
392
275
  return forwarded;
393
276
  if (arguments.length < 2)
394
277
  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
- }
278
+ if (arguments.length > 2)
279
+ throw Error('Signal.insert() expects two arguments');
407
280
  if (typeof index !== 'number' || !Number.isFinite(index)) {
408
281
  throw Error('Signal.insert() expects a numeric index');
409
282
  }
410
- const $target = resolveRelativePathTarget(this, segments);
411
- return arrayInsertOnSignal($target, index, values);
283
+ return arrayInsertOnSignal(this, index, values);
412
284
  }
413
- async pop(path) {
285
+ async pop() {
414
286
  const forwarded = forwardRef(this, 'pop', arguments);
415
287
  if (forwarded)
416
288
  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);
289
+ if (arguments.length > 0)
290
+ throw Error('Signal.pop() does not accept any arguments');
291
+ return arrayPopOnSignal(this);
422
292
  }
423
- async shift(path) {
293
+ async shift() {
424
294
  const forwarded = forwardRef(this, 'shift', arguments);
425
295
  if (forwarded)
426
296
  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);
297
+ if (arguments.length > 0)
298
+ throw Error('Signal.shift() does not accept any arguments');
299
+ return arrayShiftOnSignal(this);
432
300
  }
433
- async remove(path, index, howMany) {
301
+ async remove(index, howMany) {
434
302
  const forwarded = forwardRef(this, 'remove', arguments);
435
303
  if (forwarded)
436
304
  return forwarded;
@@ -444,129 +312,53 @@ class SignalCompat extends Signal {
444
312
  const $target = resolveSignal($root, segments);
445
313
  return arrayRemoveOnSignal($target, +index, howMany);
446
314
  }
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
- }
315
+ if (arguments.length > 2)
316
+ throw Error('Signal.remove() expects zero to two arguments');
478
317
  if (typeof index !== 'number' || !Number.isFinite(index)) {
479
318
  throw Error('Signal.remove() expects a numeric index');
480
319
  }
481
- const $target = resolveRelativePathTarget(this, segments);
482
- return arrayRemoveOnSignal($target, index, howMany);
320
+ return arrayRemoveOnSignal(this, index, howMany);
483
321
  }
484
- async move(path, from, to, howMany) {
322
+ async move(from, to, howMany) {
485
323
  const forwarded = forwardRef(this, 'move', arguments);
486
324
  if (forwarded)
487
325
  return forwarded;
488
326
  if (arguments.length < 2)
489
327
  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
- }
328
+ if (arguments.length > 3)
329
+ throw Error('Signal.move() expects two or three arguments');
515
330
  if (typeof from !== 'number' || !Number.isFinite(from) || typeof to !== 'number' || !Number.isFinite(to)) {
516
331
  throw Error('Signal.move() expects numeric from/to');
517
332
  }
518
- const $target = resolveRelativePathTarget(this, segments);
519
- return arrayMoveOnSignal($target, from, to, howMany);
333
+ return arrayMoveOnSignal(this, from, to, howMany);
520
334
  }
521
- async stringInsert(path, index, text) {
335
+ async stringInsert(index, text) {
522
336
  const forwarded = forwardRef(this, 'stringInsert', arguments);
523
337
  if (forwarded)
524
338
  return forwarded;
525
339
  if (arguments.length < 2)
526
340
  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
- }
341
+ if (arguments.length > 2)
342
+ throw Error('Signal.stringInsert() expects two arguments');
539
343
  if (typeof index !== 'number' || !Number.isFinite(index)) {
540
344
  throw Error('Signal.stringInsert() expects a numeric index');
541
345
  }
542
- const $target = resolveRelativePathTarget(this, segments);
543
- return stringInsertOnSignal($target, index, text);
346
+ return stringInsertOnSignal(this, index, text);
544
347
  }
545
- async stringRemove(path, index, howMany) {
348
+ async stringRemove(index, howMany) {
546
349
  const forwarded = forwardRef(this, 'stringRemove', arguments);
547
350
  if (forwarded)
548
351
  return forwarded;
549
352
  if (arguments.length < 2)
550
353
  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
- }
354
+ if (arguments.length > 2)
355
+ throw Error('Signal.stringRemove() expects two arguments');
563
356
  if (typeof index !== 'number' || !Number.isFinite(index)) {
564
357
  throw Error('Signal.stringRemove() expects a numeric index');
565
358
  }
566
359
  if (howMany == null)
567
360
  howMany = 1;
568
- const $target = resolveRelativePathTarget(this, segments);
569
- return stringRemoveOnSignal($target, index, howMany);
361
+ return stringRemoveOnSignal(this, index, howMany);
570
362
  }
571
363
  async assign(value) {
572
364
  const forwarded = forwardRef(this, 'assign', arguments);
@@ -626,63 +418,50 @@ class SignalCompat extends Signal {
626
418
  return removeCustomEventListener(eventName, handler);
627
419
  }
628
420
  ref(path, target, options) {
629
- if (arguments.length > 3)
630
- throw Error('Signal.ref() expects one to three arguments');
631
- let $from = this;
421
+ if (arguments.length < 1 || arguments.length > 2)
422
+ throw Error('Signal.ref() expects one or two arguments');
632
423
  let $to;
633
424
  if (arguments.length === 1) {
634
425
  $to = resolveRefTarget(this, path, 'Signal.ref()');
635
426
  }
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
427
  else {
648
- const segments = parseAtSubpath(path, 1, 'Signal.ref()');
649
- $from = resolveSignal(this, segments);
650
- $to = resolveRefTarget(this, target, 'Signal.ref()');
428
+ $to = resolveRefTarget(this, path, 'Signal.ref()');
429
+ options = target;
651
430
  }
652
431
  if (!$to)
653
432
  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();
433
+ if (this === $to)
434
+ return this;
435
+ ensurePrivateRefSource(this, 'Signal.ref()');
436
+ const store = getRefStore(this);
437
+ const fromPath = this.path();
659
438
  const existing = store.get(fromPath);
660
439
  if (existing)
661
440
  existing.stop();
662
441
  const mirrorOnly = !!($to?.[IS_QUERY] || $to?.[IS_AGGREGATION]);
663
- const { stop, onChange } = createRefLink($from, $to, { mirrorOnly, options });
442
+ const { stop, onChange } = createRefLink(this, $to, { mirrorOnly, options });
664
443
  store.set(fromPath, { stop });
665
- const fromRootId = (getRoot($from) || $from)?.[ROOT_ID];
444
+ const fromRootId = (getRoot(this) || this)?.[ROOT_ID];
666
445
  const toRootId = (getRoot($to) || $to)?.[ROOT_ID];
667
446
  if (!mirrorOnly) {
668
- $from[REF_TARGET] = $to;
669
- setRefLink(fromRootId, fromPath, $to.path(), $from[SEGMENTS], $to[SEGMENTS], {
447
+ this[REF_TARGET] = $to;
448
+ setRefLink(fromRootId, fromPath, $to.path(), this[SEGMENTS], $to[SEGMENTS], {
670
449
  mirrorOnly: false,
671
450
  fromRootId,
672
451
  toRootId
673
452
  });
674
453
  }
675
454
  else {
676
- setRefLink(fromRootId, fromPath, $to.path(), $from[SEGMENTS], $to[SEGMENTS], {
455
+ setRefLink(fromRootId, fromPath, $to.path(), this[SEGMENTS], $to[SEGMENTS], {
677
456
  mirrorOnly: true,
678
457
  onChange,
679
458
  fromRootId,
680
459
  toRootId
681
460
  });
682
- if ($from[REF_TARGET])
683
- delete $from[REF_TARGET];
461
+ if (this[REF_TARGET])
462
+ delete this[REF_TARGET];
684
463
  }
685
- return $from;
464
+ return this;
686
465
  }
687
466
  refExtra(path) {
688
467
  if (arguments.length !== 1)
@@ -707,40 +486,24 @@ class SignalCompat extends Signal {
707
486
  const $target = resolveSignal($root, segments);
708
487
  return SignalCompat.prototype.ref.call($target, this.ids);
709
488
  }
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();
489
+ removeRef() {
490
+ if (arguments.length > 0)
491
+ throw Error('Signal.removeRef() does not accept any arguments');
492
+ const store = getRefStore(this);
493
+ const fromPath = this.path();
720
494
  const existing = store.get(fromPath);
721
495
  if (existing) {
722
496
  existing.stop();
723
497
  store.delete(fromPath);
724
498
  }
725
- const fromRootId = (getRoot($from) || $from)?.[ROOT_ID];
499
+ const fromRootId = (getRoot(this) || this)?.[ROOT_ID];
726
500
  removeRefLink(fromRootId, fromPath);
727
- const $target = resolveRefSignal($from);
728
- if ($target !== $from) {
729
- setDiffDeepBypassRef($from, deepCopy($target.get()));
501
+ const $target = resolveRefSignal(this);
502
+ if ($target !== this) {
503
+ setDiffDeepBypassRef(this, deepCopy($target.get()));
730
504
  }
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);
505
+ if (this[REF_TARGET])
506
+ delete this[REF_TARGET];
744
507
  }
745
508
  }
746
509
  const SILENT_WRAPPER = Symbol('compat silent wrapper');
@@ -935,22 +698,6 @@ function parseAtSubpath(subpath, argsLength, methodName) {
935
698
  return [subpath];
936
699
  throw Error(`${methodName} expects a string or integer argument`);
937
700
  }
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
701
  function resolveSignal($signal, segments) {
955
702
  let $cursor = $signal;
956
703
  for (const segment of segments) {
@@ -958,24 +705,6 @@ function resolveSignal($signal, segments) {
958
705
  }
959
706
  return $cursor;
960
707
  }
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
708
  function isMissingPublicDocDeleteError($signal, error) {
980
709
  const segments = $signal?.[SEGMENTS];
981
710
  if (!Array.isArray(segments) || segments.length < 2)
@@ -1175,10 +904,6 @@ function deepEqualCompat(left, right) {
1175
904
  function racerEqualCompat(left, right) {
1176
905
  return left === right || (Number.isNaN(left) && Number.isNaN(right));
1177
906
  }
1178
- function getSignalValueAt($signal, segments) {
1179
- const $target = resolveRelativePathTarget($signal, segments);
1180
- return $target.get();
1181
- }
1182
907
  async function setReplaceOnSignal($signal, value) {
1183
908
  const segments = $signal[SEGMENTS];
1184
909
  if (segments.length === 0)
@@ -29,6 +29,8 @@ export declare class Signal<TValue = unknown> extends Function {
29
29
  toString(): string;
30
30
  /** Customize Object.prototype.toString.call($signal) for debugging. */
31
31
  get [Symbol.toStringTag](): string;
32
+ /** Return the owning root signal. */
33
+ root(): this | import("./Root.js").RootSignalRuntime;
32
34
  /**
33
35
  * Return the parent signal `levels` above this signal.
34
36
  * @param levels Number of parent levels to walk upward. Defaults to `1`.
@@ -98,6 +100,11 @@ export declare class Signal<TValue = unknown> extends Function {
98
100
  * @param value New value to store at this signal path.
99
101
  */
100
102
  set(value: TValue): Promise<void>;
103
+ /**
104
+ * Replace this signal's value without deep-diffing object/array branches.
105
+ * @param value New value to store at this signal path.
106
+ */
107
+ setReplace(value: TValue): Promise<void>;
101
108
  /**
102
109
  * Set multiple object fields at once. Fields set to `null` or `undefined` are deleted.
103
110
  * @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';
@@ -147,6 +147,12 @@ export class Signal extends Function {
147
147
  get [Symbol.toStringTag]() {
148
148
  return 'Signal';
149
149
  }
150
+ /** Return the owning root signal. */
151
+ root() {
152
+ if (arguments.length > 0)
153
+ throw Error('Signal.root() does not accept any arguments');
154
+ return getRoot(this) || this;
155
+ }
150
156
  /**
151
157
  * Return the parent signal `levels` above this signal.
152
158
  * @param levels Number of parent levels to walk upward. Defaults to `1`.
@@ -250,6 +256,42 @@ export class Signal extends Function {
250
256
  throw Error('Signal.set() expects a single argument');
251
257
  await setSignalValue(this, SIGNAL_VALUE_MUTATION_CONTEXT, value);
252
258
  }
259
+ /**
260
+ * Replace this signal's value without deep-diffing object/array branches.
261
+ * @param value New value to store at this signal path.
262
+ */
263
+ async setReplace(value) {
264
+ if (arguments.length > 1)
265
+ throw Error('Signal.setReplace() expects a single argument');
266
+ const segments = this[SEGMENTS];
267
+ if (segments.length === 0)
268
+ throw Error('Can\'t set the root signal data');
269
+ const idFields = getIdFieldsForSegments(segments);
270
+ if (isIdFieldPath(segments, idFields))
271
+ return;
272
+ const nextValue = isPublicDocPath(segments)
273
+ ? normalizeIdFields(value, idFields, segments[1])
274
+ : value;
275
+ if (isPublicCollection(segments[0])) {
276
+ if (value === undefined) {
277
+ await _setPublicDoc(segments, nextValue);
278
+ if (segments.length === 2) {
279
+ _del(segments);
280
+ }
281
+ }
282
+ else {
283
+ await _setPublicDocReplace(segments, nextValue);
284
+ }
285
+ return;
286
+ }
287
+ if (isPrivateMutationForbidden()) {
288
+ throw Error(`
289
+ Can't modify private collections data when 'publicOnly' is enabled.
290
+ On the server you can only work with public collections.
291
+ `);
292
+ }
293
+ setReplacePrivateData(getSignalOwningRootId(this), segments, nextValue);
294
+ }
253
295
  /**
254
296
  * Set multiple object fields at once. Fields set to `null` or `undefined` are deleted.
255
297
  * @param value Object containing fields to set or delete.
@@ -513,8 +555,9 @@ export const extremelyLateBindings = {
513
555
  if (segments[0] === AGGREGATIONS) {
514
556
  const aggregationDocId = getAggregationDocId(segments, getRoot(signal)?.[ROOT_ID]);
515
557
  if (aggregationDocId) {
516
- if (segments.length === 3 && key === 'set')
558
+ if (segments.length === 3 && (key === 'set' || key === 'setReplace')) {
517
559
  throw Error(ERRORS.setAggregationDoc(segments, key));
560
+ }
518
561
  const collectionName = getAggregationCollectionName(segments);
519
562
  const subDocSegments = segments.slice(3);
520
563
  const $original = getSignal(getRoot(signal), [collectionName, aggregationDocId, ...subDocSegments]);
@@ -94,8 +94,6 @@ function getDefaultProxyHandlers({ useExtremelyLateBindings } = {}) {
94
94
  return undefined;
95
95
  }
96
96
  }
97
- if (key === 'root')
98
- return Reflect.get(signal, key, receiver);
99
97
  return baseHandlers.get
100
98
  ? baseHandlers.get(signal, key, receiver)
101
99
  : Reflect.get(signal, key, receiver);
@@ -2,4 +2,4 @@ export const SEGMENTS = Symbol('path segments targeting the particular node in t
2
2
  export const ARRAY_METHOD = Symbol('run array method on the signal');
3
3
  export const GET = Symbol('get the value of the signal - either observed or raw');
4
4
  export const GETTERS = Symbol('get the list of this signal\'s getters');
5
- export const DEFAULT_GETTERS = ['path', 'id', 'get', 'peek', 'getId', 'map', 'reduce', 'find', 'getIds', 'getExtra', 'getCollection'];
5
+ export const DEFAULT_GETTERS = ['path', 'root', 'id', 'get', 'peek', 'getId', 'map', 'reduce', 'find', 'getIds', 'getExtra', 'getCollection'];
@@ -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.8",
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": "a883c9d07948ea203021c20e7d234ad390ec9835"
132
138
  }