@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,63 +1,69 @@
|
|
|
1
1
|
import { createTopicHub } from "./topic-hub.js";
|
|
2
|
+
// src/realtime/broadcast-channel-transport.ts
|
|
2
3
|
function isEnvelope(value) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
if (typeof value !== "object" || value === null) return false;
|
|
5
|
+
if (!("topic" in value) || typeof value.topic !== "string") return false;
|
|
6
|
+
if (!("event" in value)) return false;
|
|
7
|
+
const { event } = value;
|
|
8
|
+
return typeof event === "object" && event !== null && "type" in event && typeof event.type === "string";
|
|
8
9
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
10
|
+
/** Carries realtime events between the tabs of one browser, with no server. */
|
|
11
|
+
function broadcastChannelTransport({ channel, onError }) {
|
|
12
|
+
if (typeof BroadcastChannel === "undefined") throw new Error("broadcastChannelTransport needs the global BroadcastChannel, which this environment does not have.");
|
|
13
|
+
const hub = createTopicHub({ onError });
|
|
14
|
+
const broadcast = new BroadcastChannel(channel);
|
|
15
|
+
let closed = false;
|
|
16
|
+
const onMessage = (message) => {
|
|
17
|
+
if (!isEnvelope(message.data)) {
|
|
18
|
+
hub.report({
|
|
19
|
+
kind: "parse_failed",
|
|
20
|
+
cause: message.data,
|
|
21
|
+
retrying: false
|
|
22
|
+
});
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const { topic, event } = message.data;
|
|
26
|
+
hub.dispatch({
|
|
27
|
+
payload: void 0,
|
|
28
|
+
...event,
|
|
29
|
+
topic
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
broadcast.addEventListener("message", onMessage);
|
|
33
|
+
return {
|
|
34
|
+
subscribe: hub.subscribe,
|
|
35
|
+
async publish(topic, event) {
|
|
36
|
+
if (closed) throw new Error("broadcastChannelTransport is closed");
|
|
37
|
+
try {
|
|
38
|
+
broadcast.postMessage({
|
|
39
|
+
topic,
|
|
40
|
+
event
|
|
41
|
+
});
|
|
42
|
+
} catch (cause) {
|
|
43
|
+
hub.report({
|
|
44
|
+
kind: "send_failed",
|
|
45
|
+
topic,
|
|
46
|
+
cause,
|
|
47
|
+
retrying: false
|
|
48
|
+
});
|
|
49
|
+
throw cause;
|
|
50
|
+
}
|
|
51
|
+
hub.dispatch({
|
|
52
|
+
...event,
|
|
53
|
+
topic
|
|
54
|
+
});
|
|
55
|
+
},
|
|
56
|
+
onReconnect: hub.onReconnect,
|
|
57
|
+
onStatusChange: hub.onStatusChange,
|
|
58
|
+
onError: hub.onError,
|
|
59
|
+
getStatus: hub.getStatus,
|
|
60
|
+
close() {
|
|
61
|
+
if (closed) return;
|
|
62
|
+
closed = true;
|
|
63
|
+
broadcast.removeEventListener("message", onMessage);
|
|
64
|
+
broadcast.close();
|
|
65
|
+
hub.setStatus("disconnected");
|
|
66
|
+
}
|
|
67
|
+
};
|
|
60
68
|
}
|
|
61
|
-
export {
|
|
62
|
-
broadcastChannelTransport
|
|
63
|
-
};
|
|
69
|
+
export { broadcastChannelTransport };
|
|
@@ -1,16 +1,24 @@
|
|
|
1
|
+
// src/realtime/copy-members.ts
|
|
2
|
+
/**
|
|
3
|
+
* A copy of `source` that keeps what a spread drops: methods on the prototype
|
|
4
|
+
* chain of a class instance, bound to `source` so they still see its state.
|
|
5
|
+
*/
|
|
1
6
|
function copyMembers(source) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
const copy = { ...source };
|
|
8
|
+
let proto = Object.getPrototypeOf(source);
|
|
9
|
+
while (proto && proto !== Object.prototype) {
|
|
10
|
+
for (const key of Reflect.ownKeys(proto)) {
|
|
11
|
+
if (key === "constructor" || Object.hasOwn(copy, key)) continue;
|
|
12
|
+
const { value } = Object.getOwnPropertyDescriptor(proto, key) ?? {};
|
|
13
|
+
if (typeof value === "function") Object.defineProperty(copy, key, {
|
|
14
|
+
value: value.bind(source),
|
|
15
|
+
writable: true,
|
|
16
|
+
enumerable: true,
|
|
17
|
+
configurable: true
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
proto = Object.getPrototypeOf(proto);
|
|
21
|
+
}
|
|
22
|
+
return copy;
|
|
13
23
|
}
|
|
14
|
-
export {
|
|
15
|
-
copyMembers
|
|
16
|
-
};
|
|
24
|
+
export { copyMembers };
|
|
@@ -1,51 +1,43 @@
|
|
|
1
1
|
import { announceLock } from "./announce-lock.js";
|
|
2
2
|
import { LockConflictError } from "./types.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
} = {}) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
return store.get(storeKey(resource, id)) ?? null;
|
|
43
|
-
},
|
|
44
|
-
async getLocks(resource) {
|
|
45
|
-
return [...store.values()].filter((lock) => lock.resource === resource);
|
|
46
|
-
}
|
|
47
|
-
};
|
|
3
|
+
// src/realtime/in-memory-lock-provider.ts
|
|
4
|
+
var storeKey = (resource, id) => JSON.stringify([resource, String(id)]);
|
|
5
|
+
/** A `LockProvider` kept in a `Map`, for tests and demos. */
|
|
6
|
+
function inMemoryLockProvider({ publisher } = {}) {
|
|
7
|
+
const store = /* @__PURE__ */ new Map();
|
|
8
|
+
return {
|
|
9
|
+
async lock(resource, { id, identity }) {
|
|
10
|
+
const key = storeKey(resource, id);
|
|
11
|
+
const existing = store.get(key);
|
|
12
|
+
if (existing) {
|
|
13
|
+
if (String(existing.identity) !== String(identity)) throw new LockConflictError(existing);
|
|
14
|
+
return existing;
|
|
15
|
+
}
|
|
16
|
+
const lock = {
|
|
17
|
+
resource,
|
|
18
|
+
recordId: id,
|
|
19
|
+
identity,
|
|
20
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
21
|
+
};
|
|
22
|
+
store.set(key, lock);
|
|
23
|
+
await announceLock(publisher, "locked", lock);
|
|
24
|
+
return lock;
|
|
25
|
+
},
|
|
26
|
+
async unlock(resource, { id, identity }) {
|
|
27
|
+
const key = storeKey(resource, id);
|
|
28
|
+
const existing = store.get(key);
|
|
29
|
+
if (!existing) throw new Error(`No lock on ${resource}/${String(id)} to release`);
|
|
30
|
+
if (String(existing.identity) !== String(identity)) throw new LockConflictError(existing);
|
|
31
|
+
store.delete(key);
|
|
32
|
+
await announceLock(publisher, "unlocked", existing);
|
|
33
|
+
return existing;
|
|
34
|
+
},
|
|
35
|
+
async getLock(resource, { id }) {
|
|
36
|
+
return store.get(storeKey(resource, id)) ?? null;
|
|
37
|
+
},
|
|
38
|
+
async getLocks(resource) {
|
|
39
|
+
return [...store.values()].filter((lock) => lock.resource === resource);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
48
42
|
}
|
|
49
|
-
export {
|
|
50
|
-
inMemoryLockProvider
|
|
51
|
-
};
|
|
43
|
+
export { inMemoryLockProvider };
|
package/dist/realtime/live.js
CHANGED
|
@@ -1,118 +1,112 @@
|
|
|
1
1
|
import { lockKey, locksKey, resourceKey } from "../data/keys.js";
|
|
2
2
|
import { hasUnsettledUndoables, onUndoablesSettled } from "../data/undoable.js";
|
|
3
3
|
import { assertRealtimeDataProvider } from "./realtime-data-provider.js";
|
|
4
|
-
import {
|
|
4
|
+
import { lockResourceTopic, lockTopic, recordTopic, resourceTopic } from "./topics.js";
|
|
5
|
+
// src/realtime/live.ts
|
|
5
6
|
function subscribeLive(ctx, spec) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
missed = false;
|
|
56
|
-
onEvent();
|
|
57
|
-
}
|
|
58
|
-
};
|
|
7
|
+
const { dataProvider } = ctx;
|
|
8
|
+
assertRealtimeDataProvider(dataProvider, spec.caller);
|
|
9
|
+
let stopped = false;
|
|
10
|
+
let scheduled = false;
|
|
11
|
+
let missed = false;
|
|
12
|
+
const schedule = () => {
|
|
13
|
+
if (scheduled) return;
|
|
14
|
+
scheduled = true;
|
|
15
|
+
queueMicrotask(() => {
|
|
16
|
+
scheduled = false;
|
|
17
|
+
if (!stopped) spec.invalidate();
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
let stopWaiting;
|
|
21
|
+
const holdForUndoable = () => {
|
|
22
|
+
if (stopWaiting) return;
|
|
23
|
+
stopWaiting = onUndoablesSettled(() => {
|
|
24
|
+
stopWaiting?.();
|
|
25
|
+
stopWaiting = void 0;
|
|
26
|
+
onEvent();
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
const onEvent = () => {
|
|
30
|
+
if (stopped) return;
|
|
31
|
+
if (spec.holdWhileUndoable && hasUnsettledUndoables()) {
|
|
32
|
+
holdForUndoable();
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (spec.options?.paused?.()) {
|
|
36
|
+
missed = true;
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
schedule();
|
|
40
|
+
};
|
|
41
|
+
const unsubscribes = spec.topics.map((topic) => dataProvider.subscribe(topic, onEvent));
|
|
42
|
+
if (spec.topics.length > 0 && dataProvider.onReconnect) unsubscribes.push(dataProvider.onReconnect(onEvent));
|
|
43
|
+
return {
|
|
44
|
+
stop() {
|
|
45
|
+
stopped = true;
|
|
46
|
+
stopWaiting?.();
|
|
47
|
+
stopWaiting = void 0;
|
|
48
|
+
for (const unsubscribe of unsubscribes.splice(0)) unsubscribe();
|
|
49
|
+
},
|
|
50
|
+
resume() {
|
|
51
|
+
if (stopped || !missed) return;
|
|
52
|
+
missed = false;
|
|
53
|
+
onEvent();
|
|
54
|
+
}
|
|
55
|
+
};
|
|
59
56
|
}
|
|
57
|
+
/** Invalidates everything under the resource except lock queries, which have their own subscribers. */
|
|
60
58
|
function invalidateResource(ctx, resource) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
59
|
+
ctx.queryClient.invalidateQueries({
|
|
60
|
+
queryKey: resourceKey(resource),
|
|
61
|
+
predicate: ({ queryKey }) => queryKey[1] !== "getLock" && queryKey[1] !== "getLocks"
|
|
62
|
+
});
|
|
65
63
|
}
|
|
64
|
+
/** Refetches the resource's lists, shows and edits when anything in it changes or the connection comes back. */
|
|
66
65
|
function subscribeLiveResource(ctx, resource, options) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
66
|
+
return subscribeLive(ctx, {
|
|
67
|
+
caller: "subscribeLiveResource",
|
|
68
|
+
topics: [resourceTopic(resource)],
|
|
69
|
+
invalidate: () => invalidateResource(ctx, resource),
|
|
70
|
+
options,
|
|
71
|
+
holdWhileUndoable: true
|
|
72
|
+
});
|
|
74
73
|
}
|
|
74
|
+
/** Like `subscribeLiveResource`, for the events of one record. */
|
|
75
75
|
function subscribeLiveRecord(ctx, resource, id, options) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
76
|
+
return subscribeLive(ctx, {
|
|
77
|
+
caller: "subscribeLiveRecord",
|
|
78
|
+
topics: [recordTopic(resource, id)],
|
|
79
|
+
invalidate: () => invalidateResource(ctx, resource),
|
|
80
|
+
options,
|
|
81
|
+
holdWhileUndoable: true
|
|
82
|
+
});
|
|
83
83
|
}
|
|
84
|
+
/** Like `subscribeLiveRecord`, for several records: one invalidation however many of them change. */
|
|
84
85
|
function subscribeLiveRecords(ctx, resource, ids, options) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
});
|
|
86
|
+
return subscribeLive(ctx, {
|
|
87
|
+
caller: "subscribeLiveRecords",
|
|
88
|
+
topics: [...new Set(ids.map((id) => recordTopic(resource, id)))],
|
|
89
|
+
invalidate: () => invalidateResource(ctx, resource),
|
|
90
|
+
options,
|
|
91
|
+
holdWhileUndoable: true
|
|
92
|
+
});
|
|
93
93
|
}
|
|
94
|
+
/** Refetches one record's lock when it is taken or released. */
|
|
94
95
|
function subscribeLiveLock(ctx, resource, id) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
holdWhileUndoable: false
|
|
102
|
-
});
|
|
96
|
+
return subscribeLive(ctx, {
|
|
97
|
+
caller: "subscribeLiveLock",
|
|
98
|
+
topics: [lockTopic(resource, id)],
|
|
99
|
+
invalidate: () => void ctx.queryClient.invalidateQueries({ queryKey: lockKey(resource, { id }) }),
|
|
100
|
+
holdWhileUndoable: false
|
|
101
|
+
});
|
|
103
102
|
}
|
|
103
|
+
/** Refetches the resource's lock list when any lock is taken or released. */
|
|
104
104
|
function subscribeLiveLocks(ctx, resource) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
105
|
+
return subscribeLive(ctx, {
|
|
106
|
+
caller: "subscribeLiveLocks",
|
|
107
|
+
topics: [lockResourceTopic(resource)],
|
|
108
|
+
invalidate: () => void ctx.queryClient.invalidateQueries({ queryKey: locksKey(resource) }),
|
|
109
|
+
holdWhileUndoable: false
|
|
110
|
+
});
|
|
111
111
|
}
|
|
112
|
-
export {
|
|
113
|
-
subscribeLiveLock,
|
|
114
|
-
subscribeLiveLocks,
|
|
115
|
-
subscribeLiveRecord,
|
|
116
|
-
subscribeLiveRecords,
|
|
117
|
-
subscribeLiveResource
|
|
118
|
-
};
|
|
112
|
+
export { subscribeLiveLock, subscribeLiveLocks, subscribeLiveRecord, subscribeLiveRecords, subscribeLiveResource };
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { lockKey, locksKey } from "../data/keys.js";
|
|
2
2
|
import { assertRealtimeDataProvider } from "./realtime-data-provider.js";
|
|
3
|
+
// src/realtime/lock-options.ts
|
|
4
|
+
/** One record's lock, cached under `lockKey`. Resolves to `null` when unlocked. */
|
|
3
5
|
function getLockOptions(ctx, resource, params) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
const { dataProvider } = ctx;
|
|
7
|
+
assertRealtimeDataProvider(dataProvider, "getLockOptions");
|
|
8
|
+
return {
|
|
9
|
+
queryKey: lockKey(resource, params),
|
|
10
|
+
queryFn: () => dataProvider.getLock(resource, params)
|
|
11
|
+
};
|
|
10
12
|
}
|
|
13
|
+
/** Every lock held on a resource, cached under `locksKey`. */
|
|
11
14
|
function getLocksOptions(ctx, resource) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
const { dataProvider } = ctx;
|
|
16
|
+
assertRealtimeDataProvider(dataProvider, "getLocksOptions");
|
|
17
|
+
return {
|
|
18
|
+
queryKey: locksKey(resource),
|
|
19
|
+
queryFn: () => dataProvider.getLocks(resource)
|
|
20
|
+
};
|
|
18
21
|
}
|
|
19
|
-
export {
|
|
20
|
-
getLockOptions,
|
|
21
|
-
getLocksOptions
|
|
22
|
-
};
|
|
22
|
+
export { getLockOptions, getLocksOptions };
|