@chelone/core 0.6.0 → 0.9.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 +6 -0
- package/dist/assistant/assistant-session.js +204 -181
- package/dist/assistant/echo-transport.js +26 -29
- package/dist/assistant/http-transport.d.ts +10 -0
- package/dist/assistant/http-transport.js +98 -0
- package/dist/assistant/types.d.ts +1 -7
- package/dist/auth/access-control.d.ts +13 -5
- package/dist/auth/access-control.js +25 -21
- package/dist/auth/auth-options.d.ts +23 -17
- package/dist/auth/auth-options.js +82 -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 +64 -0
- package/dist/block-editor/block-document.js +147 -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.js +46 -44
- package/dist/command-menu/hotkey.js +58 -47
- package/dist/command-menu/recents.d.ts +4 -0
- package/dist/command-menu/recents.js +12 -11
- package/dist/command-menu/registry.d.ts +9 -5
- package/dist/command-menu/registry.js +36 -46
- package/dist/controller/calendar-dates.d.ts +12 -0
- package/dist/controller/calendar-dates.js +94 -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 +43 -0
- package/dist/controller/in-place-editor.js +43 -0
- package/dist/controller/infinite-list-controller.js +219 -189
- package/dist/controller/inspector.d.ts +55 -0
- package/dist/controller/inspector.js +70 -0
- package/dist/controller/job-monitor.d.ts +10 -4
- package/dist/controller/job-monitor.js +46 -47
- package/dist/controller/kanban-board.js +45 -24
- package/dist/controller/list-controller.d.ts +8 -5
- package/dist/controller/list-controller.js +447 -400
- package/dist/controller/list-params.js +96 -87
- package/dist/controller/pivot-grid.d.ts +4 -4
- package/dist/controller/pivot-grid.js +89 -95
- 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 +5 -5
- package/dist/controller/record-timeline.js +42 -30
- 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.d.ts +2 -0
- package/dist/controller/reference-many-controller.js +199 -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 +4 -3
- package/dist/csv/export.js +43 -40
- package/dist/csv/import-controller.d.ts +4 -0
- package/dist/csv/import-controller.js +189 -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 -188
- 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 +135 -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 +22 -2
- package/dist/form/choices-controller.js +315 -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 +171 -118
- package/dist/form/input-values.d.ts +140 -0
- package/dist/form/input-values.js +206 -0
- package/dist/form/json-text.d.ts +11 -0
- package/dist/form/json-text.js +62 -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.d.ts +10 -0
- package/dist/geo/coordinates.js +44 -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 +9 -8
- package/dist/geo/map-layers.d.ts +42 -7
- package/dist/geo/map-layers.js +88 -62
- package/dist/geo/map-style.d.ts +12 -0
- package/dist/geo/map-style.js +43 -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 +44 -0
- package/dist/guards.js +77 -0
- package/dist/i18n/default-messages.js +34 -29
- package/dist/i18n/english-messages.d.ts +172 -0
- package/dist/i18n/english-messages.js +359 -189
- package/dist/i18n/i18n.d.ts +2 -2
- package/dist/i18n/i18n.js +47 -60
- 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 +4 -0
- package/dist/i18n/missing-keys.js +70 -62
- package/dist/i18n/translatable.d.ts +16 -1
- package/dist/i18n/translatable.js +40 -47
- package/dist/index.d.ts +87 -39
- package/dist/index.js +54 -301
- 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 +2 -0
- package/dist/onboarding-tour/placement.js +65 -78
- package/dist/onboarding-tour/tour-controller.js +46 -54
- package/dist/realtime/add-events-for-mutations.js +75 -81
- package/dist/realtime/announce-lock.js +16 -13
- package/dist/realtime/broadcast-channel-transport.js +65 -59
- package/dist/realtime/copy-members.js +22 -14
- package/dist/realtime/in-memory-lock-provider.js +40 -48
- 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 +25 -25
- 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.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.js +62 -71
- 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 +247 -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 +23 -2
- package/dist/rich-text/rich-text-extras.d.ts +134 -0
- package/dist/rich-text/rich-text-extras.js +181 -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 +6 -0
- package/dist/rich-text/rich-text.js +125 -88
- package/dist/router/location.d.ts +24 -4
- package/dist/router/location.js +43 -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/dist/ui-defaults.d.ts +15 -0
- package/dist/ui-defaults.js +17 -0
- package/package.json +13 -11
|
@@ -1,122 +1,143 @@
|
|
|
1
|
+
import { getAtPath } from "../resource/get-at-path.js";
|
|
2
|
+
// src/data/fake-provider.ts
|
|
1
3
|
function applyFilter(rows, filter) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
if (!filter) return rows;
|
|
5
|
+
return rows.filter((row) => Object.entries(filter).every(([key, value]) => getAtPath(row, key) === value));
|
|
6
|
+
}
|
|
7
|
+
/** What `<` reduces a value to: dates by time, booleans and null as numbers. */
|
|
8
|
+
function toComparable(value) {
|
|
9
|
+
if (value instanceof Date) return value.getTime();
|
|
10
|
+
if (typeof value === "number" || typeof value === "string") return value;
|
|
11
|
+
if (typeof value === "boolean") return Number(value);
|
|
12
|
+
if (value === null) return 0;
|
|
13
|
+
return NaN;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Orders as `<` does, coercion included: null sorts as 0, a numeric string
|
|
17
|
+
* against a number compares as a number, and values `<` cannot order
|
|
18
|
+
* (undefined, objects, a non-numeric string against a number) tie.
|
|
19
|
+
*/
|
|
20
|
+
function compareValues(a, b) {
|
|
21
|
+
const x = toComparable(a);
|
|
22
|
+
const y = toComparable(b);
|
|
23
|
+
if (typeof x === "string" && typeof y === "string") {
|
|
24
|
+
if (x < y) return -1;
|
|
25
|
+
return x > y ? 1 : 0;
|
|
26
|
+
}
|
|
27
|
+
const nx = Number(x);
|
|
28
|
+
const ny = Number(y);
|
|
29
|
+
if (nx < ny) return -1;
|
|
30
|
+
return nx > ny ? 1 : 0;
|
|
6
31
|
}
|
|
7
32
|
function applySort(rows, sort) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return 0;
|
|
20
|
-
});
|
|
33
|
+
if (!sort) return rows;
|
|
34
|
+
const keys = Array.isArray(sort) ? sort : [sort];
|
|
35
|
+
if (keys.length === 0) return rows;
|
|
36
|
+
return [...rows].sort((a, b) => {
|
|
37
|
+
for (const { field, order } of keys) {
|
|
38
|
+
const dir = order === "ASC" ? 1 : -1;
|
|
39
|
+
const cmp = compareValues(getAtPath(a, field), getAtPath(b, field));
|
|
40
|
+
if (cmp !== 0) return cmp * dir;
|
|
41
|
+
}
|
|
42
|
+
return 0;
|
|
43
|
+
});
|
|
21
44
|
}
|
|
22
45
|
function paginate(rows, pagination) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
if (!pagination) return {
|
|
47
|
+
data: rows,
|
|
48
|
+
total: rows.length
|
|
49
|
+
};
|
|
50
|
+
if ("page" in pagination) {
|
|
51
|
+
const start = (pagination.page - 1) * pagination.perPage;
|
|
52
|
+
return {
|
|
53
|
+
data: rows.slice(start, start + pagination.perPage),
|
|
54
|
+
total: rows.length
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const offset = pagination.cursor === null ? 0 : Number(pagination.cursor);
|
|
58
|
+
const data = rows.slice(offset, offset + pagination.limit);
|
|
59
|
+
const next = offset + pagination.limit;
|
|
60
|
+
return {
|
|
61
|
+
data,
|
|
62
|
+
total: rows.length,
|
|
63
|
+
pageInfo: {
|
|
64
|
+
nextCursor: next < rows.length ? String(next) : null,
|
|
65
|
+
prevCursor: offset > 0 ? String(Math.max(0, offset - pagination.limit)) : null,
|
|
66
|
+
hasNextPage: next < rows.length,
|
|
67
|
+
hasPreviousPage: offset > 0
|
|
68
|
+
}
|
|
69
|
+
};
|
|
44
70
|
}
|
|
71
|
+
/** In-memory DataProvider for tests and dogfooding. Mutates its own copy of the seed. */
|
|
45
72
|
function fakeDataProvider(initialData) {
|
|
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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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
|
-
return { data: params.ids };
|
|
117
|
-
}
|
|
118
|
-
};
|
|
73
|
+
const store = structuredClone(initialData);
|
|
74
|
+
const table = (resource) => {
|
|
75
|
+
const rows = store[resource];
|
|
76
|
+
if (rows) return rows;
|
|
77
|
+
if (!Object.hasOwn(store, resource)) throw new Error(`fakeDataProvider: unknown resource "${resource}"`);
|
|
78
|
+
const empty = [];
|
|
79
|
+
store[resource] = empty;
|
|
80
|
+
return empty;
|
|
81
|
+
};
|
|
82
|
+
const find = (resource, id) => {
|
|
83
|
+
const row = table(resource).find((r) => String(r.id) === String(id));
|
|
84
|
+
if (!row) throw new Error(`fakeDataProvider: ${resource}#${String(id)} not found`);
|
|
85
|
+
return row;
|
|
86
|
+
};
|
|
87
|
+
let nextId = 1e6;
|
|
88
|
+
const listLike = (rows, params) => {
|
|
89
|
+
const page = paginate(applySort(applyFilter(rows, params.filter), params.sort), params.pagination);
|
|
90
|
+
return {
|
|
91
|
+
...page,
|
|
92
|
+
data: structuredClone(page.data)
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
return {
|
|
96
|
+
async getList(resource, params) {
|
|
97
|
+
return listLike(table(resource), params);
|
|
98
|
+
},
|
|
99
|
+
async getOne(resource, params) {
|
|
100
|
+
return { data: structuredClone(find(resource, params.id)) };
|
|
101
|
+
},
|
|
102
|
+
async getMany(resource, params) {
|
|
103
|
+
return { data: params.ids.map((id) => structuredClone(find(resource, id))) };
|
|
104
|
+
},
|
|
105
|
+
async getManyReference(resource, params) {
|
|
106
|
+
const rows = table(resource).filter((r) => String(getAtPath(r, params.target)) === String(params.id));
|
|
107
|
+
return listLike(rows, params);
|
|
108
|
+
},
|
|
109
|
+
async create(resource, params) {
|
|
110
|
+
const row = {
|
|
111
|
+
id: nextId++,
|
|
112
|
+
...structuredClone(params.data)
|
|
113
|
+
};
|
|
114
|
+
table(resource).push(row);
|
|
115
|
+
return { data: structuredClone(row) };
|
|
116
|
+
},
|
|
117
|
+
async update(resource, params) {
|
|
118
|
+
const row = find(resource, params.id);
|
|
119
|
+
Object.assign(row, structuredClone(params.data));
|
|
120
|
+
return { data: structuredClone(row) };
|
|
121
|
+
},
|
|
122
|
+
async updateMany(resource, params) {
|
|
123
|
+
for (const id of params.ids) Object.assign(find(resource, id), structuredClone(params.data));
|
|
124
|
+
return { data: params.ids };
|
|
125
|
+
},
|
|
126
|
+
async delete(resource, params) {
|
|
127
|
+
const rows = table(resource);
|
|
128
|
+
const idx = rows.findIndex((r) => String(r.id) === String(params.id));
|
|
129
|
+
const removed = idx === -1 ? void 0 : rows.splice(idx, 1)[0];
|
|
130
|
+
if (!removed) throw new Error(`fakeDataProvider: ${resource}#${String(params.id)} not found`);
|
|
131
|
+
return { data: structuredClone(removed) };
|
|
132
|
+
},
|
|
133
|
+
async deleteMany(resource, params) {
|
|
134
|
+
for (const id of params.ids) {
|
|
135
|
+
const rows = table(resource);
|
|
136
|
+
const idx = rows.findIndex((r) => String(r.id) === String(id));
|
|
137
|
+
if (idx !== -1) rows.splice(idx, 1);
|
|
138
|
+
}
|
|
139
|
+
return { data: params.ids };
|
|
140
|
+
}
|
|
141
|
+
};
|
|
119
142
|
}
|
|
120
|
-
export {
|
|
121
|
-
fakeDataProvider
|
|
122
|
-
};
|
|
143
|
+
export { fakeDataProvider };
|
package/dist/data/fetch-utils.js
CHANGED
|
@@ -1,56 +1,73 @@
|
|
|
1
1
|
import { HttpError } from "./http-error.js";
|
|
2
|
+
// src/data/fetch-utils.ts
|
|
2
3
|
function parseJson(text) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
try {
|
|
5
|
+
return JSON.parse(text);
|
|
6
|
+
} catch {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
8
9
|
}
|
|
9
10
|
function errorMessage(json, response) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
const message = json != null && typeof json === "object" ? json.message : void 0;
|
|
12
|
+
if (typeof message === "string") return message;
|
|
13
|
+
return response.statusText || `HTTP ${response.status}`;
|
|
13
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* A thin call to the global `fetch`.
|
|
17
|
+
*
|
|
18
|
+
* - Resolves `{ status, statusText, headers, body, json }` on a 2xx; `json` is
|
|
19
|
+
* `undefined` when the text is not JSON.
|
|
20
|
+
* - Rejects a non-2xx with an `HttpError` whose `body` is the parsed JSON.
|
|
21
|
+
* - Rejects a network failure with the error `fetch` threw, unchanged.
|
|
22
|
+
* - Sets `Accept: application/json`, and `Content-Type: application/json` for
|
|
23
|
+
* a string `body` when the caller set none.
|
|
24
|
+
* - A non-empty `token` is sent as `Authorization: Bearer <token>` and wins
|
|
25
|
+
* over an `Authorization` header in `options.headers`; an empty one is
|
|
26
|
+
* ignored.
|
|
27
|
+
*/
|
|
14
28
|
async function fetchJson(url, options = {}) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
};
|
|
29
|
+
const { token, ...init } = options;
|
|
30
|
+
const headers = new Headers(init.headers);
|
|
31
|
+
if (!headers.has("Accept")) headers.set("Accept", "application/json");
|
|
32
|
+
if (typeof init.body === "string" && !headers.has("Content-Type")) headers.set("Content-Type", "application/json");
|
|
33
|
+
if (token) headers.set("Authorization", `Bearer ${token}`);
|
|
34
|
+
const response = await fetch(url, {
|
|
35
|
+
...init,
|
|
36
|
+
headers
|
|
37
|
+
});
|
|
38
|
+
const body = await response.text();
|
|
39
|
+
const json = parseJson(body);
|
|
40
|
+
if (!response.ok) throw new HttpError(errorMessage(json, response), response.status, json);
|
|
41
|
+
return {
|
|
42
|
+
status: response.status,
|
|
43
|
+
statusText: response.statusText,
|
|
44
|
+
headers: response.headers,
|
|
45
|
+
body,
|
|
46
|
+
json
|
|
47
|
+
};
|
|
35
48
|
}
|
|
36
49
|
function encodeValue(value) {
|
|
37
|
-
|
|
38
|
-
|
|
50
|
+
if (value instanceof Date) return value.toISOString();
|
|
51
|
+
return typeof value === "object" ? JSON.stringify(value) : String(value);
|
|
39
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Builds a query string (no leading `?`). Skips `undefined` and `null`,
|
|
55
|
+
* repeats the key for an array, writes a `Date` as its ISO string and
|
|
56
|
+
* JSON-encodes any other object.
|
|
57
|
+
*/
|
|
40
58
|
function queryParameters(params) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
return parts.join("&");
|
|
59
|
+
const parts = [];
|
|
60
|
+
for (const [key, value] of Object.entries(params)) {
|
|
61
|
+
const values = Array.isArray(value) ? value : [value];
|
|
62
|
+
for (const item of values) {
|
|
63
|
+
if (item === void 0 || item === null) continue;
|
|
64
|
+
parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(encodeValue(item))}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return parts.join("&");
|
|
52
68
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
69
|
+
var fetchUtils = {
|
|
70
|
+
fetchJson,
|
|
71
|
+
queryParameters
|
|
56
72
|
};
|
|
73
|
+
export { fetchUtils };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { isRecord } from "../guards.js";
|
|
2
|
+
// src/data/filter-branch.ts
|
|
3
|
+
/**
|
|
4
|
+
* Does a filter value nest, so a walker descends into it? An object that is
|
|
5
|
+
* not an array and not a Date. Not the prototype check: a class instance nests.
|
|
6
|
+
*/
|
|
7
|
+
function isFilterBranch(value) {
|
|
8
|
+
return isRecord(value) && !(value instanceof Date);
|
|
9
|
+
}
|
|
10
|
+
export { isFilterBranch };
|
|
@@ -1,85 +1,93 @@
|
|
|
1
|
-
import { hashKey } from "@tanstack/query-core";
|
|
2
1
|
import { manyKey, oneKey } from "./keys.js";
|
|
3
|
-
|
|
2
|
+
import { hashKey } from "@tanstack/query-core";
|
|
3
|
+
// src/data/get-many-aggregate.ts
|
|
4
|
+
/**
|
|
5
|
+
* One pending batch per resource and meta, per provider. A flushed batch leaves
|
|
6
|
+
* the map. Contexts that share a provider share a batch, so the flush seeds the
|
|
7
|
+
* cache of every caller's `queryClient`.
|
|
8
|
+
*/
|
|
9
|
+
var pending = /* @__PURE__ */ new WeakMap();
|
|
4
10
|
function flush(ctx, batchKey, batch) {
|
|
5
|
-
|
|
6
|
-
|
|
11
|
+
pending.get(ctx.dataProvider)?.delete(batchKey);
|
|
12
|
+
settle(ctx, batch);
|
|
7
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Every failure on the way, a synchronous throw from the provider or a
|
|
16
|
+
* malformed result included, rejects the whole batch. Rejecting a caller that
|
|
17
|
+
* already resolved is a no-op.
|
|
18
|
+
*/
|
|
8
19
|
async function settle(ctx, batch) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
caller.resolve([...own.values()]);
|
|
32
|
-
}
|
|
33
|
-
} catch (error) {
|
|
34
|
-
for (const caller of batch.callers) caller.reject(error);
|
|
35
|
-
}
|
|
20
|
+
try {
|
|
21
|
+
const provider = ctx.dataProvider;
|
|
22
|
+
const params = { ids: [...batch.ids.values()] };
|
|
23
|
+
if (batch.meta !== void 0) params.meta = batch.meta;
|
|
24
|
+
const result = await provider.getMany(batch.resource, params);
|
|
25
|
+
const queryClients = new Set(batch.callers.map((c) => c.queryClient));
|
|
26
|
+
const byId = /* @__PURE__ */ new Map();
|
|
27
|
+
for (const record of result.data) {
|
|
28
|
+
byId.set(String(record.id), record);
|
|
29
|
+
for (const queryClient of queryClients) queryClient.setQueryData(oneKey(batch.resource, { id: record.id }), record);
|
|
30
|
+
}
|
|
31
|
+
for (const caller of batch.callers) {
|
|
32
|
+
const own = /* @__PURE__ */ new Map();
|
|
33
|
+
for (const id of caller.ids) {
|
|
34
|
+
const record = byId.get(String(id));
|
|
35
|
+
if (record) own.set(String(id), record);
|
|
36
|
+
}
|
|
37
|
+
caller.resolve([...own.values()]);
|
|
38
|
+
}
|
|
39
|
+
} catch (error) {
|
|
40
|
+
for (const caller of batch.callers) caller.reject(error);
|
|
41
|
+
}
|
|
36
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Joins the pending batch for this provider, resource and `meta`, opening it
|
|
45
|
+
* and scheduling its `setTimeout(0)` flush if there is none. Resolves once the
|
|
46
|
+
* flush has the provider's answer, with this caller's own records in its own id
|
|
47
|
+
* order, repeated ids once and ids the provider omitted left out. Rejects with
|
|
48
|
+
* the batch's error.
|
|
49
|
+
*/
|
|
37
50
|
function enqueue(ctx, resource, params) {
|
|
38
|
-
|
|
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
|
-
});
|
|
51
|
+
const batchKey = hashKey([resource, { meta: params.meta }]);
|
|
52
|
+
let batches = pending.get(ctx.dataProvider);
|
|
53
|
+
if (!batches) {
|
|
54
|
+
batches = /* @__PURE__ */ new Map();
|
|
55
|
+
pending.set(ctx.dataProvider, batches);
|
|
56
|
+
}
|
|
57
|
+
let batch = batches.get(batchKey);
|
|
58
|
+
if (!batch) {
|
|
59
|
+
const created = {
|
|
60
|
+
resource,
|
|
61
|
+
meta: params.meta,
|
|
62
|
+
ids: /* @__PURE__ */ new Map(),
|
|
63
|
+
callers: []
|
|
64
|
+
};
|
|
65
|
+
batch = created;
|
|
66
|
+
batches.set(batchKey, created);
|
|
67
|
+
setTimeout(() => flush(ctx, batchKey, created), 0);
|
|
68
|
+
}
|
|
69
|
+
for (const id of params.ids) if (!batch.ids.has(String(id))) batch.ids.set(String(id), id);
|
|
70
|
+
const target = batch;
|
|
71
|
+
return new Promise((resolve, reject) => {
|
|
72
|
+
target.callers.push({
|
|
73
|
+
queryClient: ctx.queryClient,
|
|
74
|
+
ids: [...params.ids],
|
|
75
|
+
resolve,
|
|
76
|
+
reject
|
|
77
|
+
});
|
|
78
|
+
});
|
|
68
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Same signature and result as `getManyOptions`, but reads started in the same
|
|
82
|
+
* tick reach the data provider as one `getMany` per resource and `meta`.
|
|
83
|
+
*/
|
|
69
84
|
function getManyAggregateOptions(ctx, resource, params) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
params
|
|
78
|
-
);
|
|
79
|
-
return records;
|
|
80
|
-
}
|
|
81
|
-
};
|
|
85
|
+
return {
|
|
86
|
+
queryKey: manyKey(resource, params),
|
|
87
|
+
queryFn: async () => {
|
|
88
|
+
if (params.ids.length === 0) return [];
|
|
89
|
+
return await enqueue(ctx, resource, params);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
82
92
|
}
|
|
83
|
-
export {
|
|
84
|
-
getManyAggregateOptions
|
|
85
|
-
};
|
|
93
|
+
export { getManyAggregateOptions };
|
package/dist/data/http-error.js
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
// src/data/http-error.ts
|
|
2
|
+
/**
|
|
3
|
+
* Rejected by `fetchUtils.fetchJson` on a non-2xx response. `status` is what
|
|
4
|
+
* `authProvider.checkError` reads to log a user out on 401/403; `body` is the
|
|
5
|
+
* parsed response body (a provider maps a 422 onto `ValidationError` from it).
|
|
6
|
+
* Framework-free by design.
|
|
7
|
+
*/
|
|
8
|
+
var HttpError = class extends Error {
|
|
9
|
+
name = "HttpError";
|
|
10
|
+
status;
|
|
11
|
+
body;
|
|
12
|
+
constructor(message, status, body) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.status = status;
|
|
15
|
+
this.body = body;
|
|
16
|
+
}
|
|
13
17
|
};
|
|
18
|
+
export { HttpError };
|