@fozy-labs/rx-toolkit 0.5.4 → 0.6.2
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/LICENSE +1 -1
- package/README.md +22 -13
- package/dist/common/devtools/reduxDevtools.js +17 -2
- package/dist/common/react/index.d.ts +1 -0
- package/dist/common/react/index.js +1 -0
- package/dist/common/react/useIsomorphicLayoutEffect.d.ts +17 -0
- package/dist/common/react/useIsomorphicLayoutEffect.js +17 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.js +1 -2
- package/dist/query/api/createApi.d.ts +4 -0
- package/dist/query/api/createApi.js +9 -0
- package/dist/query/api/index.d.ts +1 -0
- package/dist/query/api/index.js +1 -0
- package/dist/query/constants.d.ts +12 -0
- package/dist/query/constants.js +15 -0
- package/dist/query/core/api/Api.d.ts +20 -0
- package/dist/query/core/api/Api.js +129 -0
- package/dist/query/core/api/constants.d.ts +2 -0
- package/dist/query/core/api/constants.js +3 -0
- package/dist/query/core/api/index.d.ts +3 -0
- package/dist/query/core/api/index.js +3 -0
- package/dist/query/core/api/mergeHooks.d.ts +2 -0
- package/dist/query/core/api/mergeHooks.js +26 -0
- package/dist/query/core/api/normalizeLinks.d.ts +2 -0
- package/dist/query/core/api/normalizeLinks.js +11 -0
- package/dist/query/core/cache/CacheEntry.d.ts +21 -0
- package/dist/query/core/cache/CacheEntry.js +54 -0
- package/dist/query/core/cache/CacheMap.d.ts +19 -0
- package/dist/query/core/cache/CacheMap.js +32 -0
- package/dist/query/core/cache/QueryCacheEntry.d.ts +21 -0
- package/dist/query/core/cache/QueryCacheEntry.js +136 -0
- package/dist/query/core/cache/index.d.ts +3 -0
- package/dist/query/core/cache/index.js +3 -0
- package/dist/query/core/command/Command.d.ts +67 -0
- package/dist/query/core/command/Command.js +253 -0
- package/dist/query/core/command/CommandAgent.d.ts +17 -0
- package/dist/query/core/command/CommandAgent.js +67 -0
- package/dist/query/core/command/LinkManager.d.ts +24 -0
- package/dist/query/core/command/LinkManager.js +71 -0
- package/dist/query/core/command/index.d.ts +2 -0
- package/dist/query/core/command/index.js +2 -0
- package/dist/query/core/errors/CacheEntryRemovedError.d.ts +7 -0
- package/dist/query/core/errors/CacheEntryRemovedError.js +9 -0
- package/dist/query/core/errors/MachineStateError.d.ts +8 -0
- package/dist/query/core/errors/MachineStateError.js +10 -0
- package/dist/query/core/errors/MachineTransitionError.d.ts +7 -0
- package/dist/query/core/errors/MachineTransitionError.js +9 -0
- package/dist/query/core/errors/index.d.ts +3 -0
- package/dist/query/core/errors/index.js +3 -0
- package/dist/query/core/index.d.ts +8 -0
- package/dist/query/core/index.js +8 -0
- package/dist/query/core/machine/Machine.d.ts +21 -0
- package/dist/query/core/machine/Machine.js +42 -0
- package/dist/query/core/machine/MachineBase.d.ts +31 -0
- package/dist/query/core/machine/MachineBase.js +176 -0
- package/dist/query/core/machine/MachineError.d.ts +10 -0
- package/dist/query/core/machine/MachineError.js +19 -0
- package/dist/query/core/machine/MachinePending.d.ts +13 -0
- package/dist/query/core/machine/MachinePending.js +32 -0
- package/dist/query/core/machine/MachineRefreshError.d.ts +12 -0
- package/dist/query/core/machine/MachineRefreshError.js +23 -0
- package/dist/query/core/machine/MachineRefreshing.d.ts +15 -0
- package/dist/query/core/machine/MachineRefreshing.js +43 -0
- package/dist/query/core/machine/MachineSuccess.d.ts +12 -0
- package/dist/query/core/machine/MachineSuccess.js +23 -0
- package/dist/query/core/machine/MachineWithData.d.ts +25 -0
- package/dist/query/core/machine/MachineWithData.js +73 -0
- package/dist/query/core/machine/index.d.ts +9 -0
- package/dist/query/core/machine/index.js +9 -0
- package/dist/query/core/machine/machine-helpers.d.ts +9 -0
- package/dist/query/core/machine/machine-helpers.js +80 -0
- package/dist/query/core/patcher/Patcher.d.ts +30 -0
- package/dist/query/core/patcher/Patcher.js +122 -0
- package/dist/query/core/patcher/index.d.ts +1 -0
- package/dist/query/core/patcher/index.js +1 -0
- package/dist/query/core/resource/Resource.d.ts +105 -0
- package/dist/query/core/resource/Resource.js +340 -0
- package/dist/query/core/resource/ResourceAgent.d.ts +37 -0
- package/dist/query/core/resource/ResourceAgent.js +179 -0
- package/dist/query/core/resource/index.d.ts +2 -0
- package/dist/query/core/resource/index.js +2 -0
- package/dist/query/core/snapshoter/Snapshoter.d.ts +22 -0
- package/dist/query/core/snapshoter/Snapshoter.js +78 -0
- package/dist/query/core/snapshoter/index.d.ts +2 -0
- package/dist/query/core/snapshoter/index.js +1 -0
- package/dist/query/core/syncer/Syncer.d.ts +32 -0
- package/dist/query/core/syncer/Syncer.js +85 -0
- package/dist/query/core/syncer/index.d.ts +2 -0
- package/dist/query/core/syncer/index.js +1 -0
- package/dist/query/index.d.ts +5 -10
- package/dist/query/index.js +5 -13
- package/dist/query/lib/broadcastSyncDriver.d.ts +5 -0
- package/dist/query/lib/broadcastSyncDriver.js +46 -0
- package/dist/query/lib/index.d.ts +3 -0
- package/dist/query/lib/index.js +3 -0
- package/dist/{query-v2 → query}/lib/stableStringify.js +5 -3
- package/dist/query/lib/toKeyed.d.ts +11 -0
- package/dist/query/lib/toKeyed.js +18 -0
- package/dist/query/react/ReactHooksPlugin.d.ts +31 -0
- package/dist/query/react/ReactHooksPlugin.js +21 -0
- package/dist/query/react/index.d.ts +3 -0
- package/dist/query/react/index.js +3 -0
- package/dist/query/react/useCommand.d.ts +2 -0
- package/dist/query/react/useCommand.js +14 -0
- package/dist/query/react/useResource.d.ts +2 -0
- package/dist/query/react/useResource.js +16 -0
- package/dist/query/types/api.d.ts +39 -0
- package/dist/query/types/cache.d.ts +51 -0
- package/dist/query/types/command.d.ts +52 -0
- package/dist/query/types/common.d.ts +65 -0
- package/dist/query/types/index.d.ts +8 -4
- package/dist/query/types/index.js +8 -5
- package/dist/query/types/plugin-hkt.d.ts +64 -0
- package/dist/query/types/resource.d.ts +49 -0
- package/dist/query/types/snapshot.d.ts +27 -0
- package/dist/query/types/snapshot.js +2 -0
- package/dist/query/types/state.d.ts +24 -0
- package/dist/signals/base/ComputeCache.js +1 -1
- package/dist/signals/base/Devtools.js +2 -6
- package/dist/signals/signals/Computed.d.ts +1 -0
- package/dist/signals/signals/Computed.js +5 -1
- package/dist/signals/signals/Effect.d.ts +0 -4
- package/dist/signals/signals/Effect.js +0 -6
- package/dist/signals/signals/LocalState.d.ts +1 -10
- package/dist/signals/signals/LocalState.js +0 -12
- package/dist/signals/signals/Signal.d.ts +2 -8
- package/dist/signals/signals/Signal.js +1 -10
- package/dist/signals/signals/State.d.ts +2 -1
- package/dist/signals/signals/State.js +9 -0
- package/dist/signals/types/SignalOptions.d.ts +0 -2
- package/dist/signals/types/normalizeSignalOptions.js +0 -3
- package/dist/signals/types/signals.types.d.ts +3 -1
- package/docs/CHANGELOG.md +54 -2
- package/docs/contributing/release/README.md +2 -8
- package/docs/migrations/0.6.0.md +224 -0
- package/docs/query/README.md +52 -562
- package/docs/query/api/README.md +59 -0
- package/docs/query/api/_CacheEntry.md +39 -0
- package/docs/query/api/_CacheMap.md +30 -0
- package/docs/query/api/_QueryCacheEntry.md +81 -0
- package/docs/query/api/command-agent.md +60 -0
- package/docs/query/api/command.md +76 -0
- package/docs/query/api/resource-agent.md +68 -0
- package/docs/query/api/resource.md +77 -0
- package/docs/query/concepts/agent.md +70 -0
- package/docs/query/concepts/architecture.md +139 -0
- package/docs/query/concepts/cache.md +81 -0
- package/docs/query/concepts/dataflows.md +473 -0
- package/docs/query/concepts/keyed.md +42 -0
- package/docs/query/concepts/machine.md +106 -0
- package/docs/query/concepts/patching.md +85 -0
- package/docs/query/usage/broadcast.md +188 -0
- package/docs/query/usage/command.md +203 -0
- package/docs/query/usage/lifecycle.md +114 -0
- package/docs/query/usage/links.md +125 -0
- package/docs/query/usage/plugins.md +96 -0
- package/docs/query/usage/resource.md +206 -0
- package/docs/query/usage/snapshot.md +80 -0
- package/docs/usage/react/README.md +45 -91
- package/package.json +5 -7
- package/dist/query/SKIP_TOKEN.d.ts +0 -1
- package/dist/query/SKIP_TOKEN.js +0 -1
- package/dist/query/api/createCommand.d.ts +0 -21
- package/dist/query/api/createCommand.js +0 -20
- package/dist/query/api/createOperation.d.ts +0 -5
- package/dist/query/api/createOperation.js +0 -6
- package/dist/query/api/createResource.d.ts +0 -3
- package/dist/query/api/createResource.js +0 -2
- package/dist/query/api/createResourceDuplicator.d.ts +0 -4
- package/dist/query/api/createResourceDuplicator.js +0 -2
- package/dist/query/api/resetAllQueriesCache.d.ts +0 -1
- package/dist/query/api/resetAllQueriesCache.js +0 -4
- package/dist/query/core/Command/Command.d.ts +0 -35
- package/dist/query/core/Command/Command.js +0 -210
- package/dist/query/core/Command/CommandAgent.d.ts +0 -19
- package/dist/query/core/Command/CommandAgent.js +0 -54
- package/dist/query/core/Command/index.d.ts +0 -2
- package/dist/query/core/Command/index.js +0 -2
- package/dist/query/core/Operation/Operation.d.ts +0 -8
- package/dist/query/core/Operation/Operation.js +0 -4
- package/dist/query/core/Operation/OperationAgent.d.ts +0 -4
- package/dist/query/core/Operation/OperationAgent.js +0 -4
- package/dist/query/core/QueriesCache.d.ts +0 -9
- package/dist/query/core/QueriesCache.js +0 -28
- package/dist/query/core/QueriesLifetimeHooks.d.ts +0 -22
- package/dist/query/core/QueriesLifetimeHooks.js +0 -86
- package/dist/query/core/ResetAllQueriesSignal.d.ts +0 -6
- package/dist/query/core/ResetAllQueriesSignal.js +0 -11
- package/dist/query/core/Resource/Resource.d.ts +0 -51
- package/dist/query/core/Resource/Resource.js +0 -232
- package/dist/query/core/Resource/ResourceAgent.d.ts +0 -35
- package/dist/query/core/Resource/ResourceAgent.js +0 -110
- package/dist/query/core/Resource/ResourceDuplicator.d.ts +0 -73
- package/dist/query/core/Resource/ResourceDuplicator.js +0 -227
- package/dist/query/core/Resource/ResourceDuplicatorAgent.d.ts +0 -35
- package/dist/query/core/Resource/ResourceDuplicatorAgent.js +0 -110
- package/dist/query/core/Resource/ResourceRef.d.ts +0 -16
- package/dist/query/core/Resource/ResourceRef.js +0 -136
- package/dist/query/lib/IndirectMap.d.ts +0 -19
- package/dist/query/lib/IndirectMap.js +0 -88
- package/dist/query/lib/ReactiveCache.d.ts +0 -62
- package/dist/query/lib/ReactiveCache.js +0 -80
- package/dist/query/react/useCommandAgent.d.ts +0 -24
- package/dist/query/react/useCommandAgent.js +0 -39
- package/dist/query/react/useOperationAgent.d.ts +0 -6
- package/dist/query/react/useOperationAgent.js +0 -6
- package/dist/query/react/useResourceAgent.d.ts +0 -6
- package/dist/query/react/useResourceAgent.js +0 -31
- package/dist/query/react/useResourceRef.d.ts +0 -5
- package/dist/query/react/useResourceRef.js +0 -13
- package/dist/query/types/Command.types.d.ts +0 -154
- package/dist/query/types/Command.types.js +0 -1
- package/dist/query/types/Operation.types.d.ts +0 -13
- package/dist/query/types/Operation.types.js +0 -1
- package/dist/query/types/Resource.types.d.ts +0 -129
- package/dist/query/types/Resource.types.js +0 -1
- package/dist/query/types/shared.types.d.ts +0 -26
- package/dist/query/types/shared.types.js +0 -1
- package/dist/query-v2/api/createApi.d.ts +0 -10
- package/dist/query-v2/api/createApi.js +0 -83
- package/dist/query-v2/core/common/CacheEntry.d.ts +0 -29
- package/dist/query-v2/core/common/CacheEntry.js +0 -71
- package/dist/query-v2/core/common/CacheMap.d.ts +0 -38
- package/dist/query-v2/core/common/CacheMap.js +0 -127
- package/dist/query-v2/core/common/LifecycleHooks.d.ts +0 -22
- package/dist/query-v2/core/common/LifecycleHooks.js +0 -104
- package/dist/query-v2/core/common/index.d.ts +0 -3
- package/dist/query-v2/core/common/index.js +0 -3
- package/dist/query-v2/core/index.d.ts +0 -3
- package/dist/query-v2/core/index.js +0 -3
- package/dist/query-v2/core/machines/Machine.d.ts +0 -14
- package/dist/query-v2/core/machines/Machine.js +0 -33
- package/dist/query-v2/core/machines/MachineError.d.ts +0 -11
- package/dist/query-v2/core/machines/MachineError.js +0 -26
- package/dist/query-v2/core/machines/MachineIdle.d.ts +0 -8
- package/dist/query-v2/core/machines/MachineIdle.js +0 -19
- package/dist/query-v2/core/machines/MachinePending.d.ts +0 -12
- package/dist/query-v2/core/machines/MachinePending.js +0 -29
- package/dist/query-v2/core/machines/MachineRefreshing.d.ts +0 -14
- package/dist/query-v2/core/machines/MachineRefreshing.js +0 -46
- package/dist/query-v2/core/machines/MachineSuccess.d.ts +0 -16
- package/dist/query-v2/core/machines/MachineSuccess.js +0 -42
- package/dist/query-v2/core/machines/MachineWithData.d.ts +0 -18
- package/dist/query-v2/core/machines/MachineWithData.js +0 -40
- package/dist/query-v2/core/machines/Patcher.d.ts +0 -20
- package/dist/query-v2/core/machines/Patcher.js +0 -104
- package/dist/query-v2/core/machines/index.d.ts +0 -8
- package/dist/query-v2/core/machines/index.js +0 -8
- package/dist/query-v2/core/resource/ResourceV2.d.ts +0 -120
- package/dist/query-v2/core/resource/ResourceV2.js +0 -464
- package/dist/query-v2/core/resource/ResourceV2Agent.d.ts +0 -26
- package/dist/query-v2/core/resource/ResourceV2Agent.js +0 -132
- package/dist/query-v2/core/resource/index.d.ts +0 -2
- package/dist/query-v2/core/resource/index.js +0 -2
- package/dist/query-v2/index.d.ts +0 -11
- package/dist/query-v2/index.js +0 -17
- package/dist/query-v2/lib/NO_VALUE.d.ts +0 -2
- package/dist/query-v2/lib/NO_VALUE.js +0 -1
- package/dist/query-v2/lib/SKIP_TOKEN.d.ts +0 -2
- package/dist/query-v2/lib/SKIP_TOKEN.js +0 -1
- package/dist/query-v2/lib/index.d.ts +0 -4
- package/dist/query-v2/lib/index.js +0 -3
- package/dist/query-v2/plugins/ReactHooksPlugin.d.ts +0 -25
- package/dist/query-v2/plugins/ReactHooksPlugin.js +0 -19
- package/dist/query-v2/plugins/types.d.ts +0 -1
- package/dist/query-v2/react/__tests__/helpers.d.ts +0 -12
- package/dist/query-v2/react/__tests__/helpers.js +0 -33
- package/dist/query-v2/react/index.d.ts +0 -2
- package/dist/query-v2/react/index.js +0 -2
- package/dist/query-v2/react/useResourceV2Agent.d.ts +0 -12
- package/dist/query-v2/react/useResourceV2Agent.js +0 -36
- package/dist/query-v2/react/useResourceV2Ref.d.ts +0 -12
- package/dist/query-v2/react/useResourceV2Ref.js +0 -57
- package/dist/query-v2/snapshot/Snapshot.d.ts +0 -13
- package/dist/query-v2/snapshot/Snapshot.js +0 -76
- package/dist/query-v2/types/agent.types.d.ts +0 -54
- package/dist/query-v2/types/api.types.d.ts +0 -22
- package/dist/query-v2/types/cache.types.d.ts +0 -37
- package/dist/query-v2/types/index.d.ts +0 -9
- package/dist/query-v2/types/index.js +0 -9
- package/dist/query-v2/types/lifecycle.types.d.ts +0 -25
- package/dist/query-v2/types/machine.types.d.ts +0 -67
- package/dist/query-v2/types/plugin.types.d.ts +0 -38
- package/dist/query-v2/types/resource.types.d.ts +0 -35
- package/dist/query-v2/types/resource.types.js +0 -1
- package/dist/query-v2/types/shared.types.d.ts +0 -20
- package/dist/query-v2/types/shared.types.js +0 -1
- package/dist/query-v2/types/snapshot.types.d.ts +0 -21
- package/dist/query-v2/types/snapshot.types.js +0 -1
- package/docs/contributing/query-v2/README.md +0 -379
- package/docs/migrations/query-v2.md +0 -171
- package/docs/query-v2/README.md +0 -280
- package/docs/query-v2/api-reference.md +0 -235
- package/docs/query-v2/optimistic-updates.md +0 -148
- package/docs/query-v2/ssr.md +0 -130
- /package/dist/{query-v2 → query}/lib/stableStringify.d.ts +0 -0
- /package/dist/{query-v2/plugins/types.js → query/types/api.js} +0 -0
- /package/dist/{query-v2/types/agent.types.js → query/types/cache.js} +0 -0
- /package/dist/{query-v2/types/api.types.js → query/types/command.js} +0 -0
- /package/dist/{query-v2/types/cache.types.js → query/types/common.js} +0 -0
- /package/dist/{query-v2/types/lifecycle.types.js → query/types/plugin-hkt.js} +0 -0
- /package/dist/{query-v2/types/machine.types.js → query/types/resource.js} +0 -0
- /package/dist/{query-v2/types/plugin.types.js → query/types/state.js} +0 -0
|
@@ -1,464 +0,0 @@
|
|
|
1
|
-
import { shallowEqual } from "../../../common/utils/shallowEqual";
|
|
2
|
-
import { SKIP } from "../../../query-v2/lib/SKIP_TOKEN";
|
|
3
|
-
import { stableStringify } from "../../../query-v2/lib/stableStringify";
|
|
4
|
-
import { Batcher } from "../../../signals";
|
|
5
|
-
import { CacheEntry } from "../common/CacheEntry";
|
|
6
|
-
import { CacheMap } from "../common/CacheMap";
|
|
7
|
-
import { LifecycleHooks } from "../common/LifecycleHooks";
|
|
8
|
-
import { MachineIdle } from "../machines/MachineIdle";
|
|
9
|
-
import { MachineRefreshing } from "../machines/MachineRefreshing";
|
|
10
|
-
import { MachineSuccess } from "../machines/MachineSuccess";
|
|
11
|
-
import { MachineWithData } from "../machines/MachineWithData";
|
|
12
|
-
import { ResourceV2Agent } from "./ResourceV2Agent";
|
|
13
|
-
/**
|
|
14
|
-
* Cache-backed resource manager.
|
|
15
|
-
* Orchestrates queries, caching, lifecycle hooks, GC, and optimistic patches for a single resource type.
|
|
16
|
-
*/
|
|
17
|
-
export class ResourceV2 {
|
|
18
|
-
_cache;
|
|
19
|
-
_queryFn;
|
|
20
|
-
_lifecycleHooks;
|
|
21
|
-
_serializeArgs;
|
|
22
|
-
_compareArg;
|
|
23
|
-
_keyStrategy;
|
|
24
|
-
_cacheLifetime;
|
|
25
|
-
_beforeDevtoolsPush;
|
|
26
|
-
_key;
|
|
27
|
-
_keyPrefix;
|
|
28
|
-
/** In-flight queries keyed by serialized args — for dedup + abort */
|
|
29
|
-
_inFlight = new Map();
|
|
30
|
-
/** Cache lifetime timers keyed by serialized args */
|
|
31
|
-
_gcTimers = new Map();
|
|
32
|
-
/** Refresh error listeners (used by Agent for refreshError tracking) */
|
|
33
|
-
_refreshErrorListeners = new Set();
|
|
34
|
-
constructor(config) {
|
|
35
|
-
this._queryFn = config.queryFn;
|
|
36
|
-
this._serializeArgs = config.serializeArgs ?? stableStringify;
|
|
37
|
-
this._compareArg = config.compareArg ?? shallowEqual;
|
|
38
|
-
this._keyStrategy = config.keyStrategy ?? "serialize";
|
|
39
|
-
this._cacheLifetime = config.cacheLifetime ?? 60_000;
|
|
40
|
-
this._beforeDevtoolsPush = config.beforeDevtoolsPush;
|
|
41
|
-
this._key = config.key;
|
|
42
|
-
this._keyPrefix = config.keyPrefix;
|
|
43
|
-
this._cache = CacheMap.create({
|
|
44
|
-
keyStrategy: this._keyStrategy,
|
|
45
|
-
serializeArgs: this._serializeArgs,
|
|
46
|
-
compareArg: this._compareArg,
|
|
47
|
-
doCacheArgs: config.doCacheArgs ?? false,
|
|
48
|
-
});
|
|
49
|
-
this._lifecycleHooks = new LifecycleHooks({
|
|
50
|
-
onCacheEntryAdded: config.onCacheEntryAdded,
|
|
51
|
-
onQueryStarted: config.onQueryStarted,
|
|
52
|
-
serializeArgs: this._serializeArgs,
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Create an agent that tracks a single cache entry with reactive state (SWR).
|
|
57
|
-
*
|
|
58
|
-
* @returns A new agent bound to this resource.
|
|
59
|
-
*/
|
|
60
|
-
createAgent() {
|
|
61
|
-
return new ResourceV2Agent(this);
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Execute a query for the given args, returning the cache entry.
|
|
65
|
-
* Deduplicates concurrent calls for the same args unless `doForce` is set.
|
|
66
|
-
*
|
|
67
|
-
* @param args - Query arguments (used as cache key).
|
|
68
|
-
* @param doForce - If true, bypass dedup and re-execute the query.
|
|
69
|
-
* @returns The cache entry after query initiation.
|
|
70
|
-
*/
|
|
71
|
-
async query(args, doForce) {
|
|
72
|
-
// SKIP check
|
|
73
|
-
if (args === SKIP) {
|
|
74
|
-
throw new Error("SKIP_TOKEN is not valid for direct query()");
|
|
75
|
-
}
|
|
76
|
-
const key = this._serializeArgs(args);
|
|
77
|
-
// Cache hit — return existing entry (unless force)
|
|
78
|
-
const existing = this._cache.get(args);
|
|
79
|
-
if (existing && !doForce) {
|
|
80
|
-
const machine = existing.peek();
|
|
81
|
-
// If already success or pending or refreshing, return the entry
|
|
82
|
-
if (machine.state.status !== "idle") {
|
|
83
|
-
return existing;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
// Query dedup — if already in-flight for same args, return same promise
|
|
87
|
-
if (!doForce) {
|
|
88
|
-
const flight = this._inFlight.get(key);
|
|
89
|
-
if (flight) {
|
|
90
|
-
return flight.promise;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
// Cancel existing in-flight for same args (ADR-4 Layer 1)
|
|
94
|
-
const existingFlight = this._inFlight.get(key);
|
|
95
|
-
if (existingFlight) {
|
|
96
|
-
existingFlight.abortController.abort();
|
|
97
|
-
this._inFlight.delete(key);
|
|
98
|
-
}
|
|
99
|
-
// Cancel any pending GC timer for these args
|
|
100
|
-
this._cancelGcTimer(key);
|
|
101
|
-
const abortController = new AbortController();
|
|
102
|
-
const isNewEntry = !existing;
|
|
103
|
-
// Create or reuse entry inside Batcher for atomic updates
|
|
104
|
-
let cacheEntry;
|
|
105
|
-
// Set up entry and pending state
|
|
106
|
-
Batcher.run(() => {
|
|
107
|
-
if (isNewEntry || doForce) {
|
|
108
|
-
if (existing && doForce) {
|
|
109
|
-
cacheEntry = existing;
|
|
110
|
-
// Transition to refreshing or pending based on current state
|
|
111
|
-
const current = cacheEntry.peek();
|
|
112
|
-
if (current instanceof MachineSuccess) {
|
|
113
|
-
const refreshing = current.invalidate();
|
|
114
|
-
cacheEntry.set(refreshing);
|
|
115
|
-
}
|
|
116
|
-
else if (current instanceof MachineRefreshing) {
|
|
117
|
-
// Already refreshing — it'll be re-queried
|
|
118
|
-
}
|
|
119
|
-
else {
|
|
120
|
-
const idle = MachineIdle.create();
|
|
121
|
-
const pending = idle.start(args);
|
|
122
|
-
cacheEntry.set(pending);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
else {
|
|
126
|
-
// New entry
|
|
127
|
-
const idle = MachineIdle.create();
|
|
128
|
-
const pending = idle.start(args);
|
|
129
|
-
cacheEntry = new CacheEntry(pending, this._buildCacheEntryOptions(args));
|
|
130
|
-
this._cache.set(args, cacheEntry);
|
|
131
|
-
// Fire onCacheEntryAdded for new entries
|
|
132
|
-
this._lifecycleHooks.fireCacheEntryAdded(args, () => cacheEntry.peek());
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
cacheEntry = existing;
|
|
137
|
-
const current = cacheEntry.peek();
|
|
138
|
-
const pending = current.start(args);
|
|
139
|
-
cacheEntry.set(pending);
|
|
140
|
-
}
|
|
141
|
-
// Fire onQueryStarted
|
|
142
|
-
this._lifecycleHooks.fireQueryStarted(args, () => cacheEntry);
|
|
143
|
-
});
|
|
144
|
-
// Execute queryFn
|
|
145
|
-
const promise = this._executeQuery(args, key, cacheEntry, abortController);
|
|
146
|
-
this._inFlight.set(key, { promise: promise, abortController });
|
|
147
|
-
return promise;
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Reactive query — read machine state as a signal dependency.
|
|
151
|
-
* Initiates the query if not already cached.
|
|
152
|
-
*
|
|
153
|
-
* @param args - Query arguments.
|
|
154
|
-
* @returns Current machine state (registers a reactive subscription).
|
|
155
|
-
*/
|
|
156
|
-
query$(args, doForce) {
|
|
157
|
-
if (args === SKIP) {
|
|
158
|
-
return MachineIdle.create().state;
|
|
159
|
-
}
|
|
160
|
-
// Trigger query (fire-and-forget) and read entry signal reactively
|
|
161
|
-
const entryResult = this._cache.get(args);
|
|
162
|
-
if (!entryResult) {
|
|
163
|
-
// Initiate query
|
|
164
|
-
this.query(args, doForce);
|
|
165
|
-
// Return idle while it's being initiated
|
|
166
|
-
const newEntry = this._cache.get(args);
|
|
167
|
-
if (newEntry) {
|
|
168
|
-
return newEntry.machine$().state;
|
|
169
|
-
}
|
|
170
|
-
return MachineIdle.create().state;
|
|
171
|
-
}
|
|
172
|
-
if (doForce) {
|
|
173
|
-
this.query(args, true);
|
|
174
|
-
}
|
|
175
|
-
// Reactive read — registers signal dependency
|
|
176
|
-
return entryResult.machine$().state;
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Get the cache entry for the given args without initiating a query (unless `doInitiate` is set).
|
|
180
|
-
*
|
|
181
|
-
* @param args - Query arguments.
|
|
182
|
-
* @returns The cache entry, or `null` if not cached.
|
|
183
|
-
*/
|
|
184
|
-
entry(args, doInitiate) {
|
|
185
|
-
const existing = this._cache.get(args);
|
|
186
|
-
if (existing) {
|
|
187
|
-
return existing;
|
|
188
|
-
}
|
|
189
|
-
if (doInitiate) {
|
|
190
|
-
// Fire-and-forget query initiation
|
|
191
|
-
this.query(args);
|
|
192
|
-
return this._cache.get(args) ?? null;
|
|
193
|
-
}
|
|
194
|
-
return null;
|
|
195
|
-
}
|
|
196
|
-
entry$(args, doInitiate) {
|
|
197
|
-
if (args === SKIP) {
|
|
198
|
-
return MachineIdle.create().state;
|
|
199
|
-
}
|
|
200
|
-
const existing = this._cache.get(args);
|
|
201
|
-
if (!existing && doInitiate) {
|
|
202
|
-
this.query(args);
|
|
203
|
-
const created = this._cache.get(args);
|
|
204
|
-
if (created) {
|
|
205
|
-
return created.machine$().state;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
if (existing) {
|
|
209
|
-
return existing.machine$().state;
|
|
210
|
-
}
|
|
211
|
-
return MachineIdle.create().state;
|
|
212
|
-
}
|
|
213
|
-
invalidate(args) {
|
|
214
|
-
const existing = this._cache.get(args);
|
|
215
|
-
if (!existing)
|
|
216
|
-
return;
|
|
217
|
-
const machine = existing.peek();
|
|
218
|
-
// Only invalidate from success state
|
|
219
|
-
if (!(machine instanceof MachineSuccess))
|
|
220
|
-
return;
|
|
221
|
-
const key = this._serializeArgs(args);
|
|
222
|
-
// Abort any existing in-flight for these args (ADR-4 Layer 1)
|
|
223
|
-
const flight = this._inFlight.get(key);
|
|
224
|
-
if (flight) {
|
|
225
|
-
flight.abortController.abort();
|
|
226
|
-
this._inFlight.delete(key);
|
|
227
|
-
}
|
|
228
|
-
const abortController = new AbortController();
|
|
229
|
-
Batcher.run(() => {
|
|
230
|
-
const refreshing = machine.invalidate();
|
|
231
|
-
existing.set(refreshing);
|
|
232
|
-
this._lifecycleHooks.fireQueryStarted(args, () => existing);
|
|
233
|
-
});
|
|
234
|
-
const promise = this._executeRefresh(args, key, existing, abortController);
|
|
235
|
-
this._inFlight.set(key, { promise, abortController });
|
|
236
|
-
}
|
|
237
|
-
compareArgs(a, b) {
|
|
238
|
-
if (this._keyStrategy === "compare") {
|
|
239
|
-
return this._compareArg(a, b);
|
|
240
|
-
}
|
|
241
|
-
return this._serializeArgs(a) === this._serializeArgs(b);
|
|
242
|
-
}
|
|
243
|
-
/** Public key getter for API registry */
|
|
244
|
-
get key() {
|
|
245
|
-
return this._key;
|
|
246
|
-
}
|
|
247
|
-
/** Public keyStrategy getter for snapshot validation */
|
|
248
|
-
get keyStrategy() {
|
|
249
|
-
return this._keyStrategy;
|
|
250
|
-
}
|
|
251
|
-
/** Serialize args to string key */
|
|
252
|
-
getSerializedKey(args) {
|
|
253
|
-
return this._serializeArgs(args);
|
|
254
|
-
}
|
|
255
|
-
/** Iterate cache entries — for snapshot */
|
|
256
|
-
cacheEntries() {
|
|
257
|
-
return this._cache.entries();
|
|
258
|
-
}
|
|
259
|
-
/** Hydrate a cache entry from snapshot data */
|
|
260
|
-
hydrateEntry(args, machine) {
|
|
261
|
-
const existing = this._cache.get(args);
|
|
262
|
-
if (existing)
|
|
263
|
-
return; // Don't overwrite existing entries
|
|
264
|
-
const entry = new CacheEntry(machine, this._buildCacheEntryOptions(args));
|
|
265
|
-
this._cache.set(args, entry);
|
|
266
|
-
// Fire lifecycle for hydrated entries
|
|
267
|
-
this._lifecycleHooks.fireCacheEntryAdded(args, () => entry.peek());
|
|
268
|
-
if (machine.state.status === "success") {
|
|
269
|
-
this._lifecycleHooks.resolveCacheDataLoaded(args, machine.state.data);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
/** Check if cache entry exists for given args */
|
|
273
|
-
hasEntry(args) {
|
|
274
|
-
return this._cache.has(args);
|
|
275
|
-
}
|
|
276
|
-
/** Pre-populate cache with data */
|
|
277
|
-
populateEntry(args, data) {
|
|
278
|
-
const existing = this._cache.get(args);
|
|
279
|
-
if (existing) {
|
|
280
|
-
const success = MachineSuccess.create(data, args);
|
|
281
|
-
existing.set(success);
|
|
282
|
-
return;
|
|
283
|
-
}
|
|
284
|
-
const success = MachineSuccess.create(data, args);
|
|
285
|
-
const entry = new CacheEntry(success, this._buildCacheEntryOptions(args));
|
|
286
|
-
this._cache.set(args, entry);
|
|
287
|
-
}
|
|
288
|
-
/** Create an optimistic patch on a cache entry */
|
|
289
|
-
createEntryPatch(args, patchFn) {
|
|
290
|
-
const entry = this._cache.get(args);
|
|
291
|
-
if (!entry)
|
|
292
|
-
return null;
|
|
293
|
-
const machine = entry.peek();
|
|
294
|
-
if (!(machine instanceof MachineWithData))
|
|
295
|
-
return null;
|
|
296
|
-
const { machine: patchedMachine, patch } = machine.createPatch(patchFn);
|
|
297
|
-
entry.set(patchedMachine);
|
|
298
|
-
return {
|
|
299
|
-
commit: () => {
|
|
300
|
-
const current = entry.peek();
|
|
301
|
-
if (current instanceof MachineWithData) {
|
|
302
|
-
const finished = current.finishPatch("commit", patch);
|
|
303
|
-
entry.set(finished);
|
|
304
|
-
}
|
|
305
|
-
},
|
|
306
|
-
abort: () => {
|
|
307
|
-
const current = entry.peek();
|
|
308
|
-
if (current instanceof MachineWithData) {
|
|
309
|
-
const finished = current.finishPatch("abort", patch);
|
|
310
|
-
entry.set(finished);
|
|
311
|
-
}
|
|
312
|
-
},
|
|
313
|
-
};
|
|
314
|
-
}
|
|
315
|
-
/** Lock a cache entry — prevent GC eviction. Returns unlock function. */
|
|
316
|
-
lockEntry(args) {
|
|
317
|
-
this.cancelGc(args);
|
|
318
|
-
return {
|
|
319
|
-
unlock: () => {
|
|
320
|
-
// Re-schedule GC (will be cancelled again if still subscribed)
|
|
321
|
-
this.scheduleGc(args);
|
|
322
|
-
},
|
|
323
|
-
};
|
|
324
|
-
}
|
|
325
|
-
/** Subscribe to refresh error events (used by Agent) */
|
|
326
|
-
onRefreshError(listener) {
|
|
327
|
-
this._refreshErrorListeners.add(listener);
|
|
328
|
-
return () => {
|
|
329
|
-
this._refreshErrorListeners.delete(listener);
|
|
330
|
-
};
|
|
331
|
-
}
|
|
332
|
-
/** Reset the entire cache — aborts in-flight requests, clears GC timers, completes all entries. */
|
|
333
|
-
resetCache() {
|
|
334
|
-
// Abort all in-flight requests
|
|
335
|
-
for (const [, flight] of this._inFlight) {
|
|
336
|
-
flight.abortController.abort();
|
|
337
|
-
}
|
|
338
|
-
this._inFlight.clear();
|
|
339
|
-
// Clear all GC timers
|
|
340
|
-
for (const [, timer] of this._gcTimers) {
|
|
341
|
-
clearTimeout(timer);
|
|
342
|
-
}
|
|
343
|
-
this._gcTimers.clear();
|
|
344
|
-
// Complete all cache entries
|
|
345
|
-
for (const entry of this._cache.values()) {
|
|
346
|
-
entry.complete();
|
|
347
|
-
}
|
|
348
|
-
// Clear lifecycle hooks
|
|
349
|
-
this._lifecycleHooks.clearAll();
|
|
350
|
-
// Clear the cache map
|
|
351
|
-
this._cache.clear();
|
|
352
|
-
}
|
|
353
|
-
/**
|
|
354
|
-
* Schedule GC for a cache entry after cacheLifetime.
|
|
355
|
-
* Called when subscriber count drops to 0.
|
|
356
|
-
*/
|
|
357
|
-
scheduleGc(args) {
|
|
358
|
-
const key = this._serializeArgs(args);
|
|
359
|
-
this._cancelGcTimer(key);
|
|
360
|
-
this._gcTimers.set(key, setTimeout(() => {
|
|
361
|
-
this._gcTimers.delete(key);
|
|
362
|
-
this._evictEntry(args, key);
|
|
363
|
-
}, this._cacheLifetime));
|
|
364
|
-
}
|
|
365
|
-
/**
|
|
366
|
-
* Cancel pending GC for a cache entry.
|
|
367
|
-
* Called when a new subscriber appears.
|
|
368
|
-
*/
|
|
369
|
-
cancelGc(args) {
|
|
370
|
-
const key = this._serializeArgs(args);
|
|
371
|
-
this._cancelGcTimer(key);
|
|
372
|
-
}
|
|
373
|
-
// --- Private helpers ---
|
|
374
|
-
_cancelGcTimer(key) {
|
|
375
|
-
const timer = this._gcTimers.get(key);
|
|
376
|
-
if (timer != null) {
|
|
377
|
-
clearTimeout(timer);
|
|
378
|
-
this._gcTimers.delete(key);
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
_evictEntry(args, key) {
|
|
382
|
-
const entry = this._cache.get(args);
|
|
383
|
-
if (!entry)
|
|
384
|
-
return;
|
|
385
|
-
// Abort in-flight if any
|
|
386
|
-
const flight = this._inFlight.get(key);
|
|
387
|
-
if (flight) {
|
|
388
|
-
flight.abortController.abort();
|
|
389
|
-
this._inFlight.delete(key);
|
|
390
|
-
}
|
|
391
|
-
// Fire lifecycle removal
|
|
392
|
-
this._lifecycleHooks.fireCacheEntryRemoved(args);
|
|
393
|
-
// Complete the entry (ADR-4 Layer 3)
|
|
394
|
-
entry.complete();
|
|
395
|
-
// Remove from cache
|
|
396
|
-
this._cache.delete(args);
|
|
397
|
-
}
|
|
398
|
-
async _executeQuery(args, key, cacheEntry, abortController) {
|
|
399
|
-
try {
|
|
400
|
-
const data = await this._queryFn(args, {
|
|
401
|
-
abortSignal: abortController.signal,
|
|
402
|
-
});
|
|
403
|
-
// If aborted after await, don't process result
|
|
404
|
-
if (abortController.signal.aborted) {
|
|
405
|
-
return cacheEntry;
|
|
406
|
-
}
|
|
407
|
-
Batcher.run(() => {
|
|
408
|
-
const current = cacheEntry.peek();
|
|
409
|
-
if (current.state.status === "pending") {
|
|
410
|
-
const success = current.successHappened(data);
|
|
411
|
-
cacheEntry.set(success);
|
|
412
|
-
}
|
|
413
|
-
else if (current.state.status === "refreshing") {
|
|
414
|
-
const success = current.successHappened(data);
|
|
415
|
-
cacheEntry.set(success);
|
|
416
|
-
}
|
|
417
|
-
});
|
|
418
|
-
this._lifecycleHooks.resolveCacheDataLoaded(args, data);
|
|
419
|
-
this._lifecycleHooks.resolveQueryFulfilled(data);
|
|
420
|
-
}
|
|
421
|
-
catch (error) {
|
|
422
|
-
if (abortController.signal.aborted) {
|
|
423
|
-
this._lifecycleHooks.rejectQueryFulfilled(error);
|
|
424
|
-
return cacheEntry;
|
|
425
|
-
}
|
|
426
|
-
Batcher.run(() => {
|
|
427
|
-
const current = cacheEntry.peek();
|
|
428
|
-
if (current.state.status === "pending") {
|
|
429
|
-
const errorMachine = current.errorHappened(error);
|
|
430
|
-
cacheEntry.set(errorMachine);
|
|
431
|
-
}
|
|
432
|
-
else if (current.state.status === "refreshing") {
|
|
433
|
-
// ADR-2: Preserve stale data
|
|
434
|
-
const success = current.errorHappened(error);
|
|
435
|
-
cacheEntry.set(success);
|
|
436
|
-
// Notify refresh error listeners (used by Agent)
|
|
437
|
-
for (const listener of this._refreshErrorListeners) {
|
|
438
|
-
listener(args, error);
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
});
|
|
442
|
-
this._lifecycleHooks.rejectQueryFulfilled(error);
|
|
443
|
-
}
|
|
444
|
-
finally {
|
|
445
|
-
this._inFlight.delete(key);
|
|
446
|
-
}
|
|
447
|
-
return cacheEntry;
|
|
448
|
-
}
|
|
449
|
-
async _executeRefresh(args, key, cacheEntry, abortController) {
|
|
450
|
-
return this._executeQuery(args, key, cacheEntry, abortController);
|
|
451
|
-
}
|
|
452
|
-
_buildCacheEntryOptions(args) {
|
|
453
|
-
const parts = [];
|
|
454
|
-
if (this._keyPrefix)
|
|
455
|
-
parts.push(this._keyPrefix);
|
|
456
|
-
if (this._key)
|
|
457
|
-
parts.push(this._key);
|
|
458
|
-
parts.push(this._serializeArgs(args));
|
|
459
|
-
return {
|
|
460
|
-
keyParts: parts.length > 0 ? parts : undefined,
|
|
461
|
-
beforeDevtoolsPush: this._beforeDevtoolsPush,
|
|
462
|
-
};
|
|
463
|
-
}
|
|
464
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { type SKIP_TOKEN } from "../../../query-v2/lib/SKIP_TOKEN";
|
|
2
|
-
import type { IResourceV2Agent, IResourceV2AgentState } from "../../../query-v2/types/agent.types";
|
|
3
|
-
import type { ComputeFn } from "../../../signals";
|
|
4
|
-
import type { ResourceV2 } from "./ResourceV2";
|
|
5
|
-
/**
|
|
6
|
-
* Agent that tracks a single cache entry with reactive state, designed for React hook consumption.
|
|
7
|
-
* Provides SWR (stale-while-revalidate) semantics by keeping previous data while new data loads.
|
|
8
|
-
*/
|
|
9
|
-
export declare class ResourceV2Agent<TArgs, TData, TError = Error> implements IResourceV2Agent<TArgs, TData, TError> {
|
|
10
|
-
private readonly _resource;
|
|
11
|
-
private readonly _tracking$;
|
|
12
|
-
private readonly _refreshError$;
|
|
13
|
-
private readonly _state$;
|
|
14
|
-
private readonly _unsubRefreshError;
|
|
15
|
-
private _currentArgs;
|
|
16
|
-
constructor(resource: ResourceV2<TArgs, TData, TError>);
|
|
17
|
-
/** Computed reactive state signal — projects CacheEntry machine state into a flat agent state object. */
|
|
18
|
-
get state$(): ComputeFn<IResourceV2AgentState<TArgs, TData, TError>>;
|
|
19
|
-
/**
|
|
20
|
-
* Start (or re-start) the agent with new args. Skips if args are unchanged.
|
|
21
|
-
*
|
|
22
|
-
* @param args - Query arguments, or `SKIP_TOKEN` to do nothing.
|
|
23
|
-
*/
|
|
24
|
-
start(args: TArgs | SKIP_TOKEN): Promise<void>;
|
|
25
|
-
compareArgs(a: TArgs, b: TArgs): boolean;
|
|
26
|
-
}
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import { SKIP } from "../../../query-v2/lib/SKIP_TOKEN";
|
|
2
|
-
import { Signal } from "../../../signals";
|
|
3
|
-
/**
|
|
4
|
-
* Agent that tracks a single cache entry with reactive state, designed for React hook consumption.
|
|
5
|
-
* Provides SWR (stale-while-revalidate) semantics by keeping previous data while new data loads.
|
|
6
|
-
*/
|
|
7
|
-
export class ResourceV2Agent {
|
|
8
|
-
_resource;
|
|
9
|
-
_tracking$;
|
|
10
|
-
_refreshError$;
|
|
11
|
-
_state$;
|
|
12
|
-
_unsubRefreshError;
|
|
13
|
-
_currentArgs = null;
|
|
14
|
-
constructor(resource) {
|
|
15
|
-
this._resource = resource;
|
|
16
|
-
// Agent signals are internal derived state for React hooks — only CacheEntry signals belong in devtools
|
|
17
|
-
this._tracking$ = Signal.state({ previous: null, current: null }, { isDisabled: true });
|
|
18
|
-
// Agent signal — excluded from devtools; only CacheEntry signals represent canonical cache state
|
|
19
|
-
this._refreshError$ = Signal.state(null, { isDisabled: true });
|
|
20
|
-
// Subscribe to refresh errors from the resource
|
|
21
|
-
this._unsubRefreshError = this._resource.onRefreshError((args, error) => {
|
|
22
|
-
if (this._currentArgs !== null && this._resource.compareArgs(this._currentArgs, args)) {
|
|
23
|
-
this._refreshError$.set(error);
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
// Agent signal — excluded from devtools; only CacheEntry signals represent canonical cache state
|
|
27
|
-
this._state$ = Signal.compute(() => {
|
|
28
|
-
const { previous, current } = this._tracking$();
|
|
29
|
-
if (!current) {
|
|
30
|
-
return {
|
|
31
|
-
status: "idle",
|
|
32
|
-
data: null,
|
|
33
|
-
error: null,
|
|
34
|
-
args: null,
|
|
35
|
-
isLoading: false,
|
|
36
|
-
isInitialLoading: false,
|
|
37
|
-
isRefreshing: false,
|
|
38
|
-
isSuccess: false,
|
|
39
|
-
isError: false,
|
|
40
|
-
refreshError: this._refreshError$(),
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
// Read machine$ reactively — this is the key reactive subscription
|
|
44
|
-
const machine = current.machine$();
|
|
45
|
-
const machineState = machine.state;
|
|
46
|
-
const status = machineState.status;
|
|
47
|
-
// Determine previous data for SWR
|
|
48
|
-
let previousData = null;
|
|
49
|
-
if (previous) {
|
|
50
|
-
const prevMachine = previous.machine$();
|
|
51
|
-
const prevState = prevMachine.state;
|
|
52
|
-
if (prevState.data != null) {
|
|
53
|
-
previousData = prevState.data;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
const currentData = machineState.data;
|
|
57
|
-
const isLoading = status === "pending" || status === "refreshing";
|
|
58
|
-
const isRefreshing = status === "refreshing";
|
|
59
|
-
// SWR: use previous data if current is loading and has no data yet
|
|
60
|
-
const data = currentData ?? (isLoading ? previousData : null);
|
|
61
|
-
const hasPreviousData = previousData !== null;
|
|
62
|
-
const isInitialLoading = isLoading && !hasPreviousData && currentData === null;
|
|
63
|
-
const isSuccess = data !== null;
|
|
64
|
-
const isError = status === "error";
|
|
65
|
-
const error = isError ? machineState.error : null;
|
|
66
|
-
return {
|
|
67
|
-
status,
|
|
68
|
-
data,
|
|
69
|
-
error,
|
|
70
|
-
args: machineState.args ?? null,
|
|
71
|
-
isLoading,
|
|
72
|
-
isInitialLoading,
|
|
73
|
-
isRefreshing,
|
|
74
|
-
isSuccess,
|
|
75
|
-
isError,
|
|
76
|
-
refreshError: this._refreshError$(),
|
|
77
|
-
};
|
|
78
|
-
}, { isDisabled: true });
|
|
79
|
-
}
|
|
80
|
-
/** Computed reactive state signal — projects CacheEntry machine state into a flat agent state object. */
|
|
81
|
-
get state$() {
|
|
82
|
-
return this._state$;
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Start (or re-start) the agent with new args. Skips if args are unchanged.
|
|
86
|
-
*
|
|
87
|
-
* @param args - Query arguments, or `SKIP_TOKEN` to do nothing.
|
|
88
|
-
*/
|
|
89
|
-
async start(args) {
|
|
90
|
-
// SKIP: no-op
|
|
91
|
-
if (args === SKIP) {
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
const typedArgs = args;
|
|
95
|
-
// Same args check — skip if unchanged
|
|
96
|
-
if (this._currentArgs !== null && this._resource.compareArgs(this._currentArgs, typedArgs)) {
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
this._currentArgs = typedArgs;
|
|
100
|
-
// Query the resource — get a cache entry
|
|
101
|
-
const entryPromise = this._resource.query(typedArgs);
|
|
102
|
-
// Get the entry synchronously from the resource
|
|
103
|
-
const entry = this._resource.entry(typedArgs);
|
|
104
|
-
// Swap previous/current
|
|
105
|
-
const oldTracking = this._tracking$.peek();
|
|
106
|
-
this._tracking$.set({
|
|
107
|
-
previous: oldTracking.current,
|
|
108
|
-
current: entry,
|
|
109
|
-
});
|
|
110
|
-
// Wait for the query to resolve and then clear previous
|
|
111
|
-
try {
|
|
112
|
-
await entryPromise;
|
|
113
|
-
// Clear refreshError on successful query completion
|
|
114
|
-
this._refreshError$.set(null);
|
|
115
|
-
}
|
|
116
|
-
catch {
|
|
117
|
-
// query() shouldn't reject, but handle gracefully
|
|
118
|
-
}
|
|
119
|
-
// Clear previous after current resolves (success or error)
|
|
120
|
-
// Only if current hasn't changed (latest-wins)
|
|
121
|
-
const currentTracking = this._tracking$.peek();
|
|
122
|
-
if (currentTracking.current === entry) {
|
|
123
|
-
this._tracking$.set({
|
|
124
|
-
previous: null,
|
|
125
|
-
current: entry,
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
compareArgs(a, b) {
|
|
130
|
-
return this._resource.compareArgs(a, b);
|
|
131
|
-
}
|
|
132
|
-
}
|
package/dist/query-v2/index.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export { SKIP, type SKIP_TOKEN } from "./lib/SKIP_TOKEN";
|
|
2
|
-
export { NO_VALUE } from "./lib/NO_VALUE";
|
|
3
|
-
export type { NO_VALUE as NO_VALUE_TYPE } from "./lib/NO_VALUE";
|
|
4
|
-
export { stableStringify } from "./lib/stableStringify";
|
|
5
|
-
export { Machine, type TMachineInstance, MachineIdle, MachinePending, MachineSuccess, MachineError, MachineRefreshing, MachineWithData, Patcher, CacheEntry, type CacheEntryOptions, CacheMap, type TCacheMapInstance, LifecycleHooks, ResourceV2, type ResourceV2Config, ResourceV2Agent, } from "./core";
|
|
6
|
-
export { createApi } from "./api/createApi";
|
|
7
|
-
export { ReactHooksPlugin } from "./plugins/ReactHooksPlugin";
|
|
8
|
-
export type { IReactHooksPluginContributions } from "./plugins/ReactHooksPlugin";
|
|
9
|
-
export { useResourceV2Agent, useResourceV2Ref } from "./react";
|
|
10
|
-
export { getSnapshot, hydrateSnapshot, CURRENT_SNAPSHOT_VERSION } from "./snapshot/Snapshot";
|
|
11
|
-
export * from "./types";
|
package/dist/query-v2/index.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
// Sentinel tokens
|
|
2
|
-
export { SKIP } from "./lib/SKIP_TOKEN";
|
|
3
|
-
export { NO_VALUE } from "./lib/NO_VALUE";
|
|
4
|
-
// Utilities
|
|
5
|
-
export { stableStringify } from "./lib/stableStringify";
|
|
6
|
-
// Core — Machine classes
|
|
7
|
-
export { Machine, MachineIdle, MachinePending, MachineSuccess, MachineError, MachineRefreshing, MachineWithData, Patcher, CacheEntry, CacheMap, LifecycleHooks, ResourceV2, ResourceV2Agent, } from "./core";
|
|
8
|
-
// API factory
|
|
9
|
-
export { createApi } from "./api/createApi";
|
|
10
|
-
// Plugins
|
|
11
|
-
export { ReactHooksPlugin } from "./plugins/ReactHooksPlugin";
|
|
12
|
-
// React hooks (standalone)
|
|
13
|
-
export { useResourceV2Agent, useResourceV2Ref } from "./react";
|
|
14
|
-
// Snapshot
|
|
15
|
-
export { getSnapshot, hydrateSnapshot, CURRENT_SNAPSHOT_VERSION } from "./snapshot/Snapshot";
|
|
16
|
-
// Types
|
|
17
|
-
export * from "./types";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const NO_VALUE = Symbol("NO_VALUE");
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const SKIP = Symbol("SKIP");
|