teamplay 0.5.0-alpha.14 → 0.5.0-alpha.16

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
@@ -57,7 +57,7 @@ export { default as sub } from './orm/sub.js';
57
57
  export { default as useSub, useAsyncSub, setUseDeferredValue as __setUseDeferredValue, setDefaultDefer as __setDefaultDefer } from './react/useSub.js';
58
58
  export { default as useSuspendMemo, useSuspendMemoByKey } from './react/useSuspendMemo.js';
59
59
  export declare const observer: ObserverFunction;
60
- export { useBatch, useDoc, useDoc$, useBatchDoc, useBatchDoc$, useAsyncDoc, useAsyncDoc$, useQuery, useQuery$, useAsyncQuery, useAsyncQuery$, useBatchQuery, useBatchQuery$, useQueryIds, useBatchQueryIds, useAsyncQueryIds, useQueryDoc, useQueryDoc$, useBatchQueryDoc, useBatchQueryDoc$, useAsyncQueryDoc, useAsyncQueryDoc$ } from './orm/Compat/hooksCompat.js';
60
+ export { useBatch, useBatchDoc, useBatchDoc$, useBatchQuery, useBatchQuery$, useQueryIds, useBatchQueryIds, useAsyncQueryIds, useQueryDoc, useQueryDoc$, useBatchQueryDoc, useBatchQueryDoc$, useAsyncQueryDoc, useAsyncQueryDoc$ } from './orm/Compat/hooksCompat.js';
61
61
  export { emit, useOn, useEmit } from './orm/Compat/eventsCompat.js';
62
62
  export { useDidUpdate, useOnce, useSyncEffect } from './react/helpers.js';
63
63
  export { connection, setConnection, getConnection, getDefaultFetchOnly, setDefaultFetchOnly, publicOnly, setPublicOnly } from './orm/connection.js';
package/dist/index.js CHANGED
@@ -18,7 +18,7 @@ export { default as sub } from "./orm/sub.js";
18
18
  export { default as useSub, useAsyncSub, setUseDeferredValue as __setUseDeferredValue, setDefaultDefer as __setDefaultDefer } from "./react/useSub.js";
19
19
  export { default as useSuspendMemo, useSuspendMemoByKey } from "./react/useSuspendMemo.js";
20
20
  export const observer = runtimeObserver;
21
- export { useBatch, useDoc, useDoc$, useBatchDoc, useBatchDoc$, useAsyncDoc, useAsyncDoc$, useQuery, useQuery$, useAsyncQuery, useAsyncQuery$, useBatchQuery, useBatchQuery$, useQueryIds, useBatchQueryIds, useAsyncQueryIds, useQueryDoc, useQueryDoc$, useBatchQueryDoc, useBatchQueryDoc$, useAsyncQueryDoc, useAsyncQueryDoc$ } from './orm/Compat/hooksCompat.js';
21
+ export { useBatch, useBatchDoc, useBatchDoc$, useBatchQuery, useBatchQuery$, useQueryIds, useBatchQueryIds, useAsyncQueryIds, useQueryDoc, useQueryDoc$, useBatchQueryDoc, useBatchQueryDoc$, useAsyncQueryDoc, useAsyncQueryDoc$ } from './orm/Compat/hooksCompat.js';
22
22
  export { emit, useOn, useEmit } from './orm/Compat/eventsCompat.js';
23
23
  export { useDidUpdate, useOnce, useSyncEffect } from "./react/helpers.js";
24
24
  export { connection, setConnection, getConnection, getDefaultFetchOnly, setDefaultFetchOnly, publicOnly, setPublicOnly } from "./orm/connection.js";
@@ -1,14 +1,6 @@
1
1
  export const useBatch: any
2
- export const useDoc: any
3
- export const useDoc$: any
4
2
  export const useBatchDoc: any
5
3
  export const useBatchDoc$: any
6
- export const useAsyncDoc: any
7
- export const useAsyncDoc$: any
8
- export const useQuery: any
9
- export const useQuery$: any
10
- export const useAsyncQuery: any
11
- export const useAsyncQuery$: any
12
4
  export const useBatchQuery: any
13
5
  export const useBatchQuery$: any
14
6
  export const useQueryIds: any
@@ -11,15 +11,6 @@ export function useBatch() {
11
11
  if (promise)
12
12
  throw promise;
13
13
  }
14
- export function useDoc$(collection, id, options) {
15
- const $doc = getDocSignal(collection, id, 'useDoc');
16
- const normalizedOptions = normalizeSyncSubOptions(options);
17
- return useSub($doc, undefined, normalizedOptions);
18
- }
19
- export function useDoc(collection, id, options) {
20
- const $doc = useDoc$(collection, id, options);
21
- return [$doc.get(), $doc];
22
- }
23
14
  export function useBatchDoc(collection, id, options) {
24
15
  const $doc = useBatchDoc$(collection, id, options);
25
16
  if (!$doc)
@@ -31,16 +22,6 @@ export function useBatchDoc$(collection, id, _options) {
31
22
  const options = _options ? { ..._options, ...BATCH_SUB_OPTIONS } : BATCH_SUB_OPTIONS;
32
23
  return useSub($doc, undefined, options);
33
24
  }
34
- export function useAsyncDoc$(collection, id, options) {
35
- const $doc = getDocSignal(collection, id, 'useAsyncDoc');
36
- return useAsyncSub($doc, undefined, options);
37
- }
38
- export function useAsyncDoc(collection, id, options) {
39
- const $doc = useAsyncDoc$(collection, id, options);
40
- if (!$doc)
41
- return [undefined, undefined];
42
- return [$doc.get(), $doc];
43
- }
44
25
  function useSubscribedQuery(collection, query, options, hookName, subscribe) {
45
26
  const normalizedQuery = normalizeQuery(query, hookName);
46
27
  const $collection = getCollectionSignal(collection, query, hookName);
@@ -56,22 +37,13 @@ function getExtraQuerySignal($query, normalizedQuery) {
56
37
  return $query;
57
38
  return isExtraQuery(normalizedQuery) ? $query.extra : $query;
58
39
  }
59
- export function useQuery$(collection, query, options) {
40
+ function useSyncQueryResult(collection, query, options, hookName) {
60
41
  const normalizedOptions = normalizeSyncSubOptions(options);
61
- const { $query } = useSubscribedQuery(collection, query, normalizedOptions, 'useQuery', useSub);
62
- return $query;
63
- }
64
- export function useQuery(collection, query, options) {
65
- const normalizedOptions = normalizeSyncSubOptions(options);
66
- const { $collection, $query } = useSubscribedQuery(collection, query, normalizedOptions, 'useQuery', useSub);
42
+ const { $collection, $query } = useSubscribedQuery(collection, query, normalizedOptions, hookName, useSub);
67
43
  return [$query.get(), $collection];
68
44
  }
69
- export function useAsyncQuery$(collection, query, options) {
70
- const { $query } = useSubscribedQuery(collection, query, options, 'useAsyncQuery', useAsyncSub);
71
- return $query;
72
- }
73
- export function useAsyncQuery(collection, query, options) {
74
- const { $collection, $query } = useSubscribedQuery(collection, query, options, 'useAsyncQuery', useAsyncSub);
45
+ function useAsyncQueryResult(collection, query, options, hookName) {
46
+ const { $collection, $query } = useSubscribedQuery(collection, query, options, hookName, useAsyncSub);
75
47
  if (!$query)
76
48
  return [undefined, $collection];
77
49
  return [$query.get(), $collection];
@@ -92,7 +64,7 @@ export function useQueryIds(collection, ids = [], options = {}) {
92
64
  const list = Array.isArray(ids) ? ids.slice() : [];
93
65
  if (options?.reverse)
94
66
  list.reverse();
95
- const [docs, $collection] = useQuery(collection, { _id: { $in: list } }, options);
67
+ const [docs, $collection] = useSyncQueryResult(collection, { _id: { $in: list } }, options, 'useQueryIds');
96
68
  if (!docs)
97
69
  return [docs, $collection];
98
70
  const docsById = new Map();
@@ -124,7 +96,7 @@ export function useAsyncQueryIds(collection, ids = [], options = {}) {
124
96
  const list = Array.isArray(ids) ? ids.slice() : [];
125
97
  if (options?.reverse)
126
98
  list.reverse();
127
- const [docs, $collection] = useAsyncQuery(collection, { _id: { $in: list } }, options);
99
+ const [docs, $collection] = useAsyncQueryResult(collection, { _id: { $in: list } }, options, 'useAsyncQueryIds');
128
100
  if (docs == null)
129
101
  return [undefined, $collection];
130
102
  const docsById = new Map();
@@ -143,7 +115,7 @@ export function useQueryDoc(collection, query, options) {
143
115
  $limit: 1,
144
116
  $sort: normalized.$sort || { createdAt: -1 }
145
117
  };
146
- const [docs, $collection] = useQuery(collection, queryDoc, options);
118
+ const [docs, $collection] = useSyncQueryResult(collection, queryDoc, options, 'useQueryDoc');
147
119
  const doc = docs && docs[0];
148
120
  const docId = doc?._id ?? doc?.id;
149
121
  const $doc = docId != null ? $collection[docId] : undefined;
@@ -179,7 +151,7 @@ export function useAsyncQueryDoc(collection, query, options) {
179
151
  $limit: 1,
180
152
  $sort: normalized.$sort || { createdAt: -1 }
181
153
  };
182
- const [docs, $collection] = useAsyncQuery(collection, queryDoc, options);
154
+ const [docs, $collection] = useAsyncQueryResult(collection, queryDoc, options, 'useAsyncQueryDoc');
183
155
  if (docs == null)
184
156
  return [undefined, undefined];
185
157
  const doc = docs && docs[0];
@@ -247,7 +219,6 @@ function isExtraQuery(query) {
247
219
  const BATCH_SUB_OPTIONS = Object.freeze({
248
220
  async: false,
249
221
  batch: true,
250
- renderAttemptCleanup: true,
251
222
  // Batch hooks are a hard suspense barrier. Deferred params can skip the barrier
252
223
  // on route transitions and cause immediate reads from stale/empty local nodes.
253
224
  defer: false
@@ -259,7 +230,6 @@ function normalizeSyncSubOptions(options) {
259
230
  return {
260
231
  ...(options || {}),
261
232
  async: false,
262
- renderAttemptCleanup: true,
263
233
  // Compat sync hooks are strict by design: no deferred snapshots between route/tab switches.
264
234
  defer: false
265
235
  };
@@ -7,7 +7,6 @@ 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";
11
10
  const DEFAULT_THROTTLE_TIMEOUT = 100;
12
11
  export default function convertToObserver(BaseComponent, { forwardRef, cache: enableCache = true, throttle, ...options } = {}) {
13
12
  throttle = normalizeThrottle(throttle);
@@ -33,7 +32,7 @@ export default function convertToObserver(BaseComponent, { forwardRef, cache: en
33
32
  hasDeferredUpdateAfterExecutionContext = false;
34
33
  triggerUpdate();
35
34
  }
36
- else if (isCompatComponent(componentId)) {
35
+ else {
37
36
  if (hasDeferredUpdateAfterExecutionContext)
38
37
  return;
39
38
  hasDeferredUpdateAfterExecutionContext = true;
@@ -53,7 +52,6 @@ export default function convertToObserver(BaseComponent, { forwardRef, cache: en
53
52
  if (!reactionRef.current)
54
53
  throw Error(`NO REACTION REF - ${where}`);
55
54
  destroyRef.current = undefined;
56
- unmarkCompatComponent(componentId);
57
55
  unobserve(reactionRef.current);
58
56
  reactionRef.current = undefined;
59
57
  destroyCache(where);
@@ -71,7 +69,6 @@ export default function convertToObserver(BaseComponent, { forwardRef, cache: en
71
69
  }
72
70
  // clean up observer on unmount
73
71
  useUnmount(() => {
74
- unmarkCompatComponent(componentId);
75
72
  destroyRef.current?.('useUnmount()');
76
73
  });
77
74
  return reactionRef.current(...args);
@@ -1,17 +1,9 @@
1
- type DestroyAttempt = () => unknown | Promise<unknown>;
2
1
  declare class RenderAttemptDestroyer {
3
- fns: DestroyAttempt[];
4
- renderAttemptCleanupArmed: boolean;
5
2
  suspenseGateArmed: boolean;
6
3
  constructor();
7
- add(fn: DestroyAttempt | undefined, { renderAttemptCleanup }?: {
8
- renderAttemptCleanup?: boolean;
9
- }): void;
10
- armRenderAttemptCleanup(): void;
11
4
  armSuspenseGate(): void;
12
5
  consumeThenableHandling(): {
13
6
  shouldKeepShellAlive: boolean;
14
- destroyAttempt?: () => Promise<void>;
15
7
  };
16
8
  reset(): void;
17
9
  }
@@ -1,45 +1,19 @@
1
1
  class RenderAttemptDestroyer {
2
- fns;
3
- renderAttemptCleanupArmed;
4
2
  suspenseGateArmed;
5
3
  constructor() {
6
- this.fns = [];
7
- this.renderAttemptCleanupArmed = false;
8
4
  this.suspenseGateArmed = false;
9
5
  }
10
- add(fn, { renderAttemptCleanup = false } = {}) {
11
- if (typeof fn !== 'function')
12
- return;
13
- this.fns.push(fn);
14
- if (renderAttemptCleanup)
15
- this.renderAttemptCleanupArmed = true;
16
- }
17
- armRenderAttemptCleanup() {
18
- this.renderAttemptCleanupArmed = true;
19
- }
20
6
  armSuspenseGate() {
21
7
  this.suspenseGateArmed = true;
22
8
  }
23
9
  consumeThenableHandling() {
24
- const shouldRunAttemptCleanup = this.renderAttemptCleanupArmed && this.fns.length > 0;
25
- const shouldKeepShellAlive = this.suspenseGateArmed || shouldRunAttemptCleanup;
26
- let destroyAttempt;
27
- if (shouldRunAttemptCleanup) {
28
- const fns = [...this.fns];
29
- destroyAttempt = async () => {
30
- await Promise.allSettled(fns.map(fn => fn()));
31
- fns.length = 0;
32
- };
33
- }
10
+ const shouldKeepShellAlive = this.suspenseGateArmed;
34
11
  this.reset();
35
12
  return {
36
- shouldKeepShellAlive,
37
- destroyAttempt
13
+ shouldKeepShellAlive
38
14
  };
39
15
  }
40
16
  reset() {
41
- this.fns.length = 0;
42
- this.renderAttemptCleanupArmed = false;
43
17
  this.suspenseGateArmed = false;
44
18
  }
45
19
  }
@@ -24,9 +24,9 @@ export default function trapRender({ render, cache, destroy, componentId }) {
24
24
  destroyed = true;
25
25
  throw err;
26
26
  }
27
- const { shouldKeepShellAlive, destroyAttempt } = renderAttemptDestroyer.consumeThenableHandling();
27
+ const { shouldKeepShellAlive } = renderAttemptDestroyer.consumeThenableHandling();
28
28
  if (shouldKeepShellAlive) {
29
- throw Promise.resolve(err).then(() => destroyAttempt?.());
29
+ throw Promise.resolve(err);
30
30
  }
31
31
  // TODO: this might only be needed only if promise is thrown
32
32
  // (check if useUnmount in convertToObserver is called if a regular error is thrown)
@@ -1,5 +1,5 @@
1
1
  import type { AggregationFunction, AggregationParams, ClientAggregationFunction } from '@teamplay/utils/aggregation';
2
- import type { CollectionSignal, ComputedQueryParamsInput, DocumentSignal, QueryParams, RegisteredAggregationInput, SignalModelConstructor, SubResult, TypedAggregationInput, TypedAggregationSignal, WildcardSignalPath } from '../orm/Signal.js';
2
+ import { type CollectionSignal, type ComputedQueryParamsInput, type DocumentSignal, type QueryParams, type RegisteredAggregationInput, type SignalModelConstructor, type SubResult, type TypedAggregationInput, type TypedAggregationSignal, type WildcardSignalPath } from '../orm/Signal.js';
3
3
  export interface UseSubOptions {
4
4
  /** Return `undefined` while loading instead of throwing a Suspense promise. */
5
5
  async?: boolean;
@@ -7,9 +7,14 @@ export interface UseSubOptions {
7
7
  defer?: boolean | number;
8
8
  /** Batch Suspense promises across multiple subscriptions in one render attempt. */
9
9
  batch?: boolean;
10
- /** Enable cleanup for observer render attempts when a subscription suspends. */
11
- renderAttemptCleanup?: boolean;
12
10
  }
11
+ /**
12
+ * Subscribe to a document signal in React async mode.
13
+ * @param signal Document signal to subscribe to.
14
+ * @param params Must be omitted for document subscriptions.
15
+ * @param options Subscription behavior options.
16
+ */
17
+ export declare function useAsyncSub<TSignal extends DocumentSignal<any, any, any>>(signal: TSignal, options?: UseSubOptions): SubResult<TSignal>;
13
18
  /**
14
19
  * Subscribe to a document signal in React async mode.
15
20
  * @param signal Document signal to subscribe to.
@@ -61,6 +66,13 @@ export declare function useAsyncSub<TDocument, TDocumentModel extends SignalMode
61
66
  * @param options Subscription behavior options.
62
67
  */
63
68
  export declare function useAsyncSub<TOutput = unknown, TCollection extends string = string>(signal: AggregationFunction<TOutput, TCollection>, params?: AggregationParams, options?: UseSubOptions): SubResult<AggregationFunction<TOutput, TCollection>, AggregationParams | undefined>;
69
+ /**
70
+ * Subscribe to a document signal in React.
71
+ * @param signal Document signal to subscribe to.
72
+ * @param params Must be omitted for document subscriptions.
73
+ * @param options Subscription behavior options.
74
+ */
75
+ export default function useSub<TSignal extends DocumentSignal<any, any, any>>(signal: TSignal, options?: UseSubOptions): SubResult<TSignal>;
64
76
  /**
65
77
  * Subscribe to a document signal in React.
66
78
  * @param signal Document signal to subscribe to.
@@ -112,8 +124,8 @@ export default function useSub<TDocument, TDocumentModel extends SignalModelCons
112
124
  * @param options Subscription behavior options.
113
125
  */
114
126
  export default function useSub<TOutput = unknown, TCollection extends string = string>(signal: AggregationFunction<TOutput, TCollection>, params?: AggregationParams, options?: UseSubOptions): SubResult<AggregationFunction<TOutput, TCollection>, AggregationParams | undefined>;
115
- export declare function useSubDeferred(signal: unknown, params?: unknown, { async, defer, batch, renderAttemptCleanup }?: UseSubOptions): unknown;
116
- export declare function useSubClassic(signal: unknown, params?: unknown, { async, batch, renderAttemptCleanup }?: UseSubOptions): unknown;
127
+ export declare function useSubDeferred(signal: unknown, params?: unknown, { async, defer, batch }?: UseSubOptions): unknown;
128
+ export declare function useSubClassic(signal: unknown, params?: unknown, { async, batch }?: UseSubOptions): unknown;
117
129
  export declare function setTestThrottling(ms: number): void;
118
130
  export declare function resetTestThrottling(): void;
119
131
  export declare function setUseDeferredValue(value: boolean): void;
@@ -1,11 +1,11 @@
1
1
  import { useRef, useDeferredValue } from 'react';
2
2
  import sub from "../orm/sub.js";
3
- import { useScheduleUpdate, useCache, useDefer, useId } from "./helpers.js";
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 renderAttemptDestroyer from "./renderAttemptDestroyer.js";
7
- import { markCompatComponent } from "./compatComponentRegistry.js";
6
+ import { isPublicDocumentSignal } from "../orm/Signal.js";
8
7
  const runtimeSub = sub;
8
+ const USE_SUB_OPTION_KEYS = new Set(['async', 'defer', 'batch']);
9
9
  let TEST_THROTTLING = false;
10
10
  // experimental feature to leverage useDeferredValue() to handle re-subscriptions.
11
11
  // Currently it does lead to issues with extra rerenders and requires further investigation
@@ -13,10 +13,27 @@ let USE_DEFERRED_VALUE = true;
13
13
  // by default we want to defer stuff if possible instead of throwing promises
14
14
  let DEFAULT_DEFER = true;
15
15
  export function useAsyncSub(signal, params, options) {
16
- return runUseSub(signal, params, { ...options, async: true });
16
+ const normalized = normalizeUseSubArgs(signal, params, options);
17
+ return runUseSub(normalized.signal, normalized.params, { ...normalized.options, async: true });
17
18
  }
18
19
  export default function useSub(signal, params, options) {
19
- return runUseSub(signal, params, options);
20
+ const normalized = normalizeUseSubArgs(signal, params, options);
21
+ return runUseSub(normalized.signal, normalized.params, normalized.options);
22
+ }
23
+ function normalizeUseSubArgs(signal, params, options) {
24
+ if (options === undefined && params !== undefined && isPublicDocumentSignal(signal) && isUseSubOptions(params)) {
25
+ return {
26
+ signal,
27
+ params: undefined,
28
+ options: params
29
+ };
30
+ }
31
+ return { signal, params, options };
32
+ }
33
+ function isUseSubOptions(value) {
34
+ if (value == null || typeof value !== 'object' || Array.isArray(value))
35
+ return false;
36
+ return Object.keys(value).every(key => USE_SUB_OPTION_KEYS.has(key));
20
37
  }
21
38
  function runUseSub(signal, params, options) {
22
39
  if (USE_DEFERRED_VALUE) {
@@ -27,13 +44,10 @@ function runUseSub(signal, params, options) {
27
44
  }
28
45
  }
29
46
  // 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, renderAttemptCleanup = false } = {}) {
47
+ export function useSubDeferred(signal, params, { async = false, defer, batch = false } = {}) {
31
48
  const $signalRef = useRef();
32
- const componentId = useId();
33
49
  const scheduleUpdate = useScheduleUpdate();
34
50
  const observerDefer = useDefer();
35
- if (renderAttemptCleanup)
36
- markCompatComponent(componentId);
37
51
  if (batch)
38
52
  promiseBatcher.activate();
39
53
  defer ??= observerDefer ?? DEFAULT_DEFER;
@@ -52,8 +66,6 @@ export function useSubDeferred(signal, params, { async = false, defer, batch = f
52
66
  // On resubscribe we keep rendering previous signal and refresh in background.
53
67
  if (!hasPreviousSignal) {
54
68
  promiseBatcher.add(promise);
55
- if (renderAttemptCleanup)
56
- registerRenderAttemptCleanup(signal, params);
57
69
  }
58
70
  else {
59
71
  scheduleUpdate(promise);
@@ -71,8 +83,6 @@ export function useSubDeferred(signal, params, { async = false, defer, batch = f
71
83
  scheduleUpdate(promise);
72
84
  return $signalRef.current;
73
85
  }
74
- if (renderAttemptCleanup)
75
- registerRenderAttemptCleanup(signal, params);
76
86
  throw promise;
77
87
  // 2. if it's a signal, we save it into ref to make sure it's not garbage collected while component exists
78
88
  }
@@ -85,13 +95,10 @@ export function useSubDeferred(signal, params, { async = false, defer, batch = f
85
95
  }
86
96
  // classic version which initially throws promise for Suspense
87
97
  // 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, renderAttemptCleanup = false } = {}) {
98
+ export function useSubClassic(signal, params, { async = false, batch = false } = {}) {
89
99
  const id = executionContextTracker.newHookId();
90
- const componentId = useId();
91
100
  const cache = useCache(undefined);
92
101
  const scheduleUpdate = useScheduleUpdate();
93
- if (renderAttemptCleanup)
94
- markCompatComponent(componentId);
95
102
  if (batch)
96
103
  promiseBatcher.activate();
97
104
  const promiseOrSignal = params != null ? runtimeSub(signal, params) : runtimeSub(signal);
@@ -104,8 +111,6 @@ export function useSubClassic(signal, params, { async = false, batch = false, re
104
111
  // On resubscribe we keep rendering previous signal and refresh in background.
105
112
  if (!hasPreviousSignal) {
106
113
  promiseBatcher.add(promise);
107
- if (renderAttemptCleanup)
108
- registerRenderAttemptCleanup(signal, params);
109
114
  }
110
115
  else {
111
116
  scheduleUpdate(promise);
@@ -126,8 +131,6 @@ export function useSubClassic(signal, params, { async = false, batch = false, re
126
131
  scheduleUpdate(promise);
127
132
  return;
128
133
  }
129
- if (renderAttemptCleanup)
130
- registerRenderAttemptCleanup(signal, params);
131
134
  // in regular mode we throw the promise to be caught by Suspense
132
135
  // this way we guarantee that the signal with all the data
133
136
  // will always be there when component is rendered
@@ -180,10 +183,3 @@ function isThenable(value) {
180
183
  (typeof value === 'object' || typeof value === 'function') &&
181
184
  typeof value.then === 'function';
182
185
  }
183
- function registerRenderAttemptCleanup(_signal, _params) {
184
- // Legacy 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.armRenderAttemptCleanup();
189
- }
@@ -1,13 +1,11 @@
1
1
  import executionContextTracker from "./executionContextTracker.js";
2
- import { useCache, useId } from "./helpers.js";
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "teamplay",
3
- "version": "0.5.0-alpha.14",
3
+ "version": "0.5.0-alpha.16",
4
4
  "description": "Full-stack signals ORM with multiplayer",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -134,5 +134,5 @@
134
134
  ]
135
135
  },
136
136
  "license": "MIT",
137
- "gitHead": "84185ddad8cdbac3d2dfcc48cff3588e5ab99630"
137
+ "gitHead": "a6f311fb793aeeba904b81416400e609ab597174"
138
138
  }
@@ -1,4 +0,0 @@
1
- export declare function markCompatComponent(componentId: string | undefined): void;
2
- export declare function unmarkCompatComponent(componentId: string | undefined): void;
3
- export declare function isCompatComponent(componentId: string | undefined): boolean;
4
- export declare function __resetCompatComponentRegistryForTests(): void;
@@ -1,19 +0,0 @@
1
- const compatComponentIds = new Set();
2
- export function markCompatComponent(componentId) {
3
- if (!componentId)
4
- return;
5
- compatComponentIds.add(componentId);
6
- }
7
- export function unmarkCompatComponent(componentId) {
8
- if (!componentId)
9
- return;
10
- compatComponentIds.delete(componentId);
11
- }
12
- export function isCompatComponent(componentId) {
13
- if (!componentId)
14
- return false;
15
- return compatComponentIds.has(componentId);
16
- }
17
- export function __resetCompatComponentRegistryForTests() {
18
- compatComponentIds.clear();
19
- }