teamplay 0.4.0-alpha.47 → 0.4.0-alpha.49

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.
@@ -225,6 +225,31 @@ class SignalCompat extends Signal {
225
225
  return setReplaceOnSignal($target, value)
226
226
  }
227
227
 
228
+ async create (path, value) {
229
+ const forwarded = forwardRef(this, 'create', arguments)
230
+ if (forwarded) return forwarded
231
+ if (arguments.length > 2) throw Error('Signal.create() expects zero to two arguments')
232
+ let segments = []
233
+ if (arguments.length === 2) {
234
+ segments = parseAtSubpath(path, 1, 'Signal.create()')
235
+ } else if (arguments.length === 1) {
236
+ if (typeof path === 'string' || typeof path === 'number') {
237
+ segments = parseAtSubpath(path, 1, 'Signal.create()')
238
+ value = {}
239
+ } else {
240
+ value = path
241
+ }
242
+ } else {
243
+ value = {}
244
+ }
245
+ const $target = resolveSignal(this, segments)
246
+ ensureCreateTarget($target, 'Signal.create()')
247
+ if ($target.get() != null) {
248
+ throw Error(`Signal.create() may only be used on a non-existing document path. Path: ${$target.path()}`)
249
+ }
250
+ return setReplaceOnSignal($target, value)
251
+ }
252
+
228
253
  async setDiffDeep (path, value) {
229
254
  const forwarded = forwardRef(this, 'setDiffDeep', arguments)
230
255
  if (forwarded) return forwarded
@@ -873,6 +898,15 @@ function ensureValueTarget ($signal) {
873
898
  return segments
874
899
  }
875
900
 
901
+ function ensureCreateTarget ($signal, methodName) {
902
+ const segments = $signal[SEGMENTS]
903
+ if ($signal[IS_QUERY]) throw Error(`${methodName} can't be used on a query signal`)
904
+ if (segments.length !== 2) {
905
+ throw Error(`${methodName} may only be used on a document path`)
906
+ }
907
+ return segments
908
+ }
909
+
876
910
  async function arrayPushOnSignal ($signal, value) {
877
911
  const segments = ensureArrayTarget($signal)
878
912
  const idFields = getIdFieldsForSegments(segments)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "teamplay",
3
- "version": "0.4.0-alpha.47",
3
+ "version": "0.4.0-alpha.49",
4
4
  "description": "Full-stack signals ORM with multiplayer",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -82,5 +82,5 @@
82
82
  ]
83
83
  },
84
84
  "license": "MIT",
85
- "gitHead": "6e0aef0801b18f7e11dcbdc83768eeffe9573dc8"
85
+ "gitHead": "a0220c29390a8ecd47d012dc0e701113fb0907ba"
86
86
  }
@@ -24,12 +24,12 @@ export function getPromiseAll () {
24
24
  const pendingPromises = promises
25
25
  const pendingChecks = Array.from(checks.values())
26
26
  const hasPromises = pendingPromises.length > 0
27
- const hasChecks = pendingChecks.length > 0
28
- const result = !hasPromises && !hasChecks
29
- ? null
30
- : hasPromises || !areChecksReady(pendingChecks)
31
- ? waitForBatchReady(pendingPromises, pendingChecks)
32
- : null
27
+ // Checks are a materialization barrier for initial batch subscriptions.
28
+ // If there were no subscription promises in this render, we are in update mode
29
+ // and should not suspend the whole subtree.
30
+ const result = hasPromises
31
+ ? waitForBatchReady(pendingPromises, pendingChecks)
32
+ : null
33
33
  reset()
34
34
  return result
35
35
  }
@@ -66,11 +66,6 @@ async function waitForChecksReady (pendingChecks) {
66
66
  }
67
67
  }
68
68
 
69
- function areChecksReady (pendingChecks) {
70
- if (pendingChecks.length === 0) return true
71
- return getNotReadyChecks(pendingChecks).length === 0
72
- }
73
-
74
69
  function getNotReadyChecks (pendingChecks) {
75
70
  const notReady = []
76
71
  for (const check of pendingChecks) {
package/react/useSub.js CHANGED
@@ -41,7 +41,14 @@ export function useSubDeferred (signal, params, { async = false, defer, batch =
41
41
  if (promiseOrSignal.then) {
42
42
  const promise = maybeThrottle(promiseOrSignal)
43
43
  if (batch) {
44
- promiseBatcher.add(promise)
44
+ const hasPreviousSignal = !!$signalRef.current
45
+ // Batch suspense must block only on initial load.
46
+ // On resubscribe we keep rendering previous signal and refresh in background.
47
+ if (!hasPreviousSignal) {
48
+ promiseBatcher.add(promise)
49
+ } else {
50
+ scheduleUpdate(promise)
51
+ }
45
52
  if (async) scheduleUpdate(promise)
46
53
  return $signalRef.current
47
54
  }
@@ -71,9 +78,16 @@ export function useSubClassic (signal, params, { async = false, batch = false }
71
78
  if (promiseOrSignal.then) {
72
79
  const promise = maybeThrottle(promiseOrSignal)
73
80
  if (batch) {
74
- promiseBatcher.add(promise)
81
+ const hasPreviousSignal = cache.has(id)
82
+ // Batch suspense must block only on initial load.
83
+ // On resubscribe we keep rendering previous signal and refresh in background.
84
+ if (!hasPreviousSignal) {
85
+ promiseBatcher.add(promise)
86
+ } else {
87
+ scheduleUpdate(promise)
88
+ }
75
89
  if (async) scheduleUpdate(promise)
76
- if (cache.has(id)) return cache.get(id)
90
+ if (hasPreviousSignal) return cache.get(id)
77
91
  return
78
92
  }
79
93
  // first time we just throw the promise to be caught by Suspense