@chelone/core 0.5.0 → 0.7.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.
Files changed (253) hide show
  1. package/dist/assistant/assistant-session.d.ts +28 -0
  2. package/dist/assistant/assistant-session.js +208 -0
  3. package/dist/assistant/echo-transport.d.ts +7 -0
  4. package/dist/assistant/echo-transport.js +28 -0
  5. package/dist/assistant/http-transport.d.ts +10 -0
  6. package/dist/assistant/http-transport.js +98 -0
  7. package/dist/assistant/types.d.ts +54 -0
  8. package/dist/auth/access-control.d.ts +13 -5
  9. package/dist/auth/access-control.js +25 -21
  10. package/dist/auth/auth-options.d.ts +21 -17
  11. package/dist/auth/auth-options.js +80 -48
  12. package/dist/auth/permission-matrix.d.ts +12 -0
  13. package/dist/auth/permission-matrix.js +67 -0
  14. package/dist/auth/types.d.ts +14 -4
  15. package/dist/block-editor/block-document.d.ts +60 -0
  16. package/dist/block-editor/block-document.js +143 -0
  17. package/dist/block-editor/data-blocks.d.ts +63 -0
  18. package/dist/block-editor/data-blocks.js +117 -0
  19. package/dist/chart/chart-data.d.ts +25 -0
  20. package/dist/chart/chart-data.js +61 -0
  21. package/dist/command-menu/hotkey.js +58 -47
  22. package/dist/command-menu/recents.js +8 -11
  23. package/dist/command-menu/registry.d.ts +9 -5
  24. package/dist/command-menu/registry.js +36 -46
  25. package/dist/controller/calendar-dates.js +82 -113
  26. package/dist/controller/calendar-events.js +93 -88
  27. package/dist/controller/client-list-controller.d.ts +2 -2
  28. package/dist/controller/client-list-controller.js +251 -254
  29. package/dist/controller/data-table-columns.d.ts +2 -0
  30. package/dist/controller/data-table-columns.js +50 -56
  31. package/dist/controller/deep-equal.d.ts +1 -0
  32. package/dist/controller/deep-equal.js +14 -0
  33. package/dist/controller/filter-toggle.js +36 -44
  34. package/dist/controller/in-place-editor.d.ts +42 -0
  35. package/dist/controller/in-place-editor.js +42 -0
  36. package/dist/controller/infinite-list-controller.js +220 -190
  37. package/dist/controller/inspector.d.ts +49 -0
  38. package/dist/controller/inspector.js +64 -0
  39. package/dist/controller/job-monitor.d.ts +41 -0
  40. package/dist/controller/job-monitor.js +49 -0
  41. package/dist/controller/kanban-board.d.ts +2 -3
  42. package/dist/controller/kanban-board.js +43 -24
  43. package/dist/controller/list-controller.d.ts +5 -5
  44. package/dist/controller/list-controller.js +444 -400
  45. package/dist/controller/list-params.js +96 -87
  46. package/dist/controller/pivot-grid.d.ts +36 -0
  47. package/dist/controller/pivot-grid.js +99 -0
  48. package/dist/controller/prev-next.d.ts +2 -2
  49. package/dist/controller/prev-next.js +74 -54
  50. package/dist/controller/record-controllers.d.ts +14 -6
  51. package/dist/controller/record-controllers.js +288 -257
  52. package/dist/controller/record-diff.d.ts +21 -0
  53. package/dist/controller/record-diff.js +50 -0
  54. package/dist/controller/record-timeline.d.ts +35 -0
  55. package/dist/controller/record-timeline.js +48 -0
  56. package/dist/controller/record-tree.js +57 -47
  57. package/dist/controller/record-workflow.d.ts +38 -16
  58. package/dist/controller/record-workflow.js +85 -64
  59. package/dist/controller/reference-many-controller.js +198 -192
  60. package/dist/controller/reference-one-controller.d.ts +1 -1
  61. package/dist/controller/reference-one-controller.js +63 -56
  62. package/dist/controller/saved-queries.js +104 -91
  63. package/dist/controller/translate-fallback.js +10 -6
  64. package/dist/csv/export.d.ts +2 -1
  65. package/dist/csv/export.js +43 -40
  66. package/dist/csv/import-controller.js +185 -169
  67. package/dist/csv/match-headers.js +29 -22
  68. package/dist/csv/parse-with.js +60 -54
  69. package/dist/csv/run-import.js +69 -72
  70. package/dist/csv/validate-rows.d.ts +1 -1
  71. package/dist/csv/validate-rows.js +65 -52
  72. package/dist/data/cache-ops.d.ts +5 -4
  73. package/dist/data/cache-ops.js +208 -190
  74. package/dist/data/combine-data-providers.js +25 -23
  75. package/dist/data/data-provider-log.d.ts +45 -0
  76. package/dist/data/data-provider-log.js +93 -0
  77. package/dist/data/errors.js +14 -10
  78. package/dist/data/fake-provider.d.ts +6 -3
  79. package/dist/data/fake-provider.js +129 -114
  80. package/dist/data/fetch-utils.js +61 -44
  81. package/dist/data/filter-branch.d.ts +5 -0
  82. package/dist/data/filter-branch.js +10 -0
  83. package/dist/data/get-many-aggregate.js +84 -76
  84. package/dist/data/http-error.js +17 -12
  85. package/dist/data/keys.js +50 -36
  86. package/dist/data/mutation-options.d.ts +14 -9
  87. package/dist/data/mutation-options.js +93 -109
  88. package/dist/data/query-options.js +73 -68
  89. package/dist/data/remove-empty.d.ts +3 -0
  90. package/dist/data/remove-empty.js +11 -0
  91. package/dist/data/undoable.d.ts +2 -2
  92. package/dist/data/undoable.js +190 -174
  93. package/dist/data/with-lifecycle-callbacks.d.ts +45 -17
  94. package/dist/data/with-lifecycle-callbacks.js +66 -52
  95. package/dist/environment/application-update-store.js +58 -55
  96. package/dist/environment/offline-store.js +21 -21
  97. package/dist/form/array-binding.d.ts +30 -11
  98. package/dist/form/array-binding.js +184 -166
  99. package/dist/form/choice-ids.d.ts +7 -0
  100. package/dist/form/choice-ids.js +11 -0
  101. package/dist/form/choices-controller.d.ts +3 -2
  102. package/dist/form/choices-controller.js +302 -275
  103. package/dist/form/date-format.d.ts +38 -0
  104. package/dist/form/date-format.js +89 -0
  105. package/dist/form/dirty-values.d.ts +2 -2
  106. package/dist/form/dirty-values.js +22 -11
  107. package/dist/form/duration.d.ts +22 -0
  108. package/dist/form/duration.js +49 -0
  109. package/dist/form/edit-create-form.d.ts +12 -5
  110. package/dist/form/edit-create-form.js +243 -188
  111. package/dist/form/event-value.d.ts +6 -0
  112. package/dist/form/event-value.js +17 -0
  113. package/dist/form/field-error.d.ts +14 -0
  114. package/dist/form/field-error.js +28 -0
  115. package/dist/form/field-name.d.ts +20 -0
  116. package/dist/form/field-name.js +6 -0
  117. package/dist/form/filter-form-values.js +63 -49
  118. package/dist/form/form-controller.d.ts +9 -1
  119. package/dist/form/form-controller.js +165 -160
  120. package/dist/form/form-groups.d.ts +4 -3
  121. package/dist/form/form-groups.js +79 -79
  122. package/dist/form/form-handle.d.ts +175 -0
  123. package/dist/form/form-handle.js +68 -0
  124. package/dist/form/input-binding.d.ts +56 -31
  125. package/dist/form/input-binding.js +169 -118
  126. package/dist/form/input-values.d.ts +130 -0
  127. package/dist/form/input-values.js +177 -0
  128. package/dist/form/json-text.js +51 -37
  129. package/dist/form/save-pipeline.d.ts +6 -8
  130. package/dist/form/save-pipeline.js +91 -82
  131. package/dist/form/set-form-values.d.ts +6 -0
  132. package/dist/form/set-form-values.js +10 -0
  133. package/dist/form/source.js +97 -65
  134. package/dist/form/text-of.d.ts +2 -0
  135. package/dist/form/text-of.js +7 -0
  136. package/dist/form/validators.d.ts +58 -19
  137. package/dist/form/validators.js +97 -71
  138. package/dist/geo/bbox.d.ts +5 -4
  139. package/dist/geo/bbox.js +69 -48
  140. package/dist/geo/bounds.d.ts +14 -3
  141. package/dist/geo/bounds.js +98 -68
  142. package/dist/geo/constraints.js +88 -93
  143. package/dist/geo/coordinates.js +31 -23
  144. package/dist/geo/editor.d.ts +13 -13
  145. package/dist/geo/editor.js +176 -153
  146. package/dist/geo/geocoding.d.ts +4 -4
  147. package/dist/geo/geocoding.js +38 -41
  148. package/dist/geo/geojson.d.ts +12 -74
  149. package/dist/geo/geojson.js +52 -40
  150. package/dist/geo/geometry-math.d.ts +4 -4
  151. package/dist/geo/geometry-math.js +100 -93
  152. package/dist/geo/index.d.ts +7 -6
  153. package/dist/geo/map-layers.d.ts +42 -7
  154. package/dist/geo/map-layers.js +88 -62
  155. package/dist/geo/map-style.js +31 -32
  156. package/dist/geo/messages.js +48 -45
  157. package/dist/geo/nominatim.js +88 -80
  158. package/dist/geo/osm-presets.d.ts +4 -3
  159. package/dist/geo/osm-presets.js +108 -86
  160. package/dist/geo/osm-tags.js +14 -12
  161. package/dist/geo/overpass.d.ts +14 -2
  162. package/dist/geo/overpass.js +83 -90
  163. package/dist/geo/shape-value.d.ts +9 -5
  164. package/dist/geo/shape-value.js +169 -146
  165. package/dist/geo/snap-to-roads.d.ts +3 -3
  166. package/dist/geo/snap-to-roads.js +55 -50
  167. package/dist/geo/throttle.js +36 -39
  168. package/dist/guards.d.ts +37 -0
  169. package/dist/guards.js +62 -0
  170. package/dist/i18n/default-messages.js +34 -29
  171. package/dist/i18n/english-messages.js +187 -189
  172. package/dist/i18n/i18n.d.ts +8 -2
  173. package/dist/i18n/i18n.js +47 -48
  174. package/dist/i18n/inflection.d.ts +34 -0
  175. package/dist/i18n/inflection.js +82 -0
  176. package/dist/i18n/messages.d.ts +10 -2
  177. package/dist/i18n/messages.js +17 -4
  178. package/dist/i18n/missing-keys.d.ts +19 -0
  179. package/dist/i18n/missing-keys.js +68 -0
  180. package/dist/i18n/translatable.d.ts +16 -1
  181. package/dist/i18n/translatable.js +40 -47
  182. package/dist/index.d.ts +96 -22
  183. package/dist/index.js +52 -257
  184. package/dist/json/deep-equal.d.ts +8 -0
  185. package/dist/json/deep-equal.js +24 -0
  186. package/dist/json/strip-json-comments.js +38 -42
  187. package/dist/noop.d.ts +2 -0
  188. package/dist/noop.js +4 -0
  189. package/dist/notification/error-message.d.ts +2 -0
  190. package/dist/notification/error-message.js +10 -0
  191. package/dist/notification/notification-store.d.ts +3 -2
  192. package/dist/notification/notification-store.js +41 -45
  193. package/dist/onboarding-tour/placement.d.ts +34 -0
  194. package/dist/onboarding-tour/placement.js +67 -0
  195. package/dist/onboarding-tour/tour-controller.d.ts +25 -0
  196. package/dist/onboarding-tour/tour-controller.js +50 -0
  197. package/dist/realtime/add-events-for-mutations.js +75 -81
  198. package/dist/realtime/announce-lock.d.ts +7 -0
  199. package/dist/realtime/announce-lock.js +18 -0
  200. package/dist/realtime/broadcast-channel-transport.d.ts +14 -0
  201. package/dist/realtime/broadcast-channel-transport.js +69 -0
  202. package/dist/realtime/copy-members.js +22 -14
  203. package/dist/realtime/in-memory-lock-provider.js +41 -60
  204. package/dist/realtime/live.js +95 -101
  205. package/dist/realtime/lock-options.js +16 -16
  206. package/dist/realtime/lock-session.js +91 -78
  207. package/dist/realtime/memory-transport.js +26 -67
  208. package/dist/realtime/presence.js +120 -122
  209. package/dist/realtime/realtime-data-provider.d.ts +10 -0
  210. package/dist/realtime/realtime-data-provider.js +45 -42
  211. package/dist/realtime/reconnect-backoff.d.ts +15 -0
  212. package/dist/realtime/reconnect-backoff.js +17 -0
  213. package/dist/realtime/sse-transport.d.ts +31 -0
  214. package/dist/realtime/sse-transport.js +235 -0
  215. package/dist/realtime/status-store.js +23 -28
  216. package/dist/realtime/topic-hub.d.ts +24 -0
  217. package/dist/realtime/topic-hub.js +66 -0
  218. package/dist/realtime/topics.js +10 -12
  219. package/dist/realtime/types.js +10 -12
  220. package/dist/realtime/unread-count.js +21 -21
  221. package/dist/realtime/websocket-transport.d.ts +32 -0
  222. package/dist/realtime/websocket-transport.js +306 -0
  223. package/dist/resource/describe-resource.d.ts +2 -0
  224. package/dist/resource/describe-resource.js +232 -219
  225. package/dist/resource/get-at-path.js +29 -14
  226. package/dist/resource/identifier.d.ts +18 -0
  227. package/dist/resource/identifier.js +27 -0
  228. package/dist/resource/record.d.ts +4 -0
  229. package/dist/resource/record.js +10 -0
  230. package/dist/resource/register.d.ts +7 -0
  231. package/dist/resource/registry-store.d.ts +45 -15
  232. package/dist/resource/registry-store.js +67 -60
  233. package/dist/resource/registry.d.ts +10 -0
  234. package/dist/resource/registry.js +8 -4
  235. package/dist/resource/source-path.d.ts +16 -1
  236. package/dist/rich-text/rich-text-extras.d.ts +132 -0
  237. package/dist/rich-text/rich-text-extras.js +179 -0
  238. package/dist/rich-text/rich-text-image.d.ts +124 -0
  239. package/dist/rich-text/rich-text-image.js +163 -0
  240. package/dist/rich-text/rich-text.d.ts +62 -0
  241. package/dist/rich-text/rich-text.js +142 -0
  242. package/dist/router/location.d.ts +22 -4
  243. package/dist/router/location.js +41 -18
  244. package/dist/router/match.js +47 -39
  245. package/dist/router/paths.js +40 -34
  246. package/dist/router/record-from-location.d.ts +1 -1
  247. package/dist/router/record-from-location.js +25 -17
  248. package/dist/store/adapters.js +51 -55
  249. package/dist/store/micro-store.js +57 -59
  250. package/dist/store/shallow-equal.d.ts +12 -0
  251. package/dist/store/shallow-equal.js +20 -0
  252. package/dist/store/store.js +54 -57
  253. package/package.json +13 -11
package/dist/data/keys.js CHANGED
@@ -1,55 +1,69 @@
1
+ // src/data/keys.ts
2
+ /** Root key for a resource — invalidation scope for everything under it. */
1
3
  function resourceKey(resource) {
2
- return [resource];
4
+ return [resource];
3
5
  }
4
6
  function listKey(resource, params = {}) {
5
- return [resource, "getList", params];
7
+ return [
8
+ resource,
9
+ "getList",
10
+ params
11
+ ];
6
12
  }
7
13
  function infiniteListKey(resource, params) {
8
- return [resource, "getInfiniteList", params];
14
+ return [
15
+ resource,
16
+ "getInfiniteList",
17
+ params
18
+ ];
9
19
  }
20
+ /** Partial-match key covering every `getInfiniteList` cache variant of a resource. */
10
21
  function infiniteListKeyPrefix(resource) {
11
- return [resource, "getInfiniteList"];
22
+ return [resource, "getInfiniteList"];
12
23
  }
13
24
  function oneKey(resource, params) {
14
- return [
15
- resource,
16
- "getOne",
17
- params.meta === void 0 ? { id: String(params.id) } : { id: String(params.id), meta: params.meta }
18
- ];
25
+ return [
26
+ resource,
27
+ "getOne",
28
+ params.meta === void 0 ? { id: String(params.id) } : {
29
+ id: String(params.id),
30
+ meta: params.meta
31
+ }
32
+ ];
19
33
  }
20
34
  function manyKey(resource, params) {
21
- const ids = params.ids.map(String).sort();
22
- return [
23
- resource,
24
- "getMany",
25
- params.meta === void 0 ? { ids } : { ids, meta: params.meta }
26
- ];
35
+ const ids = params.ids.map(String).sort();
36
+ return [
37
+ resource,
38
+ "getMany",
39
+ params.meta === void 0 ? { ids } : {
40
+ ids,
41
+ meta: params.meta
42
+ }
43
+ ];
27
44
  }
45
+ /** Partial-match key covering every `getMany` cache variant of a resource. */
28
46
  function manyKeyPrefix(resource) {
29
- return [resource, "getMany"];
47
+ return [resource, "getMany"];
30
48
  }
31
49
  function manyReferenceKey(resource, params) {
32
- return [resource, "getManyReference", params];
50
+ return [
51
+ resource,
52
+ "getManyReference",
53
+ params
54
+ ];
33
55
  }
34
56
  function lockKey(resource, params) {
35
- return [
36
- resource,
37
- "getLock",
38
- params.meta === void 0 ? { id: String(params.id) } : { id: String(params.id), meta: params.meta }
39
- ];
57
+ return [
58
+ resource,
59
+ "getLock",
60
+ params.meta === void 0 ? { id: String(params.id) } : {
61
+ id: String(params.id),
62
+ meta: params.meta
63
+ }
64
+ ];
40
65
  }
41
66
  function locksKey(resource) {
42
- return [resource, "getLocks"];
43
- }
44
- export {
45
- infiniteListKey,
46
- infiniteListKeyPrefix,
47
- listKey,
48
- lockKey,
49
- locksKey,
50
- manyKey,
51
- manyKeyPrefix,
52
- manyReferenceKey,
53
- oneKey,
54
- resourceKey
55
- };
67
+ return [resource, "getLocks"];
68
+ }
69
+ export { infiniteListKey, infiniteListKeyPrefix, listKey, lockKey, locksKey, manyKey, manyKeyPrefix, manyReferenceKey, oneKey, resourceKey };
@@ -1,3 +1,5 @@
1
+ import type { QueryKey } from "@tanstack/query-core";
2
+ import type { ResourceRecord } from "../resource/record.js";
1
3
  import type { RecordOf, ResourceMap } from "../resource/registry.js";
2
4
  import type { DataContext } from "./query-options.js";
3
5
  import type { CreateParams, DeleteParams, UpdateParams } from "./types.js";
@@ -11,11 +13,14 @@ export type MutationMode = "pessimistic" | "optimistic" | "undoable";
11
13
  export interface MutationModeOptions {
12
14
  mutationMode?: MutationMode;
13
15
  }
14
- type ManySnapshot = Array<[readonly unknown[], unknown]>;
15
- interface OptimisticContext {
16
- previous?: unknown;
17
- key?: readonly unknown[];
18
- manySnapshot?: ManySnapshot;
16
+ type ManySnapshot<TRecord extends ResourceRecord> = Array<[
17
+ QueryKey,
18
+ TRecord[] | undefined
19
+ ]>;
20
+ interface OptimisticContext<TRecord extends ResourceRecord> {
21
+ previous?: TRecord;
22
+ key?: QueryKey;
23
+ manySnapshot?: ManySnapshot<TRecord>;
19
24
  rollbackLists?: () => void;
20
25
  }
21
26
  export declare function createMutationOptions<TResources extends ResourceMap, TName extends keyof TResources & string>(ctx: DataContext<TResources>, resource: TName): {
@@ -39,10 +44,10 @@ export declare function updateMutationOptions<TResources extends ResourceMap, TN
39
44
  id: string;
40
45
  meta: {} | null;
41
46
  }];
42
- manySnapshot: ManySnapshot;
47
+ manySnapshot: ManySnapshot<RecordOf<TResources, TName>>;
43
48
  rollbackLists: () => void;
44
49
  }>;
45
- onError: (_error: unknown, _params: UpdateParams<RecordOf<TResources, TName>>, context: OptimisticContext | undefined) => void;
50
+ onError: (_error: Error, _params: UpdateParams<RecordOf<TResources, TName>>, context: OptimisticContext<RecordOf<TResources, TName>> | undefined) => void;
46
51
  onSettled: () => Promise<void> | undefined;
47
52
  };
48
53
  export declare function deleteMutationOptions<TResources extends ResourceMap, TName extends keyof TResources & string>(ctx: DataContext<TResources>, resource: TName, options?: MutationModeOptions): {
@@ -60,9 +65,9 @@ export declare function deleteMutationOptions<TResources extends ResourceMap, TN
60
65
  id: string;
61
66
  meta: {} | null;
62
67
  }];
63
- manySnapshot: ManySnapshot;
68
+ manySnapshot: ManySnapshot<RecordOf<TResources, TName>>;
64
69
  }>;
65
- onError: (_error: unknown, _params: DeleteParams<RecordOf<TResources, TName>>, context: OptimisticContext | undefined) => void;
70
+ onError: (_error: Error, _params: DeleteParams<RecordOf<TResources, TName>>, context: OptimisticContext<RecordOf<TResources, TName>> | undefined) => void;
66
71
  onSettled: () => Promise<void>;
67
72
  };
68
73
  export {};
@@ -1,125 +1,109 @@
1
- import { removeManyEntries, patchManyEntries, patchListEntries } from "./cache-ops.js";
2
- import { oneKey, resourceKey, manyKeyPrefix } from "./keys.js";
1
+ import { patchListEntries, patchManyEntries, removeManyEntries } from "./cache-ops.js";
2
+ import { manyKeyPrefix, oneKey, resourceKey } from "./keys.js";
3
+ // src/data/mutation-options.ts
3
4
  function invalidateResource(ctx, resource) {
4
- return ctx.queryClient.invalidateQueries({ queryKey: resourceKey(resource) });
5
+ return ctx.queryClient.invalidateQueries({ queryKey: resourceKey(resource) });
5
6
  }
6
- const unsettledUpdates = /* @__PURE__ */ new WeakMap();
7
+ /**
8
+ * Optimistic updates that have started and not yet settled, per client and
9
+ * resource. `isMutating` cannot stand in: TanStack runs `onSettled` before it
10
+ * marks the mutation done, so two updates answered in the same tick each count
11
+ * the other as pending and both would skip the refetch.
12
+ */
13
+ var unsettledUpdates = /* @__PURE__ */ new WeakMap();
7
14
  function countUpdate(queryClient, resource, by) {
8
- const counts = unsettledUpdates.get(queryClient) ?? /* @__PURE__ */ new Map();
9
- unsettledUpdates.set(queryClient, counts);
10
- const next = (counts.get(resource) ?? 0) + by;
11
- counts.set(resource, next);
12
- return next;
15
+ const counts = unsettledUpdates.get(queryClient) ?? /* @__PURE__ */ new Map();
16
+ unsettledUpdates.set(queryClient, counts);
17
+ const next = (counts.get(resource) ?? 0) + by;
18
+ counts.set(resource, next);
19
+ return next;
13
20
  }
21
+ /** Cancels in-flight list fetches (`getList`, `getManyReference`, `getInfiniteList`) so they cannot overwrite a patch. */
14
22
  function cancelListQueries(ctx, resource) {
15
- return ctx.queryClient.cancelQueries({
16
- queryKey: resourceKey(resource),
17
- predicate: ({ queryKey }) => queryKey[1] === "getList" || queryKey[1] === "getManyReference" || queryKey[1] === "getInfiniteList"
18
- });
23
+ return ctx.queryClient.cancelQueries({
24
+ queryKey: resourceKey(resource),
25
+ predicate: ({ queryKey }) => queryKey[1] === "getList" || queryKey[1] === "getManyReference" || queryKey[1] === "getInfiniteList"
26
+ });
19
27
  }
28
+ /** Cancels in-flight `getMany` fetches so they cannot overwrite the patch, then snapshots the entries. */
20
29
  async function snapshotManyEntries(ctx, resource) {
21
- await ctx.queryClient.cancelQueries({ queryKey: manyKeyPrefix(resource) });
22
- return ctx.queryClient.getQueriesData({ queryKey: manyKeyPrefix(resource) });
30
+ await ctx.queryClient.cancelQueries({ queryKey: manyKeyPrefix(resource) });
31
+ return ctx.queryClient.getQueriesData({ queryKey: manyKeyPrefix(resource) });
23
32
  }
24
33
  function restoreManyEntries(ctx, snapshot) {
25
- for (const [key, value] of snapshot ?? []) {
26
- ctx.queryClient.setQueryData(key, value);
27
- }
34
+ for (const [key, value] of snapshot ?? []) ctx.queryClient.setQueryData(key, value);
28
35
  }
29
36
  function createMutationOptions(ctx, resource) {
30
- return {
31
- mutationFn: async (params) => {
32
- const result = await ctx.dataProvider.create(resource, params);
33
- return result.data;
34
- },
35
- onSettled: () => invalidateResource(ctx, resource)
36
- };
37
+ return {
38
+ mutationFn: async (params) => {
39
+ return (await ctx.dataProvider.create(resource, params)).data;
40
+ },
41
+ onSettled: () => invalidateResource(ctx, resource)
42
+ };
37
43
  }
38
44
  function updateMutationOptions(ctx, resource, options = {}) {
39
- const mode = options.mutationMode ?? "pessimistic";
40
- const mutationKey = [resource, "update"];
41
- return {
42
- mutationKey,
43
- mutationFn: async (params) => {
44
- const result = await ctx.dataProvider.update(resource, params);
45
- return result.data;
46
- },
47
- onMutate: async (params) => {
48
- if (mode !== "optimistic") return {};
49
- countUpdate(ctx.queryClient, resource, 1);
50
- const key = oneKey(resource, { id: params.id });
51
- await ctx.queryClient.cancelQueries({ queryKey: key });
52
- const previous = ctx.queryClient.getQueryData(key);
53
- if (previous !== void 0) {
54
- const merged = Object.assign(
55
- structuredClone(previous),
56
- structuredClone(params.data)
57
- );
58
- ctx.queryClient.setQueryData(key, merged);
59
- }
60
- const manySnapshot = await snapshotManyEntries(ctx, resource);
61
- patchManyEntries(
62
- ctx.queryClient,
63
- resource,
64
- /* @__PURE__ */ new Set([String(params.id)]),
65
- structuredClone(params.data)
66
- );
67
- await cancelListQueries(ctx, resource);
68
- const rollbackLists = patchListEntries(
69
- ctx.queryClient,
70
- resource,
71
- /* @__PURE__ */ new Set([String(params.id)]),
72
- structuredClone(params.data)
73
- );
74
- return { previous, key, manySnapshot, rollbackLists };
75
- },
76
- onError: (_error, _params, context) => {
77
- if (context?.key && context.previous !== void 0) {
78
- ctx.queryClient.setQueryData(context.key, context.previous);
79
- }
80
- restoreManyEntries(ctx, context?.manySnapshot);
81
- context?.rollbackLists?.();
82
- },
83
- onSettled: () => {
84
- if (mode === "optimistic" && countUpdate(ctx.queryClient, resource, -1) > 0) {
85
- return;
86
- }
87
- return invalidateResource(ctx, resource);
88
- }
89
- };
45
+ const mode = options.mutationMode ?? "pessimistic";
46
+ return {
47
+ mutationKey: [resource, "update"],
48
+ mutationFn: async (params) => {
49
+ return (await ctx.dataProvider.update(resource, params)).data;
50
+ },
51
+ onMutate: async (params) => {
52
+ if (mode !== "optimistic") return {};
53
+ countUpdate(ctx.queryClient, resource, 1);
54
+ const key = oneKey(resource, { id: params.id });
55
+ await ctx.queryClient.cancelQueries({ queryKey: key });
56
+ const previous = ctx.queryClient.getQueryData(key);
57
+ if (previous !== void 0) {
58
+ const merged = Object.assign(structuredClone(previous), structuredClone(params.data));
59
+ ctx.queryClient.setQueryData(key, merged);
60
+ }
61
+ const manySnapshot = await snapshotManyEntries(ctx, resource);
62
+ patchManyEntries(ctx.queryClient, resource, /* @__PURE__ */ new Set([String(params.id)]), structuredClone(params.data));
63
+ await cancelListQueries(ctx, resource);
64
+ return {
65
+ previous,
66
+ key,
67
+ manySnapshot,
68
+ rollbackLists: patchListEntries(ctx.queryClient, resource, /* @__PURE__ */ new Set([String(params.id)]), structuredClone(params.data))
69
+ };
70
+ },
71
+ onError: (_error, _params, context) => {
72
+ if (context?.key && context.previous !== void 0) ctx.queryClient.setQueryData(context.key, context.previous);
73
+ restoreManyEntries(ctx, context?.manySnapshot);
74
+ context?.rollbackLists?.();
75
+ },
76
+ onSettled: () => {
77
+ if (mode === "optimistic" && countUpdate(ctx.queryClient, resource, -1) > 0) return;
78
+ return invalidateResource(ctx, resource);
79
+ }
80
+ };
90
81
  }
91
82
  function deleteMutationOptions(ctx, resource, options = {}) {
92
- const mode = options.mutationMode ?? "pessimistic";
93
- return {
94
- mutationFn: async (params) => {
95
- const result = await ctx.dataProvider.delete(resource, params);
96
- return result.data;
97
- },
98
- onMutate: async (params) => {
99
- if (mode !== "optimistic") return {};
100
- const key = oneKey(resource, { id: params.id });
101
- await ctx.queryClient.cancelQueries({ queryKey: key });
102
- const previous = ctx.queryClient.getQueryData(key);
103
- ctx.queryClient.removeQueries({ queryKey: key });
104
- const manySnapshot = await snapshotManyEntries(ctx, resource);
105
- removeManyEntries(
106
- ctx.queryClient,
107
- resource,
108
- /* @__PURE__ */ new Set([String(params.id)])
109
- );
110
- return { previous, key, manySnapshot };
111
- },
112
- onError: (_error, _params, context) => {
113
- if (context?.key && context.previous !== void 0) {
114
- ctx.queryClient.setQueryData(context.key, context.previous);
115
- }
116
- restoreManyEntries(ctx, context?.manySnapshot);
117
- },
118
- onSettled: () => invalidateResource(ctx, resource)
119
- };
83
+ const mode = options.mutationMode ?? "pessimistic";
84
+ return {
85
+ mutationFn: async (params) => {
86
+ return (await ctx.dataProvider.delete(resource, params)).data;
87
+ },
88
+ onMutate: async (params) => {
89
+ if (mode !== "optimistic") return {};
90
+ const key = oneKey(resource, { id: params.id });
91
+ await ctx.queryClient.cancelQueries({ queryKey: key });
92
+ const previous = ctx.queryClient.getQueryData(key);
93
+ ctx.queryClient.removeQueries({ queryKey: key });
94
+ const manySnapshot = await snapshotManyEntries(ctx, resource);
95
+ removeManyEntries(ctx.queryClient, resource, /* @__PURE__ */ new Set([String(params.id)]));
96
+ return {
97
+ previous,
98
+ key,
99
+ manySnapshot
100
+ };
101
+ },
102
+ onError: (_error, _params, context) => {
103
+ if (context?.key && context.previous !== void 0) ctx.queryClient.setQueryData(context.key, context.previous);
104
+ restoreManyEntries(ctx, context?.manySnapshot);
105
+ },
106
+ onSettled: () => invalidateResource(ctx, resource)
107
+ };
120
108
  }
121
- export {
122
- createMutationOptions,
123
- deleteMutationOptions,
124
- updateMutationOptions
125
- };
109
+ export { createMutationOptions, deleteMutationOptions, updateMutationOptions };
@@ -1,81 +1,86 @@
1
1
  import { infiniteListKey, listKey, manyKey, manyReferenceKey, oneKey } from "./keys.js";
2
+ // src/data/query-options.ts
2
3
  function seedRecords(queryClient, resource, records) {
3
- for (const record of records) {
4
- queryClient.setQueryData(oneKey(resource, { id: record.id }), record);
5
- }
4
+ for (const record of records) queryClient.setQueryData(oneKey(resource, { id: record.id }), record);
6
5
  }
6
+ /** Plain option objects — consumable by any framework's useQuery AND server-side prefetchQuery. */
7
7
  function getListOptions(ctx, resource, params = {}) {
8
- return {
9
- queryKey: listKey(resource, params),
10
- queryFn: async () => {
11
- const result = await ctx.dataProvider.getList(resource, params);
12
- seedRecords(ctx.queryClient, resource, result.data);
13
- return result;
14
- }
15
- };
8
+ return {
9
+ queryKey: listKey(resource, params),
10
+ queryFn: async () => {
11
+ const result = await ctx.dataProvider.getList(resource, params);
12
+ seedRecords(ctx.queryClient, resource, result.data);
13
+ return result;
14
+ }
15
+ };
16
16
  }
17
+ /**
18
+ * One query that gathers pages: an infinite observer or `fetchInfiniteQuery`
19
+ * consumes it. The page param is the page number; rows are seeded into
20
+ * `oneKey` like `getListOptions` does.
21
+ */
17
22
  function getInfiniteListOptions(ctx, resource, params) {
18
- const { page, perPage } = params.pagination;
19
- return {
20
- queryKey: infiniteListKey(resource, params),
21
- queryFn: async ({ pageParam }) => {
22
- const result = await ctx.dataProvider.getList(resource, {
23
- ...params,
24
- pagination: { page: pageParam, perPage }
25
- });
26
- seedRecords(ctx.queryClient, resource, result.data);
27
- return result;
28
- },
29
- initialPageParam: page,
30
- getNextPageParam: (lastPage, allPages, lastPageParam, allPageParams) => {
31
- const { pageInfo, total } = lastPage;
32
- if (pageInfo?.hasNextPage !== void 0) {
33
- return pageInfo.hasNextPage ? lastPageParam + 1 : void 0;
34
- }
35
- if (total != null) {
36
- const skipped = Math.max(0, ((allPageParams[0] ?? page) - 1) * perPage);
37
- const loaded = allPages.reduce((n, p) => n + p.data.length, skipped);
38
- return loaded < total ? lastPageParam + 1 : void 0;
39
- }
40
- const { length } = lastPage.data;
41
- return length > 0 && length >= perPage ? lastPageParam + 1 : void 0;
42
- },
43
- getPreviousPageParam: (_firstPage, _allPages, firstPageParam, _allPageParams) => firstPageParam > 1 ? firstPageParam - 1 : void 0
44
- };
23
+ const { page, perPage } = params.pagination;
24
+ return {
25
+ queryKey: infiniteListKey(resource, params),
26
+ queryFn: async ({ pageParam }) => {
27
+ const result = await ctx.dataProvider.getList(resource, {
28
+ ...params,
29
+ pagination: {
30
+ page: pageParam,
31
+ perPage
32
+ }
33
+ });
34
+ seedRecords(ctx.queryClient, resource, result.data);
35
+ return result;
36
+ },
37
+ initialPageParam: page,
38
+ getNextPageParam: (lastPage, allPages, lastPageParam, allPageParams) => {
39
+ const { pageInfo, total } = lastPage;
40
+ if (pageInfo?.hasNextPage !== void 0) return pageInfo.hasNextPage ? lastPageParam + 1 : void 0;
41
+ if (total != null) {
42
+ const skipped = Math.max(0, ((allPageParams[0] ?? page) - 1) * perPage);
43
+ return allPages.reduce((n, p) => n + p.data.length, skipped) < total ? lastPageParam + 1 : void 0;
44
+ }
45
+ const { length } = lastPage.data;
46
+ return length > 0 && length >= perPage ? lastPageParam + 1 : void 0;
47
+ },
48
+ getPreviousPageParam: (_firstPage, _allPages, firstPageParam, _allPageParams) => firstPageParam > 1 ? firstPageParam - 1 : void 0
49
+ };
45
50
  }
51
+ /** One record by id, cached under `oneKey`. */
46
52
  function getOneOptions(ctx, resource, params) {
47
- return {
48
- queryKey: oneKey(resource, params),
49
- queryFn: async () => {
50
- const result = await ctx.dataProvider.getOne(resource, params);
51
- return result.data;
52
- }
53
- };
53
+ return {
54
+ queryKey: oneKey(resource, params),
55
+ queryFn: async () => {
56
+ return (await ctx.dataProvider.getOne(resource, params)).data;
57
+ }
58
+ };
54
59
  }
60
+ /** Records for an array of ids, seeded into `oneKey`. Resolves to the rows only. */
55
61
  function getManyOptions(ctx, resource, params) {
56
- return {
57
- queryKey: manyKey(resource, params),
58
- queryFn: async () => {
59
- const result = await ctx.dataProvider.getMany(resource, params);
60
- seedRecords(ctx.queryClient, resource, result.data);
61
- return result.data;
62
- }
63
- };
62
+ return {
63
+ queryKey: manyKey(resource, params),
64
+ queryFn: async () => {
65
+ const result = await ctx.dataProvider.getMany(resource, params);
66
+ seedRecords(ctx.queryClient, resource, result.data);
67
+ return result.data;
68
+ }
69
+ };
64
70
  }
71
+ /**
72
+ * Records whose `params.target` field equals `params.id` (the FK on the
73
+ * referenced-FROM side). Keeps the whole `GetManyReferenceResult` (rows and
74
+ * `total`) and seeds each row into the `oneKey` cache.
75
+ */
65
76
  function getManyReferenceOptions(ctx, resource, params) {
66
- return {
67
- queryKey: manyReferenceKey(resource, params),
68
- queryFn: async () => {
69
- const result = await ctx.dataProvider.getManyReference(resource, params);
70
- seedRecords(ctx.queryClient, resource, result.data);
71
- return result;
72
- }
73
- };
77
+ return {
78
+ queryKey: manyReferenceKey(resource, params),
79
+ queryFn: async () => {
80
+ const result = await ctx.dataProvider.getManyReference(resource, params);
81
+ seedRecords(ctx.queryClient, resource, result.data);
82
+ return result;
83
+ }
84
+ };
74
85
  }
75
- export {
76
- getInfiniteListOptions,
77
- getListOptions,
78
- getManyOptions,
79
- getManyReferenceOptions,
80
- getOneOptions
81
- };
86
+ export { getInfiniteListOptions, getListOptions, getManyOptions, getManyReferenceOptions, getOneOptions };
@@ -0,0 +1,3 @@
1
+ import type { FilterPayload } from "./types.js";
2
+ /** Strips `''`, `null` and `undefined` values. Always returns a FRESH object. */
3
+ export declare function removeEmpty(filter: FilterPayload): FilterPayload;
@@ -0,0 +1,11 @@
1
+ // src/data/remove-empty.ts
2
+ /** Strips `''`, `null` and `undefined` values. Always returns a FRESH object. */
3
+ function removeEmpty(filter) {
4
+ const result = {};
5
+ for (const [key, value] of Object.entries(filter)) {
6
+ if (value === "" || value === null || value === void 0) continue;
7
+ result[key] = value;
8
+ }
9
+ return result;
10
+ }
11
+ export { removeEmpty };
@@ -1,6 +1,6 @@
1
1
  import { type QueryClient, type QueryKey } from "@tanstack/query-core";
2
2
  import type { Identifier } from "../resource/identifier.js";
3
- import type { ResourceRecord } from "../resource/record.js";
3
+ import type { LooseRecord, ResourceRecord } from "../resource/record.js";
4
4
  import type { DeleteParams, UpdateManyParams, UpdateParams } from "./types.js";
5
5
  /**
6
6
  * A snapshot of the query cache taken BEFORE an optimistic apply: an array of
@@ -102,7 +102,7 @@ export interface UndoableCacheOptions {
102
102
  };
103
103
  }
104
104
  /** Patch `ids` in the `resource` caches now; the notification reads "updated". */
105
- export declare function undoableUpdateOptions(queryClient: QueryClient, resource: string, ids: Identifier[], data: object): UndoableCacheOptions;
105
+ export declare function undoableUpdateOptions<TRecord extends ResourceRecord = LooseRecord>(queryClient: QueryClient, resource: string, ids: Identifier[], data: Partial<NoInfer<TRecord>>): UndoableCacheOptions;
106
106
  /** Remove `ids` from the `resource` caches now; the notification reads "deleted". */
107
107
  export declare function undoableDeleteOptions(queryClient: QueryClient, resource: string, ids: Identifier[]): UndoableCacheOptions;
108
108
  /** The record an undoable update shows at once: the previous one with the patch on top. */