@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.
- package/dist/assistant/assistant-session.d.ts +28 -0
- package/dist/assistant/assistant-session.js +208 -0
- package/dist/assistant/echo-transport.d.ts +7 -0
- package/dist/assistant/echo-transport.js +28 -0
- package/dist/assistant/http-transport.d.ts +10 -0
- package/dist/assistant/http-transport.js +98 -0
- package/dist/assistant/types.d.ts +54 -0
- package/dist/auth/access-control.d.ts +13 -5
- package/dist/auth/access-control.js +25 -21
- package/dist/auth/auth-options.d.ts +21 -17
- package/dist/auth/auth-options.js +80 -48
- package/dist/auth/permission-matrix.d.ts +12 -0
- package/dist/auth/permission-matrix.js +67 -0
- package/dist/auth/types.d.ts +14 -4
- package/dist/block-editor/block-document.d.ts +60 -0
- package/dist/block-editor/block-document.js +143 -0
- package/dist/block-editor/data-blocks.d.ts +63 -0
- package/dist/block-editor/data-blocks.js +117 -0
- package/dist/chart/chart-data.d.ts +25 -0
- package/dist/chart/chart-data.js +61 -0
- package/dist/command-menu/hotkey.js +58 -47
- package/dist/command-menu/recents.js +8 -11
- package/dist/command-menu/registry.d.ts +9 -5
- package/dist/command-menu/registry.js +36 -46
- package/dist/controller/calendar-dates.js +82 -113
- package/dist/controller/calendar-events.js +93 -88
- package/dist/controller/client-list-controller.d.ts +2 -2
- package/dist/controller/client-list-controller.js +251 -254
- package/dist/controller/data-table-columns.d.ts +2 -0
- package/dist/controller/data-table-columns.js +50 -56
- package/dist/controller/deep-equal.d.ts +1 -0
- package/dist/controller/deep-equal.js +14 -0
- package/dist/controller/filter-toggle.js +36 -44
- package/dist/controller/in-place-editor.d.ts +42 -0
- package/dist/controller/in-place-editor.js +42 -0
- package/dist/controller/infinite-list-controller.js +220 -190
- package/dist/controller/inspector.d.ts +49 -0
- package/dist/controller/inspector.js +64 -0
- package/dist/controller/job-monitor.d.ts +41 -0
- package/dist/controller/job-monitor.js +49 -0
- package/dist/controller/kanban-board.d.ts +2 -3
- package/dist/controller/kanban-board.js +43 -24
- package/dist/controller/list-controller.d.ts +5 -5
- package/dist/controller/list-controller.js +444 -400
- package/dist/controller/list-params.js +96 -87
- package/dist/controller/pivot-grid.d.ts +36 -0
- package/dist/controller/pivot-grid.js +99 -0
- package/dist/controller/prev-next.d.ts +2 -2
- package/dist/controller/prev-next.js +74 -54
- package/dist/controller/record-controllers.d.ts +14 -6
- package/dist/controller/record-controllers.js +288 -257
- package/dist/controller/record-diff.d.ts +21 -0
- package/dist/controller/record-diff.js +50 -0
- package/dist/controller/record-timeline.d.ts +35 -0
- package/dist/controller/record-timeline.js +48 -0
- package/dist/controller/record-tree.js +57 -47
- package/dist/controller/record-workflow.d.ts +38 -16
- package/dist/controller/record-workflow.js +85 -64
- package/dist/controller/reference-many-controller.js +198 -192
- package/dist/controller/reference-one-controller.d.ts +1 -1
- package/dist/controller/reference-one-controller.js +63 -56
- package/dist/controller/saved-queries.js +104 -91
- package/dist/controller/translate-fallback.js +10 -6
- package/dist/csv/export.d.ts +2 -1
- package/dist/csv/export.js +43 -40
- package/dist/csv/import-controller.js +185 -169
- package/dist/csv/match-headers.js +29 -22
- package/dist/csv/parse-with.js +60 -54
- package/dist/csv/run-import.js +69 -72
- package/dist/csv/validate-rows.d.ts +1 -1
- package/dist/csv/validate-rows.js +65 -52
- package/dist/data/cache-ops.d.ts +5 -4
- package/dist/data/cache-ops.js +208 -190
- package/dist/data/combine-data-providers.js +25 -23
- package/dist/data/data-provider-log.d.ts +45 -0
- package/dist/data/data-provider-log.js +93 -0
- package/dist/data/errors.js +14 -10
- package/dist/data/fake-provider.d.ts +6 -3
- package/dist/data/fake-provider.js +129 -114
- package/dist/data/fetch-utils.js +61 -44
- package/dist/data/filter-branch.d.ts +5 -0
- package/dist/data/filter-branch.js +10 -0
- package/dist/data/get-many-aggregate.js +84 -76
- package/dist/data/http-error.js +17 -12
- package/dist/data/keys.js +50 -36
- package/dist/data/mutation-options.d.ts +14 -9
- package/dist/data/mutation-options.js +93 -109
- package/dist/data/query-options.js +73 -68
- package/dist/data/remove-empty.d.ts +3 -0
- package/dist/data/remove-empty.js +11 -0
- package/dist/data/undoable.d.ts +2 -2
- package/dist/data/undoable.js +190 -174
- package/dist/data/with-lifecycle-callbacks.d.ts +45 -17
- package/dist/data/with-lifecycle-callbacks.js +66 -52
- package/dist/environment/application-update-store.js +58 -55
- package/dist/environment/offline-store.js +21 -21
- package/dist/form/array-binding.d.ts +30 -11
- package/dist/form/array-binding.js +184 -166
- package/dist/form/choice-ids.d.ts +7 -0
- package/dist/form/choice-ids.js +11 -0
- package/dist/form/choices-controller.d.ts +3 -2
- package/dist/form/choices-controller.js +302 -275
- package/dist/form/date-format.d.ts +38 -0
- package/dist/form/date-format.js +89 -0
- package/dist/form/dirty-values.d.ts +2 -2
- package/dist/form/dirty-values.js +22 -11
- package/dist/form/duration.d.ts +22 -0
- package/dist/form/duration.js +49 -0
- package/dist/form/edit-create-form.d.ts +12 -5
- package/dist/form/edit-create-form.js +243 -188
- package/dist/form/event-value.d.ts +6 -0
- package/dist/form/event-value.js +17 -0
- package/dist/form/field-error.d.ts +14 -0
- package/dist/form/field-error.js +28 -0
- package/dist/form/field-name.d.ts +20 -0
- package/dist/form/field-name.js +6 -0
- package/dist/form/filter-form-values.js +63 -49
- package/dist/form/form-controller.d.ts +9 -1
- package/dist/form/form-controller.js +165 -160
- package/dist/form/form-groups.d.ts +4 -3
- package/dist/form/form-groups.js +79 -79
- package/dist/form/form-handle.d.ts +175 -0
- package/dist/form/form-handle.js +68 -0
- package/dist/form/input-binding.d.ts +56 -31
- package/dist/form/input-binding.js +169 -118
- package/dist/form/input-values.d.ts +130 -0
- package/dist/form/input-values.js +177 -0
- package/dist/form/json-text.js +51 -37
- package/dist/form/save-pipeline.d.ts +6 -8
- package/dist/form/save-pipeline.js +91 -82
- package/dist/form/set-form-values.d.ts +6 -0
- package/dist/form/set-form-values.js +10 -0
- package/dist/form/source.js +97 -65
- package/dist/form/text-of.d.ts +2 -0
- package/dist/form/text-of.js +7 -0
- package/dist/form/validators.d.ts +58 -19
- package/dist/form/validators.js +97 -71
- package/dist/geo/bbox.d.ts +5 -4
- package/dist/geo/bbox.js +69 -48
- package/dist/geo/bounds.d.ts +14 -3
- package/dist/geo/bounds.js +98 -68
- package/dist/geo/constraints.js +88 -93
- package/dist/geo/coordinates.js +31 -23
- package/dist/geo/editor.d.ts +13 -13
- package/dist/geo/editor.js +176 -153
- package/dist/geo/geocoding.d.ts +4 -4
- package/dist/geo/geocoding.js +38 -41
- package/dist/geo/geojson.d.ts +12 -74
- package/dist/geo/geojson.js +52 -40
- package/dist/geo/geometry-math.d.ts +4 -4
- package/dist/geo/geometry-math.js +100 -93
- package/dist/geo/index.d.ts +7 -6
- package/dist/geo/map-layers.d.ts +42 -7
- package/dist/geo/map-layers.js +88 -62
- package/dist/geo/map-style.js +31 -32
- package/dist/geo/messages.js +48 -45
- package/dist/geo/nominatim.js +88 -80
- package/dist/geo/osm-presets.d.ts +4 -3
- package/dist/geo/osm-presets.js +108 -86
- package/dist/geo/osm-tags.js +14 -12
- package/dist/geo/overpass.d.ts +14 -2
- package/dist/geo/overpass.js +83 -90
- package/dist/geo/shape-value.d.ts +9 -5
- package/dist/geo/shape-value.js +169 -146
- package/dist/geo/snap-to-roads.d.ts +3 -3
- package/dist/geo/snap-to-roads.js +55 -50
- package/dist/geo/throttle.js +36 -39
- package/dist/guards.d.ts +37 -0
- package/dist/guards.js +62 -0
- package/dist/i18n/default-messages.js +34 -29
- package/dist/i18n/english-messages.js +187 -189
- package/dist/i18n/i18n.d.ts +8 -2
- package/dist/i18n/i18n.js +47 -48
- package/dist/i18n/inflection.d.ts +34 -0
- package/dist/i18n/inflection.js +82 -0
- package/dist/i18n/messages.d.ts +10 -2
- package/dist/i18n/messages.js +17 -4
- package/dist/i18n/missing-keys.d.ts +19 -0
- package/dist/i18n/missing-keys.js +68 -0
- package/dist/i18n/translatable.d.ts +16 -1
- package/dist/i18n/translatable.js +40 -47
- package/dist/index.d.ts +96 -22
- package/dist/index.js +52 -257
- package/dist/json/deep-equal.d.ts +8 -0
- package/dist/json/deep-equal.js +24 -0
- package/dist/json/strip-json-comments.js +38 -42
- package/dist/noop.d.ts +2 -0
- package/dist/noop.js +4 -0
- package/dist/notification/error-message.d.ts +2 -0
- package/dist/notification/error-message.js +10 -0
- package/dist/notification/notification-store.d.ts +3 -2
- package/dist/notification/notification-store.js +41 -45
- package/dist/onboarding-tour/placement.d.ts +34 -0
- package/dist/onboarding-tour/placement.js +67 -0
- package/dist/onboarding-tour/tour-controller.d.ts +25 -0
- package/dist/onboarding-tour/tour-controller.js +50 -0
- package/dist/realtime/add-events-for-mutations.js +75 -81
- package/dist/realtime/announce-lock.d.ts +7 -0
- package/dist/realtime/announce-lock.js +18 -0
- package/dist/realtime/broadcast-channel-transport.d.ts +14 -0
- package/dist/realtime/broadcast-channel-transport.js +69 -0
- package/dist/realtime/copy-members.js +22 -14
- package/dist/realtime/in-memory-lock-provider.js +41 -60
- package/dist/realtime/live.js +95 -101
- package/dist/realtime/lock-options.js +16 -16
- package/dist/realtime/lock-session.js +91 -78
- package/dist/realtime/memory-transport.js +26 -67
- package/dist/realtime/presence.js +120 -122
- package/dist/realtime/realtime-data-provider.d.ts +10 -0
- package/dist/realtime/realtime-data-provider.js +45 -42
- package/dist/realtime/reconnect-backoff.d.ts +15 -0
- package/dist/realtime/reconnect-backoff.js +17 -0
- package/dist/realtime/sse-transport.d.ts +31 -0
- package/dist/realtime/sse-transport.js +235 -0
- package/dist/realtime/status-store.js +23 -28
- package/dist/realtime/topic-hub.d.ts +24 -0
- package/dist/realtime/topic-hub.js +66 -0
- package/dist/realtime/topics.js +10 -12
- package/dist/realtime/types.js +10 -12
- package/dist/realtime/unread-count.js +21 -21
- package/dist/realtime/websocket-transport.d.ts +32 -0
- package/dist/realtime/websocket-transport.js +306 -0
- package/dist/resource/describe-resource.d.ts +2 -0
- package/dist/resource/describe-resource.js +232 -219
- package/dist/resource/get-at-path.js +29 -14
- package/dist/resource/identifier.d.ts +18 -0
- package/dist/resource/identifier.js +27 -0
- package/dist/resource/record.d.ts +4 -0
- package/dist/resource/record.js +10 -0
- package/dist/resource/register.d.ts +7 -0
- package/dist/resource/registry-store.d.ts +45 -15
- package/dist/resource/registry-store.js +67 -60
- package/dist/resource/registry.d.ts +10 -0
- package/dist/resource/registry.js +8 -4
- package/dist/resource/source-path.d.ts +16 -1
- package/dist/rich-text/rich-text-extras.d.ts +132 -0
- package/dist/rich-text/rich-text-extras.js +179 -0
- package/dist/rich-text/rich-text-image.d.ts +124 -0
- package/dist/rich-text/rich-text-image.js +163 -0
- package/dist/rich-text/rich-text.d.ts +62 -0
- package/dist/rich-text/rich-text.js +142 -0
- package/dist/router/location.d.ts +22 -4
- package/dist/router/location.js +41 -18
- package/dist/router/match.js +47 -39
- package/dist/router/paths.js +40 -34
- package/dist/router/record-from-location.d.ts +1 -1
- package/dist/router/record-from-location.js +25 -17
- package/dist/store/adapters.js +51 -55
- package/dist/store/micro-store.js +57 -59
- package/dist/store/shallow-equal.d.ts +12 -0
- package/dist/store/shallow-equal.js +20 -0
- package/dist/store/store.js +54 -57
- 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
|
-
|
|
4
|
+
return [resource];
|
|
3
5
|
}
|
|
4
6
|
function listKey(resource, params = {}) {
|
|
5
|
-
|
|
7
|
+
return [
|
|
8
|
+
resource,
|
|
9
|
+
"getList",
|
|
10
|
+
params
|
|
11
|
+
];
|
|
6
12
|
}
|
|
7
13
|
function infiniteListKey(resource, params) {
|
|
8
|
-
|
|
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
|
-
|
|
22
|
+
return [resource, "getInfiniteList"];
|
|
12
23
|
}
|
|
13
24
|
function oneKey(resource, params) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
47
|
+
return [resource, "getMany"];
|
|
30
48
|
}
|
|
31
49
|
function manyReferenceKey(resource, params) {
|
|
32
|
-
|
|
50
|
+
return [
|
|
51
|
+
resource,
|
|
52
|
+
"getManyReference",
|
|
53
|
+
params
|
|
54
|
+
];
|
|
33
55
|
}
|
|
34
56
|
function lockKey(resource, params) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
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<[
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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:
|
|
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:
|
|
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 {
|
|
2
|
-
import { oneKey, resourceKey
|
|
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
|
-
|
|
5
|
+
return ctx.queryClient.invalidateQueries({ queryKey: resourceKey(resource) });
|
|
5
6
|
}
|
|
6
|
-
|
|
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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
22
|
-
|
|
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
|
-
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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
|
-
|
|
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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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,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 };
|
package/dist/data/undoable.d.ts
CHANGED
|
@@ -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:
|
|
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. */
|