@prabhask5/stellar-engine 1.1.6 → 1.1.8

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 (265) hide show
  1. package/README.md +68 -25
  2. package/dist/actions/remoteChange.d.ts +143 -18
  3. package/dist/actions/remoteChange.d.ts.map +1 -1
  4. package/dist/actions/remoteChange.js +182 -58
  5. package/dist/actions/remoteChange.js.map +1 -1
  6. package/dist/actions/truncateTooltip.d.ts +56 -0
  7. package/dist/actions/truncateTooltip.d.ts.map +1 -0
  8. package/dist/actions/truncateTooltip.js +312 -0
  9. package/dist/actions/truncateTooltip.js.map +1 -0
  10. package/dist/auth/admin.d.ts +40 -3
  11. package/dist/auth/admin.d.ts.map +1 -1
  12. package/dist/auth/admin.js +45 -5
  13. package/dist/auth/admin.js.map +1 -1
  14. package/dist/auth/crypto.d.ts +55 -5
  15. package/dist/auth/crypto.d.ts.map +1 -1
  16. package/dist/auth/crypto.js +58 -5
  17. package/dist/auth/crypto.js.map +1 -1
  18. package/dist/auth/deviceVerification.d.ts +236 -20
  19. package/dist/auth/deviceVerification.d.ts.map +1 -1
  20. package/dist/auth/deviceVerification.js +293 -40
  21. package/dist/auth/deviceVerification.js.map +1 -1
  22. package/dist/auth/displayUtils.d.ts +98 -0
  23. package/dist/auth/displayUtils.d.ts.map +1 -0
  24. package/dist/auth/displayUtils.js +133 -0
  25. package/dist/auth/displayUtils.js.map +1 -0
  26. package/dist/auth/loginGuard.d.ts +108 -14
  27. package/dist/auth/loginGuard.d.ts.map +1 -1
  28. package/dist/auth/loginGuard.js +153 -31
  29. package/dist/auth/loginGuard.js.map +1 -1
  30. package/dist/auth/offlineCredentials.d.ts +132 -15
  31. package/dist/auth/offlineCredentials.d.ts.map +1 -1
  32. package/dist/auth/offlineCredentials.js +167 -23
  33. package/dist/auth/offlineCredentials.js.map +1 -1
  34. package/dist/auth/offlineLogin.d.ts +96 -10
  35. package/dist/auth/offlineLogin.d.ts.map +1 -1
  36. package/dist/auth/offlineLogin.js +82 -15
  37. package/dist/auth/offlineLogin.js.map +1 -1
  38. package/dist/auth/offlineSession.d.ts +83 -9
  39. package/dist/auth/offlineSession.d.ts.map +1 -1
  40. package/dist/auth/offlineSession.js +104 -13
  41. package/dist/auth/offlineSession.js.map +1 -1
  42. package/dist/auth/resolveAuthState.d.ts +70 -8
  43. package/dist/auth/resolveAuthState.d.ts.map +1 -1
  44. package/dist/auth/resolveAuthState.js +142 -46
  45. package/dist/auth/resolveAuthState.js.map +1 -1
  46. package/dist/auth/singleUser.d.ts +390 -37
  47. package/dist/auth/singleUser.d.ts.map +1 -1
  48. package/dist/auth/singleUser.js +505 -133
  49. package/dist/auth/singleUser.js.map +1 -1
  50. package/dist/bin/install-pwa.d.ts +25 -0
  51. package/dist/bin/install-pwa.d.ts.map +1 -0
  52. package/dist/bin/install-pwa.js +2197 -0
  53. package/dist/bin/install-pwa.js.map +1 -0
  54. package/dist/config.d.ts +132 -12
  55. package/dist/config.d.ts.map +1 -1
  56. package/dist/config.js +87 -9
  57. package/dist/config.js.map +1 -1
  58. package/dist/conflicts.d.ts +246 -23
  59. package/dist/conflicts.d.ts.map +1 -1
  60. package/dist/conflicts.js +495 -46
  61. package/dist/conflicts.js.map +1 -1
  62. package/dist/data.d.ts +338 -18
  63. package/dist/data.d.ts.map +1 -1
  64. package/dist/data.js +385 -34
  65. package/dist/data.js.map +1 -1
  66. package/dist/database.d.ts +72 -14
  67. package/dist/database.d.ts.map +1 -1
  68. package/dist/database.js +120 -29
  69. package/dist/database.js.map +1 -1
  70. package/dist/debug.d.ts +77 -1
  71. package/dist/debug.d.ts.map +1 -1
  72. package/dist/debug.js +88 -1
  73. package/dist/debug.js.map +1 -1
  74. package/dist/deviceId.d.ts +38 -7
  75. package/dist/deviceId.d.ts.map +1 -1
  76. package/dist/deviceId.js +68 -10
  77. package/dist/deviceId.js.map +1 -1
  78. package/dist/engine.d.ts +175 -3
  79. package/dist/engine.d.ts.map +1 -1
  80. package/dist/engine.js +831 -110
  81. package/dist/engine.js.map +1 -1
  82. package/dist/entries/actions.d.ts +14 -0
  83. package/dist/entries/actions.d.ts.map +1 -1
  84. package/dist/entries/actions.js +27 -1
  85. package/dist/entries/actions.js.map +1 -1
  86. package/dist/entries/auth.d.ts +16 -0
  87. package/dist/entries/auth.d.ts.map +1 -1
  88. package/dist/entries/auth.js +73 -1
  89. package/dist/entries/auth.js.map +1 -1
  90. package/dist/entries/config.d.ts +12 -0
  91. package/dist/entries/config.d.ts.map +1 -1
  92. package/dist/entries/config.js +18 -1
  93. package/dist/entries/config.js.map +1 -1
  94. package/dist/entries/kit.d.ts +21 -9
  95. package/dist/entries/kit.d.ts.map +1 -1
  96. package/dist/entries/kit.js +57 -8
  97. package/dist/entries/kit.js.map +1 -1
  98. package/dist/entries/stores.d.ts +11 -0
  99. package/dist/entries/stores.d.ts.map +1 -1
  100. package/dist/entries/stores.js +43 -2
  101. package/dist/entries/stores.js.map +1 -1
  102. package/dist/entries/types.d.ts +11 -1
  103. package/dist/entries/types.d.ts.map +1 -1
  104. package/dist/entries/types.js +10 -0
  105. package/dist/entries/types.js.map +1 -1
  106. package/dist/entries/utils.d.ts +7 -1
  107. package/dist/entries/utils.d.ts.map +1 -1
  108. package/dist/entries/utils.js +23 -2
  109. package/dist/entries/utils.js.map +1 -1
  110. package/dist/entries/vite.d.ts +20 -0
  111. package/dist/entries/vite.d.ts.map +1 -0
  112. package/dist/entries/vite.js +26 -0
  113. package/dist/entries/vite.js.map +1 -0
  114. package/dist/index.d.ts +33 -2
  115. package/dist/index.d.ts.map +1 -1
  116. package/dist/index.js +176 -21
  117. package/dist/index.js.map +1 -1
  118. package/dist/kit/auth.d.ts +80 -0
  119. package/dist/kit/auth.d.ts.map +1 -0
  120. package/dist/kit/auth.js +72 -0
  121. package/dist/kit/auth.js.map +1 -0
  122. package/dist/kit/confirm.d.ts +111 -0
  123. package/dist/kit/confirm.d.ts.map +1 -0
  124. package/dist/kit/confirm.js +169 -0
  125. package/dist/kit/confirm.js.map +1 -0
  126. package/dist/kit/loads.d.ts +189 -0
  127. package/dist/kit/loads.d.ts.map +1 -0
  128. package/dist/kit/loads.js +205 -0
  129. package/dist/kit/loads.js.map +1 -0
  130. package/dist/kit/server.d.ts +175 -0
  131. package/dist/kit/server.d.ts.map +1 -0
  132. package/dist/kit/server.js +297 -0
  133. package/dist/kit/server.js.map +1 -0
  134. package/dist/kit/sw.d.ts +176 -0
  135. package/dist/kit/sw.d.ts.map +1 -0
  136. package/dist/kit/sw.js +320 -0
  137. package/dist/kit/sw.js.map +1 -0
  138. package/dist/queue.d.ts +274 -0
  139. package/dist/queue.d.ts.map +1 -1
  140. package/dist/queue.js +556 -38
  141. package/dist/queue.js.map +1 -1
  142. package/dist/realtime.d.ts +241 -27
  143. package/dist/realtime.d.ts.map +1 -1
  144. package/dist/realtime.js +633 -109
  145. package/dist/realtime.js.map +1 -1
  146. package/dist/runtime/runtimeConfig.d.ts +91 -16
  147. package/dist/runtime/runtimeConfig.d.ts.map +1 -1
  148. package/dist/runtime/runtimeConfig.js +146 -19
  149. package/dist/runtime/runtimeConfig.js.map +1 -1
  150. package/dist/stores/authState.d.ts +150 -11
  151. package/dist/stores/authState.d.ts.map +1 -1
  152. package/dist/stores/authState.js +169 -17
  153. package/dist/stores/authState.js.map +1 -1
  154. package/dist/stores/network.d.ts +39 -0
  155. package/dist/stores/network.d.ts.map +1 -1
  156. package/dist/stores/network.js +169 -16
  157. package/dist/stores/network.js.map +1 -1
  158. package/dist/stores/remoteChanges.d.ts +327 -52
  159. package/dist/stores/remoteChanges.d.ts.map +1 -1
  160. package/dist/stores/remoteChanges.js +337 -75
  161. package/dist/stores/remoteChanges.js.map +1 -1
  162. package/dist/stores/sync.d.ts +130 -0
  163. package/dist/stores/sync.d.ts.map +1 -1
  164. package/dist/stores/sync.js +167 -7
  165. package/dist/stores/sync.js.map +1 -1
  166. package/dist/supabase/auth.d.ts +326 -19
  167. package/dist/supabase/auth.d.ts.map +1 -1
  168. package/dist/supabase/auth.js +374 -26
  169. package/dist/supabase/auth.js.map +1 -1
  170. package/dist/supabase/client.d.ts +79 -6
  171. package/dist/supabase/client.d.ts.map +1 -1
  172. package/dist/supabase/client.js +158 -15
  173. package/dist/supabase/client.js.map +1 -1
  174. package/dist/supabase/validate.d.ts +101 -7
  175. package/dist/supabase/validate.d.ts.map +1 -1
  176. package/dist/supabase/validate.js +117 -8
  177. package/dist/supabase/validate.js.map +1 -1
  178. package/dist/sw/build/vite-plugin.d.ts +74 -0
  179. package/dist/sw/build/vite-plugin.d.ts.map +1 -0
  180. package/dist/sw/build/vite-plugin.js +183 -0
  181. package/dist/sw/build/vite-plugin.js.map +1 -0
  182. package/dist/sw/sw.js +669 -0
  183. package/dist/types.d.ts +150 -45
  184. package/dist/types.d.ts.map +1 -1
  185. package/dist/types.js +12 -10
  186. package/dist/types.js.map +1 -1
  187. package/dist/utils.d.ts +55 -13
  188. package/dist/utils.d.ts.map +1 -1
  189. package/dist/utils.js +83 -22
  190. package/dist/utils.js.map +1 -1
  191. package/package.json +20 -22
  192. package/src/components/DeferredChangesBanner.svelte +477 -0
  193. package/src/components/SyncStatus.svelte +1732 -0
  194. package/dist/crdt/awareness.d.ts +0 -54
  195. package/dist/crdt/awareness.d.ts.map +0 -1
  196. package/dist/crdt/awareness.js +0 -219
  197. package/dist/crdt/awareness.js.map +0 -1
  198. package/dist/crdt/doc.d.ts +0 -56
  199. package/dist/crdt/doc.d.ts.map +0 -1
  200. package/dist/crdt/doc.js +0 -130
  201. package/dist/crdt/doc.js.map +0 -1
  202. package/dist/crdt/index.d.ts +0 -15
  203. package/dist/crdt/index.d.ts.map +0 -1
  204. package/dist/crdt/index.js +0 -20
  205. package/dist/crdt/index.js.map +0 -1
  206. package/dist/crdt/offline.d.ts +0 -91
  207. package/dist/crdt/offline.d.ts.map +0 -1
  208. package/dist/crdt/offline.js +0 -353
  209. package/dist/crdt/offline.js.map +0 -1
  210. package/dist/crdt/sync.d.ts +0 -58
  211. package/dist/crdt/sync.d.ts.map +0 -1
  212. package/dist/crdt/sync.js +0 -399
  213. package/dist/crdt/sync.js.map +0 -1
  214. package/dist/crdt/types.d.ts +0 -62
  215. package/dist/crdt/types.d.ts.map +0 -1
  216. package/dist/crdt/types.js +0 -7
  217. package/dist/crdt/types.js.map +0 -1
  218. package/dist/email/sendEmail.d.ts +0 -31
  219. package/dist/email/sendEmail.d.ts.map +0 -1
  220. package/dist/email/sendEmail.js +0 -39
  221. package/dist/email/sendEmail.js.map +0 -1
  222. package/dist/email/validateSmtp.d.ts +0 -18
  223. package/dist/email/validateSmtp.d.ts.map +0 -1
  224. package/dist/email/validateSmtp.js +0 -33
  225. package/dist/email/validateSmtp.js.map +0 -1
  226. package/dist/entries/crdt.d.ts +0 -3
  227. package/dist/entries/crdt.d.ts.map +0 -1
  228. package/dist/entries/crdt.js +0 -13
  229. package/dist/entries/crdt.js.map +0 -1
  230. package/dist/entries/email.d.ts +0 -4
  231. package/dist/entries/email.d.ts.map +0 -1
  232. package/dist/entries/email.js +0 -4
  233. package/dist/entries/email.js.map +0 -1
  234. package/dist/kit/authPresets.d.ts +0 -28
  235. package/dist/kit/authPresets.d.ts.map +0 -1
  236. package/dist/kit/authPresets.js +0 -23
  237. package/dist/kit/authPresets.js.map +0 -1
  238. package/dist/kit/configEndpoint.d.ts +0 -18
  239. package/dist/kit/configEndpoint.d.ts.map +0 -1
  240. package/dist/kit/configEndpoint.js +0 -27
  241. package/dist/kit/configEndpoint.js.map +0 -1
  242. package/dist/kit/deployEndpoint.d.ts +0 -22
  243. package/dist/kit/deployEndpoint.d.ts.map +0 -1
  244. package/dist/kit/deployEndpoint.js +0 -79
  245. package/dist/kit/deployEndpoint.js.map +0 -1
  246. package/dist/kit/layoutLoad.d.ts +0 -23
  247. package/dist/kit/layoutLoad.d.ts.map +0 -1
  248. package/dist/kit/layoutLoad.js +0 -41
  249. package/dist/kit/layoutLoad.js.map +0 -1
  250. package/dist/kit/protectedLoad.d.ts +0 -16
  251. package/dist/kit/protectedLoad.d.ts.map +0 -1
  252. package/dist/kit/protectedLoad.js +0 -28
  253. package/dist/kit/protectedLoad.js.map +0 -1
  254. package/dist/kit/setupLoad.d.ts +0 -11
  255. package/dist/kit/setupLoad.d.ts.map +0 -1
  256. package/dist/kit/setupLoad.js +0 -28
  257. package/dist/kit/setupLoad.js.map +0 -1
  258. package/dist/kit/validateEndpoint.d.ts +0 -9
  259. package/dist/kit/validateEndpoint.d.ts.map +0 -1
  260. package/dist/kit/validateEndpoint.js +0 -25
  261. package/dist/kit/validateEndpoint.js.map +0 -1
  262. package/dist/kit/vercelApi.d.ts +0 -6
  263. package/dist/kit/vercelApi.d.ts.map +0 -1
  264. package/dist/kit/vercelApi.js +0 -48
  265. package/dist/kit/vercelApi.js.map +0 -1
package/README.md CHANGED
@@ -18,7 +18,6 @@ A local-first, offline-capable sync engine for **SvelteKit + Supabase + Dexie**
18
18
  - **Operation coalescing** -- batches of rapid local writes (e.g., 50 individual increments) are compressed into a single outbound operation, reducing sync traffic dramatically.
19
19
  - **Tombstone management** -- soft deletes are propagated cleanly, and stale tombstones are garbage-collected after a configurable retention period.
20
20
  - **Egress optimization** -- column-level select lists and ownership filters ensure only the data your client needs is fetched from Supabase.
21
- - **Email** -- optional SMTP email sending for share link invitations and notifications, with credential validation.
22
21
 
23
22
  ## Quick start
24
23
 
@@ -106,31 +105,61 @@ if (!auth.singleUserSetUp) {
106
105
  }
107
106
  ```
108
107
 
109
- ### Email (optional)
108
+ ## Install PWA Command
110
109
 
111
- Send emails via SMTP for share link invitations:
110
+ Scaffold a complete offline-first PWA project:
112
111
 
113
- ```ts
114
- import { sendEmail, validateSmtpCredentials } from '@prabhask5/stellar-engine/email';
115
-
116
- // Validate SMTP credentials
117
- const { valid, error } = await validateSmtpCredentials({
118
- smtpHost: 'smtp.example.com',
119
- smtpPort: 587,
120
- smtpUser: 'user@example.com',
121
- smtpPass: 'password',
122
- fromEmail: 'noreply@example.com',
123
- fromName: 'My App'
124
- });
125
-
126
- // Send an email
127
- const result = await sendEmail(config, {
128
- to: 'recipient@example.com',
129
- subject: 'You have been invited',
130
- html: '<p>Click here to view the shared note.</p>'
131
- });
112
+ ```bash
113
+ npx @prabhask5/stellar-engine install pwa --name "My App" --short_name "App" --prefix "myapp" [--description "..."]
132
114
  ```
133
115
 
116
+ ### What it generates
117
+
118
+ The command creates a full SvelteKit 2 + Svelte 5 project with:
119
+
120
+ **Configuration files (8):** `vite.config.ts`, `tsconfig.json`, `svelte.config.js`, `eslint.config.js`, `.prettierrc`, `.prettierignore`, `knip.json`, `.gitignore`
121
+
122
+ **Documentation (3):** `README.md`, `ARCHITECTURE.md`, `FRAMEWORKS.md`
123
+
124
+ **Static assets (13):** `manifest.json`, `offline.html`, placeholder SVG icons (app, dark, maskable, favicon, monochrome, splash, apple-touch), email template placeholders (signup, change-email, device-verification)
125
+
126
+ **Database (1):** `supabase-schema.sql` with helper functions, example table pattern, and `trusted_devices` table
127
+
128
+ **Source files (2):** `src/app.html` (PWA-ready with iOS meta tags, landscape blocker, zoom prevention, SW registration), `src/app.d.ts`
129
+
130
+ **Route files (16):**
131
+ | File | What stellar-engine manages | What you customize (TODO) |
132
+ |------|---------------------------|--------------------------|
133
+ | `src/routes/+layout.ts` | Auth resolution, config init, sync engine startup via `resolveAuthState()`, `initConfig()`, `startSyncEngine()` | `initEngine()` config with your database schema |
134
+ | `src/routes/+layout.svelte` | Auth state hydration via `hydrateAuthState()` | App shell (navbar, tab bar, overlays) |
135
+ | `src/routes/+page.svelte` | Imports `resolveFirstName`, `onSyncComplete`, `authState`; derives `firstName` reactively | Home page UI |
136
+ | `src/routes/+error.svelte` | — | Error page UI |
137
+ | `src/routes/setup/+page.ts` | Config check, session validation, admin check via `getConfig()`, `getValidSession()`, `isAdmin()` | — (fully managed) |
138
+ | `src/routes/setup/+page.svelte` | Imports `setConfig`, `isOnline`, `pollForNewServiceWorker` | Setup wizard UI |
139
+ | `src/routes/policy/+page.svelte` | — | Privacy policy content |
140
+ | `src/routes/login/+page.svelte` | All auth functions: `setupSingleUser`, `unlockSingleUser`, `getSingleUserInfo`, `completeSingleUserSetup`, `completeDeviceVerification`, `pollDeviceVerification`, `fetchRemoteGateConfig`, `linkSingleUserDevice`, `sendDeviceVerification` | Login page UI |
141
+ | `src/routes/confirm/+page.svelte` | Email confirmation via `handleEmailConfirmation()`, `broadcastAuthConfirmed()` | Confirmation page UI |
142
+ | `src/routes/api/config/+server.ts` | Fully managed: `getServerConfig()` | — |
143
+ | `src/routes/api/setup/deploy/+server.ts` | Fully managed: `deployToVercel()` | — |
144
+ | `src/routes/api/setup/validate/+server.ts` | Fully managed: `createValidateHandler()` | — |
145
+ | `src/routes/[...catchall]/+page.ts` | Redirect to `/` | — |
146
+ | `src/routes/(protected)/+layout.ts` | Auth guard via `resolveAuthState()` with login redirect | — (fully managed) |
147
+ | `src/routes/(protected)/+layout.svelte` | — | Protected area chrome |
148
+ | `src/routes/(protected)/profile/+page.svelte` | All profile functions: `changeSingleUserGate`, `updateSingleUserProfile`, `getSingleUserInfo`, `changeSingleUserEmail`, `completeSingleUserEmailChange`, `resetDatabase`, `getTrustedDevices`, `removeTrustedDevice`, `getCurrentDeviceId`, `isDebugMode`, `setDebugMode` | Profile page UI |
149
+
150
+ **Library (1):** `src/lib/types.ts` with re-exports from stellar-engine + app-specific type stubs
151
+
152
+ **Git hooks (1):** `.husky/pre-commit` with lint + format + validate
153
+
154
+ ### Parameters
155
+
156
+ | Flag | Required | Description |
157
+ |------|----------|-------------|
158
+ | `--name` | Yes | Full app name (e.g., "My Stellar App") |
159
+ | `--short_name` | Yes | Short name for PWA home screen |
160
+ | `--prefix` | Yes | App prefix for localStorage keys, SW, debug utils |
161
+ | `--description` | No | App description (default: "A self-hosted offline-first PWA") |
162
+
134
163
  ## Subpath exports
135
164
 
136
165
  Import only what you need via subpath exports:
@@ -143,10 +172,11 @@ Import only what you need via subpath exports:
143
172
  | `@prabhask5/stellar-engine/stores` | Reactive stores + event subscriptions (`syncStatusStore`, `authState`, `onSyncComplete`, etc.) |
144
173
  | `@prabhask5/stellar-engine/types` | All type exports (`Session`, `SyncEngineConfig`, `BatchOperation`, `SingleUserConfig`, etc.) |
145
174
  | `@prabhask5/stellar-engine/utils` | Utility functions (`generateId`, `now`, `calculateNewOrder`, `snakeToCamel`, `debug`, etc.) |
146
- | `@prabhask5/stellar-engine/actions` | Svelte `use:` actions (`remoteChangeAnimation`, `trackEditing`, `triggerLocalAnimation`) |
175
+ | `@prabhask5/stellar-engine/actions` | Svelte `use:` actions (`remoteChangeAnimation`, `trackEditing`, `triggerLocalAnimation`, `truncateTooltip`) |
176
+ | `@prabhask5/stellar-engine/kit` | SvelteKit route helpers, server APIs, load functions, confirmation, auth hydration |
177
+ | `@prabhask5/stellar-engine/components/SyncStatus` | Sync status indicator Svelte component |
178
+ | `@prabhask5/stellar-engine/components/DeferredChangesBanner` | Cross-device conflict banner Svelte component |
147
179
  | `@prabhask5/stellar-engine/config` | Runtime config (`initConfig`, `getConfig`, `setConfig`, `getDexieTableFor`) |
148
- | `@prabhask5/stellar-engine/crdt` | CRDT document lifecycle, realtime sync, awareness/presence, offline cache |
149
- | `@prabhask5/stellar-engine/email` | Email sending (`sendEmail`, `validateSmtpCredentials`) |
150
180
 
151
181
  The root export (`@prabhask5/stellar-engine`) re-exports everything for backward compatibility.
152
182
 
@@ -280,6 +310,9 @@ Alternatively, you can provide a pre-created Dexie instance via the `db` config
280
310
  | `changeEmail(newEmail)` | Request email change (sends confirmation to new address). Returns `{ error, confirmationRequired }`. |
281
311
  | `completeEmailChange()` | Finalize email change after confirmation. Refreshes session and updates cached credentials. |
282
312
  | `getUserProfile` / `updateProfile` | Profile read/write via Supabase user metadata. |
313
+ | `resolveFirstName(session, offline, fallback?)` | Resolve display name from session or offline profile with configurable fallback. |
314
+ | `resolveUserId(session, offline)` | Extract user UUID from session or offline credentials. |
315
+ | `resolveAvatarInitial(session, offline, fallback?)` | Single uppercase initial for avatar display. |
283
316
 
284
317
  ### Offline auth
285
318
 
@@ -395,6 +428,16 @@ When debug mode is enabled, the engine exposes utilities on the `window` object
395
428
  | `remoteChangeAnimation` | Svelte `use:` action that animates an element when a remote change arrives. |
396
429
  | `trackEditing` | Action that signals the engine a field is being actively edited (suppresses incoming overwrites). |
397
430
  | `triggerLocalAnimation` | Programmatically trigger the local-change animation on a node. |
431
+ | `truncateTooltip` | Action that shows a tooltip with full text when content is truncated via CSS overflow. |
432
+
433
+ ### Svelte components
434
+
435
+ | Export | Description |
436
+ |---|---|
437
+ | `@prabhask5/stellar-engine/components/SyncStatus` | Full Svelte 5 component for animated sync-state indicator with tooltip and PWA refresh. Shows offline/syncing/synced/error/pending states with live indicator. |
438
+ | `@prabhask5/stellar-engine/components/DeferredChangesBanner` | Full Svelte 5 component for cross-device data conflict notification. Shows when another device pushes changes while user is editing. Provides Update/Dismiss/Show Changes actions with diff preview. |
439
+
440
+ The `UpdatePrompt` component is **not** shipped as a stellar-engine export. Instead, it is generated by `stellar-engine install pwa` at `src/lib/components/UpdatePrompt.svelte` with TODO UI placeholders. The generated component imports `monitorSwLifecycle` and `handleSwUpdate` from `@prabhask5/stellar-engine/kit` for all SW lifecycle logic.
398
441
 
399
442
  ## Use cases
400
443
 
@@ -1,66 +1,191 @@
1
1
  /**
2
- * Remote Change Animation Action
2
+ * @fileoverview Remote Change Animation Action
3
3
  *
4
4
  * A Svelte action that automatically adds remote change animations to elements.
5
- * Use this on list items, cards, or any element that can be updated remotely.
5
+ * Use this on list items, cards, or any element that can be updated remotely
6
+ * (e.g., via Supabase Realtime subscriptions).
6
7
  *
7
8
  * The action detects the ACTION TYPE from the remote change and applies
8
- * the appropriate animation:
9
- * - 'create' item-created (slide in with burst)
10
- * - 'delete' item-deleting (slide out with fade)
11
- * - 'toggle' checkbox-animating + completion-ripple
12
- * - 'increment' counter-increment
13
- * - 'decrement' counter-decrement
14
- * - 'reorder' item-reordering
15
- * - 'rename' text-changed
16
- * - 'update' item-changed (default highlight)
17
- *
18
- * Usage:
9
+ * the appropriate CSS animation class:
10
+ * - `'create'` --> `item-created` (slide in with burst)
11
+ * - `'delete'` --> `item-deleting` (slide out with fade)
12
+ * - `'toggle'` --> `item-toggled` (+ checkbox-animating + completion-ripple)
13
+ * - `'increment'` --> `counter-increment` (bump up)
14
+ * - `'decrement'` --> `counter-decrement` (bump down)
15
+ * - `'reorder'` --> `item-reordering` (slide to new position)
16
+ * - `'rename'` --> `text-changed` (highlight flash)
17
+ * - `'update'` --> `item-changed` (default highlight)
18
+ *
19
+ * @example
19
20
  * ```svelte
20
21
  * <div use:remoteChangeAnimation={{ entityId: item.id, entityType: 'goals' }}>
21
22
  * ...
22
23
  * </div>
23
24
  * ```
25
+ *
26
+ * @see {@link remoteChangeAnimation} for the main Svelte action
27
+ * @see {@link trackEditing} for deferred-change tracking on forms
28
+ * @see {@link triggerLocalAnimation} for programmatic local animations
24
29
  */
25
30
  import { type RemoteActionType } from '../stores/remoteChanges';
31
+ /**
32
+ * Configuration options for the {@link remoteChangeAnimation} Svelte action.
33
+ */
26
34
  interface RemoteChangeOptions {
35
+ /** The unique identifier of the entity being watched (e.g., a row UUID). */
27
36
  entityId: string;
37
+ /** The entity type / table name (e.g., `'goals'`, `'tasks'`). */
28
38
  entityType: string;
39
+ /**
40
+ * Optional list of field names to watch. When provided, animations are
41
+ * only triggered if the remote change includes at least one of these
42
+ * fields (or the wildcard `'*'`). Omit to animate on any field change.
43
+ */
29
44
  fields?: string[];
45
+ /**
46
+ * Optional CSS class override. When set, this class is used instead of
47
+ * the default mapping from {@link ACTION_ANIMATION_MAP}.
48
+ */
30
49
  animationClass?: string;
50
+ /**
51
+ * Optional callback invoked when a remote action is detected.
52
+ * Useful for component-specific handling beyond CSS animations
53
+ * (e.g., updating local state, playing sounds, showing toasts).
54
+ *
55
+ * @param actionType - The type of remote action detected.
56
+ * @param fields - The list of fields that changed.
57
+ */
31
58
  onAction?: (actionType: RemoteActionType, fields: string[]) => void;
32
59
  }
60
+ /**
61
+ * Svelte action that watches for remote changes on a specific entity and
62
+ * applies the appropriate CSS animation class to the host element.
63
+ *
64
+ * **Lifecycle:**
65
+ * 1. On mount, checks for a recent change that may have arrived before
66
+ * the element was rendered (important for CREATE animations on new items).
67
+ * 2. Subscribes to the `remoteChangesStore` for future changes.
68
+ * 3. Subscribes to a pending-delete indicator for delete animations.
69
+ * 4. On update, re-subscribes if the entity identity changes.
70
+ * 5. On destroy, unsubscribes and cleans up CSS classes.
71
+ *
72
+ * @param node - The DOM element to animate.
73
+ * @param options - Configuration specifying which entity to watch.
74
+ * @returns A Svelte action lifecycle object with `update` and `destroy` methods.
75
+ *
76
+ * @example
77
+ * ```svelte
78
+ * <div use:remoteChangeAnimation={{ entityId: item.id, entityType: 'goals' }}>
79
+ * {item.name}
80
+ * </div>
81
+ * ```
82
+ */
33
83
  export declare function remoteChangeAnimation(node: HTMLElement, options: RemoteChangeOptions): {
84
+ /**
85
+ * Called when the action's options change. If the entity identity
86
+ * (`entityId` or `entityType`) has changed, tears down old subscriptions
87
+ * and creates new ones for the updated entity.
88
+ *
89
+ * @param newOptions - The updated {@link RemoteChangeOptions}.
90
+ */
34
91
  update(newOptions: RemoteChangeOptions): void;
92
+ /**
93
+ * Cleanup handler — unsubscribes from all stores, removes the base
94
+ * CSS class, and clears the element from the animation tracking set.
95
+ */
35
96
  destroy(): void;
36
97
  };
37
98
  /**
38
- * Action for form elements that should track editing state.
39
- * Use this on modal forms with Save buttons to defer remote changes.
99
+ * Svelte action for form elements that should track editing state.
100
+ * Use this on modal forms with Save buttons to defer remote changes
101
+ * while the user is actively editing, preventing disruptive overwrites.
102
+ *
103
+ * When the form is destroyed (e.g., modal closes), any deferred changes
104
+ * are passed to the `onDeferredChanges` callback so the component can
105
+ * decide how to reconcile them.
40
106
  *
41
- * Usage:
107
+ * @example
42
108
  * ```svelte
43
109
  * <form use:trackEditing={{ entityId: item.id, entityType: 'goals', formType: 'manual-save' }}>
44
110
  * ...
45
111
  * </form>
46
112
  * ```
47
113
  */
114
+ /**
115
+ * Configuration options for the {@link trackEditing} Svelte action.
116
+ */
48
117
  interface TrackEditingOptions {
118
+ /** The unique identifier of the entity being edited. */
49
119
  entityId: string;
120
+ /** The entity type / table name (e.g., `'goals'`, `'tasks'`). */
50
121
  entityType: string;
122
+ /**
123
+ * The save behaviour of the form:
124
+ * - `'auto-save'` — changes are saved immediately (e.g., inline editing).
125
+ * - `'manual-save'` — changes are saved on explicit submit (e.g., modal form).
126
+ */
51
127
  formType: 'auto-save' | 'manual-save';
128
+ /**
129
+ * Optional list of field names this form edits. When provided, only
130
+ * remote changes to these fields are deferred; changes to other fields
131
+ * are applied immediately.
132
+ */
52
133
  fields?: string[];
134
+ /**
135
+ * Callback invoked when the form closes and there are deferred changes
136
+ * that need processing (e.g., conflict resolution, data refresh).
137
+ *
138
+ * @param changes - The array of deferred remote change objects.
139
+ */
53
140
  onDeferredChanges?: (changes: unknown[]) => void;
54
141
  }
142
+ /**
143
+ * Svelte action that marks an entity as "being edited" in the remote changes
144
+ * store. While editing, incoming remote changes for the same entity are
145
+ * deferred instead of applied immediately.
146
+ *
147
+ * **Lifecycle:**
148
+ * 1. On mount, calls `remoteChangesStore.startEditing()` to begin deferral.
149
+ * 2. Periodically checks for deferred changes and toggles a CSS class
150
+ * (`has-deferred-changes`) on the node for visual indication.
151
+ * 3. On update, re-registers if the entity identity changes.
152
+ * 4. On destroy, calls `remoteChangesStore.stopEditing()` and invokes
153
+ * `onDeferredChanges` if any changes were deferred.
154
+ *
155
+ * @param node - The form DOM element.
156
+ * @param options - Configuration specifying which entity is being edited.
157
+ * @returns A Svelte action lifecycle object with `update` and `destroy` methods.
158
+ */
55
159
  export declare function trackEditing(node: HTMLElement, options: TrackEditingOptions): {
160
+ /**
161
+ * Called when the action's options change. If the entity identity
162
+ * changes, stops tracking the old entity and starts tracking the new one.
163
+ *
164
+ * @param newOptions - The updated {@link TrackEditingOptions}.
165
+ */
56
166
  update(newOptions: TrackEditingOptions): void;
167
+ /**
168
+ * Cleanup handler — stops the polling interval, removes CSS classes,
169
+ * stops editing in the store, and notifies the callback of any
170
+ * deferred changes that accumulated during the editing session.
171
+ */
57
172
  destroy(): void;
58
173
  };
59
174
  /**
60
175
  * Trigger a local action animation on an element.
61
- * Use this to make local actions animate the same way as remote actions.
62
176
  *
63
- * Usage in components:
177
+ * Use this to make local user actions (e.g., tapping a checkbox, incrementing
178
+ * a counter) animate with the same visual treatment as remote changes, giving
179
+ * the UI a consistent feel.
180
+ *
181
+ * For `increment` and `decrement` actions, rapid repeated invocations will
182
+ * restart the animation instead of being blocked — this allows the counter
183
+ * to visually "bump" on each tap.
184
+ *
185
+ * @param element - The DOM element to animate (or `null`, in which case this is a no-op).
186
+ * @param actionType - The type of animation to apply.
187
+ *
188
+ * @example
64
189
  * ```svelte
65
190
  * <script>
66
191
  * import { triggerLocalAnimation } from '@prabhask5/stellar-engine';
@@ -1 +1 @@
1
- {"version":3,"file":"remoteChange.d.ts","sourceRoot":"","sources":["../../src/actions/remoteChange.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,yBAAyB,CAAC;AAEjC,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IAEnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAElB,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,QAAQ,CAAC,EAAE,CAAC,UAAU,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CACrE;AAiCD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,mBAAmB;uBAqH9D,mBAAmB;;EAkCzC;AAED;;;;;;;;;;GAUG;AAEH,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,WAAW,GAAG,aAAa,CAAC;IACtC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAElB,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CAClD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,mBAAmB;uBAqBrD,mBAAmB;;EAyBzC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,WAAW,GAAG,IAAI,EAC3B,UAAU,EAAE,gBAAgB,GAC3B,IAAI,CA8DN"}
1
+ {"version":3,"file":"remoteChange.d.ts","sourceRoot":"","sources":["../../src/actions/remoteChange.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,yBAAyB,CAAC;AAMjC;;GAEG;AACH,UAAU,mBAAmB;IAC3B,4EAA4E;IAC5E,QAAQ,EAAE,MAAM,CAAC;IAEjB,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC;IAEnB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAElB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,CAAC,UAAU,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CACrE;AAsDD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,mBAAmB;IAgJjF;;;;;;OAMG;uBACgB,mBAAmB;IA4BtC;;;OAGG;;EAQN;AAMD;;;;;;;;;;;;;;;GAeG;AAEH;;GAEG;AACH,UAAU,mBAAmB;IAC3B,wDAAwD;IACxD,QAAQ,EAAE,MAAM,CAAC;IAEjB,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC;IAEnB;;;;OAIG;IACH,QAAQ,EAAE,WAAW,GAAG,aAAa,CAAC;IAEtC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAElB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CAClD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,mBAAmB;IAwBxE;;;;;OAKG;uBACgB,mBAAmB;IAatC;;;;OAIG;;EAcN;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,WAAW,GAAG,IAAI,EAC3B,UAAU,EAAE,gBAAgB,GAC3B,IAAI,CA8DN"}