@prabhask5/stellar-engine 1.2.1 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,23 +1,22 @@
1
1
  # @prabhask5/stellar-engine [![npm version](https://img.shields.io/npm/v/@prabhask5/stellar-engine.svg?style=flat)](https://www.npmjs.com/package/@prabhask5/stellar-engine) [![Made with Supabase](https://supabase.com/badge-made-with-supabase-dark.svg)](https://supabase.com)
2
2
 
3
- An offline-first, real-time sync engine for **Supabase + Dexie.js** applications. All reads come from IndexedDB, all writes land locally first, and a background sync loop ships changes to Supabase -- so your app stays fast and functional regardless of network state. Optional SvelteKit integrations are included for teams building with Svelte 5.
3
+ A plug-and-play, offline-first sync engine for **Supabase + Dexie.js** applications. All reads come from IndexedDB, all writes land locally first, and a background sync loop ships changes to Supabase -- so your app stays fast and functional regardless of network state. Optional **SvelteKit** integrations are included for teams building with Svelte 5, but the core engine works with any framework or vanilla JS.
4
4
 
5
5
  ## Documentation
6
6
 
7
- - [API Reference](./API_REFERENCE.md) -- full signatures, parameters, and usage examples for every public export
8
7
  - [Architecture](./ARCHITECTURE.md) -- internal design, data flow, and module responsibilities
9
- - [Frameworks](./FRAMEWORKS.md) -- More reading on
10
- frameworks used in stellar-engine
8
+ - [API Reference](./API_REFERENCE.md) -- full signatures, parameters, and usage examples for every public export
9
+ - [Frameworks](./FRAMEWORKS.md) -- more reading on frameworks used in stellar-engine
11
10
 
12
11
  ## Features
13
12
 
14
- - **Schema-driven configuration** -- declare tables once and the engine auto-generates Dexie stores, database versioning, TypeScript interfaces, and Supabase SQL
13
+ - **Schema-driven configuration** -- declare tables once in a simple object; the engine auto-generates Dexie stores, database versioning, TypeScript interfaces, and Supabase SQL
15
14
  - **Intent-based sync operations** -- operations preserve intent (`increment`, `set`, `create`, `delete`) instead of final state, enabling smarter coalescing and conflict handling
16
15
  - **6-step operation coalescing** -- 50 rapid writes are compressed into 1 outbound operation, dramatically reducing sync traffic
17
16
  - **Three-tier conflict resolution** -- field-level auto-merge for non-overlapping changes, different-field merge, and same-field resolution (`local_pending` > `delete_wins` > `last_write_wins` with device ID tiebreaker)
18
17
  - **Offline authentication** -- SHA-256 credential caching and offline session tokens let users sign in and work without connectivity; sessions reconcile automatically on reconnect
19
18
  - **Single-user PIN/password auth** -- simplified gate backed by real Supabase email/password auth; PIN is padded to meet minimum length and verified server-side
20
- - **Device verification** -- email OTP for untrusted devices with 90-day trust duration
19
+ - **Device verification** -- email OTP for untrusted devices with configurable trust duration
21
20
  - **Realtime subscriptions** -- Supabase Realtime WebSocket push with echo suppression and deduplication against polling
22
21
  - **Tombstone management** -- soft deletes with configurable garbage collection
23
22
  - **Egress optimization** -- column-level selects, operation coalescing, push-only mode when realtime is healthy, cursor-based pulls
@@ -28,6 +27,7 @@ frameworks used in stellar-engine
28
27
  - **Svelte actions** -- `remoteChangeAnimation`, `trackEditing`, `triggerLocalAnimation` for declarative UI behavior
29
28
  - **SQL generation** -- auto-generate `CREATE TABLE` statements, RLS policies, and migrations from your schema config
30
29
  - **TypeScript generation** -- auto-generate interfaces from schema
30
+ - **Migration generation** -- auto-generate `ALTER TABLE` rename and column rename SQL from `renamedFrom` / `renamedColumns` hints
31
31
  - **Diagnostics** -- comprehensive runtime diagnostics covering sync, queue, realtime, conflicts, egress, and network
32
32
  - **Debug utilities** -- opt-in debug logging and `window` debug utilities for browser console inspection
33
33
  - **SvelteKit integration** (optional) -- layout helpers, server handlers, email confirmation, service worker lifecycle, and auth hydration
@@ -50,92 +50,73 @@ frameworks used in stellar-engine
50
50
  // npm install @prabhask5/stellar-engine
51
51
 
52
52
  // ─── 1. Initialize the engine ──────────────────────────────────────
53
- // Call once at app startup (e.g., root layout, main entry point)
53
+ // Call once at app startup (e.g., root layout, main entry point).
54
+ // Schema-driven: declare tables once, engine handles everything else.
54
55
 
55
- import {
56
- initEngine,
57
- startSyncEngine,
58
- supabase,
59
- getDb,
60
- resetDatabase,
61
- validateSupabaseCredentials,
62
- validateSchema,
63
- } from '@prabhask5/stellar-engine';
56
+ import { initEngine, startSyncEngine, getDb, resetDatabase } from '@prabhask5/stellar-engine';
64
57
  import { initConfig } from '@prabhask5/stellar-engine/config';
65
58
  import { resolveAuthState } from '@prabhask5/stellar-engine/auth';
66
59
 
67
60
  initEngine({
68
61
  prefix: 'myapp',
69
- supabase,
70
- // Schema-driven: declare tables once, engine handles the rest
71
- tables: [
72
- {
73
- supabaseName: 'projects', // Supabase table name
74
- // Dexie name auto-derived: 'projects'
75
- columns: 'id, name, description, sort_order, created_at, updated_at, is_deleted, user_id',
76
- ownershipFilter: 'user_id', // RLS-aware egress filter
77
- mergeFields: [], // Fields for numeric merge
78
- excludeFromConflictResolution: ['updated_at'], // Fields to skip in conflict diffing
79
- },
80
- {
81
- supabaseName: 'tasks',
82
- columns: 'id, title, project_id, count, sort_order, created_at, updated_at, is_deleted, user_id',
83
- ownershipFilter: 'user_id',
84
- mergeFields: ['count'], // Numeric merge: concurrent increments add up
62
+
63
+ // Schema-driven: declare tables once, engine handles the rest.
64
+ // System indexes (id, user_id, created_at, updated_at, deleted, _version)
65
+ // are auto-appended to every table. Database name auto-derived as `${prefix}DB`.
66
+ schema: {
67
+ projects: 'order', // String shorthand = indexes only
68
+ tasks: 'project_id, order', // Comma-separated Dexie indexes
69
+ focus_settings: { singleton: true }, // Object form for full control
70
+ goals: {
71
+ indexes: 'goal_list_id, order',
72
+ numericMergeFields: ['current_value'], // Additive merge on conflicts
73
+ excludeFromConflict: ['device_id'], // Skip these in conflict diffing
85
74
  },
86
- ],
87
-
88
- // Declarative database versioning -- system tables (syncQueue, conflictHistory,
89
- // offlineCredentials, offlineSession, singleUserConfig) are auto-merged
90
- database: {
91
- name: 'MyAppDB',
92
- versions: [
93
- {
94
- version: 1,
95
- stores: {
96
- projects: 'id, user_id, updated_at',
97
- tasks: 'id, project_id, user_id, updated_at',
98
- },
99
- },
100
- ],
101
75
  },
102
76
 
103
- // Auth config -- single-user mode with 4-digit PIN
77
+ // Auth: flat format with sensible defaults (all fields optional).
78
+ // No nested `singleUser` key needed -- engine normalizes internally.
104
79
  auth: {
105
- singleUser: { gateType: 'code', codeLength: 4 },
106
- enableOfflineAuth: true,
107
- // emailConfirmation: { enabled: true },
108
- // deviceVerification: { enabled: true },
80
+ gateType: 'code', // 'code' | 'password' (default: 'code')
81
+ codeLength: 6, // 4 | 6 (default: 6)
82
+ emailConfirmation: true, // default: true
83
+ deviceVerification: true, // default: true
84
+ profileExtractor: (meta) => ({ firstName: meta.first_name }),
85
+ profileToMetadata: (p) => ({ first_name: p.firstName }),
109
86
  },
110
87
 
111
- // Demo mode config (optional)
88
+ // Optional CRDT collaborative editing
89
+ crdt: true, // or { persistIntervalMs: 60000, maxOfflineDocuments: 50 }
90
+
91
+ // Optional demo mode
112
92
  demo: {
113
93
  seedData: async (db) => {
114
94
  await db.table('projects').bulkPut([
115
- { id: 'demo-1', name: 'Sample Project', sort_order: 1, is_deleted: false },
95
+ { id: 'demo-1', name: 'Sample Project', order: 1 },
116
96
  ]);
117
97
  },
118
- mockProfile: { email: 'demo@example.com', firstName: 'Demo', lastName: 'User' },
98
+ mockProfile: { email: 'demo@test.com', firstName: 'Demo', lastName: 'User' },
119
99
  },
120
100
 
121
- // CRDT config (optional)
122
- crdt: {
123
- persistIntervalMs: 30000,
124
- maxOfflineDocuments: 50,
125
- },
101
+ // Tuning (all optional with defaults)
102
+ syncDebounceMs: 2000, // Default: 2000
103
+ syncIntervalMs: 900000, // Default: 900000 (15 min)
104
+ tombstoneMaxAgeDays: 7, // Default: 7
126
105
  });
127
106
 
128
107
  // ─── 2. Resolve auth and start the engine ──────────────────────────
108
+ // The engine fetches runtime config (Supabase URL + anon key) from
109
+ // your /api/config endpoint -- no need to pass a supabase client.
129
110
 
130
111
  await initConfig();
131
112
  const auth = await resolveAuthState();
132
113
 
133
114
  if (!auth.singleUserSetUp) {
134
115
  // First-time setup flow
135
- // call setupSingleUser(code, profile, email) from your UI
116
+ // -> call setupSingleUser(code, profile, email) from your UI
136
117
  } else if (auth.authMode === 'none') {
137
118
  // Locked -- show unlock screen
138
- // call unlockSingleUser(code) from your UI
119
+ // -> call unlockSingleUser(code) from your UI
139
120
  } else {
140
121
  // Authenticated -- start syncing
141
122
  await startSyncEngine();
@@ -160,10 +141,10 @@ const projectId = generateId();
160
141
  await engineCreate('projects', {
161
142
  id: projectId,
162
143
  name: 'New Project',
163
- sort_order: 1,
144
+ order: 1,
164
145
  created_at: now(),
165
146
  updated_at: now(),
166
- is_deleted: false,
147
+ deleted: false,
167
148
  user_id: 'current-user-id',
168
149
  });
169
150
 
@@ -177,7 +158,7 @@ await engineUpdate('tasks', taskId, {
177
158
  await engineDelete('tasks', taskId);
178
159
 
179
160
  // Increment (intent-preserved -- concurrent increments merge correctly)
180
- await engineIncrement('tasks', taskId, 'count', 1);
161
+ await engineIncrement('goals', goalId, 'current_value', 1);
181
162
 
182
163
  // Query all rows from local IndexedDB
183
164
  const projects = await queryAll('projects');
@@ -186,20 +167,19 @@ const projects = await queryAll('projects');
186
167
  const project = await queryOne('projects', projectId);
187
168
 
188
169
  // Get or create (atomic upsert)
189
- const { record, created } = await engineGetOrCreate('projects', projectId, {
190
- id: projectId,
191
- name: 'Default Project',
192
- sort_order: 0,
170
+ const { record, created } = await engineGetOrCreate('focus_settings', settingsId, {
171
+ id: settingsId,
172
+ theme: 'dark',
193
173
  created_at: now(),
194
174
  updated_at: now(),
195
- is_deleted: false,
175
+ deleted: false,
196
176
  user_id: 'current-user-id',
197
177
  });
198
178
 
199
179
  // Batch writes (multiple operations in one sync push)
200
180
  await engineBatchWrite([
201
- { type: 'create', table: 'tasks', data: { id: generateId(), title: 'Task 1', project_id: projectId, count: 0, sort_order: 1, created_at: now(), updated_at: now(), is_deleted: false, user_id: 'current-user-id' } },
202
- { type: 'create', table: 'tasks', data: { id: generateId(), title: 'Task 2', project_id: projectId, count: 0, sort_order: 2, created_at: now(), updated_at: now(), is_deleted: false, user_id: 'current-user-id' } },
181
+ { type: 'create', table: 'tasks', data: { id: generateId(), title: 'Task 1', project_id: projectId, order: 1, created_at: now(), updated_at: now(), deleted: false, user_id: 'uid' } },
182
+ { type: 'create', table: 'tasks', data: { id: generateId(), title: 'Task 2', project_id: projectId, order: 2, created_at: now(), updated_at: now(), deleted: false, user_id: 'uid' } },
203
183
  { type: 'update', table: 'projects', id: projectId, data: { updated_at: now() } },
204
184
  ]);
205
185
 
@@ -209,8 +189,8 @@ import { createCollectionStore, createDetailStore } from '@prabhask5/stellar-eng
209
189
 
210
190
  // Collection store -- live-updating list from IndexedDB
211
191
  const projectsStore = createCollectionStore('projects', {
212
- filter: (p) => !p.is_deleted,
213
- sort: (a, b) => a.sort_order - b.sort_order,
192
+ filter: (p) => !p.deleted,
193
+ sort: (a, b) => a.order - b.order,
214
194
  });
215
195
  // Subscribe: projectsStore.subscribe(items => { ... })
216
196
 
@@ -218,7 +198,7 @@ const projectsStore = createCollectionStore('projects', {
218
198
  const projectDetail = createDetailStore('projects', projectId);
219
199
  // Subscribe: projectDetail.subscribe(record => { ... })
220
200
 
221
- // ─── 5. Reactive stores ───────────────────────────────────────────
201
+ // ─── 5. Reactive stores ────────────────────────────────────────────
222
202
 
223
203
  import {
224
204
  syncStatusStore,
@@ -228,12 +208,27 @@ import {
228
208
  onSyncComplete,
229
209
  } from '@prabhask5/stellar-engine/stores';
230
210
 
211
+ // $syncStatusStore -- current SyncStatus, last sync time, errors
212
+ // $authState -- { mode, session, offlineProfile, isLoading, authKickedMessage }
213
+ // $isOnline -- reactive boolean reflecting network state
214
+ // remoteChangesStore -- tracks entities recently changed by remote peers
215
+
231
216
  // Listen for sync completions
232
217
  onSyncComplete(() => {
233
218
  console.log('Sync cycle finished');
234
219
  });
235
220
 
236
- // ─── 6. CRDT collaborative editing ────────────────────────────────
221
+ // ─── 6. Svelte actions ─────────────────────────────────────────────
222
+
223
+ import { remoteChangeAnimation, trackEditing } from '@prabhask5/stellar-engine/actions';
224
+
225
+ // use:remoteChangeAnimation={{ table: 'tasks', id: task.id }}
226
+ // Animates elements when remote changes arrive for that entity.
227
+
228
+ // use:trackEditing={{ table: 'tasks', id: task.id }}
229
+ // Signals the engine a field is being actively edited (suppresses incoming overwrites).
230
+
231
+ // ─── 7. CRDT collaborative editing ────────────────────────────────
237
232
 
238
233
  import {
239
234
  openDocument,
@@ -255,6 +250,9 @@ const provider = await openDocument('doc-1', 'page-1', {
255
250
  const { content, meta } = createBlockDocument(provider.doc);
256
251
  meta.set('title', 'My Page');
257
252
 
253
+ // Shared text for simpler use cases
254
+ const text = createSharedText(provider.doc);
255
+
258
256
  // Track collaborator cursors and presence
259
257
  const unsub = onCollaboratorsChange('doc-1', (collaborators) => {
260
258
  // Update avatar list, cursor positions, etc.
@@ -262,52 +260,55 @@ const unsub = onCollaboratorsChange('doc-1', (collaborators) => {
262
260
 
263
261
  await closeDocument('doc-1');
264
262
 
265
- // ─── 7. Demo mode ─────────────────────────────────────────────────
263
+ // ─── 8. Demo mode ──────────────────────────────────────────────────
264
+
265
+ import { setDemoMode, isDemoMode } from '@prabhask5/stellar-engine';
266
266
 
267
- import { setDemoMode } from '@prabhask5/stellar-engine';
267
+ // Check if demo mode is active
268
+ if (isDemoMode()) {
269
+ // In demo mode:
270
+ // - Uses '${prefix}DB_demo' IndexedDB (real DB never opened)
271
+ // - Zero Supabase network requests
272
+ // - authMode === 'demo', protected routes work with mock data
273
+ // - seedData callback runs on each page load
274
+ }
268
275
 
269
- // Toggle demo mode (requires full page reload)
276
+ // Toggle demo mode from your UI (requires full page reload)
270
277
  setDemoMode(true);
271
278
  window.location.href = '/';
272
279
 
273
- // In demo mode:
274
- // - Uses '${name}_demo' IndexedDB (real DB never opened)
275
- // - Zero Supabase network requests
276
- // - authMode === 'demo', protected routes work with mock data
277
- // - seedData callback runs on each page load
280
+ // ─── 9. SQL and TypeScript generation ──────────────────────────────
278
281
 
279
- // ─── 8. Diagnostics and debug ──────────────────────────────────────
282
+ import { generateSupabaseSQL, generateTypeScript } from '@prabhask5/stellar-engine/utils';
283
+ import { getEngineConfig } from '@prabhask5/stellar-engine';
280
284
 
281
- import {
282
- setDebugMode,
283
- isDebugMode,
284
- getSyncDiagnostics,
285
- getQueueDiagnostics,
286
- getRealtimeDiagnostics,
287
- getConflictDiagnostics,
288
- getEgressDiagnostics,
289
- getNetworkDiagnostics,
290
- } from '@prabhask5/stellar-engine/utils';
285
+ const config = getEngineConfig();
291
286
 
292
- setDebugMode(true);
287
+ // Auto-generate Supabase SQL (CREATE TABLE + RLS policies) from schema
288
+ const sql = generateSupabaseSQL(config.schema!);
293
289
 
294
- // Runtime diagnostics
295
- const syncInfo = getSyncDiagnostics();
296
- const queueInfo = getQueueDiagnostics();
297
- const egressInfo = getEgressDiagnostics();
290
+ // Auto-generate TypeScript interfaces from schema
291
+ const ts = generateTypeScript(config.schema!);
298
292
 
299
- // ─── 9. SQL and TypeScript generation ──────────────────────────────
293
+ // ─── 10. Diagnostics and debug ─────────────────────────────────────
300
294
 
301
- import {
302
- generateCreateTableSQL,
303
- generateRLSPolicies,
304
- generateTypeScriptInterfaces,
305
- } from '@prabhask5/stellar-engine/utils';
306
-
307
- // Auto-generate Supabase SQL from your schema config
308
- const sql = generateCreateTableSQL('projects', tableConfig);
309
- const rls = generateRLSPolicies('projects', tableConfig);
310
- const tsInterfaces = generateTypeScriptInterfaces(allTables);
295
+ import { setDebugMode, isDebugMode } from '@prabhask5/stellar-engine/utils';
296
+ import { getDiagnostics } from '@prabhask5/stellar-engine';
297
+
298
+ setDebugMode(true);
299
+
300
+ // Comprehensive runtime diagnostics
301
+ const diagnostics = await getDiagnostics();
302
+ // diagnostics.sync -- sync cycle statistics and recent cycle details
303
+ // diagnostics.queue -- pending operation queue state
304
+ // diagnostics.realtime -- realtime connection state and health
305
+ // diagnostics.conflict -- conflict resolution history and stats
306
+ // diagnostics.egress -- data transfer from Supabase (bytes, per-table breakdown)
307
+ // diagnostics.network -- network state and connectivity info
308
+
309
+ // When debug mode is enabled, utilities are exposed on `window`:
310
+ // window.__myappSyncStats(), window.__myappEgress(), window.__myappTombstones()
311
+ // window.__myappSync.forceFullSync()
311
312
  ```
312
313
 
313
314
  ## Commands
@@ -346,7 +347,7 @@ Generates **34+ files** for a production-ready SvelteKit 2 + Svelte 5 project:
346
347
 
347
348
  | Export | Description |
348
349
  |---|---|
349
- | `initEngine(config)` | Initialize the engine with table definitions, auth, database, and optional CRDT/demo config |
350
+ | `initEngine(config)` | Initialize the engine with schema, auth, and optional CRDT/demo config |
350
351
  | `startSyncEngine()` | Start the sync loop, realtime subscriptions, and event listeners |
351
352
  | `stopSyncEngine()` | Tear down sync loop and subscriptions cleanly |
352
353
  | `runFullSync()` | Run a complete pull-then-push cycle |
@@ -359,12 +360,11 @@ Generates **34+ files** for a production-ready SvelteKit 2 + Svelte 5 project:
359
360
 
360
361
  | Export | Description |
361
362
  |---|---|
362
- | `supabase` | The configured `SupabaseClient` instance |
363
363
  | `getDb()` | Get the Dexie database instance |
364
364
  | `resetDatabase()` | Drop and recreate the local IndexedDB database |
365
365
  | `clearLocalCache()` | Wipe all local application data |
366
366
  | `clearPendingSyncQueue()` | Drop all pending outbound operations |
367
- | `getSupabaseAsync()` | Async getter that waits for initialization |
367
+ | `getSupabaseAsync()` | Async getter that waits for Supabase client initialization |
368
368
  | `resetSupabaseClient()` | Tear down and reinitialize the Supabase client |
369
369
 
370
370
  ### CRUD and Query Operations
@@ -465,7 +465,7 @@ Generates **34+ files** for a production-ready SvelteKit 2 + Svelte 5 project:
465
465
 
466
466
  | Export | Description |
467
467
  |---|---|
468
- | `initConfig()` | Initialize runtime configuration |
468
+ | `initConfig()` | Initialize runtime configuration (fetches Supabase credentials from `/api/config`) |
469
469
  | `getConfig()` | Get current config |
470
470
  | `setConfig(config)` | Update runtime config |
471
471
  | `waitForConfig()` | Async getter that waits for config initialization |
@@ -477,12 +477,7 @@ Generates **34+ files** for a production-ready SvelteKit 2 + Svelte 5 project:
477
477
 
478
478
  | Export | Description |
479
479
  |---|---|
480
- | `getSyncDiagnostics()` | Sync cycle statistics and recent cycle details |
481
- | `getQueueDiagnostics()` | Pending operation queue state |
482
- | `getRealtimeDiagnostics()` | Realtime connection state and health |
483
- | `getConflictDiagnostics()` | Conflict resolution history and stats |
484
- | `getEgressDiagnostics()` | Data transfer from Supabase (bytes, per-table breakdown) |
485
- | `getNetworkDiagnostics()` | Network state and connectivity info |
480
+ | `getDiagnostics()` | Comprehensive runtime diagnostics (sync, queue, realtime, conflict, egress, network) |
486
481
  | `setDebugMode(enabled)` | Enable/disable debug logging |
487
482
  | `isDebugMode()` | Check if debug mode is active |
488
483
  | `debugLog` / `debugWarn` / `debugError` | Prefixed console helpers (gated by debug mode) |
@@ -503,9 +498,9 @@ When debug mode is enabled, the engine exposes utilities on `window` using your
503
498
 
504
499
  | Export | Description |
505
500
  |---|---|
506
- | `generateCreateTableSQL(name, config)` | Generate `CREATE TABLE` statement from schema config |
507
- | `generateRLSPolicies(name, config)` | Generate Row-Level Security policies |
508
- | `generateTypeScriptInterfaces(tables)` | Generate TypeScript interfaces from all table configs |
501
+ | `generateSupabaseSQL(schema)` | Generate `CREATE TABLE` statements and RLS policies from schema |
502
+ | `generateTypeScript(schema)` | Generate TypeScript interfaces from schema |
503
+ | `generateMigrationSQL(oldSchema, newSchema)` | Generate `ALTER TABLE` migration SQL for schema changes |
509
504
 
510
505
  ### Svelte Actions
511
506
 
@@ -516,17 +511,17 @@ When debug mode is enabled, the engine exposes utilities on `window` using your
516
511
  | `triggerLocalAnimation` | Programmatically trigger the local-change animation on a node |
517
512
  | `truncateTooltip` | Action that shows a tooltip with full text when content is truncated |
518
513
 
519
- ### Svelte Components
514
+ ### Svelte Components (Optional - SvelteKit)
520
515
 
521
516
  | Export | Description |
522
517
  |---|---|
523
- | `@prabhask5/stellar-engine/components/SyncStatus` | Animated sync-state indicator with tooltip and PWA refresh (offline/syncing/synced/error/pending states) |
524
- | `@prabhask5/stellar-engine/components/DeferredChangesBanner` | Cross-device data conflict notification with Update/Dismiss/Show Changes actions and diff preview |
518
+ | `@prabhask5/stellar-engine/components/SyncStatus` | Animated sync-state indicator with tooltip and PWA refresh |
519
+ | `@prabhask5/stellar-engine/components/DeferredChangesBanner` | Cross-device data conflict notification with diff preview |
525
520
  | `@prabhask5/stellar-engine/components/DemoBanner` | Demo mode indicator banner |
526
521
 
527
- ### SvelteKit Helpers (optional)
522
+ ### SvelteKit Helpers (Optional - SvelteKit)
528
523
 
529
- These require `svelte ^5.0.0` as a peer dependency.
524
+ These require `svelte ^5.0.0` and `@sveltejs/kit` as peer dependencies.
530
525
 
531
526
  | Export | Description |
532
527
  |---|---|
@@ -553,7 +548,7 @@ These require `svelte ^5.0.0` as a peer dependency.
553
548
 
554
549
  All TypeScript types are available from `@prabhask5/stellar-engine/types`:
555
550
 
556
- `Session`, `SyncEngineConfig`, `TableConfig`, `BatchOperation`, `SingleUserConfig`, `DemoConfig`, `SyncStatus`, `AuthState`, `CRDTConfig`, and more.
551
+ `Session`, `SyncEngineConfig`, `TableConfig`, `AuthConfig`, `SchemaDefinition`, `SchemaTableConfig`, `FieldType`, `BatchOperation`, `SingleUserConfig`, `DemoConfig`, `SyncStatus`, `AuthMode`, `CRDTConfig`, and more.
557
552
 
558
553
  ## Subpath exports
559
554
 
@@ -561,7 +556,7 @@ Import only what you need:
561
556
 
562
557
  | Subpath | Contents |
563
558
  |---|---|
564
- | `@prabhask5/stellar-engine` | Core: `initEngine`, `startSyncEngine`, `runFullSync`, `supabase`, `getDb`, `resetDatabase`, `validateSupabaseCredentials`, `validateSchema`, CRUD, auth, stores, and all re-exports |
559
+ | `@prabhask5/stellar-engine` | Core: `initEngine`, `startSyncEngine`, `runFullSync`, `getDb`, `resetDatabase`, `getDiagnostics`, CRUD, auth, stores, and all re-exports |
565
560
  | `@prabhask5/stellar-engine/data` | CRUD + query operations + helpers |
566
561
  | `@prabhask5/stellar-engine/auth` | All auth functions |
567
562
  | `@prabhask5/stellar-engine/stores` | Reactive stores + store factories + event subscriptions |
@@ -580,7 +575,7 @@ Import only what you need:
580
575
 
581
576
  stellar-engine includes a built-in demo mode that provides a completely isolated sandbox. When active:
582
577
 
583
- - **Separate database** -- uses `${name}_demo` IndexedDB; the real database is never opened
578
+ - **Separate database** -- uses `${prefix}DB_demo` IndexedDB; the real database is never opened
584
579
  - **No Supabase** -- zero network requests to the backend
585
580
  - **Mock auth** -- `authMode === 'demo'`; protected routes work with mock data only
586
581
  - **Auto-seeded** -- your `seedData(db)` callback populates the demo database on each page load
@@ -588,13 +583,13 @@ stellar-engine includes a built-in demo mode that provides a completely isolated
588
583
 
589
584
  ```ts
590
585
  import type { DemoConfig } from '@prabhask5/stellar-engine';
591
- import { setDemoMode } from '@prabhask5/stellar-engine';
586
+ import { setDemoMode, isDemoMode } from '@prabhask5/stellar-engine';
592
587
 
593
588
  // Define demo config in initEngine
594
589
  const demoConfig: DemoConfig = {
595
590
  seedData: async (db) => {
596
591
  await db.table('projects').bulkPut([
597
- { id: 'demo-1', name: 'Sample Project', sort_order: 1, is_deleted: false },
592
+ { id: 'demo-1', name: 'Sample Project', order: 1 },
598
593
  ]);
599
594
  },
600
595
  mockProfile: { email: 'demo@example.com', firstName: 'Demo', lastName: 'User' },
@@ -149,27 +149,14 @@ async function resolveSingleUserAuthState() {
149
149
  return { session: null, authMode: 'none', offlineProfile: null, singleUserSetUp: false };
150
150
  }
151
151
  if (!config.email) {
152
- /* Legacy config from anonymous auth era -- no email means user needs to
153
- go through the new setup flow (email + PIN). Old anonymous data will not
154
- be accessible under ownership-based RLS anyway.
155
- Nuke all legacy auth artifacts so the user gets a clean slate. */
156
- debugLog('[Auth] Legacy config without email detected, clearing old auth state');
157
- try {
158
- await db.table('singleUserConfig').delete('config');
159
- await db.table('offlineCredentials').delete('current_user');
160
- await db.table('offlineSession').delete('current_session');
161
- }
162
- catch (e) {
163
- debugWarn('[Auth] Failed to clear legacy auth state:', e);
164
- }
152
+ /* Config without email is invalid user needs to go through setup. */
165
153
  return { session: null, authMode: 'none', offlineProfile: null, singleUserSetUp: false };
166
154
  }
167
155
  /* codeLength migration: if the engine config specifies a different PIN length
168
156
  than what is stored locally, the user must re-setup. This handles the case
169
- where the app developer changes the codeLength in their engine config.
170
- Existing configs from before codeLength was stored default to 4. */
157
+ where the app developer changes the codeLength in their engine config. */
171
158
  const expectedCodeLength = getEngineConfig().auth?.singleUser?.codeLength;
172
- const storedCodeLength = config.codeLength ?? 4;
159
+ const storedCodeLength = config.codeLength;
173
160
  if (expectedCodeLength && storedCodeLength !== expectedCodeLength) {
174
161
  debugLog('[Auth] codeLength mismatch detected:', storedCodeLength, '→', expectedCodeLength);
175
162
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"resolveAuthState.js","sourceRoot":"","sources":["../../src/auth/resolveAuthState.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resolveAuthState.js","sourceRoot":"","sources":["../../src/auth/resolveAuthState.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"singleUser.d.ts","sourceRoot":"","sources":["../../src/auth/singleUser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"singleUser.d.ts","sourceRoot":"","sources":["../../src/auth/singleUser.ts"],"names":[],"mappings":"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"}
@@ -564,9 +564,8 @@ export async function unlockSingleUser(gate) {
564
564
  return { error: null };
565
565
  }
566
566
  else {
567
- // --- OFFLINE UNLOCK (or no email — legacy migration) ---
568
- /* Fall back to local hash verification when offline or when the
569
- config has no email (legacy accounts before email was required) */
567
+ // --- OFFLINE UNLOCK ---
568
+ /* Fall back to local hash verification when offline */
570
569
  const inputHash = await hashValue(gate);
571
570
  if (config.gateHash && inputHash !== config.gateHash) {
572
571
  return { error: 'Incorrect code' };