teamplay 0.4.0-alpha.57 → 0.4.0-alpha.59
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.
|
@@ -119,10 +119,11 @@ export function useAsyncDoc (collection, id, options) {
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
export function useQuery$ (collection, query, options) {
|
|
122
|
+
const normalizedQuery = normalizeQuery(query, 'useQuery')
|
|
122
123
|
const $collection = getCollectionSignal(collection, query, 'useQuery')
|
|
123
124
|
const normalizedOptions = normalizeSyncSubOptions(options)
|
|
124
|
-
const $query = useSub($collection,
|
|
125
|
-
return $query
|
|
125
|
+
const $query = useSub($collection, normalizedQuery, normalizedOptions)
|
|
126
|
+
return isExtraQuery(normalizedQuery) ? $query.extra : $query
|
|
126
127
|
}
|
|
127
128
|
|
|
128
129
|
export function useQuery (collection, query, options) {
|
|
@@ -133,9 +134,11 @@ export function useQuery (collection, query, options) {
|
|
|
133
134
|
}
|
|
134
135
|
|
|
135
136
|
export function useAsyncQuery$ (collection, query, options) {
|
|
137
|
+
const normalizedQuery = normalizeQuery(query, 'useAsyncQuery')
|
|
136
138
|
const $collection = getCollectionSignal(collection, query, 'useAsyncQuery')
|
|
137
|
-
const $query = useAsyncSub($collection,
|
|
138
|
-
return $query
|
|
139
|
+
const $query = useAsyncSub($collection, normalizedQuery, options)
|
|
140
|
+
if (!$query) return $query
|
|
141
|
+
return isExtraQuery(normalizedQuery) ? $query.extra : $query
|
|
139
142
|
}
|
|
140
143
|
|
|
141
144
|
export function useAsyncQuery (collection, query, options) {
|
|
@@ -150,7 +153,9 @@ export function useBatchQuery$ (collection, query, _options) {
|
|
|
150
153
|
const $collection = getCollectionSignal(collection, query, 'useBatchQuery')
|
|
151
154
|
registerBatchQueryReadinessCheck(collection, normalizedQuery)
|
|
152
155
|
const options = _options ? { ..._options, ...BATCH_SUB_OPTIONS } : BATCH_SUB_OPTIONS
|
|
153
|
-
|
|
156
|
+
const $query = useSub($collection, normalizedQuery, options)
|
|
157
|
+
if (!$query) return $query
|
|
158
|
+
return isExtraQuery(normalizedQuery) ? $query.extra : $query
|
|
154
159
|
}
|
|
155
160
|
|
|
156
161
|
export function useBatchQuery (collection, query, options) {
|
|
@@ -317,6 +322,15 @@ function normalizeQuery (query, hookName) {
|
|
|
317
322
|
return query
|
|
318
323
|
}
|
|
319
324
|
|
|
325
|
+
function isExtraQuery (query) {
|
|
326
|
+
if (!query || typeof query !== 'object') return false
|
|
327
|
+
return !!(
|
|
328
|
+
query.$count ||
|
|
329
|
+
query.$queryName ||
|
|
330
|
+
query.$aggregationName
|
|
331
|
+
)
|
|
332
|
+
}
|
|
333
|
+
|
|
320
334
|
const BATCH_SUB_OPTIONS = Object.freeze({
|
|
321
335
|
async: false,
|
|
322
336
|
batch: true,
|
|
@@ -378,11 +392,20 @@ function registerBatchQueryReadinessCheck (collection, query) {
|
|
|
378
392
|
const extraSegments = [QUERIES, hash, 'extra']
|
|
379
393
|
const aggregationSegments = [AGGREGATIONS, hash]
|
|
380
394
|
const isAggregate = Array.isArray(query.$aggregate)
|
|
395
|
+
const hasExtraResult = isExtraQuery(query)
|
|
381
396
|
promiseBatcher.addCheck({
|
|
382
397
|
key: `query:${hash}`,
|
|
383
|
-
type: 'query',
|
|
384
|
-
details: { collection, hash, query, isAggregate },
|
|
385
|
-
isReady: () => isQueryReady(
|
|
398
|
+
type: hasExtraResult ? 'queryExtra' : 'query',
|
|
399
|
+
details: { collection, hash, query, isAggregate, hasExtraResult },
|
|
400
|
+
isReady: () => isQueryReady(
|
|
401
|
+
collection,
|
|
402
|
+
idsSegments,
|
|
403
|
+
docsSegments,
|
|
404
|
+
extraSegments,
|
|
405
|
+
aggregationSegments,
|
|
406
|
+
isAggregate,
|
|
407
|
+
hasExtraResult
|
|
408
|
+
),
|
|
386
409
|
getState: () => {
|
|
387
410
|
const ids = getRaw(idsSegments)
|
|
388
411
|
const docs = getRaw(docsSegments)
|
|
@@ -404,7 +427,18 @@ function registerBatchQueryReadinessCheck (collection, query) {
|
|
|
404
427
|
})
|
|
405
428
|
}
|
|
406
429
|
|
|
407
|
-
function isQueryReady (
|
|
430
|
+
function isQueryReady (
|
|
431
|
+
collection,
|
|
432
|
+
idsSegments,
|
|
433
|
+
docsSegments,
|
|
434
|
+
extraSegments,
|
|
435
|
+
aggregationSegments,
|
|
436
|
+
isAggregate,
|
|
437
|
+
hasExtraResult
|
|
438
|
+
) {
|
|
439
|
+
if (hasExtraResult) {
|
|
440
|
+
return getRaw(extraSegments) !== undefined
|
|
441
|
+
}
|
|
408
442
|
if (isAggregate) {
|
|
409
443
|
const docs = getRaw(docsSegments)
|
|
410
444
|
if (Array.isArray(docs)) return true
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "teamplay",
|
|
3
|
-
"version": "0.4.0-alpha.
|
|
3
|
+
"version": "0.4.0-alpha.59",
|
|
4
4
|
"description": "Full-stack signals ORM with multiplayer",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -83,5 +83,5 @@
|
|
|
83
83
|
]
|
|
84
84
|
},
|
|
85
85
|
"license": "MIT",
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "c981ac82c249772524a9ccd5ccb4f6d437af4e4c"
|
|
87
87
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const compatComponentIds = new Set()
|
|
2
|
+
|
|
3
|
+
export function markCompatComponent (componentId) {
|
|
4
|
+
if (!componentId) return
|
|
5
|
+
compatComponentIds.add(componentId)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function unmarkCompatComponent (componentId) {
|
|
9
|
+
if (!componentId) return
|
|
10
|
+
compatComponentIds.delete(componentId)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function isCompatComponent (componentId) {
|
|
14
|
+
if (!componentId) return false
|
|
15
|
+
return compatComponentIds.has(componentId)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function __resetCompatComponentRegistryForTests () {
|
|
19
|
+
compatComponentIds.clear()
|
|
20
|
+
}
|
|
@@ -7,6 +7,7 @@ import executionContextTracker from './executionContextTracker.js'
|
|
|
7
7
|
import { pipeComponentMeta, useUnmount, useId, useTriggerUpdate } from './helpers.js'
|
|
8
8
|
import trapRender from './trapRender.js'
|
|
9
9
|
import { scheduleReaction } from '../orm/batchScheduler.js'
|
|
10
|
+
import { isCompatComponent, unmarkCompatComponent } from './compatComponentRegistry.js'
|
|
10
11
|
|
|
11
12
|
const DEFAULT_THROTTLE_TIMEOUT = 100
|
|
12
13
|
|
|
@@ -33,15 +34,29 @@ export default function convertToObserver (BaseComponent, {
|
|
|
33
34
|
const reactionRef = useRef()
|
|
34
35
|
const destroyRef = useRef()
|
|
35
36
|
if (!reactionRef.current) {
|
|
37
|
+
let hasDeferredUpdateAfterExecutionContext = false
|
|
36
38
|
let update = () => {
|
|
37
39
|
// It's important to block updates caused by rendering itself
|
|
38
40
|
// (when the sync rendering is in progress).
|
|
39
|
-
if (!executionContextTracker.isActive())
|
|
41
|
+
if (!executionContextTracker.isActive()) {
|
|
42
|
+
hasDeferredUpdateAfterExecutionContext = false
|
|
43
|
+
triggerUpdate()
|
|
44
|
+
} else if (isCompatComponent(componentId)) {
|
|
45
|
+
if (hasDeferredUpdateAfterExecutionContext) return
|
|
46
|
+
hasDeferredUpdateAfterExecutionContext = true
|
|
47
|
+
queueMicrotask(() => {
|
|
48
|
+
if (!hasDeferredUpdateAfterExecutionContext) return
|
|
49
|
+
if (executionContextTracker.isActive()) return
|
|
50
|
+
hasDeferredUpdateAfterExecutionContext = false
|
|
51
|
+
update()
|
|
52
|
+
})
|
|
53
|
+
}
|
|
40
54
|
}
|
|
41
55
|
if (throttle) update = _throttle(update, throttle)
|
|
42
56
|
destroyRef.current = (where) => {
|
|
43
57
|
if (!reactionRef.current) throw Error(`NO REACTION REF - ${where}`)
|
|
44
58
|
destroyRef.current = undefined
|
|
59
|
+
unmarkCompatComponent(componentId)
|
|
45
60
|
unobserve(reactionRef.current)
|
|
46
61
|
reactionRef.current = undefined
|
|
47
62
|
destroyCache(where)
|
|
@@ -60,6 +75,7 @@ export default function convertToObserver (BaseComponent, {
|
|
|
60
75
|
|
|
61
76
|
// clean up observer on unmount
|
|
62
77
|
useUnmount(() => {
|
|
78
|
+
unmarkCompatComponent(componentId)
|
|
63
79
|
destroyRef.current?.('useUnmount()')
|
|
64
80
|
})
|
|
65
81
|
|
package/react/useSub.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { useRef, useDeferredValue } from 'react'
|
|
2
2
|
import sub from '../orm/sub.js'
|
|
3
|
-
import { useScheduleUpdate, useCache, useDefer } from './helpers.js'
|
|
3
|
+
import { useScheduleUpdate, useCache, useDefer, useId } from './helpers.js'
|
|
4
4
|
import executionContextTracker from './executionContextTracker.js'
|
|
5
5
|
import * as promiseBatcher from './promiseBatcher.js'
|
|
6
6
|
import renderAttemptDestroyer from './renderAttemptDestroyer.js'
|
|
7
|
+
import { markCompatComponent } from './compatComponentRegistry.js'
|
|
7
8
|
|
|
8
9
|
let TEST_THROTTLING = false
|
|
9
10
|
|
|
@@ -28,8 +29,10 @@ export default function useSub (signal, params, options) {
|
|
|
28
29
|
// version of sub() which works as a react hook and throws promise for Suspense
|
|
29
30
|
export function useSubDeferred (signal, params, { async = false, defer, batch = false, compatAttemptCleanup = false } = {}) {
|
|
30
31
|
const $signalRef = useRef() // eslint-disable-line react-hooks/rules-of-hooks
|
|
32
|
+
const componentId = useId()
|
|
31
33
|
const scheduleUpdate = useScheduleUpdate()
|
|
32
34
|
const observerDefer = useDefer()
|
|
35
|
+
if (compatAttemptCleanup) markCompatComponent(componentId)
|
|
33
36
|
if (batch) promiseBatcher.activate()
|
|
34
37
|
defer ??= observerDefer ?? DEFAULT_DEFER
|
|
35
38
|
if (defer) {
|
|
@@ -72,9 +75,11 @@ export function useSubDeferred (signal, params, { async = false, defer, batch =
|
|
|
72
75
|
// but if we get a promise second time, we return the last signal and wait for promise to resolve
|
|
73
76
|
export function useSubClassic (signal, params, { async = false, batch = false, compatAttemptCleanup = false } = {}) {
|
|
74
77
|
const id = executionContextTracker.newHookId()
|
|
78
|
+
const componentId = useId()
|
|
75
79
|
const cache = useCache()
|
|
76
80
|
const activePromiseRef = useRef()
|
|
77
81
|
const scheduleUpdate = useScheduleUpdate()
|
|
82
|
+
if (compatAttemptCleanup) markCompatComponent(componentId)
|
|
78
83
|
if (batch) promiseBatcher.activate()
|
|
79
84
|
const promiseOrSignal = params != null ? sub(signal, params) : sub(signal)
|
|
80
85
|
// 1. if it's a promise, throw it so that Suspense can catch it and wait for subscription to finish
|