teamplay 0.5.0-alpha.8 → 0.5.0
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/README.md +3 -3
- package/dist/config.d.ts +2 -0
- package/dist/config.js +1 -0
- package/dist/connect/index.d.ts +1 -1
- package/dist/connect/index.js +6 -2
- package/dist/connect/offline/index.d.ts +1 -1
- package/dist/connect/offline/index.js +8 -4
- package/dist/connect/offline/react-native.d.ts +1 -1
- package/dist/connect/offline/web.d.ts +1 -1
- package/dist/connect/test.d.ts +1 -1
- package/dist/connect/test.js +5 -1
- package/dist/index.d.ts +9 -5
- package/dist/index.js +6 -5
- package/dist/orm/$.js +1 -1
- package/dist/orm/Aggregation.d.ts +5 -3
- package/dist/orm/Aggregation.js +39 -15
- package/dist/orm/Doc.js +0 -55
- package/dist/orm/Query.d.ts +1 -0
- package/dist/orm/Query.js +25 -82
- package/dist/orm/Root.d.ts +4 -0
- package/dist/orm/Root.js +16 -0
- package/dist/orm/Signal.d.ts +0 -2
- package/dist/orm/Signal.js +1 -4
- package/dist/orm/SignalBase.d.ts +21 -1
- package/dist/orm/SignalBase.js +259 -56
- package/dist/orm/batchScheduler.d.ts +7 -7
- package/dist/orm/connection.d.ts +0 -4
- package/dist/orm/connection.js +0 -12
- package/dist/orm/dataTree.d.ts +12 -12
- package/dist/orm/dataTree.js +55 -107
- package/dist/orm/disposeRootContext.js +0 -14
- package/dist/orm/events.d.ts +6 -0
- package/dist/orm/events.js +48 -0
- package/dist/orm/getSignal.d.ts +1 -1
- package/dist/orm/getSignal.js +4 -33
- package/dist/orm/idFields.d.ts +10 -1
- package/dist/orm/idFields.js +102 -14
- package/dist/orm/index.d.ts +2 -0
- package/dist/orm/index.js +1 -0
- package/dist/orm/initModels.js +1 -1
- package/dist/orm/privateData.d.ts +7 -22
- package/dist/orm/privateData.js +20 -1
- package/dist/orm/queryReadiness.d.ts +13 -0
- package/dist/orm/{Compat/queryReadiness.js → queryReadiness.js} +10 -10
- package/dist/orm/reaction.d.ts +11 -0
- package/dist/orm/reaction.js +47 -0
- package/dist/orm/rootContext.d.ts +0 -16
- package/dist/orm/rootContext.js +0 -28
- package/dist/orm/signalMetadata.js +3 -3
- package/dist/orm/signalReads.js +3 -9
- package/dist/orm/signalStorageMutations.d.ts +0 -2
- package/dist/orm/signalStorageMutations.js +0 -9
- package/dist/orm/signalSymbols.js +1 -1
- package/dist/orm/signalValueMutations.d.ts +1 -1
- package/dist/orm/signalValueMutations.js +0 -3
- package/dist/orm/sub.d.ts +12 -7
- package/dist/orm/sub.js +87 -30
- package/dist/orm/subscriptionGcDelay.js +2 -6
- package/dist/react/convertToObserver.js +1 -4
- package/dist/react/promiseBatcher.js +1 -1
- package/dist/react/renderAttemptDestroyer.d.ts +0 -8
- package/dist/react/renderAttemptDestroyer.js +2 -28
- package/dist/react/trapRender.js +3 -3
- package/dist/react/useSub.d.ts +86 -5
- package/dist/react/useSub.js +191 -32
- package/dist/react/useSuspendMemo.js +1 -5
- package/dist/server.d.ts +2 -3
- package/dist/server.js +5 -3
- package/package.json +16 -14
- package/dist/orm/Compat/SignalCompat.d.ts +0 -3
- package/dist/orm/Compat/SignalCompat.js +0 -1267
- package/dist/orm/Compat/eventsCompat.d.ts +0 -3
- package/dist/orm/Compat/eventsCompat.js +0 -73
- package/dist/orm/Compat/hooksCompat.d.ts +0 -33
- package/dist/orm/Compat/hooksCompat.js +0 -360
- package/dist/orm/Compat/modelEvents.d.ts +0 -6
- package/dist/orm/Compat/modelEvents.js +0 -228
- package/dist/orm/Compat/queryReadiness.d.ts +0 -5
- package/dist/orm/Compat/refFallback.d.ts +0 -13
- package/dist/orm/Compat/refFallback.js +0 -65
- package/dist/orm/Compat/refRegistry.d.ts +0 -6
- package/dist/orm/Compat/refRegistry.js +0 -54
- package/dist/orm/Compat/silentContext.d.ts +0 -5
- package/dist/orm/Compat/silentContext.js +0 -48
- package/dist/orm/Compat/startStopCompat.d.ts +0 -3
- package/dist/orm/Compat/startStopCompat.js +0 -217
- package/dist/orm/compatEnv.d.ts +0 -1
- package/dist/orm/compatEnv.js +0 -4
- package/dist/react/compatComponentRegistry.d.ts +0 -4
- package/dist/react/compatComponentRegistry.js +0 -19
- /package/dist/orm/{Reaction.d.ts → reactionSubscriptions.d.ts} +0 -0
- /package/dist/orm/{Reaction.js → reactionSubscriptions.js} +0 -0
package/dist/react/useSub.js
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { useRef, useDeferredValue } from 'react';
|
|
2
2
|
import sub from "../orm/sub.js";
|
|
3
|
-
import { useScheduleUpdate, useCache, useDefer
|
|
3
|
+
import { useScheduleUpdate, useCache, useDefer } from "./helpers.js";
|
|
4
4
|
import executionContextTracker from "./executionContextTracker.js";
|
|
5
5
|
import * as promiseBatcher from "./promiseBatcher.js";
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
6
|
+
import { getPrivateData } from '../orm/privateData.js';
|
|
7
|
+
import { isDocReady } from '../orm/queryReadiness.js';
|
|
8
|
+
import { getRoot, ROOT_ID } from "../orm/Root.js";
|
|
9
|
+
import { COLLECTION_NAME, HASH, IS_QUERY, PARAMS, QUERIES, querySubscriptions, materializeQueryDataDocsToCollection } from '../orm/Query.js';
|
|
10
|
+
import { AGGREGATIONS, IS_AGGREGATION, aggregationSubscriptions } from '../orm/Aggregation.js';
|
|
11
|
+
import { SEGMENTS } from "../orm/signalSymbols.js";
|
|
12
|
+
import { isPublicDocumentSignal } from "../orm/Signal.js";
|
|
8
13
|
const runtimeSub = sub;
|
|
14
|
+
const USE_SUB_OPTION_KEYS = new Set(['async', 'defer', 'batch']);
|
|
9
15
|
let TEST_THROTTLING = false;
|
|
10
16
|
// experimental feature to leverage useDeferredValue() to handle re-subscriptions.
|
|
11
17
|
// Currently it does lead to issues with extra rerenders and requires further investigation
|
|
@@ -13,12 +19,39 @@ let USE_DEFERRED_VALUE = true;
|
|
|
13
19
|
// by default we want to defer stuff if possible instead of throwing promises
|
|
14
20
|
let DEFAULT_DEFER = true;
|
|
15
21
|
export function useAsyncSub(signal, params, options) {
|
|
16
|
-
|
|
22
|
+
const normalized = normalizeUseSubArgs(signal, params, options);
|
|
23
|
+
return runUseSub(normalized.signal, normalized.params, { ...normalized.options, async: true });
|
|
24
|
+
}
|
|
25
|
+
export function useBatchSub(signal, params, options) {
|
|
26
|
+
const callUseSub = useSub;
|
|
27
|
+
if (arguments.length === 0) {
|
|
28
|
+
return callUseSub(undefined, undefined, { batch: true });
|
|
29
|
+
}
|
|
30
|
+
const normalized = normalizeUseSubArgs(signal, params, options);
|
|
31
|
+
return callUseSub(normalized.signal, normalized.params, { ...normalized.options, async: false, batch: true });
|
|
17
32
|
}
|
|
18
33
|
export default function useSub(signal, params, options) {
|
|
19
|
-
|
|
34
|
+
const normalized = normalizeUseSubArgs(signal, params, options);
|
|
35
|
+
return runUseSub(normalized.signal, normalized.params, normalized.options);
|
|
36
|
+
}
|
|
37
|
+
function normalizeUseSubArgs(signal, params, options) {
|
|
38
|
+
if (options === undefined && params !== undefined && isPublicDocumentSignal(signal) && isUseSubOptions(params)) {
|
|
39
|
+
return {
|
|
40
|
+
signal,
|
|
41
|
+
params: undefined,
|
|
42
|
+
options: params
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return { signal, params, options };
|
|
46
|
+
}
|
|
47
|
+
function isUseSubOptions(value) {
|
|
48
|
+
if (value == null || typeof value !== 'object' || Array.isArray(value))
|
|
49
|
+
return false;
|
|
50
|
+
return Object.keys(value).every(key => USE_SUB_OPTION_KEYS.has(key));
|
|
20
51
|
}
|
|
21
52
|
function runUseSub(signal, params, options) {
|
|
53
|
+
if (isBatchBarrierCall(signal, params, options))
|
|
54
|
+
return closeBatchBarrier();
|
|
22
55
|
if (USE_DEFERRED_VALUE) {
|
|
23
56
|
return useSubDeferred(signal, params, options); // eslint-disable-line react-hooks/rules-of-hooks
|
|
24
57
|
}
|
|
@@ -26,14 +59,19 @@ function runUseSub(signal, params, options) {
|
|
|
26
59
|
return useSubClassic(signal, params, options); // eslint-disable-line react-hooks/rules-of-hooks
|
|
27
60
|
}
|
|
28
61
|
}
|
|
62
|
+
function isBatchBarrierCall(signal, params, options) {
|
|
63
|
+
return signal === undefined && params === undefined && !!options?.batch;
|
|
64
|
+
}
|
|
65
|
+
function closeBatchBarrier() {
|
|
66
|
+
const promise = promiseBatcher.getPromiseAll();
|
|
67
|
+
if (promise)
|
|
68
|
+
throw promise;
|
|
69
|
+
}
|
|
29
70
|
// version of sub() which works as a react hook and throws promise for Suspense
|
|
30
|
-
export function useSubDeferred(signal, params, { async = false, defer, batch = false
|
|
71
|
+
export function useSubDeferred(signal, params, { async = false, defer, batch = false } = {}) {
|
|
31
72
|
const $signalRef = useRef();
|
|
32
|
-
const componentId = useId();
|
|
33
73
|
const scheduleUpdate = useScheduleUpdate();
|
|
34
74
|
const observerDefer = useDefer();
|
|
35
|
-
if (compatAttemptCleanup)
|
|
36
|
-
markCompatComponent(componentId);
|
|
37
75
|
if (batch)
|
|
38
76
|
promiseBatcher.activate();
|
|
39
77
|
defer ??= observerDefer ?? DEFAULT_DEFER;
|
|
@@ -46,20 +84,20 @@ export function useSubDeferred(signal, params, { async = false, defer, batch = f
|
|
|
46
84
|
// 1. if it's a promise, throw it so that Suspense can catch it and wait for subscription to finish
|
|
47
85
|
if (isThenable(promiseOrSignal)) {
|
|
48
86
|
const promise = maybeThrottle(promiseOrSignal);
|
|
87
|
+
const readyPromise = batch ? getBatchReadyPromise(promise) : promise;
|
|
49
88
|
const hasPreviousSignal = !!$signalRef.current;
|
|
50
89
|
if (batch) {
|
|
51
90
|
// Batch suspense must block only on initial load.
|
|
52
91
|
// On resubscribe we keep rendering previous signal and refresh in background.
|
|
53
92
|
if (!hasPreviousSignal) {
|
|
54
93
|
promiseBatcher.add(promise);
|
|
55
|
-
|
|
56
|
-
registerCompatAttemptCleanup(signal, params);
|
|
94
|
+
addBatchReadinessCheck(promise);
|
|
57
95
|
}
|
|
58
96
|
else {
|
|
59
|
-
scheduleUpdate(
|
|
97
|
+
scheduleUpdate(readyPromise);
|
|
60
98
|
}
|
|
61
99
|
if (async)
|
|
62
|
-
scheduleUpdate(
|
|
100
|
+
scheduleUpdate(readyPromise);
|
|
63
101
|
return $signalRef.current;
|
|
64
102
|
}
|
|
65
103
|
if (async) {
|
|
@@ -71,13 +109,13 @@ export function useSubDeferred(signal, params, { async = false, defer, batch = f
|
|
|
71
109
|
scheduleUpdate(promise);
|
|
72
110
|
return $signalRef.current;
|
|
73
111
|
}
|
|
74
|
-
if (compatAttemptCleanup)
|
|
75
|
-
registerCompatAttemptCleanup(signal, params);
|
|
76
112
|
throw promise;
|
|
77
113
|
// 2. if it's a signal, we save it into ref to make sure it's not garbage collected while component exists
|
|
78
114
|
}
|
|
79
115
|
else {
|
|
80
116
|
const $signal = promiseOrSignal;
|
|
117
|
+
if (batch && !$signalRef.current)
|
|
118
|
+
addBatchReadinessCheckForSignal($signal);
|
|
81
119
|
if ($signalRef.current !== $signal)
|
|
82
120
|
$signalRef.current = $signal;
|
|
83
121
|
return $signal;
|
|
@@ -85,33 +123,30 @@ export function useSubDeferred(signal, params, { async = false, defer, batch = f
|
|
|
85
123
|
}
|
|
86
124
|
// classic version which initially throws promise for Suspense
|
|
87
125
|
// but if we get a promise second time, we return the last signal and wait for promise to resolve
|
|
88
|
-
export function useSubClassic(signal, params, { async = false, batch = false
|
|
126
|
+
export function useSubClassic(signal, params, { async = false, batch = false } = {}) {
|
|
89
127
|
const id = executionContextTracker.newHookId();
|
|
90
|
-
const componentId = useId();
|
|
91
128
|
const cache = useCache(undefined);
|
|
92
129
|
const scheduleUpdate = useScheduleUpdate();
|
|
93
|
-
if (compatAttemptCleanup)
|
|
94
|
-
markCompatComponent(componentId);
|
|
95
130
|
if (batch)
|
|
96
131
|
promiseBatcher.activate();
|
|
97
132
|
const promiseOrSignal = params != null ? runtimeSub(signal, params) : runtimeSub(signal);
|
|
98
133
|
// 1. if it's a promise, throw it so that Suspense can catch it and wait for subscription to finish
|
|
99
134
|
if (isThenable(promiseOrSignal)) {
|
|
100
135
|
const promise = maybeThrottle(promiseOrSignal);
|
|
136
|
+
const readyPromise = batch ? getBatchReadyPromise(promise) : promise;
|
|
101
137
|
if (batch) {
|
|
102
138
|
const hasPreviousSignal = cache.has(id);
|
|
103
139
|
// Batch suspense must block only on initial load.
|
|
104
140
|
// On resubscribe we keep rendering previous signal and refresh in background.
|
|
105
141
|
if (!hasPreviousSignal) {
|
|
106
142
|
promiseBatcher.add(promise);
|
|
107
|
-
|
|
108
|
-
registerCompatAttemptCleanup(signal, params);
|
|
143
|
+
addBatchReadinessCheck(promise);
|
|
109
144
|
}
|
|
110
145
|
else {
|
|
111
|
-
scheduleUpdate(
|
|
146
|
+
scheduleUpdate(readyPromise);
|
|
112
147
|
}
|
|
113
148
|
if (async)
|
|
114
|
-
scheduleUpdate(
|
|
149
|
+
scheduleUpdate(readyPromise);
|
|
115
150
|
if (hasPreviousSignal)
|
|
116
151
|
return cache.get(id);
|
|
117
152
|
return;
|
|
@@ -126,8 +161,6 @@ export function useSubClassic(signal, params, { async = false, batch = false, co
|
|
|
126
161
|
scheduleUpdate(promise);
|
|
127
162
|
return;
|
|
128
163
|
}
|
|
129
|
-
if (compatAttemptCleanup)
|
|
130
|
-
registerCompatAttemptCleanup(signal, params);
|
|
131
164
|
// in regular mode we throw the promise to be caught by Suspense
|
|
132
165
|
// this way we guarantee that the signal with all the data
|
|
133
166
|
// will always be there when component is rendered
|
|
@@ -140,6 +173,8 @@ export function useSubClassic(signal, params, { async = false, batch = false, co
|
|
|
140
173
|
}
|
|
141
174
|
else {
|
|
142
175
|
const $signal = promiseOrSignal;
|
|
176
|
+
if (batch && !cache.has(id))
|
|
177
|
+
addBatchReadinessCheckForSignal($signal);
|
|
143
178
|
if (cache.get(id) !== $signal) {
|
|
144
179
|
cache.set(id, $signal);
|
|
145
180
|
}
|
|
@@ -175,15 +210,139 @@ function maybeThrottle(promise) {
|
|
|
175
210
|
}, delay);
|
|
176
211
|
});
|
|
177
212
|
}
|
|
213
|
+
function addBatchReadinessCheck(promise) {
|
|
214
|
+
let resolvedSignal;
|
|
215
|
+
let resolved = false;
|
|
216
|
+
promise.then(signal => {
|
|
217
|
+
resolvedSignal = signal;
|
|
218
|
+
resolved = true;
|
|
219
|
+
}, () => {
|
|
220
|
+
resolved = true;
|
|
221
|
+
});
|
|
222
|
+
promiseBatcher.addCheck({
|
|
223
|
+
key: promise,
|
|
224
|
+
type: 'subscription',
|
|
225
|
+
isReady: () => resolved && isBatchSignalReady(resolvedSignal),
|
|
226
|
+
getState: () => getBatchSignalState(resolvedSignal)
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
function getBatchReadyPromise(promise) {
|
|
230
|
+
return Promise.resolve(promise).then(async (signal) => {
|
|
231
|
+
await waitForBatchSignalReady(signal);
|
|
232
|
+
return signal;
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
async function waitForBatchSignalReady(signal) {
|
|
236
|
+
while (!isBatchSignalReady(signal)) {
|
|
237
|
+
await new Promise(resolve => setTimeout(resolve, 16));
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
function addBatchReadinessCheckForSignal(signal) {
|
|
241
|
+
if (isBatchSignalReady(signal))
|
|
242
|
+
return;
|
|
243
|
+
const promise = Promise.resolve(signal);
|
|
244
|
+
promiseBatcher.add(promise);
|
|
245
|
+
addBatchReadinessCheck(promise);
|
|
246
|
+
}
|
|
247
|
+
function isBatchSignalReady(signal) {
|
|
248
|
+
if (isPublicDocumentSignal(signal)) {
|
|
249
|
+
const $doc = signal;
|
|
250
|
+
return isDocReady($doc[SEGMENTS]);
|
|
251
|
+
}
|
|
252
|
+
if (isQuerySignal(signal))
|
|
253
|
+
return isBatchQueryReady(signal);
|
|
254
|
+
return true;
|
|
255
|
+
}
|
|
256
|
+
function isBatchQueryReady(signal) {
|
|
257
|
+
const collection = signal[COLLECTION_NAME];
|
|
258
|
+
const params = signal[PARAMS];
|
|
259
|
+
if (!isBatchQueryTransportStable(signal))
|
|
260
|
+
return false;
|
|
261
|
+
const hasExtraResult = isExtraQuery(params);
|
|
262
|
+
if (hasExtraResult)
|
|
263
|
+
return readQueryExtra(signal) !== undefined;
|
|
264
|
+
const isAggregate = !!signal[IS_AGGREGATION] || isAggregationQuery(params);
|
|
265
|
+
const docs = signal.get();
|
|
266
|
+
if (isAggregate) {
|
|
267
|
+
if (Array.isArray(docs))
|
|
268
|
+
return true;
|
|
269
|
+
return readQueryExtra(signal) !== undefined;
|
|
270
|
+
}
|
|
271
|
+
if (!Array.isArray(docs))
|
|
272
|
+
return false;
|
|
273
|
+
materializeQueryDataDocsToCollection(collection, docs);
|
|
274
|
+
const ids = signal.getIds();
|
|
275
|
+
for (const id of ids) {
|
|
276
|
+
if (id == null)
|
|
277
|
+
continue;
|
|
278
|
+
if (!isDocReady([collection, id]))
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
return true;
|
|
282
|
+
}
|
|
283
|
+
function isBatchQueryTransportStable(signal) {
|
|
284
|
+
const subscriptions = signal[IS_AGGREGATION] ? aggregationSubscriptions : querySubscriptions;
|
|
285
|
+
const entry = subscriptions.entries.get(signal[HASH]);
|
|
286
|
+
if (!entry)
|
|
287
|
+
return false;
|
|
288
|
+
return entry.phase === 'stable' && entry.mode === entry.targetMode;
|
|
289
|
+
}
|
|
290
|
+
function getBatchSignalState(signal) {
|
|
291
|
+
if (isPublicDocumentSignal(signal)) {
|
|
292
|
+
const $doc = signal;
|
|
293
|
+
return {
|
|
294
|
+
kind: 'doc',
|
|
295
|
+
path: $doc[SEGMENTS],
|
|
296
|
+
ready: isDocReady($doc[SEGMENTS])
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
if (!isQuerySignal(signal))
|
|
300
|
+
return { kind: 'unknown', resolved: !!signal };
|
|
301
|
+
const rootId = getRoot(signal)?.[ROOT_ID];
|
|
302
|
+
const hash = signal[HASH];
|
|
303
|
+
const collection = signal[COLLECTION_NAME];
|
|
304
|
+
return {
|
|
305
|
+
kind: signal[IS_AGGREGATION] ? 'aggregation' : 'query',
|
|
306
|
+
collection,
|
|
307
|
+
hash,
|
|
308
|
+
ids: getPrivateData(rootId, [QUERIES, hash, 'ids'], true),
|
|
309
|
+
hasDocs: Array.isArray(getPrivateData(rootId, [QUERIES, hash, 'docs'], true)),
|
|
310
|
+
hasExtra: getPrivateData(rootId, [QUERIES, hash, 'extra'], true) !== undefined,
|
|
311
|
+
hasAggregation: getPrivateData(rootId, [AGGREGATIONS, hash], true) !== undefined
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
function readQueryExtra(signal) {
|
|
315
|
+
try {
|
|
316
|
+
return signal.extra.get();
|
|
317
|
+
}
|
|
318
|
+
catch (err) {
|
|
319
|
+
if (isThenable(err))
|
|
320
|
+
return undefined;
|
|
321
|
+
throw err;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
function isQuerySignal(signal) {
|
|
325
|
+
return !!signal &&
|
|
326
|
+
(typeof signal === 'object' || typeof signal === 'function') &&
|
|
327
|
+
!!signal[IS_QUERY] &&
|
|
328
|
+
typeof signal[COLLECTION_NAME] === 'string' &&
|
|
329
|
+
typeof signal[HASH] === 'string';
|
|
330
|
+
}
|
|
331
|
+
function isExtraQuery(query) {
|
|
332
|
+
if (!query || typeof query !== 'object')
|
|
333
|
+
return false;
|
|
334
|
+
return !!(query.$count ||
|
|
335
|
+
query.$queryName ||
|
|
336
|
+
query.$aggregationName);
|
|
337
|
+
}
|
|
338
|
+
function isAggregationQuery(query) {
|
|
339
|
+
if (!query || typeof query !== 'object')
|
|
340
|
+
return false;
|
|
341
|
+
return !!(query.$aggregate ||
|
|
342
|
+
query.$aggregationName);
|
|
343
|
+
}
|
|
178
344
|
function isThenable(value) {
|
|
179
345
|
return !!value &&
|
|
180
346
|
(typeof value === 'object' || typeof value === 'function') &&
|
|
181
347
|
typeof value.then === 'function';
|
|
182
348
|
}
|
|
183
|
-
function registerCompatAttemptCleanup(_signal, _params) {
|
|
184
|
-
// Compat hooks don't build per-hook init objects like Racer.
|
|
185
|
-
// We still need a marker so trapRender can defer observer-shell cleanup
|
|
186
|
-
// only when a real attempt cleanup exists.
|
|
187
|
-
// This path must not arm suspense-gate keep-alive by itself.
|
|
188
|
-
renderAttemptDestroyer.armCompatAttemptCleanup();
|
|
189
|
-
}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import executionContextTracker from "./executionContextTracker.js";
|
|
2
|
-
import { useCache
|
|
3
|
-
import { markCompatComponent } from "./compatComponentRegistry.js";
|
|
2
|
+
import { useCache } from "./helpers.js";
|
|
4
3
|
import renderAttemptDestroyer from "./renderAttemptDestroyer.js";
|
|
5
4
|
const IN_FLIGHT_BY_KEY = new Map();
|
|
6
5
|
export default function useSuspendMemo(factory, deps) {
|
|
7
6
|
if (typeof factory !== 'function')
|
|
8
7
|
throw Error('useSuspendMemo() expects a factory function');
|
|
9
8
|
deps = normalizeDeps(deps);
|
|
10
|
-
const componentId = useId();
|
|
11
9
|
const cache = useCache(undefined);
|
|
12
10
|
const hookId = executionContextTracker.newHookId();
|
|
13
11
|
const cacheKey = `suspendMemo:${hookId}`;
|
|
@@ -24,7 +22,6 @@ export default function useSuspendMemo(factory, deps) {
|
|
|
24
22
|
if (entry.status === 'done')
|
|
25
23
|
return entry.value;
|
|
26
24
|
if (entry.status === 'pending') {
|
|
27
|
-
markCompatComponent(componentId);
|
|
28
25
|
renderAttemptDestroyer.armSuspenseGate();
|
|
29
26
|
throw entry.promise;
|
|
30
27
|
}
|
|
@@ -45,7 +42,6 @@ export default function useSuspendMemo(factory, deps) {
|
|
|
45
42
|
});
|
|
46
43
|
entry.status = 'pending';
|
|
47
44
|
entry.promise = promise;
|
|
48
|
-
markCompatComponent(componentId);
|
|
49
45
|
renderAttemptDestroyer.armSuspenseGate();
|
|
50
46
|
throw promise;
|
|
51
47
|
}
|
package/dist/server.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
export function createBackend(options?: {}): any;
|
|
2
|
-
export function initConnection(backend: any, { fetchOnly,
|
|
2
|
+
export function initConnection(backend: any, { fetchOnly, idFields, ...options }?: {
|
|
3
3
|
fetchOnly?: boolean | undefined;
|
|
4
|
-
publicOnly?: boolean | undefined;
|
|
5
4
|
}): {
|
|
6
5
|
middleware: (req: any, res: any, next: any) => Promise<any>;
|
|
7
6
|
upgrade: (req: any, socket: any, upgradeHead: any) => Promise<void>;
|
|
8
7
|
wss: any;
|
|
9
8
|
};
|
|
10
9
|
export default createBackend;
|
|
11
|
-
export { mongo, mongoClient, createMongoIndex, redis, redlock, sqlite } from "@teamplay/backend";
|
|
10
|
+
export { mongo, mongoClient, createMongoIndex, redis, redlock, sqlite, getRedis } from "@teamplay/backend";
|
package/dist/server.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import createChannel from '@teamplay/channel/server';
|
|
2
2
|
import backendCreateBackend from '@teamplay/backend';
|
|
3
3
|
import { getModels } from "./orm/initModels.js";
|
|
4
|
-
import { connection, setConnection, setDefaultFetchOnly
|
|
4
|
+
import { connection, setConnection, setDefaultFetchOnly } from "./orm/connection.js";
|
|
5
|
+
import { configureTeamplay } from "./config.js";
|
|
5
6
|
export { default as ShareDB } from 'sharedb';
|
|
6
7
|
export { mongo, mongoClient, createMongoIndex, redis, redlock, sqlite, getRedis, Redis, getRedisOptions, redisPrefix, generateRedisPrefix } from '@teamplay/backend';
|
|
7
8
|
export function createBackend(options = {}) {
|
|
@@ -16,13 +17,14 @@ export function createBackend(options = {}) {
|
|
|
16
17
|
return backendCreateBackend(nextOptions);
|
|
17
18
|
}
|
|
18
19
|
export default createBackend;
|
|
19
|
-
export function initConnection(backend, { fetchOnly = true,
|
|
20
|
+
export function initConnection(backend, { fetchOnly = true, idFields, ...options } = {}) {
|
|
20
21
|
if (!backend)
|
|
21
22
|
throw Error('backend is required');
|
|
22
23
|
if (connection)
|
|
23
24
|
throw Error('Connection already exists');
|
|
25
|
+
if (idFields !== undefined)
|
|
26
|
+
configureTeamplay({ idFields });
|
|
24
27
|
setConnection(backend.connect());
|
|
25
28
|
setDefaultFetchOnly(fetchOnly);
|
|
26
|
-
setPublicOnly(publicOnly);
|
|
27
29
|
return createChannel(backend, options);
|
|
28
30
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "teamplay",
|
|
3
|
-
"version": "0.5.0
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Full-stack signals ORM with multiplayer",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -26,6 +26,11 @@
|
|
|
26
26
|
"teamplay-ts": "./src/connect/index.js",
|
|
27
27
|
"default": "./dist/connect/index.js"
|
|
28
28
|
},
|
|
29
|
+
"./config": {
|
|
30
|
+
"teamplay-ts": "./src/config.ts",
|
|
31
|
+
"types": "./dist/config.d.ts",
|
|
32
|
+
"default": "./dist/config.js"
|
|
33
|
+
},
|
|
29
34
|
"./server": {
|
|
30
35
|
"teamplay-ts": "./src/server.js",
|
|
31
36
|
"types": "./dist/server.d.ts",
|
|
@@ -52,16 +57,13 @@
|
|
|
52
57
|
"scripts": {
|
|
53
58
|
"build": "rm -rf dist && tsc -p tsconfig.build.json && rsync -a --include='*/' --include='*.d.ts' --include='*.cjs' --exclude='*' src/ dist/ && node ../../scripts/rewrite-dts-extensions.cjs dist",
|
|
54
59
|
"prepublishOnly": "npm run build",
|
|
55
|
-
"test": "npm run test-types && npm run test-types:external && npm run test-server && npm run test-client
|
|
60
|
+
"test": "npm run test-types && npm run test-types:external && npm run test-server && npm run test-client",
|
|
56
61
|
"test-types": "tsc -p tsconfig.type-tests.json",
|
|
57
62
|
"test-types:external": "tsc -p tsconfig.external-consumer.json",
|
|
58
63
|
"test-types:dist": "tsc -p tsconfig.external-consumer.dist.json",
|
|
59
64
|
"test-server": "NODE_OPTIONS=\"${NODE_OPTIONS:-} --expose-gc -C teamplay-ts\" mocha 'test/[!_]*.js'",
|
|
60
65
|
"test-server-only": "NODE_OPTIONS=\"${NODE_OPTIONS:-} --expose-gc -C teamplay-ts\" mocha --grep '@only' 'test/[!_]*.js'",
|
|
61
66
|
"test-client": "NODE_OPTIONS=\"${NODE_OPTIONS:-} --expose-gc --experimental-vm-modules -C teamplay-ts\" jest --runInBand",
|
|
62
|
-
"test-compat": "npm run test-server-compat && npm run test-client-compat",
|
|
63
|
-
"test-server-compat": "TEAMPLAY_COMPAT=1 NODE_OPTIONS=\"${NODE_OPTIONS:-} --expose-gc -C teamplay-ts\" mocha 'test/[!_]*.js'",
|
|
64
|
-
"test-client-compat": "TEAMPLAY_COMPAT=1 NODE_OPTIONS=\"${NODE_OPTIONS:-} --expose-gc --experimental-vm-modules -C teamplay-ts\" jest --runInBand",
|
|
65
67
|
"coverage-server": "NODE_OPTIONS=\"${NODE_OPTIONS:-} --expose-gc -C teamplay-ts\" c8 --include 'src/orm/**' --include 'src/react/**' --include 'src/utils/**' mocha 'test/[!_]*.js'",
|
|
66
68
|
"coverage-client": "NODE_OPTIONS=\"${NODE_OPTIONS:-} --expose-gc --experimental-vm-modules -C teamplay-ts\" jest --coverage --coverageDirectory=coverage-client",
|
|
67
69
|
"coverage": "npm run coverage-server && npm run coverage-client"
|
|
@@ -69,20 +71,20 @@
|
|
|
69
71
|
"dependencies": {
|
|
70
72
|
"@nx-js/observer-util": "^4.1.3",
|
|
71
73
|
"@startupjs/sharedb-mingo-memory": "^4.0.0-2",
|
|
72
|
-
"@teamplay/backend": "^0.5.0
|
|
73
|
-
"@teamplay/cache": "^0.5.0
|
|
74
|
-
"@teamplay/channel": "^0.5.0
|
|
75
|
-
"@teamplay/debug": "^0.5.0
|
|
76
|
-
"@teamplay/schema": "^0.5.0
|
|
77
|
-
"@teamplay/utils": "^0.5.0
|
|
78
|
-
"babel-plugin-teamplay": "^0.5.0
|
|
74
|
+
"@teamplay/backend": "^0.5.0",
|
|
75
|
+
"@teamplay/cache": "^0.5.0",
|
|
76
|
+
"@teamplay/channel": "^0.5.0",
|
|
77
|
+
"@teamplay/debug": "^0.5.0",
|
|
78
|
+
"@teamplay/schema": "^0.5.0",
|
|
79
|
+
"@teamplay/utils": "^0.5.0",
|
|
80
|
+
"babel-plugin-teamplay": "^0.5.0",
|
|
79
81
|
"diff-match-patch": "^1.0.5",
|
|
80
82
|
"events": "^3.3.0",
|
|
81
83
|
"json0-ot-diff": "^1.1.2",
|
|
82
84
|
"localforage": "^1.10.0",
|
|
83
85
|
"lodash": "^4.17.20",
|
|
84
86
|
"pluralize": "^8.0.0",
|
|
85
|
-
"sharedb": "
|
|
87
|
+
"sharedb": "5.2.2",
|
|
86
88
|
"stream": "npm:readable-stream@^4.7.0"
|
|
87
89
|
},
|
|
88
90
|
"devDependencies": {
|
|
@@ -134,5 +136,5 @@
|
|
|
134
136
|
]
|
|
135
137
|
},
|
|
136
138
|
"license": "MIT",
|
|
137
|
-
"gitHead": "
|
|
139
|
+
"gitHead": "4c3274c4443ab4cb59410b070fe80fd7219e6e0d"
|
|
138
140
|
}
|