@fozy-labs/rx-toolkit 0.5.3-rc.1 → 0.5.3
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 +21 -21
- package/README.md +143 -137
- package/dist/common/devtools/combineDevtools.js +3 -3
- package/dist/common/devtools/index.d.ts +3 -3
- package/dist/common/devtools/index.js +3 -3
- package/dist/common/devtools/reduxDevtools.d.ts +1 -1
- package/dist/common/devtools/reduxDevtools.js +17 -17
- package/dist/common/devtools/types.d.ts +0 -6
- package/dist/common/options/DefaultOptions.d.ts +1 -1
- package/dist/common/options/SharedOptions.d.ts +3 -2
- package/dist/common/options/SharedOptions.js +6 -0
- package/dist/common/options/index.d.ts +1 -1
- package/dist/common/options/index.js +1 -1
- package/dist/common/react/index.d.ts +2 -2
- package/dist/common/react/index.js +2 -2
- package/dist/common/react/useConstant.js +1 -1
- package/dist/common/utils/deepEqual.js +1 -1
- package/dist/common/utils/index.d.ts +3 -3
- package/dist/common/utils/index.js +3 -3
- package/dist/common/utils/shallowEqual.js +1 -1
- package/dist/index.d.ts +8 -7
- package/dist/index.js +8 -7
- package/dist/query/SKIP_TOKEN.js +1 -1
- package/dist/query/api/createCommand.d.ts +21 -0
- package/dist/query/api/createCommand.js +20 -0
- package/dist/query/api/createOperation.d.ts +5 -3
- package/dist/query/api/createOperation.js +6 -2
- package/dist/query/api/createResource.d.ts +2 -2
- package/dist/query/api/createResourceDuplicator.d.ts +2 -2
- package/dist/query/core/Command/Command.d.ts +35 -0
- package/dist/query/core/{Opertation/Operation.js → Command/Command.js} +13 -14
- package/dist/query/core/Command/CommandAgent.d.ts +19 -0
- package/dist/query/core/{Opertation/OperationAgent.js → Command/CommandAgent.js} +13 -13
- package/dist/query/core/Command/index.d.ts +2 -0
- package/dist/query/core/Command/index.js +2 -0
- package/dist/query/core/Operation/Operation.d.ts +8 -0
- package/dist/query/core/Operation/Operation.js +4 -0
- package/dist/query/core/Operation/OperationAgent.d.ts +4 -0
- package/dist/query/core/Operation/OperationAgent.js +4 -0
- package/dist/query/core/QueriesCache.d.ts +2 -2
- package/dist/query/core/QueriesCache.js +1 -1
- package/dist/query/core/QueriesLifetimeHooks.d.ts +1 -1
- package/dist/query/core/QueriesLifetimeHooks.js +7 -7
- package/dist/query/core/Resource/Resource.d.ts +16 -16
- package/dist/query/core/Resource/Resource.js +7 -7
- package/dist/query/core/Resource/ResourceAgent.d.ts +2 -2
- package/dist/query/core/Resource/ResourceAgent.js +3 -3
- package/dist/query/core/Resource/ResourceDuplicator.d.ts +17 -17
- package/dist/query/core/Resource/ResourceDuplicator.js +18 -20
- package/dist/query/core/Resource/ResourceDuplicatorAgent.d.ts +6 -6
- package/dist/query/core/Resource/ResourceDuplicatorAgent.js +3 -3
- package/dist/query/core/Resource/ResourceRef.d.ts +2 -2
- package/dist/query/core/Resource/ResourceRef.js +12 -12
- package/dist/query/index.d.ts +11 -8
- package/dist/query/index.js +14 -8
- package/dist/query/lib/IndirectMap.js +4 -4
- package/dist/query/lib/ReactiveCache.d.ts +1 -1
- package/dist/query/react/useCommandAgent.d.ts +24 -0
- package/dist/query/react/useCommandAgent.js +39 -0
- package/dist/query/react/useOperationAgent.d.ts +6 -8
- package/dist/query/react/useOperationAgent.js +6 -23
- package/dist/query/react/useResourceAgent.d.ts +4 -4
- package/dist/query/react/useResourceAgent.js +1 -1
- package/dist/query/react/useResourceRef.d.ts +3 -3
- package/dist/query/react/useResourceRef.js +7 -2
- package/dist/query/types/Command.types.d.ts +154 -0
- package/dist/query/types/Command.types.js +1 -0
- package/dist/query/types/Operation.types.d.ts +13 -154
- package/dist/query/types/Resource.types.d.ts +7 -5
- package/dist/query/types/index.d.ts +4 -3
- package/dist/query/types/index.js +5 -3
- package/dist/query-v2/api/createApi.d.ts +10 -0
- package/dist/query-v2/api/createApi.js +83 -0
- package/dist/query-v2/core/common/CacheEntry.d.ts +29 -0
- package/dist/query-v2/core/common/CacheEntry.js +71 -0
- package/dist/query-v2/core/common/CacheMap.d.ts +38 -0
- package/dist/query-v2/core/common/CacheMap.js +127 -0
- package/dist/query-v2/core/common/LifecycleHooks.d.ts +22 -0
- package/dist/query-v2/core/common/LifecycleHooks.js +104 -0
- package/dist/query-v2/core/common/index.d.ts +3 -0
- package/dist/query-v2/core/common/index.js +3 -0
- package/dist/query-v2/core/index.d.ts +3 -0
- package/dist/query-v2/core/index.js +3 -0
- package/dist/query-v2/core/machines/Machine.d.ts +14 -0
- package/dist/query-v2/core/machines/Machine.js +33 -0
- package/dist/query-v2/core/machines/MachineError.d.ts +11 -0
- package/dist/query-v2/core/machines/MachineError.js +26 -0
- package/dist/query-v2/core/machines/MachineIdle.d.ts +8 -0
- package/dist/query-v2/core/machines/MachineIdle.js +19 -0
- package/dist/query-v2/core/machines/MachinePending.d.ts +12 -0
- package/dist/query-v2/core/machines/MachinePending.js +29 -0
- package/dist/query-v2/core/machines/MachineRefreshing.d.ts +14 -0
- package/dist/query-v2/core/machines/MachineRefreshing.js +46 -0
- package/dist/query-v2/core/machines/MachineSuccess.d.ts +16 -0
- package/dist/query-v2/core/machines/MachineSuccess.js +42 -0
- package/dist/query-v2/core/machines/MachineWithData.d.ts +18 -0
- package/dist/query-v2/core/machines/MachineWithData.js +40 -0
- package/dist/query-v2/core/machines/Patcher.d.ts +20 -0
- package/dist/query-v2/core/machines/Patcher.js +104 -0
- package/dist/query-v2/core/machines/index.d.ts +8 -0
- package/dist/query-v2/core/machines/index.js +8 -0
- package/dist/query-v2/core/resource/ResourceV2.d.ts +120 -0
- package/dist/query-v2/core/resource/ResourceV2.js +464 -0
- package/dist/query-v2/core/resource/ResourceV2Agent.d.ts +26 -0
- package/dist/query-v2/core/resource/ResourceV2Agent.js +132 -0
- package/dist/query-v2/core/resource/index.d.ts +2 -0
- package/dist/query-v2/core/resource/index.js +2 -0
- package/dist/query-v2/index.d.ts +11 -0
- package/dist/query-v2/index.js +17 -0
- package/dist/query-v2/lib/NO_VALUE.d.ts +2 -0
- package/dist/query-v2/lib/NO_VALUE.js +1 -0
- package/dist/query-v2/lib/SKIP_TOKEN.d.ts +2 -0
- package/dist/query-v2/lib/SKIP_TOKEN.js +1 -0
- package/dist/query-v2/lib/index.d.ts +4 -0
- package/dist/query-v2/lib/index.js +3 -0
- package/dist/query-v2/lib/stableStringify.d.ts +8 -0
- package/dist/query-v2/lib/stableStringify.js +23 -0
- package/dist/query-v2/plugins/ReactHooksPlugin.d.ts +25 -0
- package/dist/query-v2/plugins/ReactHooksPlugin.js +19 -0
- package/dist/query-v2/plugins/types.d.ts +1 -0
- package/dist/query-v2/plugins/types.js +1 -0
- package/dist/query-v2/react/__tests__/helpers.d.ts +12 -0
- package/dist/query-v2/react/__tests__/helpers.js +33 -0
- package/dist/query-v2/react/index.d.ts +2 -0
- package/dist/query-v2/react/index.js +2 -0
- package/dist/query-v2/react/useResourceV2Agent.d.ts +12 -0
- package/dist/query-v2/react/useResourceV2Agent.js +36 -0
- package/dist/query-v2/react/useResourceV2Ref.d.ts +12 -0
- package/dist/query-v2/react/useResourceV2Ref.js +57 -0
- package/dist/query-v2/snapshot/Snapshot.d.ts +13 -0
- package/dist/query-v2/snapshot/Snapshot.js +76 -0
- package/dist/query-v2/types/agent.types.d.ts +54 -0
- package/dist/query-v2/types/agent.types.js +1 -0
- package/dist/query-v2/types/api.types.d.ts +22 -0
- package/dist/query-v2/types/api.types.js +1 -0
- package/dist/query-v2/types/cache.types.d.ts +37 -0
- package/dist/query-v2/types/cache.types.js +1 -0
- package/dist/query-v2/types/index.d.ts +9 -0
- package/dist/query-v2/types/index.js +9 -0
- package/dist/query-v2/types/lifecycle.types.d.ts +25 -0
- package/dist/query-v2/types/lifecycle.types.js +1 -0
- package/dist/query-v2/types/machine.types.d.ts +67 -0
- package/dist/query-v2/types/machine.types.js +1 -0
- package/dist/query-v2/types/plugin.types.d.ts +38 -0
- package/dist/query-v2/types/plugin.types.js +1 -0
- package/dist/query-v2/types/resource.types.d.ts +35 -0
- package/dist/query-v2/types/resource.types.js +1 -0
- package/dist/query-v2/types/shared.types.d.ts +20 -0
- package/dist/query-v2/types/shared.types.js +1 -0
- package/dist/query-v2/types/snapshot.types.d.ts +21 -0
- package/dist/query-v2/types/snapshot.types.js +1 -0
- package/dist/signals/base/Batcher.js +9 -5
- package/dist/signals/base/ComputeCache.js +3 -3
- package/dist/signals/base/DependencyTracker.js +1 -1
- package/dist/signals/base/Devtools.d.ts +3 -2
- package/dist/signals/base/Devtools.js +54 -27
- package/dist/signals/base/Indexer.js +1 -1
- package/dist/signals/base/ReadonlySignal.js +1 -1
- package/dist/signals/base/SyncObservable.d.ts +1 -2
- package/dist/signals/base/SyncObservable.js +2 -5
- package/dist/signals/base/index.d.ts +6 -6
- package/dist/signals/base/index.js +6 -6
- package/dist/signals/index.d.ts +5 -4
- package/dist/signals/index.js +5 -4
- package/dist/signals/operators/index.d.ts +1 -1
- package/dist/signals/operators/index.js +1 -1
- package/dist/signals/operators/signalize.d.ts +1 -1
- package/dist/signals/react/index.d.ts +1 -1
- package/dist/signals/react/index.js +1 -1
- package/dist/signals/signals/Computed.d.ts +3 -4
- package/dist/signals/signals/Computed.js +18 -10
- package/dist/signals/signals/Effect.js +2 -1
- package/dist/signals/signals/LocalState.d.ts +44 -0
- package/dist/signals/signals/{LocalSignal.js → LocalState.js} +62 -28
- package/dist/signals/signals/Signal.d.ts +8 -7
- package/dist/signals/signals/Signal.js +4 -1
- package/dist/signals/signals/State.d.ts +4 -5
- package/dist/signals/signals/State.js +23 -9
- package/dist/signals/signals/index.d.ts +5 -5
- package/dist/signals/signals/index.js +5 -6
- package/dist/signals/types/SignalOptions.d.ts +16 -0
- package/dist/signals/types/SignalOptions.js +1 -0
- package/dist/signals/types/index.d.ts +3 -1
- package/dist/signals/types/index.js +3 -1
- package/dist/signals/types/normalizeSignalOptions.d.ts +2 -0
- package/dist/signals/types/normalizeSignalOptions.js +10 -0
- package/dist/signals/types/signals.types.d.ts +6 -2
- package/docs/CHANGELOG.md +111 -32
- package/docs/CONTRIBUTING.md +230 -0
- package/docs/contributing/ai-assisted-development.md +47 -0
- package/docs/contributing/query-v2/README.md +379 -0
- package/docs/{release → contributing/release}/README.md +59 -59
- package/docs/devtools/README.md +228 -228
- package/docs/migrations/0.5.0.md +58 -58
- package/docs/migrations/query-v2.md +171 -0
- package/docs/options/README.md +92 -90
- package/docs/query/README.md +575 -571
- package/docs/query-v2/README.md +280 -0
- package/docs/query-v2/api-reference.md +235 -0
- package/docs/query-v2/optimistic-updates.md +148 -0
- package/docs/query-v2/ssr.md +130 -0
- package/docs/signals/README.md +300 -295
- package/docs/usage/react/README.md +309 -307
- package/package.json +86 -63
- package/dist/query/core/Opertation/Operation.d.ts +0 -35
- package/dist/query/core/Opertation/OperationAgent.d.ts +0 -19
- package/dist/signals/signals/LocalSignal.d.ts +0 -32
|
@@ -1,154 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
|
|
6
|
-
*/
|
|
7
|
-
export type
|
|
8
|
-
/**
|
|
9
|
-
|
|
10
|
-
*/
|
|
11
|
-
export type
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
/** Функция выполнения операции */
|
|
15
|
-
queryFn: (args: D["Args"]) => Promise<D["Result"]>;
|
|
16
|
-
/** Связанные ресурсы */
|
|
17
|
-
link?: (link: <RD extends ResourceDefinition>(options: LinkOptions<D, RD>) => void) => void;
|
|
18
|
-
/**
|
|
19
|
-
* Время жизни кеша в миллисекундах. По умолчанию 1_000 (1 секунда).
|
|
20
|
-
* Если указано false - кеш не удаляется автоматически.
|
|
21
|
-
*/
|
|
22
|
-
cacheLifetime?: number | false;
|
|
23
|
-
/**
|
|
24
|
-
* Хук, вызываемый при добавлении нового элемента в кеш.
|
|
25
|
-
* Также позволяет отследить:
|
|
26
|
-
* - когда данные были загружены (впервые)
|
|
27
|
-
* - когда элемент был удален из кеша
|
|
28
|
-
*/
|
|
29
|
-
onCacheEntryAdded?: OnCacheEntryAdded<D["Args"], D["Data"]>;
|
|
30
|
-
/**
|
|
31
|
-
* Хук, вызываемый при старте запроса.
|
|
32
|
-
* Также позволяет отследить:
|
|
33
|
-
* - завершение запроса с результатом или ошибкой
|
|
34
|
-
*/
|
|
35
|
-
onQueryStarted?: OnQueryStarted<D["Args"], D["Result"]>;
|
|
36
|
-
/**
|
|
37
|
-
* Настройка отображения в devtools
|
|
38
|
-
*/
|
|
39
|
-
devtoolsName?: string | false;
|
|
40
|
-
};
|
|
41
|
-
/**
|
|
42
|
-
* Настройки связи операции с ресурсом
|
|
43
|
-
*/
|
|
44
|
-
export type LinkOptions<D extends OperationDefinition, RD extends ResourceDefinition> = {
|
|
45
|
-
/**
|
|
46
|
-
* Целевой ресурс, с которым связывается операция
|
|
47
|
-
* @required
|
|
48
|
-
*/
|
|
49
|
-
resource: ResourceInstance<RD>;
|
|
50
|
-
/**
|
|
51
|
-
* Функция для получения аргументов ресурса из аргументов операции.
|
|
52
|
-
* Используется для определения какой именно элемент в кэше ресурса нужно обновить
|
|
53
|
-
* @required
|
|
54
|
-
*/
|
|
55
|
-
forwardArgs: (args: D["Args"]) => RD["Args"];
|
|
56
|
-
/**
|
|
57
|
-
* Флаг для инвалидации (очистки) кэша ресурса после выполнения операции.
|
|
58
|
-
* При true - кэш будет очищен и ресурс будет перезагружен при следующем обращении
|
|
59
|
-
* @optional @default false
|
|
60
|
-
*/
|
|
61
|
-
invalidate?: boolean;
|
|
62
|
-
/**
|
|
63
|
-
* Флаг для блокировки ресурса во время выполнения операции.
|
|
64
|
-
* При true - ресурс будет заблокирован и не сможет выполнять новые запросы
|
|
65
|
-
* @optional @default false
|
|
66
|
-
*/
|
|
67
|
-
lock?: boolean;
|
|
68
|
-
/**
|
|
69
|
-
* Функция для обновления кэша ресурса после успешного выполнения операции.
|
|
70
|
-
* Получает draft объект для мутации, аргументы операции и результат операции
|
|
71
|
-
* @optional
|
|
72
|
-
*/
|
|
73
|
-
update?: (tools: {
|
|
74
|
-
/** Immer draft объект для мутации кэша ресурса */
|
|
75
|
-
draft: RD["Data"];
|
|
76
|
-
/** Аргументы, с которыми была вызвана операция */
|
|
77
|
-
args: D["Args"];
|
|
78
|
-
/** Результат выполнения операции */
|
|
79
|
-
data: D["Data"];
|
|
80
|
-
}) => void | RD["Data"] | Promise<RD["Data"]>;
|
|
81
|
-
/**
|
|
82
|
-
* Функция для оптимистичного обновления кэша ресурса ДО выполнения операции.
|
|
83
|
-
* Позволяет обновить UI немедленно, до получения ответа от сервера
|
|
84
|
-
* @optional
|
|
85
|
-
*/
|
|
86
|
-
optimisticUpdate?: (tools: {
|
|
87
|
-
/** Immer draft объект для мутации кэша ресурса */
|
|
88
|
-
draft: RD["Data"];
|
|
89
|
-
/** Аргументы, с которыми была вызвана операция */
|
|
90
|
-
args: D["Args"];
|
|
91
|
-
}) => void | RD["Data"] | Promise<RD["Data"]>;
|
|
92
|
-
/**
|
|
93
|
-
* Функция для создания нового элемента в кэше ресурса.
|
|
94
|
-
* Используется когда операция создает новую сущность, которую нужно добавить в кэш
|
|
95
|
-
* @optional
|
|
96
|
-
*/
|
|
97
|
-
create?: (tools: {
|
|
98
|
-
/** Аргументы, с которыми была вызвана операция */
|
|
99
|
-
args: D["Args"];
|
|
100
|
-
/** Результат выполнения операции */
|
|
101
|
-
data: D["Data"];
|
|
102
|
-
}) => RD["Data"] | Promise<RD["Data"]>;
|
|
103
|
-
};
|
|
104
|
-
/**
|
|
105
|
-
* Определение типов операции
|
|
106
|
-
*/
|
|
107
|
-
export type OperationDefinition<A = any, R = any, S = any> = {
|
|
108
|
-
Args: A;
|
|
109
|
-
Result: R;
|
|
110
|
-
Selected: S;
|
|
111
|
-
Data: FallbackOnNever<S, R>;
|
|
112
|
-
};
|
|
113
|
-
/**
|
|
114
|
-
* Экземпляр операции
|
|
115
|
-
*/
|
|
116
|
-
export type OperationInstance<D extends OperationDefinition> = {
|
|
117
|
-
/** Создает агента для выполнения операции */
|
|
118
|
-
createAgent(): OperationAgentInstanse<D>;
|
|
119
|
-
/**
|
|
120
|
-
* Выполняет операцию с указанными аргументами
|
|
121
|
-
* @deprecated
|
|
122
|
-
*/
|
|
123
|
-
mutate: (args: D["Args"]) => Promise<D["Data"]>;
|
|
124
|
-
};
|
|
125
|
-
/**
|
|
126
|
-
* Агент для выполнения операции
|
|
127
|
-
*/
|
|
128
|
-
export type OperationAgentInstanse<D extends OperationDefinition> = {
|
|
129
|
-
/** Observable состояния выполнения операции */
|
|
130
|
-
state$: ReadableSignalLike<OperationQueryState<D>>;
|
|
131
|
-
/** Инициирует выполнение операции с указанными аргументами */
|
|
132
|
-
initiate(args: D["Args"]): void;
|
|
133
|
-
/** Создает новый агент операции */
|
|
134
|
-
createAgent(): OperationAgentInstanse<D>;
|
|
135
|
-
};
|
|
136
|
-
/**
|
|
137
|
-
* Состояние выполнения операции
|
|
138
|
-
*/
|
|
139
|
-
export type OperationQueryState<D extends OperationDefinition> = {
|
|
140
|
-
/** Выполняется ли операция в данный момент */
|
|
141
|
-
isLoading: boolean;
|
|
142
|
-
/** Завершена ли операция */
|
|
143
|
-
isDone: boolean;
|
|
144
|
-
/** Успешно ли завершена операция (false по умолчанию) */
|
|
145
|
-
isSuccess: boolean;
|
|
146
|
-
/** Произошла ли ошибка при выполнении операции (false по умолчанию) */
|
|
147
|
-
isError: boolean;
|
|
148
|
-
/** Оригинал ошибки, если есть */
|
|
149
|
-
error: unknown | undefined;
|
|
150
|
-
/** Результат выполнения операции */
|
|
151
|
-
data: D["Data"] | undefined;
|
|
152
|
-
/** Аргументы операции */
|
|
153
|
-
args: D["Args"];
|
|
154
|
-
};
|
|
1
|
+
import { CommandAgentInstance, CommandCreateFn, CommandCreateOptions, CommandDefinition, CommandInstance, CommandQueryState } from "./Command.types";
|
|
2
|
+
/** @deprecated Use `CommandCreateFn` instead. Will be removed in v0.6.0. */
|
|
3
|
+
export type OperationCreateFn<ARGS, RESULT, SELECTED = never> = CommandCreateFn<ARGS, RESULT, SELECTED>;
|
|
4
|
+
/** @deprecated Use `CommandCreateOptions` instead. Will be removed in v0.6.0. */
|
|
5
|
+
export type OperationCreateOptions<D extends CommandDefinition> = CommandCreateOptions<D>;
|
|
6
|
+
/** @deprecated Use `CommandDefinition` instead. Will be removed in v0.6.0. */
|
|
7
|
+
export type OperationDefinition<A = any, R = any, S = any> = CommandDefinition<A, R, S>;
|
|
8
|
+
/** @deprecated Use `CommandInstance` instead. Will be removed in v0.6.0. */
|
|
9
|
+
export type OperationInstance<D extends CommandDefinition> = CommandInstance<D>;
|
|
10
|
+
/** @deprecated Use `CommandAgentInstance` instead. Will be removed in v0.6.0. */
|
|
11
|
+
export type OperationAgentInstanse<D extends CommandDefinition> = CommandAgentInstance<D>;
|
|
12
|
+
/** @deprecated Use `CommandQueryState` instead. Will be removed in v0.6.0. */
|
|
13
|
+
export type OperationQueryState<D extends CommandDefinition> = CommandQueryState<D>;
|
|
@@ -61,7 +61,7 @@ export type ResourceInstance<D extends ResourceDefinition> = {
|
|
|
61
61
|
/** Создает агента для работы с ресурсом */
|
|
62
62
|
createAgent(): ResourceAgentInstance<D>;
|
|
63
63
|
/** Создает ссылку на ресурс с указанными аргументами */
|
|
64
|
-
createRef(args: D["Args"]):
|
|
64
|
+
createRef(args: D["Args"]): ResourceRefInstance<D>;
|
|
65
65
|
};
|
|
66
66
|
/**
|
|
67
67
|
* Агент для работы с ресурсом
|
|
@@ -107,7 +107,7 @@ export type ResourceQueryState<D extends ResourceDefinition> = {
|
|
|
107
107
|
export type ResourceTransaction = {
|
|
108
108
|
patches: ImmerPatch[];
|
|
109
109
|
inversePatches: ImmerPatch[];
|
|
110
|
-
status:
|
|
110
|
+
status: "pending" | "committed" | "aborted";
|
|
111
111
|
abort(): void;
|
|
112
112
|
commit(): void;
|
|
113
113
|
};
|
|
@@ -115,13 +115,15 @@ export type ResourceTransaction = {
|
|
|
115
115
|
* Эте не ссылка в "классическом" понимании, а абстракция
|
|
116
116
|
* для работы с элементом кеша ресурса.
|
|
117
117
|
*/
|
|
118
|
-
export type
|
|
118
|
+
export type ResourceRefInstance<D extends ResourceDefinition> = {
|
|
119
119
|
get has(): boolean;
|
|
120
120
|
lock(): {
|
|
121
121
|
unlock: () => void;
|
|
122
122
|
};
|
|
123
123
|
unlockOne(): void;
|
|
124
|
-
patch(patchFn: (data: D[
|
|
124
|
+
patch(patchFn: (data: D["Data"]) => void): ResourceTransaction | null;
|
|
125
125
|
invalidate(): void;
|
|
126
|
-
create(data: D[
|
|
126
|
+
create(data: D["Data"]): void;
|
|
127
127
|
};
|
|
128
|
+
/** @deprecated Use ResourceRefInstance. Will be removed in v0.6.0 */
|
|
129
|
+
export type ResourceRefInstanse<D extends ResourceDefinition> = ResourceRefInstance<D>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
1
|
+
export * from "./Command.types";
|
|
2
|
+
export * from "./Resource.types";
|
|
3
|
+
export * from "./shared.types";
|
|
4
|
+
export * from "./Operation.types";
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
1
|
+
export * from "./Command.types";
|
|
2
|
+
export * from "./Resource.types";
|
|
3
|
+
export * from "./shared.types";
|
|
4
|
+
// Deprecated Operation types (backward compatibility)
|
|
5
|
+
export * from "./Operation.types";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { IApi, ICreateApiOptions } from "../../query-v2/types/api.types";
|
|
2
|
+
import type { IPlugin } from "../../query-v2/types/plugin.types";
|
|
3
|
+
/**
|
|
4
|
+
* Create a query-v2 API instance — the root entry point for managing resources, snapshots, and plugins.
|
|
5
|
+
*
|
|
6
|
+
* @param options - Configuration for the API instance (keyPrefix, plugins, snapshot, cache settings).
|
|
7
|
+
* @returns API instance with `createResource`, `resetAll`, and `getSnapshot` methods.
|
|
8
|
+
* @see docs/query-v2/README.md
|
|
9
|
+
*/
|
|
10
|
+
export declare function createApi<TPlugins extends IPlugin[] = []>(options?: ICreateApiOptions<TPlugins>): IApi<TPlugins>;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { ResourceV2 } from "../../query-v2/core/resource/ResourceV2";
|
|
2
|
+
import { getSnapshot, hydrateSnapshot } from "../../query-v2/snapshot/Snapshot";
|
|
3
|
+
const DEFAULT_CACHE_LIFETIME = 60_000;
|
|
4
|
+
const DEFAULT_MAX_SNAPSHOT_DATA_AGE = 300_000; // 5 minutes
|
|
5
|
+
/**
|
|
6
|
+
* Create a query-v2 API instance — the root entry point for managing resources, snapshots, and plugins.
|
|
7
|
+
*
|
|
8
|
+
* @param options - Configuration for the API instance (keyPrefix, plugins, snapshot, cache settings).
|
|
9
|
+
* @returns API instance with `createResource`, `resetAll`, and `getSnapshot` methods.
|
|
10
|
+
* @see docs/query-v2/README.md
|
|
11
|
+
*/
|
|
12
|
+
export function createApi(options = {}) {
|
|
13
|
+
const { keyPrefix = null, keyStrategy = "serialize", serializeArgs, compareArg, initialSnapshot = null, cacheLifetime = DEFAULT_CACHE_LIFETIME, plugins = [], maxSnapshotDataAge = DEFAULT_MAX_SNAPSHOT_DATA_AGE, doCacheArgs = false, } = options;
|
|
14
|
+
// ADR-6: Generic registry (Map, not typed to resources only)
|
|
15
|
+
const registry = new Map();
|
|
16
|
+
// Plugin initialization: call install() once per plugin
|
|
17
|
+
const pluginContext = {
|
|
18
|
+
get api() {
|
|
19
|
+
return api;
|
|
20
|
+
},
|
|
21
|
+
keyStrategy,
|
|
22
|
+
};
|
|
23
|
+
for (const plugin of plugins) {
|
|
24
|
+
plugin.install(pluginContext);
|
|
25
|
+
}
|
|
26
|
+
const api = {
|
|
27
|
+
createResource(resourceOptions) {
|
|
28
|
+
// Merge: resource options override API defaults
|
|
29
|
+
const mergedConfig = {
|
|
30
|
+
key: resourceOptions.key,
|
|
31
|
+
keyPrefix: keyPrefix ?? undefined,
|
|
32
|
+
keyStrategy,
|
|
33
|
+
queryFn: resourceOptions.queryFn,
|
|
34
|
+
onCacheEntryAdded: resourceOptions.onCacheEntryAdded,
|
|
35
|
+
onQueryStarted: resourceOptions.onQueryStarted,
|
|
36
|
+
serializeArgs: resourceOptions.serializeArgs ?? serializeArgs,
|
|
37
|
+
compareArg: resourceOptions.compareArg ?? compareArg,
|
|
38
|
+
cacheLifetime: resourceOptions.cacheLifetime ?? cacheLifetime,
|
|
39
|
+
beforeDevtoolsPush: resourceOptions.beforeDevtoolsPush,
|
|
40
|
+
maxSnapshotDataAge: resourceOptions.maxSnapshotDataAge ?? maxSnapshotDataAge,
|
|
41
|
+
doCacheArgs: resourceOptions.doCacheArgs ?? doCacheArgs,
|
|
42
|
+
};
|
|
43
|
+
// Validate unique key (for serialize strategy, key is expected for snapshot)
|
|
44
|
+
const resourceKey = mergedConfig.key;
|
|
45
|
+
if (resourceKey != null) {
|
|
46
|
+
if (registry.has(resourceKey)) {
|
|
47
|
+
throw new Error(`Duplicate resource key "${resourceKey}". Each resource must have a unique key.`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Create resource
|
|
51
|
+
const resource = new ResourceV2(mergedConfig);
|
|
52
|
+
// Apply plugin augmentations
|
|
53
|
+
const augmentations = {};
|
|
54
|
+
for (const plugin of plugins) {
|
|
55
|
+
const pluginContributions = plugin.augmentResource(resource, resourceOptions);
|
|
56
|
+
Object.assign(augmentations, pluginContributions);
|
|
57
|
+
}
|
|
58
|
+
// Create the augmented resource
|
|
59
|
+
const augmentedResource = Object.assign(resource, augmentations);
|
|
60
|
+
// Register resource
|
|
61
|
+
if (resourceKey != null) {
|
|
62
|
+
registry.set(resourceKey, resource);
|
|
63
|
+
}
|
|
64
|
+
// Hydrate from initial snapshot if available
|
|
65
|
+
if (initialSnapshot && resourceKey != null) {
|
|
66
|
+
const snapshotMaxAge = mergedConfig.maxSnapshotDataAge ?? maxSnapshotDataAge;
|
|
67
|
+
const singleResourceRegistry = new Map();
|
|
68
|
+
singleResourceRegistry.set(resourceKey, resource);
|
|
69
|
+
hydrateSnapshot(initialSnapshot, singleResourceRegistry, keyPrefix, snapshotMaxAge);
|
|
70
|
+
}
|
|
71
|
+
return augmentedResource;
|
|
72
|
+
},
|
|
73
|
+
resetAll() {
|
|
74
|
+
for (const [, resource] of registry) {
|
|
75
|
+
resource.resetCache();
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
getSnapshot() {
|
|
79
|
+
return getSnapshot(registry, keyPrefix, keyStrategy);
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
return api;
|
|
83
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { TBeforeDevtoolsPushFn } from "../../../query-v2/types/shared.types";
|
|
2
|
+
import type { TMachineInstance } from "../machines/Machine";
|
|
3
|
+
export interface CacheEntryOptions {
|
|
4
|
+
keyParts?: string[];
|
|
5
|
+
beforeDevtoolsPush?: TBeforeDevtoolsPushFn<unknown>;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Cache entry wrapping a reactive signal over a state machine instance.
|
|
9
|
+
* Represents a single cached query result with its full lifecycle (idle → pending → success/error).
|
|
10
|
+
*/
|
|
11
|
+
export declare class CacheEntry<TData = unknown, TError = Error> {
|
|
12
|
+
private readonly _signal;
|
|
13
|
+
private readonly _onClean$;
|
|
14
|
+
private _completed;
|
|
15
|
+
constructor(initialMachine: TMachineInstance<TData, TError>, options?: CacheEntryOptions);
|
|
16
|
+
/** Reactive accessor for the current machine state — reading this registers a signal dependency. */
|
|
17
|
+
get machine$(): () => TMachineInstance<TData, TError>;
|
|
18
|
+
/** Non-reactive read of the current machine state (does not register a signal dependency). */
|
|
19
|
+
peek(): TMachineInstance<TData, TError>;
|
|
20
|
+
/** Transition to a new machine state. No-op if the entry has been completed. */
|
|
21
|
+
set(machine: TMachineInstance<TData, TError>): void;
|
|
22
|
+
get onClean$(): {
|
|
23
|
+
subscribe: (cb: () => void) => {
|
|
24
|
+
unsubscribe: () => void;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
/** Complete the entry — aborts pending patches, resets to idle, and notifies cleanup listeners. */
|
|
28
|
+
complete(): void;
|
|
29
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { Subject } from "rxjs";
|
|
2
|
+
import { Signal } from "../../../signals";
|
|
3
|
+
import { MachineIdle } from "../machines/MachineIdle";
|
|
4
|
+
import { MachineWithData } from "../machines/MachineWithData";
|
|
5
|
+
/**
|
|
6
|
+
* Cache entry wrapping a reactive signal over a state machine instance.
|
|
7
|
+
* Represents a single cached query result with its full lifecycle (idle → pending → success/error).
|
|
8
|
+
*/
|
|
9
|
+
export class CacheEntry {
|
|
10
|
+
_signal;
|
|
11
|
+
_onClean$ = new Subject();
|
|
12
|
+
_completed = false;
|
|
13
|
+
constructor(initialMachine, options) {
|
|
14
|
+
const userCallback = options?.beforeDevtoolsPush;
|
|
15
|
+
// Default beforeDevtoolsPush projects machine → machine.state for devtools (ADR-8).
|
|
16
|
+
// The push function types are mismatched intentionally: we push plain state objects
|
|
17
|
+
// instead of machine instances to keep devtools output JSON-friendly.
|
|
18
|
+
const beforeDevtoolsPush = ((newValue, push) => {
|
|
19
|
+
const machine = newValue;
|
|
20
|
+
const state = machine.state;
|
|
21
|
+
if (userCallback) {
|
|
22
|
+
userCallback(state, push);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
push(state);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
this._signal = Signal.state(initialMachine, {
|
|
29
|
+
key: options?.keyParts?.join("/"),
|
|
30
|
+
beforeDevtoolsPush,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
/** Reactive accessor for the current machine state — reading this registers a signal dependency. */
|
|
34
|
+
get machine$() {
|
|
35
|
+
return this._signal;
|
|
36
|
+
}
|
|
37
|
+
/** Non-reactive read of the current machine state (does not register a signal dependency). */
|
|
38
|
+
peek() {
|
|
39
|
+
return this._signal.peek();
|
|
40
|
+
}
|
|
41
|
+
/** Transition to a new machine state. No-op if the entry has been completed. */
|
|
42
|
+
set(machine) {
|
|
43
|
+
if (this._completed)
|
|
44
|
+
return;
|
|
45
|
+
this._signal.set(machine);
|
|
46
|
+
}
|
|
47
|
+
get onClean$() {
|
|
48
|
+
return {
|
|
49
|
+
subscribe: (cb) => {
|
|
50
|
+
const sub = this._onClean$.subscribe(cb);
|
|
51
|
+
return { unsubscribe: () => sub.unsubscribe() };
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/** Complete the entry — aborts pending patches, resets to idle, and notifies cleanup listeners. */
|
|
56
|
+
complete() {
|
|
57
|
+
if (this._completed)
|
|
58
|
+
return;
|
|
59
|
+
this._completed = true;
|
|
60
|
+
// Layer 3 (ADR-4): Abort all pending patches on MachineWithData instances
|
|
61
|
+
const current = this._signal.peek();
|
|
62
|
+
if (current instanceof MachineWithData) {
|
|
63
|
+
current.abortAllPendingPatches();
|
|
64
|
+
}
|
|
65
|
+
// Set to idle to release data references
|
|
66
|
+
this._signal.set(MachineIdle.create());
|
|
67
|
+
// Notify cleanup listeners
|
|
68
|
+
this._onClean$.next();
|
|
69
|
+
this._onClean$.complete();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ICacheMapOptions } from "../../../query-v2/types/cache.types";
|
|
2
|
+
import type { CacheEntry } from "./CacheEntry";
|
|
3
|
+
declare class SerializedCacheMap<TArgs, TData, TError = Error> {
|
|
4
|
+
private readonly _map;
|
|
5
|
+
private readonly _serializeArgs;
|
|
6
|
+
private readonly _argsMemo;
|
|
7
|
+
constructor(serializeArgs: (args: unknown) => string, doCacheArgs: boolean);
|
|
8
|
+
private _serialize;
|
|
9
|
+
get(args: TArgs): CacheEntry<TData, TError> | undefined;
|
|
10
|
+
set(args: TArgs, entry: CacheEntry<TData, TError>): void;
|
|
11
|
+
getOrCreate(args: TArgs, factory: () => CacheEntry<TData, TError>): CacheEntry<TData, TError>;
|
|
12
|
+
delete(args: TArgs): boolean;
|
|
13
|
+
has(args: TArgs): boolean;
|
|
14
|
+
values(): Iterable<CacheEntry<TData, TError>>;
|
|
15
|
+
entries(): Iterable<[string, CacheEntry<TData, TError>]>;
|
|
16
|
+
clear(): void;
|
|
17
|
+
get size(): number;
|
|
18
|
+
}
|
|
19
|
+
declare class CompareCacheMap<TArgs, TData, TError = Error> {
|
|
20
|
+
private readonly _items;
|
|
21
|
+
private readonly _compareArg;
|
|
22
|
+
constructor(compareArg: (a: unknown, b: unknown) => boolean);
|
|
23
|
+
private _findIndex;
|
|
24
|
+
get(args: TArgs): CacheEntry<TData, TError> | undefined;
|
|
25
|
+
set(args: TArgs, entry: CacheEntry<TData, TError>): void;
|
|
26
|
+
getOrCreate(args: TArgs, factory: () => CacheEntry<TData, TError>): CacheEntry<TData, TError>;
|
|
27
|
+
delete(args: TArgs): boolean;
|
|
28
|
+
has(args: TArgs): boolean;
|
|
29
|
+
values(): Iterable<CacheEntry<TData, TError>>;
|
|
30
|
+
entries(): Iterable<[TArgs, CacheEntry<TData, TError>]>;
|
|
31
|
+
clear(): void;
|
|
32
|
+
get size(): number;
|
|
33
|
+
}
|
|
34
|
+
export type TCacheMapInstance<TArgs, TData, TError = Error> = SerializedCacheMap<TArgs, TData, TError> | CompareCacheMap<TArgs, TData, TError>;
|
|
35
|
+
export declare const CacheMap: {
|
|
36
|
+
create<TArgs, TData, TError = Error>(options: ICacheMapOptions<TArgs>): TCacheMapInstance<TArgs, TData, TError>;
|
|
37
|
+
};
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { shallowEqual } from "../../../common/utils/shallowEqual";
|
|
2
|
+
import { stableStringify } from "../../../query-v2/lib/stableStringify";
|
|
3
|
+
class SerializedCacheMap {
|
|
4
|
+
_map = new Map();
|
|
5
|
+
_serializeArgs;
|
|
6
|
+
_argsMemo;
|
|
7
|
+
constructor(serializeArgs, doCacheArgs) {
|
|
8
|
+
this._serializeArgs = serializeArgs;
|
|
9
|
+
this._argsMemo = doCacheArgs ? new WeakMap() : null;
|
|
10
|
+
}
|
|
11
|
+
_serialize(args) {
|
|
12
|
+
if (this._argsMemo && typeof args === "object" && args !== null) {
|
|
13
|
+
let cached = this._argsMemo.get(args);
|
|
14
|
+
if (cached === undefined) {
|
|
15
|
+
cached = this._serializeArgs(args);
|
|
16
|
+
this._argsMemo.set(args, cached);
|
|
17
|
+
}
|
|
18
|
+
return cached;
|
|
19
|
+
}
|
|
20
|
+
return this._serializeArgs(args);
|
|
21
|
+
}
|
|
22
|
+
get(args) {
|
|
23
|
+
return this._map.get(this._serialize(args));
|
|
24
|
+
}
|
|
25
|
+
set(args, entry) {
|
|
26
|
+
this._map.set(this._serialize(args), entry);
|
|
27
|
+
}
|
|
28
|
+
getOrCreate(args, factory) {
|
|
29
|
+
const key = this._serialize(args);
|
|
30
|
+
let entry = this._map.get(key);
|
|
31
|
+
if (!entry) {
|
|
32
|
+
entry = factory();
|
|
33
|
+
this._map.set(key, entry);
|
|
34
|
+
}
|
|
35
|
+
return entry;
|
|
36
|
+
}
|
|
37
|
+
delete(args) {
|
|
38
|
+
return this._map.delete(this._serialize(args));
|
|
39
|
+
}
|
|
40
|
+
has(args) {
|
|
41
|
+
return this._map.has(this._serialize(args));
|
|
42
|
+
}
|
|
43
|
+
values() {
|
|
44
|
+
return this._map.values();
|
|
45
|
+
}
|
|
46
|
+
entries() {
|
|
47
|
+
return this._map.entries();
|
|
48
|
+
}
|
|
49
|
+
clear() {
|
|
50
|
+
this._map.clear();
|
|
51
|
+
}
|
|
52
|
+
get size() {
|
|
53
|
+
return this._map.size;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
class CompareCacheMap {
|
|
57
|
+
_items = [];
|
|
58
|
+
_compareArg;
|
|
59
|
+
constructor(compareArg) {
|
|
60
|
+
this._compareArg = compareArg;
|
|
61
|
+
}
|
|
62
|
+
_findIndex(args) {
|
|
63
|
+
for (let i = 0; i < this._items.length; i++) {
|
|
64
|
+
if (this._compareArg(this._items[i].args, args)) {
|
|
65
|
+
return i;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return -1;
|
|
69
|
+
}
|
|
70
|
+
get(args) {
|
|
71
|
+
const idx = this._findIndex(args);
|
|
72
|
+
return idx >= 0 ? this._items[idx].entry : undefined;
|
|
73
|
+
}
|
|
74
|
+
set(args, entry) {
|
|
75
|
+
const idx = this._findIndex(args);
|
|
76
|
+
if (idx >= 0) {
|
|
77
|
+
this._items[idx] = { args, entry };
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
this._items.push({ args, entry });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
getOrCreate(args, factory) {
|
|
84
|
+
const idx = this._findIndex(args);
|
|
85
|
+
if (idx >= 0) {
|
|
86
|
+
return this._items[idx].entry;
|
|
87
|
+
}
|
|
88
|
+
const entry = factory();
|
|
89
|
+
this._items.push({ args, entry });
|
|
90
|
+
return entry;
|
|
91
|
+
}
|
|
92
|
+
delete(args) {
|
|
93
|
+
const idx = this._findIndex(args);
|
|
94
|
+
if (idx >= 0) {
|
|
95
|
+
this._items.splice(idx, 1);
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
has(args) {
|
|
101
|
+
return this._findIndex(args) >= 0;
|
|
102
|
+
}
|
|
103
|
+
*values() {
|
|
104
|
+
for (const item of this._items) {
|
|
105
|
+
yield item.entry;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
*entries() {
|
|
109
|
+
for (const item of this._items) {
|
|
110
|
+
yield [item.args, item.entry];
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
clear() {
|
|
114
|
+
this._items.length = 0;
|
|
115
|
+
}
|
|
116
|
+
get size() {
|
|
117
|
+
return this._items.length;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
export const CacheMap = {
|
|
121
|
+
create(options) {
|
|
122
|
+
if (options.keyStrategy === "compare") {
|
|
123
|
+
return new CompareCacheMap(options.compareArg ?? shallowEqual);
|
|
124
|
+
}
|
|
125
|
+
return new SerializedCacheMap(options.serializeArgs ?? stableStringify, options.doCacheArgs);
|
|
126
|
+
},
|
|
127
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { TOnCacheEntryAdded, TOnQueryStarted } from "../../../query-v2/types/lifecycle.types";
|
|
2
|
+
import type { TMachineInstance } from "../machines/Machine";
|
|
3
|
+
import type { CacheEntry } from "./CacheEntry";
|
|
4
|
+
export declare class LifecycleHooks<TArgs, TData, TError = Error> {
|
|
5
|
+
private readonly _onCacheEntryAdded?;
|
|
6
|
+
private readonly _onQueryStarted?;
|
|
7
|
+
private _cacheEntryState;
|
|
8
|
+
private _queryState;
|
|
9
|
+
private _serializeArgs;
|
|
10
|
+
constructor(options: {
|
|
11
|
+
onCacheEntryAdded?: TOnCacheEntryAdded<TArgs, TData>;
|
|
12
|
+
onQueryStarted?: TOnQueryStarted<TArgs, TData>;
|
|
13
|
+
serializeArgs: (args: unknown) => string;
|
|
14
|
+
});
|
|
15
|
+
fireCacheEntryAdded(args: TArgs, getCacheEntry: () => TMachineInstance<TData, TError>): void;
|
|
16
|
+
fireCacheEntryRemoved(args: TArgs): void;
|
|
17
|
+
resolveCacheDataLoaded(args: TArgs, data: TData): void;
|
|
18
|
+
fireQueryStarted(args: TArgs, getCacheEntry: () => CacheEntry<TData, TError>): void;
|
|
19
|
+
resolveQueryFulfilled(data: TData): void;
|
|
20
|
+
rejectQueryFulfilled(error: unknown): void;
|
|
21
|
+
clearAll(): void;
|
|
22
|
+
}
|