@happyvertical/smrt-svelte 0.37.8 → 0.37.10

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 (90) hide show
  1. package/AGENTS.md +22 -86
  2. package/README.md +14 -10
  3. package/dist/components/workspace/MIGRATION.md +55 -0
  4. package/dist/components/workspace/README.md +22 -25
  5. package/dist/components/workspace/__tests__/AdminShell.test.js +55 -0
  6. package/dist/components/workspace/__tests__/admin-shell-hotkeys.test.js +34 -0
  7. package/dist/components/workspace/__tests__/admin-shell-settings.test.js +25 -0
  8. package/dist/components/workspace/__tests__/admin-shell-state.test.js +110 -0
  9. package/dist/components/workspace/__tests__/index.test.js +15 -24
  10. package/dist/components/workspace/__tests__/typed-tool-fixture/register-typed-tool.d.ts +2 -1
  11. package/dist/components/workspace/__tests__/typed-tool-fixture/register-typed-tool.d.ts.map +1 -1
  12. package/dist/components/workspace/__tests__/typed-tool-fixture/register-typed-tool.js +1 -1
  13. package/dist/components/workspace/admin-shell/ActivityBadge.svelte +25 -0
  14. package/dist/components/workspace/admin-shell/ActivityBadge.svelte.d.ts +9 -0
  15. package/dist/components/workspace/admin-shell/ActivityBadge.svelte.d.ts.map +1 -0
  16. package/dist/components/workspace/admin-shell/ActivityItem.svelte +85 -0
  17. package/dist/components/workspace/admin-shell/ActivityItem.svelte.d.ts +8 -0
  18. package/dist/components/workspace/admin-shell/ActivityItem.svelte.d.ts.map +1 -0
  19. package/dist/components/workspace/admin-shell/ActivityList.svelte +41 -0
  20. package/dist/components/workspace/admin-shell/ActivityList.svelte.d.ts +10 -0
  21. package/dist/components/workspace/admin-shell/ActivityList.svelte.d.ts.map +1 -0
  22. package/dist/components/workspace/admin-shell/ActivityToasts.svelte +140 -0
  23. package/dist/components/workspace/admin-shell/ActivityToasts.svelte.d.ts +16 -0
  24. package/dist/components/workspace/admin-shell/ActivityToasts.svelte.d.ts.map +1 -0
  25. package/dist/components/workspace/admin-shell/AdminShell.svelte +691 -0
  26. package/dist/components/workspace/admin-shell/AdminShell.svelte.d.ts +24 -0
  27. package/dist/components/workspace/admin-shell/AdminShell.svelte.d.ts.map +1 -0
  28. package/dist/components/workspace/admin-shell/AppScopePanel.svelte +94 -0
  29. package/dist/components/workspace/admin-shell/AppScopePanel.svelte.d.ts +14 -0
  30. package/dist/components/workspace/admin-shell/AppScopePanel.svelte.d.ts.map +1 -0
  31. package/dist/components/workspace/admin-shell/HotkeyInput.svelte +74 -0
  32. package/dist/components/workspace/admin-shell/HotkeyInput.svelte.d.ts +11 -0
  33. package/dist/components/workspace/admin-shell/HotkeyInput.svelte.d.ts.map +1 -0
  34. package/dist/components/workspace/admin-shell/ShellCorner.svelte +25 -0
  35. package/dist/components/workspace/admin-shell/ShellCorner.svelte.d.ts +9 -0
  36. package/dist/components/workspace/admin-shell/ShellCorner.svelte.d.ts.map +1 -0
  37. package/dist/components/workspace/admin-shell/ShellDockTool.svelte +19 -0
  38. package/dist/components/workspace/admin-shell/ShellDockTool.svelte.d.ts +7 -0
  39. package/dist/components/workspace/admin-shell/ShellDockTool.svelte.d.ts.map +1 -0
  40. package/dist/components/workspace/admin-shell/ShellSettingsPanel.svelte +146 -0
  41. package/dist/components/workspace/admin-shell/ShellSettingsPanel.svelte.d.ts +4 -0
  42. package/dist/components/workspace/admin-shell/ShellSettingsPanel.svelte.d.ts.map +1 -0
  43. package/dist/components/workspace/admin-shell/ShortcutsOverlay.svelte +81 -0
  44. package/dist/components/workspace/admin-shell/ShortcutsOverlay.svelte.d.ts +7 -0
  45. package/dist/components/workspace/admin-shell/ShortcutsOverlay.svelte.d.ts.map +1 -0
  46. package/dist/components/workspace/admin-shell/SystemScopePanel.svelte +118 -0
  47. package/dist/components/workspace/admin-shell/SystemScopePanel.svelte.d.ts +9 -0
  48. package/dist/components/workspace/admin-shell/SystemScopePanel.svelte.d.ts.map +1 -0
  49. package/dist/components/workspace/admin-shell/SystemStatusChips.svelte +71 -0
  50. package/dist/components/workspace/admin-shell/SystemStatusChips.svelte.d.ts +8 -0
  51. package/dist/components/workspace/admin-shell/SystemStatusChips.svelte.d.ts.map +1 -0
  52. package/dist/components/workspace/admin-shell/TenantNav.svelte +101 -0
  53. package/dist/components/workspace/admin-shell/TenantNav.svelte.d.ts +10 -0
  54. package/dist/components/workspace/admin-shell/TenantNav.svelte.d.ts.map +1 -0
  55. package/dist/components/workspace/admin-shell/context.d.ts +6 -0
  56. package/dist/components/workspace/admin-shell/context.d.ts.map +1 -0
  57. package/dist/components/workspace/admin-shell/context.js +16 -0
  58. package/dist/components/workspace/admin-shell/hotkeys.d.ts +14 -0
  59. package/dist/components/workspace/admin-shell/hotkeys.d.ts.map +1 -0
  60. package/dist/components/workspace/admin-shell/hotkeys.js +62 -0
  61. package/dist/components/workspace/admin-shell/settings.d.ts +14 -0
  62. package/dist/components/workspace/admin-shell/settings.d.ts.map +1 -0
  63. package/dist/components/workspace/admin-shell/settings.js +139 -0
  64. package/dist/components/workspace/admin-shell/state.svelte.d.ts +47 -0
  65. package/dist/components/workspace/admin-shell/state.svelte.d.ts.map +1 -0
  66. package/dist/components/workspace/admin-shell/state.svelte.js +252 -0
  67. package/dist/components/workspace/admin-shell/types.d.ts +137 -0
  68. package/dist/components/workspace/admin-shell/types.d.ts.map +1 -0
  69. package/dist/components/workspace/admin-shell/types.js +13 -0
  70. package/dist/components/workspace/index.d.ts +25 -11
  71. package/dist/components/workspace/index.d.ts.map +1 -1
  72. package/dist/components/workspace/index.js +24 -10
  73. package/dist/i18n/strings.workspace.d.ts +30 -0
  74. package/dist/i18n/strings.workspace.d.ts.map +1 -1
  75. package/dist/i18n/strings.workspace.js +31 -0
  76. package/dist/internal/logger.d.ts +13 -6
  77. package/dist/internal/logger.d.ts.map +1 -1
  78. package/dist/internal/logger.js +33 -8
  79. package/dist/internal/logger.test.js +54 -0
  80. package/dist/web/__tests__/harness.svelte +25 -0
  81. package/dist/web/__tests__/harness.svelte.d.ts +15 -0
  82. package/dist/web/__tests__/harness.svelte.d.ts.map +1 -0
  83. package/dist/web/__tests__/live-collection.svelte.test.js +184 -0
  84. package/dist/web/index.d.ts +13 -0
  85. package/dist/web/index.d.ts.map +1 -0
  86. package/dist/web/index.js +12 -0
  87. package/dist/web/live-collection.svelte.d.ts +132 -0
  88. package/dist/web/live-collection.svelte.d.ts.map +1 -0
  89. package/dist/web/live-collection.svelte.js +173 -0
  90. package/package.json +13 -4
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Svelte 5 live-query bindings for `@happyvertical/smrt-web` (#1761, slice A).
3
+ *
4
+ * Turns a SMRT-owned {@link SmrtWebCollection} into runes-reactive live-query
5
+ * state plus mutation helpers, so a consumer writes reactive components WITHOUT
6
+ * importing TanStack. The client-data engine (`@tanstack/db` +
7
+ * `@tanstack/svelte-db`) is used only inside this module — its types never
8
+ * appear on the public surface, mirroring smrt-web's own engine-absorption
9
+ * boundary (ratified condition for #1761).
10
+ *
11
+ * Two engine facts drive the shape of this file:
12
+ *
13
+ * 1. `useLiveQuery` internally uses `$state`/`$derived`/`$effect`, so it (and
14
+ * therefore {@link liveCollection}) MUST be called during Svelte component
15
+ * initialization — exactly like this package's other `use*` composables.
16
+ * Its internal `$effect` binds to the calling component's lifecycle, so the
17
+ * live subscription is torn down automatically when the component unmounts.
18
+ *
19
+ * 2. `@tanstack/svelte-db` live-query rows carry ENUMERABLE engine virtual
20
+ * props (`$key`/`$origin`/`$synced`/`$collectionId`) that would otherwise
21
+ * escape through spread or JSON. Every exposed row is projected to a plain
22
+ * DTO by stripping `$`-prefixed keys (the `$` prefix is reserved for the
23
+ * engine; SMRT columns never begin with it), mirroring smrt-web's internal
24
+ * `toPlainRow`.
25
+ */
26
+ import { getEngineCollection, } from '@happyvertical/smrt-web';
27
+ import { useLiveQuery } from '@tanstack/svelte-db';
28
+ /**
29
+ * Project an engine live-query row to a plain public DTO by dropping every
30
+ * `$`-prefixed key. Mirrors smrt-web's internal `toPlainRow`: the `$` prefix is
31
+ * reserved for the engine's enumerable virtual props (`$key`/`$origin`/
32
+ * `$synced`/`$collectionId`); SMRT columns never begin with it. Char code 36
33
+ * is `'$'`.
34
+ */
35
+ function toPlainRow(row) {
36
+ const plain = {};
37
+ for (const [key, value] of Object.entries(row)) {
38
+ if (key.charCodeAt(0) !== 36)
39
+ plain[key] = value;
40
+ }
41
+ return plain;
42
+ }
43
+ /** Map the engine's fine-grained status to the coarse SMRT-owned status. */
44
+ function toLiveStatus(isReady, isError) {
45
+ if (isError)
46
+ return 'error';
47
+ if (isReady)
48
+ return 'ready';
49
+ return 'loading';
50
+ }
51
+ /**
52
+ * Create a runes-reactive live view over a {@link SmrtWebCollection}.
53
+ *
54
+ * MUST be called during Svelte component initialization (it delegates to
55
+ * `@tanstack/svelte-db`'s `useLiveQuery`, which sets up a `$effect`). The live
56
+ * subscription is torn down automatically when the calling component unmounts.
57
+ *
58
+ * @example
59
+ * ```svelte
60
+ * <script lang="ts">
61
+ * import { createSmrtCollection } from '@happyvertical/smrt-web';
62
+ * import { liveCollection } from '@happyvertical/smrt-svelte/web';
63
+ * import { productsDefinition } from '@happyvertical/smrt-virt-web';
64
+ *
65
+ * const products = createSmrtCollection(productsDefinition, {});
66
+ * const view = liveCollection(products);
67
+ *
68
+ * async function add() {
69
+ * const m = view.insert({ id: crypto.randomUUID(), name: 'New' });
70
+ * await m.done.catch(() => {}); // error also reflected on m.error
71
+ * }
72
+ * </script>
73
+ *
74
+ * {#if view.isLoading}
75
+ * <p>Loading…</p>
76
+ * {:else if view.isError}
77
+ * <p>Failed: {String(view.error)}</p>
78
+ * {:else}
79
+ * <ul>
80
+ * {#each view.rows as row (row.id)}
81
+ * <li>{row.name}</li>
82
+ * {/each}
83
+ * </ul>
84
+ * {/if}
85
+ * ```
86
+ */
87
+ export function liveCollection(handle, options = {}) {
88
+ const { preload = true } = options;
89
+ // Bridge to the engine collection (typed `unknown` at the boundary — cast to
90
+ // the engine `Collection` here, and confine that type to this module).
91
+ const engine = getEngineCollection(handle);
92
+ // Kick the first load without forcing consumers to await preload() — the
93
+ // live query subscribes lazily, so nudge it when requested. Swallow the
94
+ // rejection: a load failure (network error, or an SSR relative-URL
95
+ // `Failed to parse URL` TypeError) already surfaces reactively via the
96
+ // live-query status; this fire-and-forget must not become an unhandled
97
+ // rejection.
98
+ if (preload) {
99
+ void handle.preload().catch(() => { });
100
+ }
101
+ // The live query over the whole base collection. No `.select()` → `data`
102
+ // carries the full row objects (with engine virtual props, stripped below).
103
+ // `useLiveQuery` installs a `$effect`; calling `liveCollection` outside a
104
+ // component surfaces Svelte's own "effect outside component" error, which is
105
+ // the correct signal.
106
+ const query = useLiveQuery((q) => q.from({ row: engine }));
107
+ // Project rows to plain DTOs reactively. `query.data` is a $state-backed
108
+ // reactive array; `$derived.by` recomputes the projection when it changes.
109
+ const rows = $derived.by(() => query.data.map((row) => toPlainRow(row)));
110
+ const status = $derived(toLiveStatus(query.isReady, query.isError));
111
+ // useLiveQuery does not surface an error object, only an error status; expose
112
+ // the status string as the error payload when the read has failed.
113
+ const error = $derived(query.isError ? query.status : null);
114
+ return {
115
+ get rows() {
116
+ return rows;
117
+ },
118
+ get status() {
119
+ return status;
120
+ },
121
+ get error() {
122
+ return error;
123
+ },
124
+ get isLoading() {
125
+ return status === 'loading';
126
+ },
127
+ get isReady() {
128
+ return status === 'ready';
129
+ },
130
+ get isError() {
131
+ return status === 'error';
132
+ },
133
+ insert(row) {
134
+ return createMutation(() => handle.insert(row).isPersisted.promise);
135
+ },
136
+ };
137
+ }
138
+ /**
139
+ * Wrap a transaction's settle promise in a reactive {@link LiveCollectionMutation}.
140
+ * Runs the mutation immediately; tracks pending/error via runes. Kept separate
141
+ * so `insert` (and future `update`/`delete` helpers) share one reactive shape.
142
+ */
143
+ function createMutation(run) {
144
+ let pending = $state(true);
145
+ let settled = $state(false);
146
+ let error = $state(null);
147
+ // `done` RESOLVES on settle whether the write persisted or rolled back — the
148
+ // failure is surfaced only reactively via `error`. Re-throwing here would
149
+ // reject `done`, which a reactive-only consumer (reads `error`/`pending` in
150
+ // markup, never awaits `done`) would leave as an unhandled rejection.
151
+ const done = run().then(() => {
152
+ pending = false;
153
+ settled = true;
154
+ }, (cause) => {
155
+ pending = false;
156
+ settled = true;
157
+ error = cause;
158
+ });
159
+ return {
160
+ get pending() {
161
+ return pending;
162
+ },
163
+ get settled() {
164
+ return settled;
165
+ },
166
+ get error() {
167
+ return error;
168
+ },
169
+ get done() {
170
+ return done;
171
+ },
172
+ };
173
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-svelte",
3
- "version": "0.37.8",
3
+ "version": "0.37.10",
4
4
  "description": "Svelte 5 components for SMRT user management - auth, users, tenants, roles, permissions, groups",
5
5
  "type": "module",
6
6
  "smrtRawPrimitives": "strict",
@@ -46,6 +46,12 @@
46
46
  "svelte": "./dist/browser-ai/svelte/index.js",
47
47
  "import": "./dist/browser-ai/svelte/index.js",
48
48
  "default": "./dist/browser-ai/svelte/index.js"
49
+ },
50
+ "./web": {
51
+ "types": "./dist/web/index.d.ts",
52
+ "svelte": "./dist/web/index.js",
53
+ "import": "./dist/web/index.js",
54
+ "default": "./dist/web/index.js"
49
55
  }
50
56
  },
51
57
  "files": [
@@ -77,10 +83,13 @@
77
83
  },
78
84
  "dependencies": {
79
85
  "@happyvertical/logger": "^0.74.11",
86
+ "@tanstack/db": "^0.6.14",
87
+ "@tanstack/svelte-db": "^0.1.91",
80
88
  "esm-env": "^1.2.2",
81
- "@happyvertical/smrt-ui": "0.37.8",
82
- "@happyvertical/smrt-languages": "0.37.8",
83
- "@happyvertical/smrt-types": "0.37.8"
89
+ "@happyvertical/smrt-languages": "0.37.10",
90
+ "@happyvertical/smrt-types": "0.37.10",
91
+ "@happyvertical/smrt-ui": "0.37.10",
92
+ "@happyvertical/smrt-web": "0.37.10"
84
93
  },
85
94
  "peerDependencies": {
86
95
  "@huggingface/transformers": ">=3.8.1",