@fozy-labs/rx-toolkit 0.5.4 → 0.6.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/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 +4 -0
- package/dist/query/core/api/index.js +4 -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 +48 -2
- 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
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown when a Machine method requires state that doesn't exist
|
|
3
|
+
* (e.g. createPatch on a state without data, finishPatch without patchState).
|
|
4
|
+
*/
|
|
5
|
+
export class MachineStateError extends Error {
|
|
6
|
+
name = "MachineStateError";
|
|
7
|
+
constructor(method, detail) {
|
|
8
|
+
super(`Machine.${method}(): ${detail}`);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown when a Machine state transition is invalid for the current status.
|
|
3
|
+
*/
|
|
4
|
+
export class MachineTransitionError extends Error {
|
|
5
|
+
name = "MachineTransitionError";
|
|
6
|
+
constructor(method, status) {
|
|
7
|
+
super(`Machine.${method}(): invalid transition from "${status}"`);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { MachineError } from "./MachineError";
|
|
2
|
+
import { MachinePending } from "./MachinePending";
|
|
3
|
+
import { MachineRefreshError } from "./MachineRefreshError";
|
|
4
|
+
import { MachineRefreshing } from "./MachineRefreshing";
|
|
5
|
+
import { MachineSuccess } from "./MachineSuccess";
|
|
6
|
+
export { MachineBase } from "./MachineBase";
|
|
7
|
+
/**
|
|
8
|
+
* Union of all Machine subtypes.
|
|
9
|
+
*
|
|
10
|
+
* Backward-compatible: existing code typed as `Machine<A,D>` still works
|
|
11
|
+
* because all subtypes extend `MachineBase<A,D>` and carry the same `.state` shape.
|
|
12
|
+
*/
|
|
13
|
+
export type Machine<TArgs, TData> = MachinePending<TArgs, TData> | MachineSuccess<TArgs, TData> | MachineError<TArgs, TData> | MachineRefreshing<TArgs, TData> | MachineRefreshError<TArgs, TData>;
|
|
14
|
+
export declare namespace Machine {
|
|
15
|
+
function pending<TArgs, TData>(args: TArgs): MachinePending<TArgs, TData>;
|
|
16
|
+
function fromSnapshot<TArgs, TData>(snapshot: {
|
|
17
|
+
args: TArgs;
|
|
18
|
+
data: TData;
|
|
19
|
+
updatedAt: number;
|
|
20
|
+
}, isStale?: boolean): MachineSuccess<TArgs, TData> | MachineRefreshing<TArgs, TData>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { MachinePending } from "./MachinePending";
|
|
2
|
+
import { MachineRefreshing } from "./MachineRefreshing";
|
|
3
|
+
import { MachineSuccess } from "./MachineSuccess";
|
|
4
|
+
export { MachineBase } from "./MachineBase";
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
6
|
+
export var Machine;
|
|
7
|
+
(function (Machine) {
|
|
8
|
+
function pending(args) {
|
|
9
|
+
const state = {
|
|
10
|
+
status: "pending",
|
|
11
|
+
args,
|
|
12
|
+
data: null,
|
|
13
|
+
error: null,
|
|
14
|
+
updatedAt: null,
|
|
15
|
+
};
|
|
16
|
+
return new MachinePending(state);
|
|
17
|
+
}
|
|
18
|
+
Machine.pending = pending;
|
|
19
|
+
function fromSnapshot(snapshot, isStale = false) {
|
|
20
|
+
if (isStale) {
|
|
21
|
+
const state = {
|
|
22
|
+
status: "refreshing",
|
|
23
|
+
args: snapshot.args,
|
|
24
|
+
data: snapshot.data,
|
|
25
|
+
error: null,
|
|
26
|
+
updatedAt: snapshot.updatedAt,
|
|
27
|
+
patchState: null,
|
|
28
|
+
};
|
|
29
|
+
return new MachineRefreshing(state);
|
|
30
|
+
}
|
|
31
|
+
const state = {
|
|
32
|
+
status: "success",
|
|
33
|
+
args: snapshot.args,
|
|
34
|
+
data: snapshot.data,
|
|
35
|
+
error: null,
|
|
36
|
+
updatedAt: snapshot.updatedAt,
|
|
37
|
+
patchState: null,
|
|
38
|
+
};
|
|
39
|
+
return new MachineSuccess(state);
|
|
40
|
+
}
|
|
41
|
+
Machine.fromSnapshot = fromSnapshot;
|
|
42
|
+
})(Machine || (Machine = {}));
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { IPatchHandle, TMachineState } from "../../../query/types";
|
|
2
|
+
/**
|
|
3
|
+
* Base class for the Machine state machine.
|
|
4
|
+
*
|
|
5
|
+
* Provides all transition methods with runtime guards.
|
|
6
|
+
* Subtypes extend this and override their valid transitions with narrower return types.
|
|
7
|
+
* Invalid transitions inherited from MachineBase throw MachineTransitionError/MachineStateError.
|
|
8
|
+
*/
|
|
9
|
+
export declare class MachineBase<TArgs, TData> {
|
|
10
|
+
readonly state: TMachineState<TArgs, TData>;
|
|
11
|
+
protected constructor(state: TMachineState<TArgs, TData>);
|
|
12
|
+
/** pending → success */
|
|
13
|
+
success(data: TData): MachineBase<TArgs, TData>;
|
|
14
|
+
/** pending → error, refreshing → refresh-error */
|
|
15
|
+
fail(error: unknown): MachineBase<TArgs, TData>;
|
|
16
|
+
/** success → refreshing, refresh-error → refreshing */
|
|
17
|
+
refresh(): MachineBase<TArgs, TData>;
|
|
18
|
+
/** error → pending */
|
|
19
|
+
retry(): MachineBase<TArgs, TData>;
|
|
20
|
+
/** refreshing → success (replays patches on new data) */
|
|
21
|
+
rebase(data: TData): MachineBase<TArgs, TData>;
|
|
22
|
+
/** Create an optimistic patch (success, refreshing, refresh-error) */
|
|
23
|
+
createPatch(patchFn: (data: TData) => void, onSettle?: () => void): {
|
|
24
|
+
machine: MachineBase<TArgs, TData>;
|
|
25
|
+
handle: IPatchHandle;
|
|
26
|
+
};
|
|
27
|
+
/** Process all settled patches up to the first pending one */
|
|
28
|
+
finishPatch(): MachineBase<TArgs, TData>;
|
|
29
|
+
/** Process all settled patches (continues past pending) */
|
|
30
|
+
finishAllPatches(): MachineBase<TArgs, TData>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { MachineStateError, MachineTransitionError } from "../errors";
|
|
2
|
+
import { createPatches } from "../patcher";
|
|
3
|
+
import { hasData, processAllPatches, processPatches, replayPatches } from "./machine-helpers";
|
|
4
|
+
/**
|
|
5
|
+
* Base class for the Machine state machine.
|
|
6
|
+
*
|
|
7
|
+
* Provides all transition methods with runtime guards.
|
|
8
|
+
* Subtypes extend this and override their valid transitions with narrower return types.
|
|
9
|
+
* Invalid transitions inherited from MachineBase throw MachineTransitionError/MachineStateError.
|
|
10
|
+
*/
|
|
11
|
+
export class MachineBase {
|
|
12
|
+
state;
|
|
13
|
+
constructor(state) {
|
|
14
|
+
this.state = state;
|
|
15
|
+
}
|
|
16
|
+
// ==================== Transition Methods ====================
|
|
17
|
+
/** pending → success */
|
|
18
|
+
success(data) {
|
|
19
|
+
if (this.state.status !== "pending") {
|
|
20
|
+
throw new MachineTransitionError("success", this.state.status);
|
|
21
|
+
}
|
|
22
|
+
const state = {
|
|
23
|
+
status: "success",
|
|
24
|
+
args: this.state.args,
|
|
25
|
+
data,
|
|
26
|
+
error: null,
|
|
27
|
+
updatedAt: Date.now(),
|
|
28
|
+
patchState: null,
|
|
29
|
+
};
|
|
30
|
+
return new MachineBase(state);
|
|
31
|
+
}
|
|
32
|
+
/** pending → error, refreshing → refresh-error */
|
|
33
|
+
fail(error) {
|
|
34
|
+
if (this.state.status === "pending") {
|
|
35
|
+
const state = {
|
|
36
|
+
status: "error",
|
|
37
|
+
args: this.state.args,
|
|
38
|
+
data: null,
|
|
39
|
+
error,
|
|
40
|
+
updatedAt: null,
|
|
41
|
+
};
|
|
42
|
+
return new MachineBase(state);
|
|
43
|
+
}
|
|
44
|
+
if (this.state.status === "refreshing") {
|
|
45
|
+
const state = {
|
|
46
|
+
status: "refresh-error",
|
|
47
|
+
args: this.state.args,
|
|
48
|
+
data: this.state.data,
|
|
49
|
+
error,
|
|
50
|
+
updatedAt: this.state.updatedAt,
|
|
51
|
+
patchState: this.state.patchState,
|
|
52
|
+
};
|
|
53
|
+
return new MachineBase(state);
|
|
54
|
+
}
|
|
55
|
+
throw new MachineTransitionError("fail", this.state.status);
|
|
56
|
+
}
|
|
57
|
+
/** success → refreshing, refresh-error → refreshing */
|
|
58
|
+
refresh() {
|
|
59
|
+
if (this.state.status === "success") {
|
|
60
|
+
const state = {
|
|
61
|
+
status: "refreshing",
|
|
62
|
+
args: this.state.args,
|
|
63
|
+
data: this.state.data,
|
|
64
|
+
error: null,
|
|
65
|
+
updatedAt: this.state.updatedAt,
|
|
66
|
+
patchState: this.state.patchState,
|
|
67
|
+
};
|
|
68
|
+
return new MachineBase(state);
|
|
69
|
+
}
|
|
70
|
+
if (this.state.status === "refresh-error") {
|
|
71
|
+
const state = {
|
|
72
|
+
status: "refreshing",
|
|
73
|
+
args: this.state.args,
|
|
74
|
+
data: this.state.data,
|
|
75
|
+
error: null,
|
|
76
|
+
updatedAt: this.state.updatedAt,
|
|
77
|
+
patchState: this.state.patchState,
|
|
78
|
+
};
|
|
79
|
+
return new MachineBase(state);
|
|
80
|
+
}
|
|
81
|
+
throw new MachineTransitionError("refresh", this.state.status);
|
|
82
|
+
}
|
|
83
|
+
/** error → pending */
|
|
84
|
+
retry() {
|
|
85
|
+
if (this.state.status !== "error") {
|
|
86
|
+
throw new MachineTransitionError("retry", this.state.status);
|
|
87
|
+
}
|
|
88
|
+
const state = {
|
|
89
|
+
status: "pending",
|
|
90
|
+
args: this.state.args,
|
|
91
|
+
data: null,
|
|
92
|
+
error: null,
|
|
93
|
+
updatedAt: null,
|
|
94
|
+
};
|
|
95
|
+
return new MachineBase(state);
|
|
96
|
+
}
|
|
97
|
+
/** refreshing → success (replays patches on new data) */
|
|
98
|
+
rebase(data) {
|
|
99
|
+
if (this.state.status !== "refreshing") {
|
|
100
|
+
throw new MachineTransitionError("rebase", this.state.status);
|
|
101
|
+
}
|
|
102
|
+
const patchState = this.state.patchState;
|
|
103
|
+
// No patches → straight to success
|
|
104
|
+
if (!patchState) {
|
|
105
|
+
const state = {
|
|
106
|
+
status: "success",
|
|
107
|
+
args: this.state.args,
|
|
108
|
+
data,
|
|
109
|
+
error: null,
|
|
110
|
+
updatedAt: Date.now(),
|
|
111
|
+
patchState: null,
|
|
112
|
+
};
|
|
113
|
+
return new MachineBase(state);
|
|
114
|
+
}
|
|
115
|
+
// Replay pending patches on new base
|
|
116
|
+
return new MachineBase(replayPatches(this.state, "success", data, patchState.patches, Date.now()));
|
|
117
|
+
}
|
|
118
|
+
// ==================== Patch Methods ====================
|
|
119
|
+
/** Create an optimistic patch (success, refreshing, refresh-error) */
|
|
120
|
+
createPatch(patchFn, onSettle) {
|
|
121
|
+
if (!hasData(this.state)) {
|
|
122
|
+
throw new MachineStateError("createPatch", `invalid state "${this.state.status}"`);
|
|
123
|
+
}
|
|
124
|
+
const currentData = this.state.data;
|
|
125
|
+
const [nextData, forward, inverse] = createPatches(currentData, patchFn);
|
|
126
|
+
const entry = {
|
|
127
|
+
forward,
|
|
128
|
+
inverse,
|
|
129
|
+
status: "pending",
|
|
130
|
+
};
|
|
131
|
+
const existingPatches = this.state.patchState?.patches ?? [];
|
|
132
|
+
const originalData = this.state.patchState?.originalData ?? currentData;
|
|
133
|
+
const newPatchState = {
|
|
134
|
+
originalData,
|
|
135
|
+
patches: [...existingPatches, entry],
|
|
136
|
+
isConsistencyViolation: false,
|
|
137
|
+
};
|
|
138
|
+
const newState = {
|
|
139
|
+
...this.state,
|
|
140
|
+
data: nextData,
|
|
141
|
+
patchState: newPatchState,
|
|
142
|
+
};
|
|
143
|
+
let isSettled = false;
|
|
144
|
+
const handle = {
|
|
145
|
+
commit: () => {
|
|
146
|
+
if (isSettled)
|
|
147
|
+
return;
|
|
148
|
+
isSettled = true;
|
|
149
|
+
entry.status = "committed";
|
|
150
|
+
onSettle?.();
|
|
151
|
+
},
|
|
152
|
+
abort: () => {
|
|
153
|
+
if (isSettled)
|
|
154
|
+
return;
|
|
155
|
+
isSettled = true;
|
|
156
|
+
entry.status = "aborted";
|
|
157
|
+
onSettle?.();
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
return { machine: new MachineBase(newState), handle };
|
|
161
|
+
}
|
|
162
|
+
/** Process all settled patches up to the first pending one */
|
|
163
|
+
finishPatch() {
|
|
164
|
+
if (!hasData(this.state) || !this.state.patchState) {
|
|
165
|
+
throw new MachineStateError("finishPatch", "no active patchState");
|
|
166
|
+
}
|
|
167
|
+
return new MachineBase(processPatches(this.state, this.state.patchState));
|
|
168
|
+
}
|
|
169
|
+
/** Process all settled patches (continues past pending) */
|
|
170
|
+
finishAllPatches() {
|
|
171
|
+
if (!hasData(this.state) || !this.state.patchState) {
|
|
172
|
+
throw new MachineStateError("finishAllPatches", "no active patchState");
|
|
173
|
+
}
|
|
174
|
+
return new MachineBase(processAllPatches(this.state, this.state.patchState));
|
|
175
|
+
}
|
|
176
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { TErrorState } from "../../../query/types";
|
|
2
|
+
import { MachineBase } from "./MachineBase";
|
|
3
|
+
import { MachinePending } from "./MachinePending";
|
|
4
|
+
export declare class MachineError<TArgs, TData> extends MachineBase<TArgs, TData> {
|
|
5
|
+
readonly status: "error";
|
|
6
|
+
readonly state: TErrorState<TArgs>;
|
|
7
|
+
constructor(state: TErrorState<TArgs>);
|
|
8
|
+
/** error → pending */
|
|
9
|
+
retry(): MachinePending<TArgs, TData>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { MachineBase } from "./MachineBase";
|
|
2
|
+
import { MachinePending } from "./MachinePending";
|
|
3
|
+
export class MachineError extends MachineBase {
|
|
4
|
+
status = "error";
|
|
5
|
+
constructor(state) {
|
|
6
|
+
super(state);
|
|
7
|
+
}
|
|
8
|
+
/** error → pending */
|
|
9
|
+
retry() {
|
|
10
|
+
const state = {
|
|
11
|
+
status: "pending",
|
|
12
|
+
args: this.state.args,
|
|
13
|
+
data: null,
|
|
14
|
+
error: null,
|
|
15
|
+
updatedAt: null,
|
|
16
|
+
};
|
|
17
|
+
return new MachinePending(state);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { TPendingState } from "../../../query/types";
|
|
2
|
+
import { MachineBase } from "./MachineBase";
|
|
3
|
+
import { MachineError } from "./MachineError";
|
|
4
|
+
import { MachineSuccess } from "./MachineSuccess";
|
|
5
|
+
export declare class MachinePending<TArgs, TData> extends MachineBase<TArgs, TData> {
|
|
6
|
+
readonly status: "pending";
|
|
7
|
+
readonly state: TPendingState<TArgs>;
|
|
8
|
+
constructor(state: TPendingState<TArgs>);
|
|
9
|
+
/** pending → success */
|
|
10
|
+
success(data: TData): MachineSuccess<TArgs, TData>;
|
|
11
|
+
/** pending → error */
|
|
12
|
+
fail(error: unknown): MachineError<TArgs, TData>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { MachineBase } from "./MachineBase";
|
|
2
|
+
import { MachineError } from "./MachineError";
|
|
3
|
+
import { MachineSuccess } from "./MachineSuccess";
|
|
4
|
+
export class MachinePending extends MachineBase {
|
|
5
|
+
status = "pending";
|
|
6
|
+
constructor(state) {
|
|
7
|
+
super(state);
|
|
8
|
+
}
|
|
9
|
+
/** pending → success */
|
|
10
|
+
success(data) {
|
|
11
|
+
const state = {
|
|
12
|
+
status: "success",
|
|
13
|
+
args: this.state.args,
|
|
14
|
+
data,
|
|
15
|
+
error: null,
|
|
16
|
+
updatedAt: Date.now(),
|
|
17
|
+
patchState: null,
|
|
18
|
+
};
|
|
19
|
+
return new MachineSuccess(state);
|
|
20
|
+
}
|
|
21
|
+
/** pending → error */
|
|
22
|
+
fail(error) {
|
|
23
|
+
const state = {
|
|
24
|
+
status: "error",
|
|
25
|
+
args: this.state.args,
|
|
26
|
+
data: null,
|
|
27
|
+
error,
|
|
28
|
+
updatedAt: null,
|
|
29
|
+
};
|
|
30
|
+
return new MachineError(state);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { TRefreshErrorState } from "../../../query/types";
|
|
2
|
+
import type { TDataState } from "./machine-helpers";
|
|
3
|
+
import { MachineRefreshing } from "./MachineRefreshing";
|
|
4
|
+
import { MachineWithData } from "./MachineWithData";
|
|
5
|
+
export declare class MachineRefreshError<TArgs, TData> extends MachineWithData<TArgs, TData> {
|
|
6
|
+
readonly status: "refresh-error";
|
|
7
|
+
readonly state: TRefreshErrorState<TArgs, TData>;
|
|
8
|
+
constructor(state: TRefreshErrorState<TArgs, TData>);
|
|
9
|
+
protected withState(state: TDataState<TArgs, TData>): this;
|
|
10
|
+
/** refresh-error → refreshing */
|
|
11
|
+
refresh(): MachineRefreshing<TArgs, TData>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { MachineRefreshing } from "./MachineRefreshing";
|
|
2
|
+
import { MachineWithData } from "./MachineWithData";
|
|
3
|
+
export class MachineRefreshError extends MachineWithData {
|
|
4
|
+
status = "refresh-error";
|
|
5
|
+
constructor(state) {
|
|
6
|
+
super(state);
|
|
7
|
+
}
|
|
8
|
+
withState(state) {
|
|
9
|
+
return new MachineRefreshError(state);
|
|
10
|
+
}
|
|
11
|
+
/** refresh-error → refreshing */
|
|
12
|
+
refresh() {
|
|
13
|
+
const state = {
|
|
14
|
+
status: "refreshing",
|
|
15
|
+
args: this.state.args,
|
|
16
|
+
data: this.state.data,
|
|
17
|
+
error: null,
|
|
18
|
+
updatedAt: this.state.updatedAt,
|
|
19
|
+
patchState: this.state.patchState,
|
|
20
|
+
};
|
|
21
|
+
return new MachineRefreshing(state);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { TRefreshingState } from "../../../query/types";
|
|
2
|
+
import type { TDataState } from "./machine-helpers";
|
|
3
|
+
import { MachineRefreshError } from "./MachineRefreshError";
|
|
4
|
+
import { MachineSuccess } from "./MachineSuccess";
|
|
5
|
+
import { MachineWithData } from "./MachineWithData";
|
|
6
|
+
export declare class MachineRefreshing<TArgs, TData> extends MachineWithData<TArgs, TData> {
|
|
7
|
+
readonly status: "refreshing";
|
|
8
|
+
readonly state: TRefreshingState<TArgs, TData>;
|
|
9
|
+
constructor(state: TRefreshingState<TArgs, TData>);
|
|
10
|
+
protected withState(state: TDataState<TArgs, TData>): this;
|
|
11
|
+
/** refreshing → success (replays patches on new data) */
|
|
12
|
+
rebase(data: TData): MachineSuccess<TArgs, TData>;
|
|
13
|
+
/** refreshing → refresh-error */
|
|
14
|
+
fail(error: unknown): MachineRefreshError<TArgs, TData>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { replayPatches } from "./machine-helpers";
|
|
2
|
+
import { MachineRefreshError } from "./MachineRefreshError";
|
|
3
|
+
import { MachineSuccess } from "./MachineSuccess";
|
|
4
|
+
import { MachineWithData } from "./MachineWithData";
|
|
5
|
+
export class MachineRefreshing extends MachineWithData {
|
|
6
|
+
status = "refreshing";
|
|
7
|
+
constructor(state) {
|
|
8
|
+
super(state);
|
|
9
|
+
}
|
|
10
|
+
withState(state) {
|
|
11
|
+
return new MachineRefreshing(state);
|
|
12
|
+
}
|
|
13
|
+
/** refreshing → success (replays patches on new data) */
|
|
14
|
+
rebase(data) {
|
|
15
|
+
const patchState = this.state.patchState;
|
|
16
|
+
if (!patchState) {
|
|
17
|
+
const state = {
|
|
18
|
+
status: "success",
|
|
19
|
+
args: this.state.args,
|
|
20
|
+
data,
|
|
21
|
+
error: null,
|
|
22
|
+
updatedAt: Date.now(),
|
|
23
|
+
patchState: null,
|
|
24
|
+
};
|
|
25
|
+
return new MachineSuccess(state);
|
|
26
|
+
}
|
|
27
|
+
// Replay pending patches on new base
|
|
28
|
+
const resultState = replayPatches(this.state, "success", data, patchState.patches, Date.now());
|
|
29
|
+
return new MachineSuccess(resultState);
|
|
30
|
+
}
|
|
31
|
+
/** refreshing → refresh-error */
|
|
32
|
+
fail(error) {
|
|
33
|
+
const state = {
|
|
34
|
+
status: "refresh-error",
|
|
35
|
+
args: this.state.args,
|
|
36
|
+
data: this.state.data,
|
|
37
|
+
error,
|
|
38
|
+
updatedAt: this.state.updatedAt,
|
|
39
|
+
patchState: this.state.patchState,
|
|
40
|
+
};
|
|
41
|
+
return new MachineRefreshError(state);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { TSuccessState } from "../../../query/types";
|
|
2
|
+
import type { TDataState } from "./machine-helpers";
|
|
3
|
+
import { MachineRefreshing } from "./MachineRefreshing";
|
|
4
|
+
import { MachineWithData } from "./MachineWithData";
|
|
5
|
+
export declare class MachineSuccess<TArgs, TData> extends MachineWithData<TArgs, TData> {
|
|
6
|
+
readonly status: "success";
|
|
7
|
+
readonly state: TSuccessState<TArgs, TData>;
|
|
8
|
+
constructor(state: TSuccessState<TArgs, TData>);
|
|
9
|
+
protected withState(state: TDataState<TArgs, TData>): this;
|
|
10
|
+
/** success → refreshing */
|
|
11
|
+
refresh(): MachineRefreshing<TArgs, TData>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { MachineRefreshing } from "./MachineRefreshing";
|
|
2
|
+
import { MachineWithData } from "./MachineWithData";
|
|
3
|
+
export class MachineSuccess extends MachineWithData {
|
|
4
|
+
status = "success";
|
|
5
|
+
constructor(state) {
|
|
6
|
+
super(state);
|
|
7
|
+
}
|
|
8
|
+
withState(state) {
|
|
9
|
+
return new MachineSuccess(state);
|
|
10
|
+
}
|
|
11
|
+
/** success → refreshing */
|
|
12
|
+
refresh() {
|
|
13
|
+
const state = {
|
|
14
|
+
status: "refreshing",
|
|
15
|
+
args: this.state.args,
|
|
16
|
+
data: this.state.data,
|
|
17
|
+
error: null,
|
|
18
|
+
updatedAt: this.state.updatedAt,
|
|
19
|
+
patchState: this.state.patchState,
|
|
20
|
+
};
|
|
21
|
+
return new MachineRefreshing(state);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { IPatchHandle, TPatchState } from "../../../query/types";
|
|
2
|
+
import { type TDataState } from "./machine-helpers";
|
|
3
|
+
import { MachineBase } from "./MachineBase";
|
|
4
|
+
export type TPatchCreateResult<TMachine> = {
|
|
5
|
+
machine: TMachine;
|
|
6
|
+
handle: IPatchHandle;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Abstract intermediate base for data-bearing machine states (success, refreshing, refresh-error).
|
|
10
|
+
*
|
|
11
|
+
* Carries `data`, `updatedAt`, `patchState` and all patch methods.
|
|
12
|
+
* Concrete subtypes (MachineSuccess, MachineRefreshing, MachineRefreshError)
|
|
13
|
+
* extend this and implement `withState` to preserve their identity on transitions.
|
|
14
|
+
*/
|
|
15
|
+
export declare abstract class MachineWithData<TArgs, TData> extends MachineBase<TArgs, TData> {
|
|
16
|
+
readonly state: TDataState<TArgs, TData>;
|
|
17
|
+
protected constructor(state: TDataState<TArgs, TData>);
|
|
18
|
+
get data(): TData;
|
|
19
|
+
get updatedAt(): number;
|
|
20
|
+
get patchState(): TPatchState<TData> | null;
|
|
21
|
+
protected abstract withState(state: TDataState<TArgs, TData>): this;
|
|
22
|
+
createPatch(patchFn: (data: TData) => void, onSettle?: () => void): TPatchCreateResult<this>;
|
|
23
|
+
finishPatch(): this;
|
|
24
|
+
finishAllPatches(): this;
|
|
25
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { MachineStateError } from "../errors";
|
|
2
|
+
import { createPatches } from "../patcher";
|
|
3
|
+
import { processAllPatches, processPatches, withDataState } from "./machine-helpers";
|
|
4
|
+
import { MachineBase } from "./MachineBase";
|
|
5
|
+
/**
|
|
6
|
+
* Abstract intermediate base for data-bearing machine states (success, refreshing, refresh-error).
|
|
7
|
+
*
|
|
8
|
+
* Carries `data`, `updatedAt`, `patchState` and all patch methods.
|
|
9
|
+
* Concrete subtypes (MachineSuccess, MachineRefreshing, MachineRefreshError)
|
|
10
|
+
* extend this and implement `withState` to preserve their identity on transitions.
|
|
11
|
+
*/
|
|
12
|
+
export class MachineWithData extends MachineBase {
|
|
13
|
+
constructor(state) {
|
|
14
|
+
super(state);
|
|
15
|
+
}
|
|
16
|
+
get data() {
|
|
17
|
+
return this.state.data;
|
|
18
|
+
}
|
|
19
|
+
get updatedAt() {
|
|
20
|
+
return this.state.updatedAt;
|
|
21
|
+
}
|
|
22
|
+
get patchState() {
|
|
23
|
+
return this.state.patchState;
|
|
24
|
+
}
|
|
25
|
+
// ==================== Patch Methods ====================
|
|
26
|
+
createPatch(patchFn, onSettle) {
|
|
27
|
+
const currentData = this.state.data;
|
|
28
|
+
const [nextData, forward, inverse] = createPatches(currentData, patchFn);
|
|
29
|
+
const entry = {
|
|
30
|
+
forward,
|
|
31
|
+
inverse,
|
|
32
|
+
status: "pending",
|
|
33
|
+
};
|
|
34
|
+
const existingPatches = this.state.patchState?.patches ?? [];
|
|
35
|
+
const originalData = this.state.patchState?.originalData ?? currentData;
|
|
36
|
+
const newPatchState = {
|
|
37
|
+
originalData,
|
|
38
|
+
patches: [...existingPatches, entry],
|
|
39
|
+
isConsistencyViolation: false,
|
|
40
|
+
};
|
|
41
|
+
const newState = withDataState(this.state, nextData, newPatchState);
|
|
42
|
+
let isSettled = false;
|
|
43
|
+
const handle = {
|
|
44
|
+
commit: () => {
|
|
45
|
+
if (isSettled)
|
|
46
|
+
return;
|
|
47
|
+
isSettled = true;
|
|
48
|
+
entry.status = "committed";
|
|
49
|
+
onSettle?.();
|
|
50
|
+
},
|
|
51
|
+
abort: () => {
|
|
52
|
+
if (isSettled)
|
|
53
|
+
return;
|
|
54
|
+
isSettled = true;
|
|
55
|
+
entry.status = "aborted";
|
|
56
|
+
onSettle?.();
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
return { machine: this.withState(newState), handle };
|
|
60
|
+
}
|
|
61
|
+
finishPatch() {
|
|
62
|
+
if (!this.state.patchState) {
|
|
63
|
+
throw new MachineStateError("finishPatch", "no active patchState");
|
|
64
|
+
}
|
|
65
|
+
return this.withState(processPatches(this.state, this.state.patchState));
|
|
66
|
+
}
|
|
67
|
+
finishAllPatches() {
|
|
68
|
+
if (!this.state.patchState) {
|
|
69
|
+
throw new MachineStateError("finishAllPatches", "no active patchState");
|
|
70
|
+
}
|
|
71
|
+
return this.withState(processAllPatches(this.state, this.state.patchState));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./Machine";
|
|
2
|
+
export * from "./MachineBase";
|
|
3
|
+
export * from "./MachinePending";
|
|
4
|
+
export * from "./MachineSuccess";
|
|
5
|
+
export * from "./MachineError";
|
|
6
|
+
export * from "./MachineRefreshing";
|
|
7
|
+
export * from "./MachineRefreshError";
|
|
8
|
+
export * from "./MachineWithData";
|
|
9
|
+
export * from "./machine-helpers";
|