@chelone/core 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (253) hide show
  1. package/dist/assistant/assistant-session.d.ts +28 -0
  2. package/dist/assistant/assistant-session.js +208 -0
  3. package/dist/assistant/echo-transport.d.ts +7 -0
  4. package/dist/assistant/echo-transport.js +28 -0
  5. package/dist/assistant/http-transport.d.ts +10 -0
  6. package/dist/assistant/http-transport.js +98 -0
  7. package/dist/assistant/types.d.ts +54 -0
  8. package/dist/auth/access-control.d.ts +13 -5
  9. package/dist/auth/access-control.js +25 -21
  10. package/dist/auth/auth-options.d.ts +21 -17
  11. package/dist/auth/auth-options.js +80 -48
  12. package/dist/auth/permission-matrix.d.ts +12 -0
  13. package/dist/auth/permission-matrix.js +67 -0
  14. package/dist/auth/types.d.ts +14 -4
  15. package/dist/block-editor/block-document.d.ts +60 -0
  16. package/dist/block-editor/block-document.js +143 -0
  17. package/dist/block-editor/data-blocks.d.ts +63 -0
  18. package/dist/block-editor/data-blocks.js +117 -0
  19. package/dist/chart/chart-data.d.ts +25 -0
  20. package/dist/chart/chart-data.js +61 -0
  21. package/dist/command-menu/hotkey.js +58 -47
  22. package/dist/command-menu/recents.js +8 -11
  23. package/dist/command-menu/registry.d.ts +9 -5
  24. package/dist/command-menu/registry.js +36 -46
  25. package/dist/controller/calendar-dates.js +82 -113
  26. package/dist/controller/calendar-events.js +93 -88
  27. package/dist/controller/client-list-controller.d.ts +2 -2
  28. package/dist/controller/client-list-controller.js +251 -254
  29. package/dist/controller/data-table-columns.d.ts +2 -0
  30. package/dist/controller/data-table-columns.js +50 -56
  31. package/dist/controller/deep-equal.d.ts +1 -0
  32. package/dist/controller/deep-equal.js +14 -0
  33. package/dist/controller/filter-toggle.js +36 -44
  34. package/dist/controller/in-place-editor.d.ts +42 -0
  35. package/dist/controller/in-place-editor.js +42 -0
  36. package/dist/controller/infinite-list-controller.js +220 -190
  37. package/dist/controller/inspector.d.ts +49 -0
  38. package/dist/controller/inspector.js +64 -0
  39. package/dist/controller/job-monitor.d.ts +41 -0
  40. package/dist/controller/job-monitor.js +49 -0
  41. package/dist/controller/kanban-board.d.ts +2 -3
  42. package/dist/controller/kanban-board.js +43 -24
  43. package/dist/controller/list-controller.d.ts +5 -5
  44. package/dist/controller/list-controller.js +444 -400
  45. package/dist/controller/list-params.js +96 -87
  46. package/dist/controller/pivot-grid.d.ts +36 -0
  47. package/dist/controller/pivot-grid.js +99 -0
  48. package/dist/controller/prev-next.d.ts +2 -2
  49. package/dist/controller/prev-next.js +74 -54
  50. package/dist/controller/record-controllers.d.ts +14 -6
  51. package/dist/controller/record-controllers.js +288 -257
  52. package/dist/controller/record-diff.d.ts +21 -0
  53. package/dist/controller/record-diff.js +50 -0
  54. package/dist/controller/record-timeline.d.ts +35 -0
  55. package/dist/controller/record-timeline.js +48 -0
  56. package/dist/controller/record-tree.js +57 -47
  57. package/dist/controller/record-workflow.d.ts +38 -16
  58. package/dist/controller/record-workflow.js +85 -64
  59. package/dist/controller/reference-many-controller.js +198 -192
  60. package/dist/controller/reference-one-controller.d.ts +1 -1
  61. package/dist/controller/reference-one-controller.js +63 -56
  62. package/dist/controller/saved-queries.js +104 -91
  63. package/dist/controller/translate-fallback.js +10 -6
  64. package/dist/csv/export.d.ts +2 -1
  65. package/dist/csv/export.js +43 -40
  66. package/dist/csv/import-controller.js +185 -169
  67. package/dist/csv/match-headers.js +29 -22
  68. package/dist/csv/parse-with.js +60 -54
  69. package/dist/csv/run-import.js +69 -72
  70. package/dist/csv/validate-rows.d.ts +1 -1
  71. package/dist/csv/validate-rows.js +65 -52
  72. package/dist/data/cache-ops.d.ts +5 -4
  73. package/dist/data/cache-ops.js +208 -190
  74. package/dist/data/combine-data-providers.js +25 -23
  75. package/dist/data/data-provider-log.d.ts +45 -0
  76. package/dist/data/data-provider-log.js +93 -0
  77. package/dist/data/errors.js +14 -10
  78. package/dist/data/fake-provider.d.ts +6 -3
  79. package/dist/data/fake-provider.js +129 -114
  80. package/dist/data/fetch-utils.js +61 -44
  81. package/dist/data/filter-branch.d.ts +5 -0
  82. package/dist/data/filter-branch.js +10 -0
  83. package/dist/data/get-many-aggregate.js +84 -76
  84. package/dist/data/http-error.js +17 -12
  85. package/dist/data/keys.js +50 -36
  86. package/dist/data/mutation-options.d.ts +14 -9
  87. package/dist/data/mutation-options.js +93 -109
  88. package/dist/data/query-options.js +73 -68
  89. package/dist/data/remove-empty.d.ts +3 -0
  90. package/dist/data/remove-empty.js +11 -0
  91. package/dist/data/undoable.d.ts +2 -2
  92. package/dist/data/undoable.js +190 -174
  93. package/dist/data/with-lifecycle-callbacks.d.ts +45 -17
  94. package/dist/data/with-lifecycle-callbacks.js +66 -52
  95. package/dist/environment/application-update-store.js +58 -55
  96. package/dist/environment/offline-store.js +21 -21
  97. package/dist/form/array-binding.d.ts +30 -11
  98. package/dist/form/array-binding.js +184 -166
  99. package/dist/form/choice-ids.d.ts +7 -0
  100. package/dist/form/choice-ids.js +11 -0
  101. package/dist/form/choices-controller.d.ts +3 -2
  102. package/dist/form/choices-controller.js +302 -275
  103. package/dist/form/date-format.d.ts +38 -0
  104. package/dist/form/date-format.js +89 -0
  105. package/dist/form/dirty-values.d.ts +2 -2
  106. package/dist/form/dirty-values.js +22 -11
  107. package/dist/form/duration.d.ts +22 -0
  108. package/dist/form/duration.js +49 -0
  109. package/dist/form/edit-create-form.d.ts +12 -5
  110. package/dist/form/edit-create-form.js +243 -188
  111. package/dist/form/event-value.d.ts +6 -0
  112. package/dist/form/event-value.js +17 -0
  113. package/dist/form/field-error.d.ts +14 -0
  114. package/dist/form/field-error.js +28 -0
  115. package/dist/form/field-name.d.ts +20 -0
  116. package/dist/form/field-name.js +6 -0
  117. package/dist/form/filter-form-values.js +63 -49
  118. package/dist/form/form-controller.d.ts +9 -1
  119. package/dist/form/form-controller.js +165 -160
  120. package/dist/form/form-groups.d.ts +4 -3
  121. package/dist/form/form-groups.js +79 -79
  122. package/dist/form/form-handle.d.ts +175 -0
  123. package/dist/form/form-handle.js +68 -0
  124. package/dist/form/input-binding.d.ts +56 -31
  125. package/dist/form/input-binding.js +169 -118
  126. package/dist/form/input-values.d.ts +130 -0
  127. package/dist/form/input-values.js +177 -0
  128. package/dist/form/json-text.js +51 -37
  129. package/dist/form/save-pipeline.d.ts +6 -8
  130. package/dist/form/save-pipeline.js +91 -82
  131. package/dist/form/set-form-values.d.ts +6 -0
  132. package/dist/form/set-form-values.js +10 -0
  133. package/dist/form/source.js +97 -65
  134. package/dist/form/text-of.d.ts +2 -0
  135. package/dist/form/text-of.js +7 -0
  136. package/dist/form/validators.d.ts +58 -19
  137. package/dist/form/validators.js +97 -71
  138. package/dist/geo/bbox.d.ts +5 -4
  139. package/dist/geo/bbox.js +69 -48
  140. package/dist/geo/bounds.d.ts +14 -3
  141. package/dist/geo/bounds.js +98 -68
  142. package/dist/geo/constraints.js +88 -93
  143. package/dist/geo/coordinates.js +31 -23
  144. package/dist/geo/editor.d.ts +13 -13
  145. package/dist/geo/editor.js +176 -153
  146. package/dist/geo/geocoding.d.ts +4 -4
  147. package/dist/geo/geocoding.js +38 -41
  148. package/dist/geo/geojson.d.ts +12 -74
  149. package/dist/geo/geojson.js +52 -40
  150. package/dist/geo/geometry-math.d.ts +4 -4
  151. package/dist/geo/geometry-math.js +100 -93
  152. package/dist/geo/index.d.ts +7 -6
  153. package/dist/geo/map-layers.d.ts +42 -7
  154. package/dist/geo/map-layers.js +88 -62
  155. package/dist/geo/map-style.js +31 -32
  156. package/dist/geo/messages.js +48 -45
  157. package/dist/geo/nominatim.js +88 -80
  158. package/dist/geo/osm-presets.d.ts +4 -3
  159. package/dist/geo/osm-presets.js +108 -86
  160. package/dist/geo/osm-tags.js +14 -12
  161. package/dist/geo/overpass.d.ts +14 -2
  162. package/dist/geo/overpass.js +83 -90
  163. package/dist/geo/shape-value.d.ts +9 -5
  164. package/dist/geo/shape-value.js +169 -146
  165. package/dist/geo/snap-to-roads.d.ts +3 -3
  166. package/dist/geo/snap-to-roads.js +55 -50
  167. package/dist/geo/throttle.js +36 -39
  168. package/dist/guards.d.ts +37 -0
  169. package/dist/guards.js +62 -0
  170. package/dist/i18n/default-messages.js +34 -29
  171. package/dist/i18n/english-messages.js +187 -189
  172. package/dist/i18n/i18n.d.ts +8 -2
  173. package/dist/i18n/i18n.js +47 -48
  174. package/dist/i18n/inflection.d.ts +34 -0
  175. package/dist/i18n/inflection.js +82 -0
  176. package/dist/i18n/messages.d.ts +10 -2
  177. package/dist/i18n/messages.js +17 -4
  178. package/dist/i18n/missing-keys.d.ts +19 -0
  179. package/dist/i18n/missing-keys.js +68 -0
  180. package/dist/i18n/translatable.d.ts +16 -1
  181. package/dist/i18n/translatable.js +40 -47
  182. package/dist/index.d.ts +96 -22
  183. package/dist/index.js +52 -257
  184. package/dist/json/deep-equal.d.ts +8 -0
  185. package/dist/json/deep-equal.js +24 -0
  186. package/dist/json/strip-json-comments.js +38 -42
  187. package/dist/noop.d.ts +2 -0
  188. package/dist/noop.js +4 -0
  189. package/dist/notification/error-message.d.ts +2 -0
  190. package/dist/notification/error-message.js +10 -0
  191. package/dist/notification/notification-store.d.ts +3 -2
  192. package/dist/notification/notification-store.js +41 -45
  193. package/dist/onboarding-tour/placement.d.ts +34 -0
  194. package/dist/onboarding-tour/placement.js +67 -0
  195. package/dist/onboarding-tour/tour-controller.d.ts +25 -0
  196. package/dist/onboarding-tour/tour-controller.js +50 -0
  197. package/dist/realtime/add-events-for-mutations.js +75 -81
  198. package/dist/realtime/announce-lock.d.ts +7 -0
  199. package/dist/realtime/announce-lock.js +18 -0
  200. package/dist/realtime/broadcast-channel-transport.d.ts +14 -0
  201. package/dist/realtime/broadcast-channel-transport.js +69 -0
  202. package/dist/realtime/copy-members.js +22 -14
  203. package/dist/realtime/in-memory-lock-provider.js +41 -60
  204. package/dist/realtime/live.js +95 -101
  205. package/dist/realtime/lock-options.js +16 -16
  206. package/dist/realtime/lock-session.js +91 -78
  207. package/dist/realtime/memory-transport.js +26 -67
  208. package/dist/realtime/presence.js +120 -122
  209. package/dist/realtime/realtime-data-provider.d.ts +10 -0
  210. package/dist/realtime/realtime-data-provider.js +45 -42
  211. package/dist/realtime/reconnect-backoff.d.ts +15 -0
  212. package/dist/realtime/reconnect-backoff.js +17 -0
  213. package/dist/realtime/sse-transport.d.ts +31 -0
  214. package/dist/realtime/sse-transport.js +235 -0
  215. package/dist/realtime/status-store.js +23 -28
  216. package/dist/realtime/topic-hub.d.ts +24 -0
  217. package/dist/realtime/topic-hub.js +66 -0
  218. package/dist/realtime/topics.js +10 -12
  219. package/dist/realtime/types.js +10 -12
  220. package/dist/realtime/unread-count.js +21 -21
  221. package/dist/realtime/websocket-transport.d.ts +32 -0
  222. package/dist/realtime/websocket-transport.js +306 -0
  223. package/dist/resource/describe-resource.d.ts +2 -0
  224. package/dist/resource/describe-resource.js +232 -219
  225. package/dist/resource/get-at-path.js +29 -14
  226. package/dist/resource/identifier.d.ts +18 -0
  227. package/dist/resource/identifier.js +27 -0
  228. package/dist/resource/record.d.ts +4 -0
  229. package/dist/resource/record.js +10 -0
  230. package/dist/resource/register.d.ts +7 -0
  231. package/dist/resource/registry-store.d.ts +45 -15
  232. package/dist/resource/registry-store.js +67 -60
  233. package/dist/resource/registry.d.ts +10 -0
  234. package/dist/resource/registry.js +8 -4
  235. package/dist/resource/source-path.d.ts +16 -1
  236. package/dist/rich-text/rich-text-extras.d.ts +132 -0
  237. package/dist/rich-text/rich-text-extras.js +179 -0
  238. package/dist/rich-text/rich-text-image.d.ts +124 -0
  239. package/dist/rich-text/rich-text-image.js +163 -0
  240. package/dist/rich-text/rich-text.d.ts +62 -0
  241. package/dist/rich-text/rich-text.js +142 -0
  242. package/dist/router/location.d.ts +22 -4
  243. package/dist/router/location.js +41 -18
  244. package/dist/router/match.js +47 -39
  245. package/dist/router/paths.js +40 -34
  246. package/dist/router/record-from-location.d.ts +1 -1
  247. package/dist/router/record-from-location.js +25 -17
  248. package/dist/store/adapters.js +51 -55
  249. package/dist/store/micro-store.js +57 -59
  250. package/dist/store/shallow-equal.d.ts +12 -0
  251. package/dist/store/shallow-equal.js +20 -0
  252. package/dist/store/store.js +54 -57
  253. package/package.json +13 -11
@@ -1,52 +1,57 @@
1
- const OSRM_MAX_POSITIONS = 100;
1
+ import { isRecord } from "../guards.js";
2
+ import { isGeoGeometry } from "./geojson.js";
3
+ // src/geo/snap-to-roads.ts
4
+ /** The match service rejects a request with more coordinates than this; a longer line is matched in chunks. */
5
+ var OSRM_MAX_POSITIONS = 100;
6
+ /**
7
+ * The line OSRM matched to one chunk, or `null` when the answer is not a
8
+ * single LineString of finite coordinates it can hand back.
9
+ */
10
+ function matchedLine(body) {
11
+ if (!isRecord(body) || body.code !== "Ok") return null;
12
+ if (!Array.isArray(body.matchings) || body.matchings.length !== 1) return null;
13
+ const matching = body.matchings[0];
14
+ if (!isRecord(matching)) return null;
15
+ const geometry = matching.geometry;
16
+ if (!isGeoGeometry(geometry) || geometry.type !== "LineString") return null;
17
+ return geometry.coordinates.length === 0 ? null : geometry.coordinates;
18
+ }
2
19
  function createOsrmProvider(options) {
3
- const { endpoint, profile = "driving" } = options;
4
- if (typeof endpoint !== "string" || endpoint.trim() === "") {
5
- throw new TypeError(
6
- 'createOsrmProvider: the "endpoint" option is required'
7
- );
8
- }
9
- const base = endpoint.trim().replace(/\/+$/, "");
10
- const doFetch = options.fetch ?? ((input, init) => globalThis.fetch(input, init));
11
- async function matchChunk(positions, signal) {
12
- const path = positions.map(([lng, lat]) => `${lng},${lat}`).join(";");
13
- try {
14
- const response = await doFetch(
15
- `${base}/match/v1/${profile}/${path}?geometries=geojson&overview=full`,
16
- { signal }
17
- );
18
- if (!response.ok) return null;
19
- const body = await response.json();
20
- if (body?.code !== "Ok") return null;
21
- if (body.matchings?.length !== 1) return null;
22
- const geometry = body.matchings[0]?.geometry;
23
- if (geometry?.type !== "LineString" || !Array.isArray(geometry.coordinates) || geometry.coordinates.length === 0) {
24
- return null;
25
- }
26
- return geometry.coordinates;
27
- } catch (error) {
28
- if (signal?.aborted) throw error;
29
- return null;
30
- }
31
- }
32
- return {
33
- name: "osrm",
34
- async snapToRoad(line, requestOptions = {}) {
35
- const { signal } = requestOptions;
36
- const positions = line.coordinates;
37
- if (positions.length < 2) return null;
38
- const joined = [];
39
- for (let start = 0; start < positions.length - 1; ) {
40
- const end = Math.min(start + OSRM_MAX_POSITIONS, positions.length);
41
- const piece = await matchChunk(positions.slice(start, end), signal);
42
- if (!piece) return null;
43
- joined.push(...start === 0 ? piece : piece.slice(1));
44
- start = end - 1;
45
- }
46
- return { type: "LineString", coordinates: joined };
47
- }
48
- };
20
+ const { endpoint, profile = "driving" } = options;
21
+ if (typeof endpoint !== "string" || endpoint.trim() === "") throw new TypeError("createOsrmProvider: the \"endpoint\" option is required");
22
+ const base = endpoint.trim().replace(/\/+$/, "");
23
+ const doFetch = options.fetch ?? ((input, init) => globalThis.fetch(input, init));
24
+ /** One match request; `null` when the server cannot match the chunk. */
25
+ async function matchChunk(positions, signal) {
26
+ const path = positions.map(([lng, lat]) => `${lng},${lat}`).join(";");
27
+ try {
28
+ const response = await doFetch(`${base}/match/v1/${profile}/${path}?geometries=geojson&overview=full`, { signal });
29
+ if (!response.ok) return null;
30
+ return matchedLine(await response.json());
31
+ } catch (error) {
32
+ if (signal?.aborted) throw error;
33
+ return null;
34
+ }
35
+ }
36
+ return {
37
+ name: "osrm",
38
+ async snapToRoad(line, requestOptions = {}) {
39
+ const { signal } = requestOptions;
40
+ const positions = line.coordinates;
41
+ if (positions.length < 2) return null;
42
+ const joined = [];
43
+ for (let start = 0; start < positions.length - 1;) {
44
+ const end = Math.min(start + OSRM_MAX_POSITIONS, positions.length);
45
+ const piece = await matchChunk(positions.slice(start, end), signal);
46
+ if (!piece) return null;
47
+ joined.push(...start === 0 ? piece : piece.slice(1));
48
+ start = end - 1;
49
+ }
50
+ return {
51
+ type: "LineString",
52
+ coordinates: joined
53
+ };
54
+ }
55
+ };
49
56
  }
50
- export {
51
- createOsrmProvider
52
- };
57
+ export { createOsrmProvider };
@@ -1,45 +1,42 @@
1
+ // src/geo/throttle.ts
1
2
  function abortError() {
2
- return new DOMException("Aborted", "AbortError");
3
+ return new DOMException("Aborted", "AbortError");
3
4
  }
4
5
  function timerSleep(ms, signal) {
5
- return new Promise((resolve, reject) => {
6
- if (signal?.aborted) return reject(abortError());
7
- const onAbort = () => {
8
- clearTimeout(timer);
9
- reject(abortError());
10
- };
11
- const timer = setTimeout(() => {
12
- signal?.removeEventListener("abort", onAbort);
13
- resolve();
14
- }, ms);
15
- signal?.addEventListener("abort", onAbort, { once: true });
16
- });
6
+ return new Promise((resolve, reject) => {
7
+ if (signal?.aborted) return reject(abortError());
8
+ const onAbort = () => {
9
+ clearTimeout(timer);
10
+ reject(abortError());
11
+ };
12
+ const timer = setTimeout(() => {
13
+ signal?.removeEventListener("abort", onAbort);
14
+ resolve();
15
+ }, ms);
16
+ signal?.addEventListener("abort", onAbort, { once: true });
17
+ });
17
18
  }
18
19
  function createThrottle(options) {
19
- const { minIntervalMs, now = Date.now, sleep = timerSleep } = options;
20
- let nextAllowedAt = Number.NEGATIVE_INFINITY;
21
- let tail = Promise.resolve();
22
- const takeTurn = async (signal) => {
23
- if (signal?.aborted) throw abortError();
24
- const delay = nextAllowedAt - now();
25
- if (delay > 0) await sleep(delay, signal);
26
- if (signal?.aborted) throw abortError();
27
- nextAllowedAt = now() + minIntervalMs;
28
- };
29
- return {
30
- wait(signal) {
31
- if (signal?.aborted) return Promise.reject(abortError());
32
- const turn = tail.then(() => takeTurn(signal));
33
- tail = turn.catch(() => void 0);
34
- if (!signal) return turn;
35
- return new Promise((resolve, reject) => {
36
- const onAbort = () => reject(abortError());
37
- signal.addEventListener("abort", onAbort, { once: true });
38
- turn.then(resolve, reject).finally(() => signal.removeEventListener("abort", onAbort));
39
- });
40
- }
41
- };
20
+ const { minIntervalMs, now = Date.now, sleep = timerSleep } = options;
21
+ let nextAllowedAt = Number.NEGATIVE_INFINITY;
22
+ let tail = Promise.resolve();
23
+ const takeTurn = async (signal) => {
24
+ if (signal?.aborted) throw abortError();
25
+ const delay = nextAllowedAt - now();
26
+ if (delay > 0) await sleep(delay, signal);
27
+ if (signal?.aborted) throw abortError();
28
+ nextAllowedAt = now() + minIntervalMs;
29
+ };
30
+ return { wait(signal) {
31
+ if (signal?.aborted) return Promise.reject(abortError());
32
+ const turn = tail.then(() => takeTurn(signal));
33
+ tail = turn.catch(() => void 0);
34
+ if (!signal) return turn;
35
+ return new Promise((resolve, reject) => {
36
+ const onAbort = () => reject(abortError());
37
+ signal.addEventListener("abort", onAbort, { once: true });
38
+ turn.then(resolve, reject).finally(() => signal.removeEventListener("abort", onAbort));
39
+ });
40
+ } };
42
41
  }
43
- export {
44
- createThrottle
45
- };
42
+ export { createThrottle };
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Core's object guards, in one place. Two questions, each answered once:
3
+ * `isRecord` — is it an object at all, so a Date, a Map and a class instance
4
+ * pass; `isPlainObject` — could a caller have written it as an object literal,
5
+ * which needs `Object.prototype` or `null` as its prototype. `isJsonObject`
6
+ * answers a third question, about what a value holds all the way down.
7
+ */
8
+ /** What JSON can hold: the members of a parsed document. */
9
+ export type JsonValue = string | number | boolean | null | JsonValue[] | JsonObject;
10
+ /** An object whose every member is a JSON value. */
11
+ export type JsonObject = {
12
+ [key: string]: JsonValue;
13
+ };
14
+ export declare function isRecord(value: unknown): value is Record<string, unknown>;
15
+ /**
16
+ * Could `value` have been written as an object literal? Only
17
+ * `Object.prototype` or `null` as its prototype passes, so a Date, a Map and a
18
+ * class instance do not.
19
+ */
20
+ export declare function isPlainObject(value: unknown): value is Record<string, unknown>;
21
+ /**
22
+ * An object that holds `key`, so `value[key]` reads without a cast. The
23
+ * member's type is `unknown`: the guard proves it is there, not what it is.
24
+ */
25
+ export declare function hasProperty<TKey extends string>(value: unknown, key: TKey): value is Record<TKey, unknown>;
26
+ /**
27
+ * Could `await value` wait on it? A promise, or any object with a `then`
28
+ * function. A bare function is refused even when it has no `then`.
29
+ */
30
+ export declare function isThenable(value: unknown): value is PromiseLike<unknown>;
31
+ /**
32
+ * True when `value` is an object JSON could have produced: plain objects and
33
+ * arrays down to strings, finite numbers, booleans and null. `NaN` and
34
+ * `Infinity` are refused, because `JSON.stringify` turns them into `null`, and
35
+ * so is a value that contains itself.
36
+ */
37
+ export declare function isJsonObject(value: unknown): value is JsonObject;
package/dist/guards.js ADDED
@@ -0,0 +1,62 @@
1
+ // src/guards.ts
2
+ function isRecord(value) {
3
+ return typeof value === "object" && value !== null && !Array.isArray(value);
4
+ }
5
+ /**
6
+ * Could `value` have been written as an object literal? Only
7
+ * `Object.prototype` or `null` as its prototype passes, so a Date, a Map and a
8
+ * class instance do not.
9
+ */
10
+ function isPlainObject(value) {
11
+ if (!isRecord(value)) return false;
12
+ const proto = Object.getPrototypeOf(value);
13
+ return proto === Object.prototype || proto === null;
14
+ }
15
+ /**
16
+ * An object that holds `key`, so `value[key]` reads without a cast. The
17
+ * member's type is `unknown`: the guard proves it is there, not what it is.
18
+ */
19
+ function hasProperty(value, key) {
20
+ return isRecord(value) && key in value;
21
+ }
22
+ /**
23
+ * Could `await value` wait on it? A promise, or any object with a `then`
24
+ * function. A bare function is refused even when it has no `then`.
25
+ */
26
+ function isThenable(value) {
27
+ return hasProperty(value, "then") && typeof value.then === "function";
28
+ }
29
+ /**
30
+ * True when `value` is an object JSON could have produced: plain objects and
31
+ * arrays down to strings, finite numbers, booleans and null. `NaN` and
32
+ * `Infinity` are refused, because `JSON.stringify` turns them into `null`, and
33
+ * so is a value that contains itself.
34
+ */
35
+ function isJsonObject(value) {
36
+ return isPlainObject(value) && isJsonValue(value, /* @__PURE__ */ new WeakSet());
37
+ }
38
+ /**
39
+ * The deep half of `isJsonObject`. `path` holds the containers `value` sits
40
+ * inside, so a value that contains itself is refused instead of walked
41
+ * forever; a shared sub-object, which no container holds twice on one path,
42
+ * still passes.
43
+ */
44
+ function isJsonValue(value, path) {
45
+ if (value === null) return true;
46
+ if (typeof value === "string" || typeof value === "boolean") return true;
47
+ if (typeof value === "number") return Number.isFinite(value);
48
+ if (Array.isArray(value)) {
49
+ if (path.has(value)) return false;
50
+ path.add(value);
51
+ const held = value.every((item) => isJsonValue(item, path));
52
+ path.delete(value);
53
+ return held;
54
+ }
55
+ if (!isPlainObject(value)) return false;
56
+ if (path.has(value)) return false;
57
+ path.add(value);
58
+ const held = Object.values(value).every((item) => isJsonValue(item, path));
59
+ path.delete(value);
60
+ return held;
61
+ }
62
+ export { hasProperty, isJsonObject, isPlainObject, isRecord, isThenable };
@@ -1,31 +1,36 @@
1
1
  import { defineMessages } from "./messages.js";
2
- const defaultMessages = defineMessages({
3
- "chelone.auth.auth_check_error": "Please login to continue",
4
- "chelone.auth.logout": "Logout",
5
- "chelone.message.access_denied": "You don't have access to this page",
6
- "chelone.message.authentication_error": "The authentication server returned an error",
7
- "chelone.message.invalid_form": "The form is not valid. Please check for errors",
8
- "chelone.message.loading": "The page is loading, just a moment please",
9
- "chelone.message.not_found": "Either you typed a wrong URL, or you followed a bad link.",
10
- "chelone.message.select_all_limit_reached": "There are too many elements to select them all. Only the first {max} elements were selected",
11
- "chelone.message.unsaved_changes": "Some of your changes weren't saved. Are you sure you want to ignore them?",
12
- "chelone.notification.created": "Element created",
13
- "chelone.notification.deleted": "Element deleted",
14
- "chelone.notification.http_error": "Server communication error",
15
- "chelone.notification.item_doesnt_exist": "Element does not exist",
16
- "chelone.notification.logged_out": "Your session has ended, please reconnect",
17
- "chelone.notification.not_authorized": "You are not authorized to access this resource",
18
- "chelone.notification.updated": "Element updated",
19
- "chelone.validation.email": "Must be a valid email",
20
- "chelone.validation.maxLength": "Must be {max} characters or less",
21
- "chelone.validation.maxValue": "Must be {max} or less",
22
- "chelone.validation.minLength": "Must be {min} characters at least",
23
- "chelone.validation.minValue": "Must be at least {min}",
24
- "chelone.validation.number": "Must be a number",
25
- "chelone.validation.oneOf": "Must be one of: {options}",
26
- "chelone.validation.regex": "Must match a specific format (regexp): {pattern}",
27
- "chelone.validation.required": "Required"
2
+ // src/i18n/default-messages.ts
3
+ /**
4
+ * English defaults for every i18n key the core controllers emit. Apps merge
5
+ * these under their own catalogs (`{ ...defaultMessages, ...appMessages }`);
6
+ * resource-scoped keys (`resources.{name}.notifications.{event}`) override
7
+ * them through the translate-fallback pattern.
8
+ */
9
+ var defaultMessages = defineMessages({
10
+ "chelone.auth.auth_check_error": "Please login to continue",
11
+ "chelone.auth.logout": "Logout",
12
+ "chelone.message.access_denied": "You don't have access to this page",
13
+ "chelone.message.authentication_error": "The authentication server returned an error",
14
+ "chelone.message.invalid_form": "The form is not valid. Please check for errors",
15
+ "chelone.message.loading": "The page is loading, just a moment please",
16
+ "chelone.message.not_found": "Either you typed a wrong URL, or you followed a bad link.",
17
+ "chelone.message.select_all_limit_reached": "There are too many elements to select them all. Only the first {max} elements were selected",
18
+ "chelone.message.unsaved_changes": "Some of your changes weren't saved. Are you sure you want to ignore them?",
19
+ "chelone.notification.created": "Element created",
20
+ "chelone.notification.deleted": "Element deleted",
21
+ "chelone.notification.http_error": "Server communication error",
22
+ "chelone.notification.item_doesnt_exist": "Element does not exist",
23
+ "chelone.notification.logged_out": "Your session has ended, please reconnect",
24
+ "chelone.notification.not_authorized": "You are not authorized to access this resource",
25
+ "chelone.notification.updated": "Element updated",
26
+ "chelone.validation.email": "Must be a valid email",
27
+ "chelone.validation.maxLength": "Must be {max} characters or less",
28
+ "chelone.validation.maxValue": "Must be {max} or less",
29
+ "chelone.validation.minLength": "Must be {min} characters at least",
30
+ "chelone.validation.minValue": "Must be at least {min}",
31
+ "chelone.validation.number": "Must be a number",
32
+ "chelone.validation.oneOf": "Must be one of: {options}",
33
+ "chelone.validation.regex": "Must match a specific format (regexp): {pattern}",
34
+ "chelone.validation.required": "Required"
28
35
  });
29
- export {
30
- defaultMessages
31
- };
36
+ export { defaultMessages };