@chelone/core 0.6.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 (242) hide show
  1. package/dist/assistant/assistant-session.d.ts +6 -0
  2. package/dist/assistant/assistant-session.js +204 -181
  3. package/dist/assistant/echo-transport.js +26 -29
  4. package/dist/assistant/http-transport.d.ts +10 -0
  5. package/dist/assistant/http-transport.js +98 -0
  6. package/dist/assistant/types.d.ts +1 -7
  7. package/dist/auth/access-control.d.ts +13 -5
  8. package/dist/auth/access-control.js +25 -21
  9. package/dist/auth/auth-options.d.ts +21 -17
  10. package/dist/auth/auth-options.js +80 -48
  11. package/dist/auth/permission-matrix.d.ts +12 -0
  12. package/dist/auth/permission-matrix.js +67 -0
  13. package/dist/auth/types.d.ts +14 -4
  14. package/dist/block-editor/block-document.d.ts +60 -0
  15. package/dist/block-editor/block-document.js +143 -0
  16. package/dist/block-editor/data-blocks.d.ts +63 -0
  17. package/dist/block-editor/data-blocks.js +117 -0
  18. package/dist/chart/chart-data.js +46 -44
  19. package/dist/command-menu/hotkey.js +58 -47
  20. package/dist/command-menu/recents.js +8 -11
  21. package/dist/command-menu/registry.d.ts +9 -5
  22. package/dist/command-menu/registry.js +36 -46
  23. package/dist/controller/calendar-dates.js +82 -113
  24. package/dist/controller/calendar-events.js +93 -88
  25. package/dist/controller/client-list-controller.d.ts +2 -2
  26. package/dist/controller/client-list-controller.js +251 -254
  27. package/dist/controller/data-table-columns.d.ts +2 -0
  28. package/dist/controller/data-table-columns.js +50 -56
  29. package/dist/controller/deep-equal.d.ts +1 -0
  30. package/dist/controller/deep-equal.js +14 -0
  31. package/dist/controller/filter-toggle.js +36 -44
  32. package/dist/controller/in-place-editor.d.ts +42 -0
  33. package/dist/controller/in-place-editor.js +42 -0
  34. package/dist/controller/infinite-list-controller.js +219 -189
  35. package/dist/controller/inspector.d.ts +49 -0
  36. package/dist/controller/inspector.js +64 -0
  37. package/dist/controller/job-monitor.d.ts +3 -4
  38. package/dist/controller/job-monitor.js +37 -47
  39. package/dist/controller/kanban-board.d.ts +2 -3
  40. package/dist/controller/kanban-board.js +43 -24
  41. package/dist/controller/list-controller.d.ts +5 -5
  42. package/dist/controller/list-controller.js +444 -400
  43. package/dist/controller/list-params.js +96 -87
  44. package/dist/controller/pivot-grid.js +89 -95
  45. package/dist/controller/prev-next.d.ts +2 -2
  46. package/dist/controller/prev-next.js +74 -54
  47. package/dist/controller/record-controllers.d.ts +14 -6
  48. package/dist/controller/record-controllers.js +288 -257
  49. package/dist/controller/record-diff.d.ts +21 -0
  50. package/dist/controller/record-diff.js +50 -0
  51. package/dist/controller/record-timeline.js +42 -30
  52. package/dist/controller/record-tree.js +57 -47
  53. package/dist/controller/record-workflow.d.ts +38 -16
  54. package/dist/controller/record-workflow.js +85 -64
  55. package/dist/controller/reference-many-controller.js +198 -192
  56. package/dist/controller/reference-one-controller.d.ts +1 -1
  57. package/dist/controller/reference-one-controller.js +63 -56
  58. package/dist/controller/saved-queries.js +104 -91
  59. package/dist/controller/translate-fallback.js +10 -6
  60. package/dist/csv/export.d.ts +2 -1
  61. package/dist/csv/export.js +43 -40
  62. package/dist/csv/import-controller.js +185 -169
  63. package/dist/csv/match-headers.js +29 -22
  64. package/dist/csv/parse-with.js +60 -54
  65. package/dist/csv/run-import.js +69 -72
  66. package/dist/csv/validate-rows.d.ts +1 -1
  67. package/dist/csv/validate-rows.js +65 -52
  68. package/dist/data/cache-ops.d.ts +5 -4
  69. package/dist/data/cache-ops.js +208 -188
  70. package/dist/data/combine-data-providers.js +25 -23
  71. package/dist/data/data-provider-log.d.ts +45 -0
  72. package/dist/data/data-provider-log.js +93 -0
  73. package/dist/data/errors.js +14 -10
  74. package/dist/data/fake-provider.d.ts +6 -3
  75. package/dist/data/fake-provider.js +129 -114
  76. package/dist/data/fetch-utils.js +61 -44
  77. package/dist/data/filter-branch.d.ts +5 -0
  78. package/dist/data/filter-branch.js +10 -0
  79. package/dist/data/get-many-aggregate.js +84 -76
  80. package/dist/data/http-error.js +17 -12
  81. package/dist/data/keys.js +50 -36
  82. package/dist/data/mutation-options.d.ts +14 -9
  83. package/dist/data/mutation-options.js +93 -109
  84. package/dist/data/query-options.js +73 -68
  85. package/dist/data/remove-empty.d.ts +3 -0
  86. package/dist/data/remove-empty.js +11 -0
  87. package/dist/data/undoable.d.ts +2 -2
  88. package/dist/data/undoable.js +190 -174
  89. package/dist/data/with-lifecycle-callbacks.d.ts +45 -17
  90. package/dist/data/with-lifecycle-callbacks.js +66 -52
  91. package/dist/environment/application-update-store.js +58 -55
  92. package/dist/environment/offline-store.js +21 -21
  93. package/dist/form/array-binding.d.ts +30 -11
  94. package/dist/form/array-binding.js +184 -166
  95. package/dist/form/choice-ids.d.ts +7 -0
  96. package/dist/form/choice-ids.js +11 -0
  97. package/dist/form/choices-controller.d.ts +3 -2
  98. package/dist/form/choices-controller.js +302 -275
  99. package/dist/form/date-format.d.ts +38 -0
  100. package/dist/form/date-format.js +89 -0
  101. package/dist/form/dirty-values.d.ts +2 -2
  102. package/dist/form/dirty-values.js +22 -11
  103. package/dist/form/duration.d.ts +22 -0
  104. package/dist/form/duration.js +49 -0
  105. package/dist/form/edit-create-form.d.ts +12 -5
  106. package/dist/form/edit-create-form.js +243 -188
  107. package/dist/form/event-value.d.ts +6 -0
  108. package/dist/form/event-value.js +17 -0
  109. package/dist/form/field-error.d.ts +14 -0
  110. package/dist/form/field-error.js +28 -0
  111. package/dist/form/field-name.d.ts +20 -0
  112. package/dist/form/field-name.js +6 -0
  113. package/dist/form/filter-form-values.js +63 -49
  114. package/dist/form/form-controller.d.ts +9 -1
  115. package/dist/form/form-controller.js +165 -160
  116. package/dist/form/form-groups.d.ts +4 -3
  117. package/dist/form/form-groups.js +79 -79
  118. package/dist/form/form-handle.d.ts +175 -0
  119. package/dist/form/form-handle.js +68 -0
  120. package/dist/form/input-binding.d.ts +56 -31
  121. package/dist/form/input-binding.js +169 -118
  122. package/dist/form/input-values.d.ts +130 -0
  123. package/dist/form/input-values.js +177 -0
  124. package/dist/form/json-text.js +51 -37
  125. package/dist/form/save-pipeline.d.ts +6 -8
  126. package/dist/form/save-pipeline.js +91 -82
  127. package/dist/form/set-form-values.d.ts +6 -0
  128. package/dist/form/set-form-values.js +10 -0
  129. package/dist/form/source.js +97 -65
  130. package/dist/form/text-of.d.ts +2 -0
  131. package/dist/form/text-of.js +7 -0
  132. package/dist/form/validators.d.ts +58 -19
  133. package/dist/form/validators.js +97 -71
  134. package/dist/geo/bbox.d.ts +5 -4
  135. package/dist/geo/bbox.js +69 -48
  136. package/dist/geo/bounds.d.ts +14 -3
  137. package/dist/geo/bounds.js +98 -68
  138. package/dist/geo/constraints.js +88 -93
  139. package/dist/geo/coordinates.js +31 -23
  140. package/dist/geo/editor.d.ts +13 -13
  141. package/dist/geo/editor.js +176 -153
  142. package/dist/geo/geocoding.d.ts +4 -4
  143. package/dist/geo/geocoding.js +38 -41
  144. package/dist/geo/geojson.d.ts +12 -74
  145. package/dist/geo/geojson.js +52 -40
  146. package/dist/geo/geometry-math.d.ts +4 -4
  147. package/dist/geo/geometry-math.js +100 -93
  148. package/dist/geo/index.d.ts +7 -6
  149. package/dist/geo/map-layers.d.ts +42 -7
  150. package/dist/geo/map-layers.js +88 -62
  151. package/dist/geo/map-style.js +31 -32
  152. package/dist/geo/messages.js +48 -45
  153. package/dist/geo/nominatim.js +88 -80
  154. package/dist/geo/osm-presets.d.ts +4 -3
  155. package/dist/geo/osm-presets.js +108 -86
  156. package/dist/geo/osm-tags.js +14 -12
  157. package/dist/geo/overpass.d.ts +14 -2
  158. package/dist/geo/overpass.js +83 -90
  159. package/dist/geo/shape-value.d.ts +9 -5
  160. package/dist/geo/shape-value.js +169 -146
  161. package/dist/geo/snap-to-roads.d.ts +3 -3
  162. package/dist/geo/snap-to-roads.js +55 -50
  163. package/dist/geo/throttle.js +36 -39
  164. package/dist/guards.d.ts +37 -0
  165. package/dist/guards.js +62 -0
  166. package/dist/i18n/default-messages.js +34 -29
  167. package/dist/i18n/english-messages.js +187 -189
  168. package/dist/i18n/i18n.d.ts +2 -2
  169. package/dist/i18n/i18n.js +47 -60
  170. package/dist/i18n/inflection.d.ts +34 -0
  171. package/dist/i18n/inflection.js +82 -0
  172. package/dist/i18n/messages.d.ts +10 -2
  173. package/dist/i18n/messages.js +17 -4
  174. package/dist/i18n/missing-keys.js +66 -62
  175. package/dist/i18n/translatable.d.ts +16 -1
  176. package/dist/i18n/translatable.js +40 -47
  177. package/dist/index.d.ts +71 -24
  178. package/dist/index.js +40 -288
  179. package/dist/json/deep-equal.d.ts +8 -0
  180. package/dist/json/deep-equal.js +24 -0
  181. package/dist/json/strip-json-comments.js +38 -42
  182. package/dist/noop.d.ts +2 -0
  183. package/dist/noop.js +4 -0
  184. package/dist/notification/error-message.d.ts +2 -0
  185. package/dist/notification/error-message.js +10 -0
  186. package/dist/notification/notification-store.d.ts +3 -2
  187. package/dist/notification/notification-store.js +41 -45
  188. package/dist/onboarding-tour/placement.js +63 -78
  189. package/dist/onboarding-tour/tour-controller.js +46 -54
  190. package/dist/realtime/add-events-for-mutations.js +75 -81
  191. package/dist/realtime/announce-lock.js +16 -13
  192. package/dist/realtime/broadcast-channel-transport.js +65 -59
  193. package/dist/realtime/copy-members.js +22 -14
  194. package/dist/realtime/in-memory-lock-provider.js +40 -48
  195. package/dist/realtime/live.js +95 -101
  196. package/dist/realtime/lock-options.js +16 -16
  197. package/dist/realtime/lock-session.js +91 -78
  198. package/dist/realtime/memory-transport.js +25 -25
  199. package/dist/realtime/presence.js +120 -122
  200. package/dist/realtime/realtime-data-provider.d.ts +10 -0
  201. package/dist/realtime/realtime-data-provider.js +45 -42
  202. package/dist/realtime/reconnect-backoff.js +17 -0
  203. package/dist/realtime/sse-transport.d.ts +31 -0
  204. package/dist/realtime/sse-transport.js +235 -0
  205. package/dist/realtime/status-store.js +23 -28
  206. package/dist/realtime/topic-hub.js +62 -71
  207. package/dist/realtime/topics.js +10 -12
  208. package/dist/realtime/types.js +10 -12
  209. package/dist/realtime/unread-count.js +21 -21
  210. package/dist/realtime/websocket-transport.d.ts +32 -0
  211. package/dist/realtime/websocket-transport.js +306 -0
  212. package/dist/resource/describe-resource.d.ts +2 -0
  213. package/dist/resource/describe-resource.js +232 -219
  214. package/dist/resource/get-at-path.js +29 -14
  215. package/dist/resource/identifier.d.ts +18 -0
  216. package/dist/resource/identifier.js +27 -0
  217. package/dist/resource/record.d.ts +4 -0
  218. package/dist/resource/record.js +10 -0
  219. package/dist/resource/register.d.ts +7 -0
  220. package/dist/resource/registry-store.d.ts +45 -15
  221. package/dist/resource/registry-store.js +67 -60
  222. package/dist/resource/registry.d.ts +10 -0
  223. package/dist/resource/registry.js +8 -4
  224. package/dist/resource/source-path.d.ts +16 -1
  225. package/dist/rich-text/rich-text-extras.d.ts +132 -0
  226. package/dist/rich-text/rich-text-extras.js +179 -0
  227. package/dist/rich-text/rich-text-image.d.ts +124 -0
  228. package/dist/rich-text/rich-text-image.js +163 -0
  229. package/dist/rich-text/rich-text.d.ts +6 -0
  230. package/dist/rich-text/rich-text.js +125 -88
  231. package/dist/router/location.d.ts +22 -4
  232. package/dist/router/location.js +41 -18
  233. package/dist/router/match.js +47 -39
  234. package/dist/router/paths.js +40 -34
  235. package/dist/router/record-from-location.d.ts +1 -1
  236. package/dist/router/record-from-location.js +25 -17
  237. package/dist/store/adapters.js +51 -55
  238. package/dist/store/micro-store.js +57 -59
  239. package/dist/store/shallow-equal.d.ts +12 -0
  240. package/dist/store/shallow-equal.js +20 -0
  241. package/dist/store/store.js +54 -57
  242. package/package.json +13 -11
@@ -1,47 +1,43 @@
1
+ // src/notification/notification-store.ts
1
2
  function createNotificationStore() {
2
- let notifications = [];
3
- let nextId = 1;
4
- const subscribers = /* @__PURE__ */ new Set();
5
- const emit = () => {
6
- for (const cb of subscribers) cb();
7
- };
8
- return {
9
- notify(message, options = {}) {
10
- const id = nextId++;
11
- notifications = [
12
- ...notifications,
13
- {
14
- id,
15
- message,
16
- type: options.type ?? "info",
17
- messageArgs: options.messageArgs,
18
- undoable: options.undoable,
19
- autoHideDuration: options.autoHideDuration,
20
- undo: options.undo,
21
- onClose: options.onClose
22
- }
23
- ];
24
- emit();
25
- return id;
26
- },
27
- dismiss(id) {
28
- const next = notifications.filter((n) => n.id !== id);
29
- if (next.length === notifications.length) return;
30
- notifications = next;
31
- emit();
32
- },
33
- clear() {
34
- if (notifications.length === 0) return;
35
- notifications = [];
36
- emit();
37
- },
38
- getSnapshot: () => notifications,
39
- subscribe(callback) {
40
- subscribers.add(callback);
41
- return () => void subscribers.delete(callback);
42
- }
43
- };
3
+ let notifications = [];
4
+ let nextId = 1;
5
+ const subscribers = /* @__PURE__ */ new Set();
6
+ const emit = () => {
7
+ for (const cb of subscribers) cb();
8
+ };
9
+ return {
10
+ notify(message, options = {}) {
11
+ const id = nextId++;
12
+ notifications = [...notifications, {
13
+ id,
14
+ message,
15
+ type: options.type ?? "info",
16
+ messageArgs: options.messageArgs,
17
+ undoable: options.undoable,
18
+ autoHideDuration: options.autoHideDuration,
19
+ undo: options.undo,
20
+ onClose: options.onClose
21
+ }];
22
+ emit();
23
+ return id;
24
+ },
25
+ dismiss(id) {
26
+ const next = notifications.filter((n) => n.id !== id);
27
+ if (next.length === notifications.length) return;
28
+ notifications = next;
29
+ emit();
30
+ },
31
+ clear() {
32
+ if (notifications.length === 0) return;
33
+ notifications = [];
34
+ emit();
35
+ },
36
+ getSnapshot: () => notifications,
37
+ subscribe(callback) {
38
+ subscribers.add(callback);
39
+ return () => void subscribers.delete(callback);
40
+ }
41
+ };
44
42
  }
45
- export {
46
- createNotificationStore
47
- };
43
+ export { createNotificationStore };
@@ -1,82 +1,67 @@
1
- const SIDES = ["bottom", "top", "right", "left"];
2
- const OPPOSITE = {
3
- top: "bottom",
4
- bottom: "top",
5
- left: "right",
6
- right: "left"
1
+ // src/onboarding-tour/placement.ts
2
+ var SIDES = [
3
+ "bottom",
4
+ "top",
5
+ "right",
6
+ "left"
7
+ ];
8
+ var OPPOSITE = {
9
+ top: "bottom",
10
+ bottom: "top",
11
+ left: "right",
12
+ right: "left"
7
13
  };
8
- function placeTourCard({
9
- target,
10
- card,
11
- viewport,
12
- placement,
13
- margin = 12
14
- }) {
15
- if (!target) {
16
- return {
17
- top: (viewport.height - card.height) / 2,
18
- left: (viewport.width - card.width) / 2,
19
- side: placement === "auto" ? "bottom" : placement
20
- };
21
- }
22
- const room = {
23
- top: target.top,
24
- bottom: viewport.height - (target.top + target.height),
25
- left: target.left,
26
- right: viewport.width - (target.left + target.width)
27
- };
28
- const needed = (side2) => (side2 === "top" || side2 === "bottom" ? card.height : card.width) + margin * 2;
29
- const fits = (side2) => room[side2] >= needed(side2);
30
- let side;
31
- if (placement === "auto") {
32
- const roomiest = (candidates) => candidates.reduce(
33
- (best, next) => room[next] > room[best] ? next : best
34
- );
35
- const fitting = SIDES.filter(fits);
36
- side = roomiest(fitting.length > 0 ? fitting : SIDES);
37
- } else {
38
- side = !fits(placement) && fits(OPPOSITE[placement]) ? OPPOSITE[placement] : placement;
39
- }
40
- const centreX = target.left + target.width / 2 - card.width / 2;
41
- const centreY = target.top + target.height / 2 - card.height / 2;
42
- let top;
43
- let left;
44
- switch (side) {
45
- case "bottom":
46
- top = target.top + target.height + margin;
47
- left = centreX;
48
- break;
49
- case "top":
50
- top = target.top - margin - card.height;
51
- left = centreX;
52
- break;
53
- case "right":
54
- top = centreY;
55
- left = target.left + target.width + margin;
56
- break;
57
- case "left":
58
- top = centreY;
59
- left = target.left - margin - card.width;
60
- break;
61
- }
62
- return {
63
- top: Math.max(
64
- margin,
65
- Math.min(top, viewport.height - card.height - margin)
66
- ),
67
- left: Math.max(
68
- margin,
69
- Math.min(left, viewport.width - card.width - margin)
70
- ),
71
- side
72
- };
14
+ function placeTourCard({ target, card, viewport, placement, margin = 12 }) {
15
+ if (!target) return {
16
+ top: (viewport.height - card.height) / 2,
17
+ left: (viewport.width - card.width) / 2,
18
+ side: placement === "auto" ? "bottom" : placement
19
+ };
20
+ const room = {
21
+ top: target.top,
22
+ bottom: viewport.height - (target.top + target.height),
23
+ left: target.left,
24
+ right: viewport.width - (target.left + target.width)
25
+ };
26
+ const needed = (side) => (side === "top" || side === "bottom" ? card.height : card.width) + margin * 2;
27
+ const fits = (side) => room[side] >= needed(side);
28
+ let side;
29
+ if (placement === "auto") {
30
+ const roomiest = (candidates) => candidates.reduce((best, next) => room[next] > room[best] ? next : best);
31
+ const fitting = SIDES.filter(fits);
32
+ side = roomiest(fitting.length > 0 ? fitting : SIDES);
33
+ } else side = !fits(placement) && fits(OPPOSITE[placement]) ? OPPOSITE[placement] : placement;
34
+ const centreX = target.left + target.width / 2 - card.width / 2;
35
+ const centreY = target.top + target.height / 2 - card.height / 2;
36
+ let top;
37
+ let left;
38
+ switch (side) {
39
+ case "bottom":
40
+ top = target.top + target.height + margin;
41
+ left = centreX;
42
+ break;
43
+ case "top":
44
+ top = target.top - margin - card.height;
45
+ left = centreX;
46
+ break;
47
+ case "right":
48
+ top = centreY;
49
+ left = target.left + target.width + margin;
50
+ break;
51
+ case "left":
52
+ top = centreY;
53
+ left = target.left - margin - card.width;
54
+ }
55
+ return {
56
+ top: Math.max(margin, Math.min(top, viewport.height - card.height - margin)),
57
+ left: Math.max(margin, Math.min(left, viewport.width - card.width - margin)),
58
+ side
59
+ };
73
60
  }
61
+ /** A CSS `clip-path` that fills the page except the target's rect. */
74
62
  function tourSpotlightPath(target) {
75
- const right = target.left + target.width;
76
- const bottom = target.top + target.height;
77
- return `polygon(0% 0%, 0% 100%, ${target.left}px 100%, ${target.left}px ${target.top}px, ${right}px ${target.top}px, ${right}px ${bottom}px, ${target.left}px ${bottom}px, ${target.left}px 100%, 100% 100%, 100% 0%)`;
63
+ const right = target.left + target.width;
64
+ const bottom = target.top + target.height;
65
+ return `polygon(0% 0%, 0% 100%, ${target.left}px 100%, ${target.left}px ${target.top}px, ${right}px ${target.top}px, ${right}px ${bottom}px, ${target.left}px ${bottom}px, ${target.left}px 100%, 100% 100%, 100% 0%)`;
78
66
  }
79
- export {
80
- placeTourCard,
81
- tourSpotlightPath
82
- };
67
+ export { placeTourCard, tourSpotlightPath };
@@ -1,58 +1,50 @@
1
1
  import { createMicroStore } from "../store/micro-store.js";
2
+ // src/onboarding-tour/tour-controller.ts
3
+ /** Where the onboarding tour keeps its done flag in a `CheloneStore`. */
2
4
  function onboardingTourKey(id) {
3
- return `onboarding-tour.${id}.completed`;
5
+ return `onboarding-tour.${id}.completed`;
4
6
  }
5
- function createTourController({
6
- id,
7
- stepCount,
8
- store,
9
- autoStart = true,
10
- onComplete
11
- }) {
12
- const key = onboardingTourKey(id);
13
- const isDone = () => store.getItem(key) === true;
14
- const micro = createMicroStore(
15
- { active: false, index: 0 },
16
- {
17
- // The store is only watched while someone is subscribed, so an unmounted
18
- // tour does not reopen when its flag is cleared.
19
- onSubscribed() {
20
- const openIfDue = () => {
21
- if (autoStart && !isDone() && !micro.getSnapshot().active) start();
22
- };
23
- openIfDue();
24
- return store.subscribe(key, openIfDue);
25
- }
26
- }
27
- );
28
- function start() {
29
- if (stepCount < 1) return;
30
- micro.setState({ active: true, index: 0 });
31
- }
32
- function end(reason) {
33
- if (!micro.getSnapshot().active) return;
34
- micro.setState({ active: false });
35
- store.setItem(key, true);
36
- onComplete?.(reason);
37
- }
38
- return {
39
- ...micro,
40
- start,
41
- next() {
42
- const { active, index } = micro.getSnapshot();
43
- if (!active) return;
44
- if (index >= stepCount - 1) end("finished");
45
- else micro.setState({ index: index + 1 });
46
- },
47
- back() {
48
- const { active, index } = micro.getSnapshot();
49
- if (active && index > 0) micro.setState({ index: index - 1 });
50
- },
51
- skip: () => end("skipped"),
52
- finish: () => end("finished")
53
- };
7
+ function createTourController({ id, stepCount, store, autoStart = true, onComplete }) {
8
+ const key = onboardingTourKey(id);
9
+ const isDone = () => store.getItem(key) === true;
10
+ const micro = createMicroStore({
11
+ active: false,
12
+ index: 0
13
+ }, { onSubscribed() {
14
+ const openIfDue = () => {
15
+ if (autoStart && !isDone() && !micro.getSnapshot().active) start();
16
+ };
17
+ openIfDue();
18
+ return store.subscribe(key, openIfDue);
19
+ } });
20
+ function start() {
21
+ if (stepCount < 1) return;
22
+ micro.setState({
23
+ active: true,
24
+ index: 0
25
+ });
26
+ }
27
+ function end(reason) {
28
+ if (!micro.getSnapshot().active) return;
29
+ micro.setState({ active: false });
30
+ store.setItem(key, true);
31
+ onComplete?.(reason);
32
+ }
33
+ return {
34
+ ...micro,
35
+ start,
36
+ next() {
37
+ const { active, index } = micro.getSnapshot();
38
+ if (!active) return;
39
+ if (index >= stepCount - 1) end("finished");
40
+ else micro.setState({ index: index + 1 });
41
+ },
42
+ back() {
43
+ const { active, index } = micro.getSnapshot();
44
+ if (active && index > 0) micro.setState({ index: index - 1 });
45
+ },
46
+ skip: () => end("skipped"),
47
+ finish: () => end("finished")
48
+ };
54
49
  }
55
- export {
56
- createTourController,
57
- onboardingTourKey
58
- };
50
+ export { createTourController, onboardingTourKey };
@@ -1,85 +1,79 @@
1
1
  import { copyMembers } from "./copy-members.js";
2
2
  import { recordTopic, resourceTopic } from "./topics.js";
3
+ // src/realtime/add-events-for-mutations.ts
4
+ /**
5
+ * Publishes after each successful write, so other clients can refresh. The
6
+ * result waits for the publishes to settle but never fails because of them;
7
+ * a rejected publish goes to `onError`. Returns the type it was given, so a
8
+ * `RealtimeDataProvider` stays one.
9
+ */
3
10
  function addEventsForMutations(base, publisher, { onError } = {}) {
4
- const publishAll = async (events) => {
5
- await Promise.all(
6
- events.map(async ([topic, event]) => {
7
- try {
8
- await publisher.publish(topic, event);
9
- } catch (error) {
10
- try {
11
- onError?.(error);
12
- } catch {
13
- }
14
- }
15
- })
16
- );
17
- };
18
- const manyEvents = (type, resource, ids) => [
19
- [resourceTopic(resource), { type, payload: { ids } }],
20
- ...ids.map(
21
- (id) => [
22
- recordTopic(resource, id),
23
- { type, payload: { id } }
24
- ]
25
- )
26
- ];
27
- const wrapped = {
28
- ...copyMembers(base),
29
- create: async (resource, params) => {
30
- const result = await base.create(resource, params);
31
- await publishAll([
32
- [
33
- resourceTopic(resource),
34
- { type: "created", payload: { ids: [result.data.id] } }
35
- ]
36
- ]);
37
- return result;
38
- },
39
- update: async (resource, params) => {
40
- const result = await base.update(resource, params);
41
- await publishAll([
42
- [
43
- recordTopic(resource, params.id),
44
- { type: "updated", payload: { id: params.id, data: result.data } }
45
- ],
46
- [
47
- resourceTopic(resource),
48
- { type: "updated", payload: { ids: [params.id] } }
49
- ]
50
- ]);
51
- return result;
52
- },
53
- delete: async (resource, params) => {
54
- const result = await base.delete(resource, params);
55
- await publishAll([
56
- [
57
- recordTopic(resource, params.id),
58
- {
59
- type: "deleted",
60
- payload: { id: params.id, previousData: result.data }
61
- }
62
- ],
63
- [
64
- resourceTopic(resource),
65
- { type: "deleted", payload: { ids: [params.id] } }
66
- ]
67
- ]);
68
- return result;
69
- },
70
- updateMany: async (resource, params) => {
71
- const result = await base.updateMany(resource, params);
72
- await publishAll(manyEvents("updated", resource, result.data));
73
- return result;
74
- },
75
- deleteMany: async (resource, params) => {
76
- const result = await base.deleteMany(resource, params);
77
- await publishAll(manyEvents("deleted", resource, result.data));
78
- return result;
79
- }
80
- };
81
- return wrapped;
11
+ const publishAll = async (events) => {
12
+ await Promise.all(events.map(async ([topic, event]) => {
13
+ try {
14
+ await publisher.publish(topic, event);
15
+ } catch (error) {
16
+ try {
17
+ onError?.(error);
18
+ } catch {}
19
+ }
20
+ }));
21
+ };
22
+ const manyEvents = (type, resource, ids) => [[resourceTopic(resource), {
23
+ type,
24
+ payload: { ids }
25
+ }], ...ids.map((id) => [recordTopic(resource, id), {
26
+ type,
27
+ payload: { id }
28
+ }])];
29
+ return {
30
+ ...copyMembers(base),
31
+ create: async (resource, params) => {
32
+ const result = await base.create(resource, params);
33
+ await publishAll([[resourceTopic(resource), {
34
+ type: "created",
35
+ payload: { ids: [result.data.id] }
36
+ }]]);
37
+ return result;
38
+ },
39
+ update: async (resource, params) => {
40
+ const result = await base.update(resource, params);
41
+ await publishAll([[recordTopic(resource, params.id), {
42
+ type: "updated",
43
+ payload: {
44
+ id: params.id,
45
+ data: result.data
46
+ }
47
+ }], [resourceTopic(resource), {
48
+ type: "updated",
49
+ payload: { ids: [params.id] }
50
+ }]]);
51
+ return result;
52
+ },
53
+ delete: async (resource, params) => {
54
+ const result = await base.delete(resource, params);
55
+ await publishAll([[recordTopic(resource, params.id), {
56
+ type: "deleted",
57
+ payload: {
58
+ id: params.id,
59
+ previousData: result.data
60
+ }
61
+ }], [resourceTopic(resource), {
62
+ type: "deleted",
63
+ payload: { ids: [params.id] }
64
+ }]]);
65
+ return result;
66
+ },
67
+ updateMany: async (resource, params) => {
68
+ const result = await base.updateMany(resource, params);
69
+ await publishAll(manyEvents("updated", resource, result.data));
70
+ return result;
71
+ },
72
+ deleteMany: async (resource, params) => {
73
+ const result = await base.deleteMany(resource, params);
74
+ await publishAll(manyEvents("deleted", resource, result.data));
75
+ return result;
76
+ }
77
+ };
82
78
  }
83
- export {
84
- addEventsForMutations
85
- };
79
+ export { addEventsForMutations };
@@ -1,15 +1,18 @@
1
- import { lockTopic, lockResourceTopic } from "./topics.js";
1
+ import { lockResourceTopic, lockTopic } from "./topics.js";
2
+ // src/realtime/announce-lock.ts
3
+ /**
4
+ * Tells a publisher of a lock or an unlock, on the record's and the
5
+ * resource's topic. A failed publish is swallowed: the lock is already taken
6
+ * or released, so a failed announcement must not report it as failed.
7
+ */
2
8
  async function announceLock(publisher, type, lock) {
3
- if (!publisher) return;
4
- const event = { type, payload: lock };
5
- try {
6
- await Promise.all([
7
- publisher.publish(lockTopic(lock.resource, lock.recordId), event),
8
- publisher.publish(lockResourceTopic(lock.resource), event)
9
- ]);
10
- } catch {
11
- }
9
+ if (!publisher) return;
10
+ const event = {
11
+ type,
12
+ payload: lock
13
+ };
14
+ try {
15
+ await Promise.all([publisher.publish(lockTopic(lock.resource, lock.recordId), event), publisher.publish(lockResourceTopic(lock.resource), event)]);
16
+ } catch {}
12
17
  }
13
- export {
14
- announceLock
15
- };
18
+ export { announceLock };