@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.
Files changed (207) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +143 -137
  3. package/dist/common/devtools/combineDevtools.js +3 -3
  4. package/dist/common/devtools/index.d.ts +3 -3
  5. package/dist/common/devtools/index.js +3 -3
  6. package/dist/common/devtools/reduxDevtools.d.ts +1 -1
  7. package/dist/common/devtools/reduxDevtools.js +17 -17
  8. package/dist/common/devtools/types.d.ts +0 -6
  9. package/dist/common/options/DefaultOptions.d.ts +1 -1
  10. package/dist/common/options/SharedOptions.d.ts +3 -2
  11. package/dist/common/options/SharedOptions.js +6 -0
  12. package/dist/common/options/index.d.ts +1 -1
  13. package/dist/common/options/index.js +1 -1
  14. package/dist/common/react/index.d.ts +2 -2
  15. package/dist/common/react/index.js +2 -2
  16. package/dist/common/react/useConstant.js +1 -1
  17. package/dist/common/utils/deepEqual.js +1 -1
  18. package/dist/common/utils/index.d.ts +3 -3
  19. package/dist/common/utils/index.js +3 -3
  20. package/dist/common/utils/shallowEqual.js +1 -1
  21. package/dist/index.d.ts +8 -7
  22. package/dist/index.js +8 -7
  23. package/dist/query/SKIP_TOKEN.js +1 -1
  24. package/dist/query/api/createCommand.d.ts +21 -0
  25. package/dist/query/api/createCommand.js +20 -0
  26. package/dist/query/api/createOperation.d.ts +5 -3
  27. package/dist/query/api/createOperation.js +6 -2
  28. package/dist/query/api/createResource.d.ts +2 -2
  29. package/dist/query/api/createResourceDuplicator.d.ts +2 -2
  30. package/dist/query/core/Command/Command.d.ts +35 -0
  31. package/dist/query/core/{Opertation/Operation.js → Command/Command.js} +13 -14
  32. package/dist/query/core/Command/CommandAgent.d.ts +19 -0
  33. package/dist/query/core/{Opertation/OperationAgent.js → Command/CommandAgent.js} +13 -13
  34. package/dist/query/core/Command/index.d.ts +2 -0
  35. package/dist/query/core/Command/index.js +2 -0
  36. package/dist/query/core/Operation/Operation.d.ts +8 -0
  37. package/dist/query/core/Operation/Operation.js +4 -0
  38. package/dist/query/core/Operation/OperationAgent.d.ts +4 -0
  39. package/dist/query/core/Operation/OperationAgent.js +4 -0
  40. package/dist/query/core/QueriesCache.d.ts +2 -2
  41. package/dist/query/core/QueriesCache.js +1 -1
  42. package/dist/query/core/QueriesLifetimeHooks.d.ts +1 -1
  43. package/dist/query/core/QueriesLifetimeHooks.js +7 -7
  44. package/dist/query/core/Resource/Resource.d.ts +16 -16
  45. package/dist/query/core/Resource/Resource.js +7 -7
  46. package/dist/query/core/Resource/ResourceAgent.d.ts +2 -2
  47. package/dist/query/core/Resource/ResourceAgent.js +3 -3
  48. package/dist/query/core/Resource/ResourceDuplicator.d.ts +17 -17
  49. package/dist/query/core/Resource/ResourceDuplicator.js +18 -20
  50. package/dist/query/core/Resource/ResourceDuplicatorAgent.d.ts +6 -6
  51. package/dist/query/core/Resource/ResourceDuplicatorAgent.js +3 -3
  52. package/dist/query/core/Resource/ResourceRef.d.ts +2 -2
  53. package/dist/query/core/Resource/ResourceRef.js +12 -12
  54. package/dist/query/index.d.ts +11 -8
  55. package/dist/query/index.js +14 -8
  56. package/dist/query/lib/IndirectMap.js +4 -4
  57. package/dist/query/lib/ReactiveCache.d.ts +1 -1
  58. package/dist/query/react/useCommandAgent.d.ts +24 -0
  59. package/dist/query/react/useCommandAgent.js +39 -0
  60. package/dist/query/react/useOperationAgent.d.ts +6 -8
  61. package/dist/query/react/useOperationAgent.js +6 -23
  62. package/dist/query/react/useResourceAgent.d.ts +4 -4
  63. package/dist/query/react/useResourceAgent.js +1 -1
  64. package/dist/query/react/useResourceRef.d.ts +3 -3
  65. package/dist/query/react/useResourceRef.js +7 -2
  66. package/dist/query/types/Command.types.d.ts +154 -0
  67. package/dist/query/types/Command.types.js +1 -0
  68. package/dist/query/types/Operation.types.d.ts +13 -154
  69. package/dist/query/types/Resource.types.d.ts +7 -5
  70. package/dist/query/types/index.d.ts +4 -3
  71. package/dist/query/types/index.js +5 -3
  72. package/dist/query-v2/api/createApi.d.ts +10 -0
  73. package/dist/query-v2/api/createApi.js +83 -0
  74. package/dist/query-v2/core/common/CacheEntry.d.ts +29 -0
  75. package/dist/query-v2/core/common/CacheEntry.js +71 -0
  76. package/dist/query-v2/core/common/CacheMap.d.ts +38 -0
  77. package/dist/query-v2/core/common/CacheMap.js +127 -0
  78. package/dist/query-v2/core/common/LifecycleHooks.d.ts +22 -0
  79. package/dist/query-v2/core/common/LifecycleHooks.js +104 -0
  80. package/dist/query-v2/core/common/index.d.ts +3 -0
  81. package/dist/query-v2/core/common/index.js +3 -0
  82. package/dist/query-v2/core/index.d.ts +3 -0
  83. package/dist/query-v2/core/index.js +3 -0
  84. package/dist/query-v2/core/machines/Machine.d.ts +14 -0
  85. package/dist/query-v2/core/machines/Machine.js +33 -0
  86. package/dist/query-v2/core/machines/MachineError.d.ts +11 -0
  87. package/dist/query-v2/core/machines/MachineError.js +26 -0
  88. package/dist/query-v2/core/machines/MachineIdle.d.ts +8 -0
  89. package/dist/query-v2/core/machines/MachineIdle.js +19 -0
  90. package/dist/query-v2/core/machines/MachinePending.d.ts +12 -0
  91. package/dist/query-v2/core/machines/MachinePending.js +29 -0
  92. package/dist/query-v2/core/machines/MachineRefreshing.d.ts +14 -0
  93. package/dist/query-v2/core/machines/MachineRefreshing.js +46 -0
  94. package/dist/query-v2/core/machines/MachineSuccess.d.ts +16 -0
  95. package/dist/query-v2/core/machines/MachineSuccess.js +42 -0
  96. package/dist/query-v2/core/machines/MachineWithData.d.ts +18 -0
  97. package/dist/query-v2/core/machines/MachineWithData.js +40 -0
  98. package/dist/query-v2/core/machines/Patcher.d.ts +20 -0
  99. package/dist/query-v2/core/machines/Patcher.js +104 -0
  100. package/dist/query-v2/core/machines/index.d.ts +8 -0
  101. package/dist/query-v2/core/machines/index.js +8 -0
  102. package/dist/query-v2/core/resource/ResourceV2.d.ts +120 -0
  103. package/dist/query-v2/core/resource/ResourceV2.js +464 -0
  104. package/dist/query-v2/core/resource/ResourceV2Agent.d.ts +26 -0
  105. package/dist/query-v2/core/resource/ResourceV2Agent.js +132 -0
  106. package/dist/query-v2/core/resource/index.d.ts +2 -0
  107. package/dist/query-v2/core/resource/index.js +2 -0
  108. package/dist/query-v2/index.d.ts +11 -0
  109. package/dist/query-v2/index.js +17 -0
  110. package/dist/query-v2/lib/NO_VALUE.d.ts +2 -0
  111. package/dist/query-v2/lib/NO_VALUE.js +1 -0
  112. package/dist/query-v2/lib/SKIP_TOKEN.d.ts +2 -0
  113. package/dist/query-v2/lib/SKIP_TOKEN.js +1 -0
  114. package/dist/query-v2/lib/index.d.ts +4 -0
  115. package/dist/query-v2/lib/index.js +3 -0
  116. package/dist/query-v2/lib/stableStringify.d.ts +8 -0
  117. package/dist/query-v2/lib/stableStringify.js +23 -0
  118. package/dist/query-v2/plugins/ReactHooksPlugin.d.ts +25 -0
  119. package/dist/query-v2/plugins/ReactHooksPlugin.js +19 -0
  120. package/dist/query-v2/plugins/types.d.ts +1 -0
  121. package/dist/query-v2/plugins/types.js +1 -0
  122. package/dist/query-v2/react/__tests__/helpers.d.ts +12 -0
  123. package/dist/query-v2/react/__tests__/helpers.js +33 -0
  124. package/dist/query-v2/react/index.d.ts +2 -0
  125. package/dist/query-v2/react/index.js +2 -0
  126. package/dist/query-v2/react/useResourceV2Agent.d.ts +12 -0
  127. package/dist/query-v2/react/useResourceV2Agent.js +36 -0
  128. package/dist/query-v2/react/useResourceV2Ref.d.ts +12 -0
  129. package/dist/query-v2/react/useResourceV2Ref.js +57 -0
  130. package/dist/query-v2/snapshot/Snapshot.d.ts +13 -0
  131. package/dist/query-v2/snapshot/Snapshot.js +76 -0
  132. package/dist/query-v2/types/agent.types.d.ts +54 -0
  133. package/dist/query-v2/types/agent.types.js +1 -0
  134. package/dist/query-v2/types/api.types.d.ts +22 -0
  135. package/dist/query-v2/types/api.types.js +1 -0
  136. package/dist/query-v2/types/cache.types.d.ts +37 -0
  137. package/dist/query-v2/types/cache.types.js +1 -0
  138. package/dist/query-v2/types/index.d.ts +9 -0
  139. package/dist/query-v2/types/index.js +9 -0
  140. package/dist/query-v2/types/lifecycle.types.d.ts +25 -0
  141. package/dist/query-v2/types/lifecycle.types.js +1 -0
  142. package/dist/query-v2/types/machine.types.d.ts +67 -0
  143. package/dist/query-v2/types/machine.types.js +1 -0
  144. package/dist/query-v2/types/plugin.types.d.ts +38 -0
  145. package/dist/query-v2/types/plugin.types.js +1 -0
  146. package/dist/query-v2/types/resource.types.d.ts +35 -0
  147. package/dist/query-v2/types/resource.types.js +1 -0
  148. package/dist/query-v2/types/shared.types.d.ts +20 -0
  149. package/dist/query-v2/types/shared.types.js +1 -0
  150. package/dist/query-v2/types/snapshot.types.d.ts +21 -0
  151. package/dist/query-v2/types/snapshot.types.js +1 -0
  152. package/dist/signals/base/Batcher.js +9 -5
  153. package/dist/signals/base/ComputeCache.js +3 -3
  154. package/dist/signals/base/DependencyTracker.js +1 -1
  155. package/dist/signals/base/Devtools.d.ts +3 -2
  156. package/dist/signals/base/Devtools.js +54 -27
  157. package/dist/signals/base/Indexer.js +1 -1
  158. package/dist/signals/base/ReadonlySignal.js +1 -1
  159. package/dist/signals/base/SyncObservable.d.ts +1 -2
  160. package/dist/signals/base/SyncObservable.js +2 -5
  161. package/dist/signals/base/index.d.ts +6 -6
  162. package/dist/signals/base/index.js +6 -6
  163. package/dist/signals/index.d.ts +5 -4
  164. package/dist/signals/index.js +5 -4
  165. package/dist/signals/operators/index.d.ts +1 -1
  166. package/dist/signals/operators/index.js +1 -1
  167. package/dist/signals/operators/signalize.d.ts +1 -1
  168. package/dist/signals/react/index.d.ts +1 -1
  169. package/dist/signals/react/index.js +1 -1
  170. package/dist/signals/signals/Computed.d.ts +3 -4
  171. package/dist/signals/signals/Computed.js +18 -10
  172. package/dist/signals/signals/Effect.js +2 -1
  173. package/dist/signals/signals/LocalState.d.ts +44 -0
  174. package/dist/signals/signals/{LocalSignal.js → LocalState.js} +62 -28
  175. package/dist/signals/signals/Signal.d.ts +8 -7
  176. package/dist/signals/signals/Signal.js +4 -1
  177. package/dist/signals/signals/State.d.ts +4 -5
  178. package/dist/signals/signals/State.js +23 -9
  179. package/dist/signals/signals/index.d.ts +5 -5
  180. package/dist/signals/signals/index.js +5 -6
  181. package/dist/signals/types/SignalOptions.d.ts +16 -0
  182. package/dist/signals/types/SignalOptions.js +1 -0
  183. package/dist/signals/types/index.d.ts +3 -1
  184. package/dist/signals/types/index.js +3 -1
  185. package/dist/signals/types/normalizeSignalOptions.d.ts +2 -0
  186. package/dist/signals/types/normalizeSignalOptions.js +10 -0
  187. package/dist/signals/types/signals.types.d.ts +6 -2
  188. package/docs/CHANGELOG.md +111 -32
  189. package/docs/CONTRIBUTING.md +230 -0
  190. package/docs/contributing/ai-assisted-development.md +47 -0
  191. package/docs/contributing/query-v2/README.md +379 -0
  192. package/docs/{release → contributing/release}/README.md +59 -59
  193. package/docs/devtools/README.md +228 -228
  194. package/docs/migrations/0.5.0.md +58 -58
  195. package/docs/migrations/query-v2.md +171 -0
  196. package/docs/options/README.md +92 -90
  197. package/docs/query/README.md +575 -571
  198. package/docs/query-v2/README.md +280 -0
  199. package/docs/query-v2/api-reference.md +235 -0
  200. package/docs/query-v2/optimistic-updates.md +148 -0
  201. package/docs/query-v2/ssr.md +130 -0
  202. package/docs/signals/README.md +300 -295
  203. package/docs/usage/react/README.md +309 -307
  204. package/package.json +86 -63
  205. package/dist/query/core/Opertation/Operation.d.ts +0 -35
  206. package/dist/query/core/Opertation/OperationAgent.d.ts +0 -19
  207. package/dist/signals/signals/LocalSignal.d.ts +0 -32
@@ -1,5 +1,5 @@
1
- import { Signal, signalize } from "@/signals";
2
1
  import { finalize, ReplaySubject, share, Subject, takeUntil, timer } from "rxjs";
2
+ import { Signal, signalize } from "../../../signals";
3
3
  import { ResourceDuplicatorAgent } from "./ResourceDuplicatorAgent";
4
4
  export class ResourceDuplicator {
5
5
  _options;
@@ -25,7 +25,7 @@ export class ResourceDuplicator {
25
25
  obs: value$.obs,
26
26
  });
27
27
  cache.onClean$.subscribe(() => {
28
- args.forEach(arg => {
28
+ args.forEach((arg) => {
29
29
  const argKey = this._options.getArgKey(arg);
30
30
  const fi = this._fis.get(argKey);
31
31
  if (!fi)
@@ -47,9 +47,9 @@ export class ResourceDuplicator {
47
47
  this._resource.initiate(unreleasedArgs);
48
48
  }
49
49
  const uninitiatedCaches = new Set();
50
- args.forEach(arg => {
50
+ args.forEach((arg) => {
51
51
  const argKey = this._options.getArgKey(arg);
52
- let fi = this._fis.get(argKey);
52
+ const fi = this._fis.get(argKey);
53
53
  if (fi && !fi.cache.value.isInitiated) {
54
54
  uninitiatedCaches.add(fi.cache);
55
55
  }
@@ -61,9 +61,9 @@ export class ResourceDuplicator {
61
61
  }
62
62
  serialize(args) {
63
63
  if (!args)
64
- return '';
65
- const argsKeys = args.map(a => this._options.getArgKey(a));
66
- return argsKeys.join('|');
64
+ return "";
65
+ const argsKeys = args.map((a) => this._options.getArgKey(a));
66
+ return argsKeys.join("|");
67
67
  }
68
68
  compareArgs(a, b) {
69
69
  return this.serialize(a) === this.serialize(b);
@@ -73,12 +73,12 @@ export class ResourceDuplicator {
73
73
  };
74
74
  /** @deprecated */
75
75
  d_init(args) {
76
- const argsKeys = args.map(a => this._options.getArgKey(a));
76
+ const argsKeys = args.map((a) => this._options.getArgKey(a));
77
77
  const releasedCaches = new Set();
78
78
  const unreleasedArgs = [];
79
- args.forEach(arg => {
79
+ args.forEach((arg) => {
80
80
  const argKey = this._options.getArgKey(arg);
81
- let fi = this._fis.get(argKey);
81
+ const fi = this._fis.get(argKey);
82
82
  if (!fi || !fi.cache.value.isInitiated) {
83
83
  unreleasedArgs.push(arg);
84
84
  return;
@@ -86,10 +86,8 @@ export class ResourceDuplicator {
86
86
  fi.k++;
87
87
  releasedCaches.add(fi.cache);
88
88
  });
89
- const queryCache = unreleasedArgs?.length > 0
90
- ? this._resource.createQueryCache(unreleasedArgs)
91
- : null;
92
- unreleasedArgs.forEach(arg => {
89
+ const queryCache = unreleasedArgs?.length > 0 ? this._resource.createQueryCache(unreleasedArgs) : null;
90
+ unreleasedArgs.forEach((arg) => {
93
91
  const argKey = this._options.getArgKey(arg);
94
92
  let fi = this._fis.get(argKey);
95
93
  if (!fi) {
@@ -109,7 +107,7 @@ export class ResourceDuplicator {
109
107
  for (const rc of releasedCaches) {
110
108
  itemsAcc.push(rc.value$.get());
111
109
  }
112
- const isNotInitiated = itemsAcc.some(i => !i.isInitiated);
110
+ const isNotInitiated = itemsAcc.some((i) => !i.isInitiated);
113
111
  const baseReturn = {
114
112
  transactions: null,
115
113
  abortController: null,
@@ -132,9 +130,9 @@ export class ResourceDuplicator {
132
130
  ...baseReturn,
133
131
  isInitiated: false,
134
132
  };
135
- const isError = itemsAcc.some(i => i.isError);
133
+ const isError = itemsAcc.some((i) => i.isError);
136
134
  if (isError) {
137
- const firstError = itemsAcc.find(i => i.isError);
135
+ const firstError = itemsAcc.find((i) => i.isError);
138
136
  return {
139
137
  ...baseReturn,
140
138
  isError: true,
@@ -142,17 +140,17 @@ export class ResourceDuplicator {
142
140
  error: firstError.error,
143
141
  };
144
142
  }
145
- const isLoading = itemsAcc.some(i => i.isLoading);
143
+ const isLoading = itemsAcc.some((i) => i.isLoading);
146
144
  if (isLoading)
147
145
  return {
148
146
  ...baseReturn,
149
147
  isLoading: true,
150
148
  };
151
149
  const dataAcc = [];
152
- itemsAcc.forEach(item => {
150
+ itemsAcc.forEach((item) => {
153
151
  item.data?.forEach((d) => {
154
152
  const dataKey = this._options.getDataKey(d);
155
- const index = argsKeys.findIndex(ak => ak === dataKey);
153
+ const index = argsKeys.findIndex((ak) => ak === dataKey);
156
154
  if (index === -1)
157
155
  return;
158
156
  dataAcc[index] = d;
@@ -1,9 +1,9 @@
1
- import { ResourceAgentInstance } from "@/query/types";
2
- import { ResourceDuplicator, DuplicatorDefinition } from "@/query/core/Resource/ResourceDuplicator";
3
- export declare class ResourceDuplicatorAgent<D extends DuplicatorDefinition> implements ResourceAgentInstance<D['RESOURCE_DEFINITION']> {
1
+ import { DuplicatorDefinition, ResourceDuplicator } from "../../../query/core/Resource/ResourceDuplicator";
2
+ import { ResourceAgentInstance } from "../../../query/types";
3
+ export declare class ResourceDuplicatorAgent<D extends DuplicatorDefinition> implements ResourceAgentInstance<D["RESOURCE_DEFINITION"]> {
4
4
  private _resource;
5
5
  private _resources$;
6
- state$: import("../../../signals/types").ComputeFn<{
6
+ state$: import("../../../signals").ComputeFn<{
7
7
  isInitiated: boolean;
8
8
  isLoading: boolean;
9
9
  isInitialLoading: boolean;
@@ -29,7 +29,7 @@ export declare class ResourceDuplicatorAgent<D extends DuplicatorDefinition> imp
29
29
  args: NonNullable<D["RESOURCE_DEFINITION"]["Args"]> | undefined;
30
30
  }>;
31
31
  constructor(_resource: ResourceDuplicator<D>);
32
- initiate(args: D['ARGS_ITEM'][], force?: boolean): void;
33
- compareArgs(args: D['ARGS_ITEM'][], otherArgs: D['ARGS_ITEM'][]): boolean;
32
+ initiate(args: D["ARGS_ITEM"][], force?: boolean): void;
33
+ compareArgs(args: D["ARGS_ITEM"][], otherArgs: D["ARGS_ITEM"][]): boolean;
34
34
  private _next;
35
35
  }
@@ -1,7 +1,7 @@
1
1
  import { Computed, Signal } from "../../../signals";
2
2
  export class ResourceDuplicatorAgent {
3
3
  _resource;
4
- _resources$ = Signal.create({
4
+ _resources$ = Signal.state({
5
5
  previous$: null,
6
6
  current$: null,
7
7
  }, { isDisabled: true });
@@ -60,8 +60,8 @@ export class ResourceDuplicatorAgent {
60
60
  isError: currState.isError,
61
61
  isLocked: currState.isLocked,
62
62
  isReloading: currState.isReloading,
63
- error: isShowPrev ? prevState.error ?? undefined : currState.error ?? undefined,
64
- data: isShowPrev ? prevState.data ?? undefined : currState.data ?? undefined,
63
+ error: isShowPrev ? (prevState.error ?? undefined) : (currState.error ?? undefined),
64
+ data: isShowPrev ? (prevState.data ?? undefined) : (currState.data ?? undefined),
65
65
  args: currState.args ?? undefined,
66
66
  };
67
67
  }, { isDisabled: true });
@@ -1,6 +1,6 @@
1
- import { ResourceDefinition, ResourceRefInstanse, ResourceTransaction } from "@/query/types";
1
+ import { ResourceDefinition, ResourceRefInstance, ResourceTransaction } from "../../../query/types";
2
2
  import { Resource } from "./Resource";
3
- export declare class ResourceRef<D extends ResourceDefinition> implements ResourceRefInstanse<D> {
3
+ export declare class ResourceRef<D extends ResourceDefinition> implements ResourceRefInstance<D> {
4
4
  private readonly _resource;
5
5
  private readonly _args;
6
6
  private _cacheItem;
@@ -23,7 +23,7 @@ export class ResourceRef {
23
23
  return;
24
24
  isLocked = false;
25
25
  this._resource.decrementLock(this._args, { cache: this._cacheItem });
26
- }
26
+ },
27
27
  };
28
28
  }
29
29
  unlockOne() {
@@ -46,9 +46,9 @@ export class ResourceRef {
46
46
  let currentData = savedData ?? data;
47
47
  const remainingTransactions = [];
48
48
  let foundPending = false;
49
- const lastPendingIndex = transactions.findLastIndex(t => t.status === 'pending');
49
+ const lastPendingIndex = transactions.findLastIndex((t) => t.status === "pending");
50
50
  transactions.forEach((transaction, index) => {
51
- if (transaction.status === 'pending') {
51
+ if (transaction.status === "pending") {
52
52
  foundPending = true;
53
53
  // Применяем pending транзакцию и оставляем в очереди
54
54
  currentData = applyPatches(currentData, transaction.patches);
@@ -56,12 +56,12 @@ export class ResourceRef {
56
56
  }
57
57
  else if (foundPending) {
58
58
  // После pending транзакции
59
- if (transaction.status === 'committed') {
59
+ if (transaction.status === "committed") {
60
60
  // Применяем и оставляем в очереди
61
61
  currentData = applyPatches(currentData, transaction.patches);
62
62
  remainingTransactions.push(transaction);
63
63
  }
64
- else if (transaction.status === 'aborted') {
64
+ else if (transaction.status === "aborted") {
65
65
  // Проверяем, есть ли pending после текущей aborted
66
66
  const hasPendingAfter = index < lastPendingIndex;
67
67
  if (hasPendingAfter) {
@@ -73,7 +73,7 @@ export class ResourceRef {
73
73
  }
74
74
  else {
75
75
  // До первой pending транзакции
76
- if (transaction.status === 'committed') {
76
+ if (transaction.status === "committed") {
77
77
  // Применяем и убираем из очереди
78
78
  const patches = transaction.patches;
79
79
  currentData = applyPatches(currentData, patches);
@@ -94,19 +94,19 @@ export class ResourceRef {
94
94
  const transaction = {
95
95
  patches: [],
96
96
  inversePatches: [],
97
- status: 'pending',
97
+ status: "pending",
98
98
  abort() {
99
- if (this.status !== 'pending')
99
+ if (this.status !== "pending")
100
100
  return;
101
- this.status = 'aborted';
101
+ this.status = "aborted";
102
102
  reapplyTransactions();
103
103
  },
104
104
  commit() {
105
- if (this.status !== 'pending')
105
+ if (this.status !== "pending")
106
106
  return;
107
- this.status = 'committed';
107
+ this.status = "committed";
108
108
  reapplyTransactions();
109
- }
109
+ },
110
110
  };
111
111
  const updateFn = (data, savedData, transactions) => {
112
112
  isSkipped = false;
@@ -1,8 +1,11 @@
1
- export * from './api/createResource';
2
- export * from './api/createOperation';
3
- export * from './api/resetAllQueriesCache';
4
- export * from './api/createResourceDuplicator';
5
- export * from './SKIP_TOKEN';
6
- export * from './react/useResourceAgent';
7
- export * from './react/useResourceRef';
8
- export * from './react/useOperationAgent';
1
+ export * from "./api/createCommand";
2
+ export * from "./react/useCommandAgent";
3
+ export * from "./api/createResource";
4
+ export * from "./api/createResourceDuplicator";
5
+ export * from "./api/resetAllQueriesCache";
6
+ export * from "./SKIP_TOKEN";
7
+ export * from "./types";
8
+ export * from "./react/useResourceAgent";
9
+ export * from "./react/useResourceRef";
10
+ export * from "./api/createOperation";
11
+ export * from "./react/useOperationAgent";
@@ -1,8 +1,14 @@
1
- export * from './api/createResource';
2
- export * from './api/createOperation';
3
- export * from './api/resetAllQueriesCache';
4
- export * from './api/createResourceDuplicator';
5
- export * from './SKIP_TOKEN';
6
- export * from './react/useResourceAgent';
7
- export * from './react/useResourceRef';
8
- export * from './react/useOperationAgent';
1
+ // Command API
2
+ export * from "./api/createCommand";
3
+ export * from "./react/useCommandAgent";
4
+ // Resource API
5
+ export * from "./api/createResource";
6
+ export * from "./api/createResourceDuplicator";
7
+ export * from "./api/resetAllQueriesCache";
8
+ export * from "./SKIP_TOKEN";
9
+ export * from "./types";
10
+ export * from "./react/useResourceAgent";
11
+ export * from "./react/useResourceRef";
12
+ // Deprecated Operation API (backward compatibility)
13
+ export * from "./api/createOperation";
14
+ export * from "./react/useOperationAgent";
@@ -22,7 +22,7 @@ export class IndirectMap {
22
22
  get(key) {
23
23
  const item = this._map.get(key);
24
24
  if (!item) {
25
- const isObject = typeof key === 'object' && key !== null;
25
+ const isObject = typeof key === "object" && key !== null;
26
26
  if (!isObject) {
27
27
  return undefined;
28
28
  }
@@ -40,7 +40,7 @@ export class IndirectMap {
40
40
  this._map.set(key, value);
41
41
  }
42
42
  else {
43
- const isObject = typeof key === 'object' && key !== null;
43
+ const isObject = typeof key === "object" && key !== null;
44
44
  if (!isObject) {
45
45
  this._map.set(key, value);
46
46
  return;
@@ -61,7 +61,7 @@ export class IndirectMap {
61
61
  * @param key
62
62
  */
63
63
  delete(key) {
64
- const isObject = typeof key === 'object' && key !== null;
64
+ const isObject = typeof key === "object" && key !== null;
65
65
  if (isObject) {
66
66
  const cachedKey = this._getCachedKey(key);
67
67
  if (cachedKey) {
@@ -73,7 +73,7 @@ export class IndirectMap {
73
73
  }
74
74
  has(key) {
75
75
  const has = this._map.has(key);
76
- if (!has && typeof key === 'object' && key !== null) {
76
+ if (!has && typeof key === "object" && key !== null) {
77
77
  const cachedKey = this._getCachedKey(key);
78
78
  if (!cachedKey) {
79
79
  return false;
@@ -1,5 +1,5 @@
1
1
  import { Observable, Subject } from "rxjs";
2
- import { ReadableSignalLike } from "@/signals/types";
2
+ import { ReadableSignalLike } from "../../signals/types";
3
3
  type Options<VALUE> = {
4
4
  /**
5
5
  * Начальное состояние кэша
@@ -0,0 +1,24 @@
1
+ import type { CommandAgentInstance, CommandDefinition, CommandQueryState, Prettify } from "../../query/types";
2
+ type WithAgent<D extends CommandDefinition> = {
3
+ createAgent: () => CommandAgentInstance<D>;
4
+ };
5
+ type TriggerFn<D extends CommandDefinition> = (args: D["Args"]) => Promise<D["Data"]>;
6
+ type Result<D extends CommandDefinition> = [TriggerFn<D>, Prettify<CommandQueryState<D>>];
7
+ /**
8
+ * React hook для работы с командой (Command).
9
+ *
10
+ * Возвращает кортеж `[trigger, state]`:
11
+ * - `trigger(args)` — инициирует выполнение команды и возвращает Promise с результатом.
12
+ * - `state` — реактивное состояние выполнения команды.
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * const [updateUser, state] = useCommandAgent(api.updateUser);
17
+ *
18
+ * const handleSubmit = async () => {
19
+ * const result = await updateUser({ id: 1, name: 'New Name' });
20
+ * };
21
+ * ```
22
+ */
23
+ export declare function useCommandAgent<D extends CommandDefinition>(op: WithAgent<D>): Result<D>;
24
+ export {};
@@ -0,0 +1,39 @@
1
+ import { useConstant, useEventHandler } from "../../common/react";
2
+ import { useSignal } from "../../signals/react";
3
+ /**
4
+ * React hook для работы с командой (Command).
5
+ *
6
+ * Возвращает кортеж `[trigger, state]`:
7
+ * - `trigger(args)` — инициирует выполнение команды и возвращает Promise с результатом.
8
+ * - `state` — реактивное состояние выполнения команды.
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * const [updateUser, state] = useCommandAgent(api.updateUser);
13
+ *
14
+ * const handleSubmit = async () => {
15
+ * const result = await updateUser({ id: 1, name: 'New Name' });
16
+ * };
17
+ * ```
18
+ */
19
+ export function useCommandAgent(op) {
20
+ const agent = useConstant(() => op.createAgent());
21
+ const state = useSignal(agent.state$);
22
+ const trigger = useEventHandler((args) => {
23
+ agent.initiate(args);
24
+ return new Promise((resolve, reject) => {
25
+ const sub = agent.state$.obs.subscribe((s) => {
26
+ if (s.isDone && !s.isLoading) {
27
+ sub.unsubscribe();
28
+ if (s.isSuccess) {
29
+ resolve(s.data);
30
+ }
31
+ else {
32
+ reject(s.error);
33
+ }
34
+ }
35
+ });
36
+ });
37
+ });
38
+ return [trigger, state];
39
+ }
@@ -1,8 +1,6 @@
1
- import type { Prettify, OperationAgentInstanse, OperationDefinition, OperationQueryState } from "../../query/types";
2
- type WithAgent<D extends OperationDefinition> = {
3
- createAgent: () => OperationAgentInstanse<D>;
4
- };
5
- type TriggerFn<D extends OperationDefinition> = (args: D['Args']) => Promise<D['Data']>;
6
- type Result<D extends OperationDefinition> = [TriggerFn<D>, Prettify<OperationQueryState<D>>];
7
- export declare function useOperationAgent<D extends OperationDefinition>(op: WithAgent<D>): Result<D>;
8
- export {};
1
+ import { useCommandAgent } from "./useCommandAgent";
2
+ /**
3
+ * @deprecated Use `useCommandAgent` instead. Will be removed in v0.6.0.
4
+ * @see useCommandAgent
5
+ */
6
+ export declare const useOperationAgent: typeof useCommandAgent;
@@ -1,23 +1,6 @@
1
- import { useConstant, useEventHandler } from "../../common/react";
2
- import { useSignal } from "../../signals/react";
3
- export function useOperationAgent(op) {
4
- const agent = useConstant(() => op.createAgent());
5
- const state = useSignal(agent.state$);
6
- const trigger = useEventHandler((args) => {
7
- agent.initiate(args);
8
- return new Promise((resolve, reject) => {
9
- const sub = agent.state$.obs.subscribe((s) => {
10
- if (s.isDone && !s.isLoading) {
11
- sub.unsubscribe();
12
- if (s.isSuccess) {
13
- resolve(s.data);
14
- }
15
- else {
16
- reject(s.error);
17
- }
18
- }
19
- });
20
- });
21
- });
22
- return [trigger, state];
23
- }
1
+ import { useCommandAgent } from "./useCommandAgent";
2
+ /**
3
+ * @deprecated Use `useCommandAgent` instead. Will be removed in v0.6.0.
4
+ * @see useCommandAgent
5
+ */
6
+ export const useOperationAgent = useCommandAgent;
@@ -1,6 +1,6 @@
1
- import { Prettify, ResourceDefinition, ResourceInstance, ResourceQueryState } from "@/query/types";
2
- import { SKIP } from "@/query/SKIP_TOKEN";
3
- import { DuplicatorDefinition, ResourceDuplicator } from "@/query/core/Resource/ResourceDuplicator";
1
+ import { DuplicatorDefinition, ResourceDuplicator } from "../../query/core/Resource/ResourceDuplicator";
2
+ import { SKIP } from "../../query/SKIP_TOKEN";
3
+ import { Prettify, ResourceDefinition, ResourceInstance, ResourceQueryState } from "../../query/types";
4
4
  type Result<D extends ResourceDefinition> = Prettify<ResourceQueryState<D>>;
5
- export declare function useResourceAgent<D extends ResourceDefinition>(res: ResourceInstance<D> | ResourceDuplicator<DuplicatorDefinition<D>>, ...argss: D['Args'] extends void ? [] | [typeof SKIP] : [D['Args'] | typeof SKIP]): Result<D>;
5
+ export declare function useResourceAgent<D extends ResourceDefinition>(res: ResourceInstance<D> | ResourceDuplicator<DuplicatorDefinition<D>>, ...argss: D["Args"] extends void ? [] | [typeof SKIP] : [D["Args"] | typeof SKIP]): Result<D>;
6
6
  export {};
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
  import { useConstant } from "../../common/react";
3
- import { useSignal } from "../../signals/react";
4
3
  import { SKIP } from "../../query/SKIP_TOKEN";
4
+ import { useSignal } from "../../signals/react";
5
5
  export function useResourceAgent(res, ...argss) {
6
6
  const args = (argss[0] === SKIP ? SKIP : argss[0]);
7
7
  const prevArgsRef = React.useRef(SKIP);
@@ -1,5 +1,5 @@
1
1
  import { SKIP } from "../../query/SKIP_TOKEN";
2
- import type { Prettify, ResourceDefinition, ResourceInstance, ResourceRefInstanse } from "../../query/types";
3
- type Result<D extends ResourceDefinition> = Prettify<ResourceRefInstanse<D>>;
4
- export declare function useResourceRef<D extends ResourceDefinition>(res: ResourceInstance<D>, ...argss: D['Args'] extends void ? [] | [typeof SKIP] : [D['Args'] | typeof SKIP]): Result<D>;
2
+ import type { Prettify, ResourceDefinition, ResourceInstance, ResourceRefInstance } from "../../query/types";
3
+ type Result<D extends ResourceDefinition> = Prettify<ResourceRefInstance<D>>;
4
+ export declare function useResourceRef<D extends ResourceDefinition>(res: ResourceInstance<D>, ...argss: D["Args"] extends void ? [] | [typeof SKIP] : [D["Args"] | typeof SKIP]): Result<D>;
5
5
  export {};
@@ -1,8 +1,13 @@
1
1
  import React from "react";
2
+ import { shallowEqual } from "../../common/utils/shallowEqual";
2
3
  import { SKIP } from "../../query/SKIP_TOKEN";
3
4
  export function useResourceRef(res, ...argss) {
4
5
  const args = (argss[0] === SKIP ? SKIP : argss[0]);
6
+ const stableArgsRef = React.useRef(args);
7
+ if (!shallowEqual(stableArgsRef.current, args)) {
8
+ stableArgsRef.current = args;
9
+ }
5
10
  return React.useMemo(() => {
6
- return res.createRef(args);
7
- }, [args]);
11
+ return res.createRef(stableArgsRef.current);
12
+ }, [stableArgsRef.current]);
8
13
  }
@@ -0,0 +1,154 @@
1
+ import { ReadableSignalLike } from "../../signals/types";
2
+ import { ResourceDefinition, ResourceInstance } from "./Resource.types";
3
+ import { FallbackOnNever, OnCacheEntryAdded, OnQueryStarted } from "./shared.types";
4
+ /**
5
+ * Функция создания команды
6
+ */
7
+ export type CommandCreateFn<ARGS, RESULT, SELECTED = never> = (options: CommandCreateOptions<CommandDefinition<ARGS, RESULT, SELECTED>>) => CommandInstance<CommandDefinition<ARGS, RESULT, SELECTED>>;
8
+ /**
9
+ * Опции создания команды
10
+ */
11
+ export type CommandCreateOptions<D extends CommandDefinition> = {
12
+ /** Функция селектора для преобразования результата команды */
13
+ select?: (data: D["Result"]) => D["Selected"];
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 CommandDefinition, 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 CommandDefinition<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 CommandInstance<D extends CommandDefinition> = {
117
+ /** Создает агента для выполнения команды */
118
+ createAgent(): CommandAgentInstance<D>;
119
+ /**
120
+ * Выполняет команду с указанными аргументами
121
+ * @deprecated
122
+ */
123
+ mutate: (args: D["Args"]) => Promise<D["Data"]>;
124
+ };
125
+ /**
126
+ * Агент для выполнения команды
127
+ */
128
+ export type CommandAgentInstance<D extends CommandDefinition> = {
129
+ /** Observable состояния выполнения команды */
130
+ state$: ReadableSignalLike<CommandQueryState<D>>;
131
+ /** Инициирует выполнение команды с указанными аргументами */
132
+ initiate(args: D["Args"]): void;
133
+ /** Создает новый агент команды */
134
+ createAgent(): CommandAgentInstance<D>;
135
+ };
136
+ /**
137
+ * Состояние выполнения команды
138
+ */
139
+ export type CommandQueryState<D extends CommandDefinition> = {
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
+ };
@@ -0,0 +1 @@
1
+ export {};