@prabhask5/stellar-engine 1.0.3

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 (138) hide show
  1. package/README.md +295 -0
  2. package/dist/actions/remoteChange.d.ts +79 -0
  3. package/dist/actions/remoteChange.d.ts.map +1 -0
  4. package/dist/actions/remoteChange.js +300 -0
  5. package/dist/actions/remoteChange.js.map +1 -0
  6. package/dist/auth/admin.d.ts +12 -0
  7. package/dist/auth/admin.d.ts.map +1 -0
  8. package/dist/auth/admin.js +23 -0
  9. package/dist/auth/admin.js.map +1 -0
  10. package/dist/auth/offlineCredentials.d.ts +41 -0
  11. package/dist/auth/offlineCredentials.d.ts.map +1 -0
  12. package/dist/auth/offlineCredentials.js +121 -0
  13. package/dist/auth/offlineCredentials.js.map +1 -0
  14. package/dist/auth/offlineLogin.d.ts +34 -0
  15. package/dist/auth/offlineLogin.d.ts.map +1 -0
  16. package/dist/auth/offlineLogin.js +75 -0
  17. package/dist/auth/offlineLogin.js.map +1 -0
  18. package/dist/auth/offlineSession.d.ts +22 -0
  19. package/dist/auth/offlineSession.d.ts.map +1 -0
  20. package/dist/auth/offlineSession.js +54 -0
  21. package/dist/auth/offlineSession.js.map +1 -0
  22. package/dist/auth/resolveAuthState.d.ts +24 -0
  23. package/dist/auth/resolveAuthState.d.ts.map +1 -0
  24. package/dist/auth/resolveAuthState.js +69 -0
  25. package/dist/auth/resolveAuthState.js.map +1 -0
  26. package/dist/config.d.ts +53 -0
  27. package/dist/config.d.ts.map +1 -0
  28. package/dist/config.js +55 -0
  29. package/dist/config.js.map +1 -0
  30. package/dist/conflicts.d.ts +70 -0
  31. package/dist/conflicts.d.ts.map +1 -0
  32. package/dist/conflicts.js +321 -0
  33. package/dist/conflicts.js.map +1 -0
  34. package/dist/data.d.ts +77 -0
  35. package/dist/data.d.ts.map +1 -0
  36. package/dist/data.js +360 -0
  37. package/dist/data.js.map +1 -0
  38. package/dist/database.d.ts +31 -0
  39. package/dist/database.d.ts.map +1 -0
  40. package/dist/database.js +51 -0
  41. package/dist/database.js.map +1 -0
  42. package/dist/debug.d.ts +11 -0
  43. package/dist/debug.d.ts.map +1 -0
  44. package/dist/debug.js +48 -0
  45. package/dist/debug.js.map +1 -0
  46. package/dist/deviceId.d.ts +16 -0
  47. package/dist/deviceId.d.ts.map +1 -0
  48. package/dist/deviceId.js +48 -0
  49. package/dist/deviceId.js.map +1 -0
  50. package/dist/engine.d.ts +14 -0
  51. package/dist/engine.d.ts.map +1 -0
  52. package/dist/engine.js +1903 -0
  53. package/dist/engine.js.map +1 -0
  54. package/dist/entries/actions.d.ts +2 -0
  55. package/dist/entries/actions.d.ts.map +1 -0
  56. package/dist/entries/actions.js +3 -0
  57. package/dist/entries/actions.js.map +1 -0
  58. package/dist/entries/auth.d.ts +7 -0
  59. package/dist/entries/auth.d.ts.map +1 -0
  60. package/dist/entries/auth.js +6 -0
  61. package/dist/entries/auth.js.map +1 -0
  62. package/dist/entries/config.d.ts +3 -0
  63. package/dist/entries/config.d.ts.map +1 -0
  64. package/dist/entries/config.js +3 -0
  65. package/dist/entries/config.js.map +1 -0
  66. package/dist/entries/stores.d.ts +9 -0
  67. package/dist/entries/stores.d.ts.map +1 -0
  68. package/dist/entries/stores.js +9 -0
  69. package/dist/entries/stores.js.map +1 -0
  70. package/dist/entries/types.d.ts +11 -0
  71. package/dist/entries/types.d.ts.map +1 -0
  72. package/dist/entries/types.js +2 -0
  73. package/dist/entries/types.js.map +1 -0
  74. package/dist/entries/utils.d.ts +3 -0
  75. package/dist/entries/utils.d.ts.map +1 -0
  76. package/dist/entries/utils.js +4 -0
  77. package/dist/entries/utils.js.map +1 -0
  78. package/dist/index.d.ts +32 -0
  79. package/dist/index.d.ts.map +1 -0
  80. package/dist/index.js +39 -0
  81. package/dist/index.js.map +1 -0
  82. package/dist/operations.d.ts +73 -0
  83. package/dist/operations.d.ts.map +1 -0
  84. package/dist/operations.js +227 -0
  85. package/dist/operations.js.map +1 -0
  86. package/dist/queue.d.ts +32 -0
  87. package/dist/queue.d.ts.map +1 -0
  88. package/dist/queue.js +377 -0
  89. package/dist/queue.js.map +1 -0
  90. package/dist/realtime.d.ts +57 -0
  91. package/dist/realtime.d.ts.map +1 -0
  92. package/dist/realtime.js +491 -0
  93. package/dist/realtime.js.map +1 -0
  94. package/dist/reconnectHandler.d.ts +16 -0
  95. package/dist/reconnectHandler.d.ts.map +1 -0
  96. package/dist/reconnectHandler.js +21 -0
  97. package/dist/reconnectHandler.js.map +1 -0
  98. package/dist/runtime/runtimeConfig.d.ts +27 -0
  99. package/dist/runtime/runtimeConfig.d.ts.map +1 -0
  100. package/dist/runtime/runtimeConfig.js +133 -0
  101. package/dist/runtime/runtimeConfig.js.map +1 -0
  102. package/dist/stores/authState.d.ts +57 -0
  103. package/dist/stores/authState.d.ts.map +1 -0
  104. package/dist/stores/authState.js +154 -0
  105. package/dist/stores/authState.js.map +1 -0
  106. package/dist/stores/network.d.ts +9 -0
  107. package/dist/stores/network.d.ts.map +1 -0
  108. package/dist/stores/network.js +97 -0
  109. package/dist/stores/network.js.map +1 -0
  110. package/dist/stores/remoteChanges.d.ts +142 -0
  111. package/dist/stores/remoteChanges.d.ts.map +1 -0
  112. package/dist/stores/remoteChanges.js +353 -0
  113. package/dist/stores/remoteChanges.js.map +1 -0
  114. package/dist/stores/sync.d.ts +35 -0
  115. package/dist/stores/sync.d.ts.map +1 -0
  116. package/dist/stores/sync.js +115 -0
  117. package/dist/stores/sync.js.map +1 -0
  118. package/dist/supabase/auth.d.ts +60 -0
  119. package/dist/supabase/auth.d.ts.map +1 -0
  120. package/dist/supabase/auth.js +298 -0
  121. package/dist/supabase/auth.js.map +1 -0
  122. package/dist/supabase/client.d.ts +15 -0
  123. package/dist/supabase/client.d.ts.map +1 -0
  124. package/dist/supabase/client.js +149 -0
  125. package/dist/supabase/client.js.map +1 -0
  126. package/dist/supabase/validate.d.ts +11 -0
  127. package/dist/supabase/validate.d.ts.map +1 -0
  128. package/dist/supabase/validate.js +38 -0
  129. package/dist/supabase/validate.js.map +1 -0
  130. package/dist/types.d.ts +78 -0
  131. package/dist/types.d.ts.map +1 -0
  132. package/dist/types.js +16 -0
  133. package/dist/types.js.map +1 -0
  134. package/dist/utils.d.ts +24 -0
  135. package/dist/utils.d.ts.map +1 -0
  136. package/dist/utils.js +56 -0
  137. package/dist/utils.js.map +1 -0
  138. package/package.json +84 -0
@@ -0,0 +1,353 @@
1
+ /**
2
+ * Remote Changes Store
3
+ *
4
+ * Manages incoming realtime changes and active editing state to enable:
5
+ * - Graceful UI animations when remote changes arrive
6
+ * - Protection of user edits from being overwritten
7
+ * - Deferred change application for entities being edited
8
+ *
9
+ * Two types of entities:
10
+ * 1. Auto-save entities (toggles, quick actions) - changes apply immediately with animation
11
+ * 2. Form entities (modals with Save button) - changes are deferred until form closes
12
+ *
13
+ * Action type detection:
14
+ * Since Supabase Realtime only sends INSERT/UPDATE/DELETE events, we detect
15
+ * the specific action type by analyzing which fields changed:
16
+ * - INSERT → 'create' action
17
+ * - DELETE → 'delete' action
18
+ * - UPDATE with 'completed' changed → 'toggle' action
19
+ * - UPDATE with 'current_value' changed → 'increment' or 'decrement' action
20
+ * - UPDATE with 'order' changed → 'reorder' action
21
+ * - UPDATE with 'name' changed → 'rename' action
22
+ * - UPDATE with 'is_enabled' changed → 'toggle' action (for block lists)
23
+ * - UPDATE with other fields → 'update' action
24
+ */
25
+ import { writable, derived } from 'svelte/store';
26
+ // ============================================================
27
+ // STORE
28
+ // ============================================================
29
+ const ANIMATION_DURATION = 2000; // How long to keep change in "recent" for animation
30
+ const CLEANUP_INTERVAL = 5000; // How often to clean up old changes
31
+ // How long to keep items in pending delete state for animation
32
+ const DELETE_ANIMATION_DURATION = 500;
33
+ function createRemoteChangesStore() {
34
+ const { subscribe, update } = writable({
35
+ recentChanges: new Map(),
36
+ activeEdits: new Map(),
37
+ deferredChanges: new Map(),
38
+ pendingDeletes: new Map()
39
+ });
40
+ // Cleanup old changes periodically
41
+ let cleanupInterval = null;
42
+ function startCleanup() {
43
+ if (cleanupInterval)
44
+ return;
45
+ if (typeof window === 'undefined')
46
+ return;
47
+ cleanupInterval = setInterval(() => {
48
+ const now = Date.now();
49
+ update((state) => {
50
+ // Remove old recent changes
51
+ for (const [key, change] of state.recentChanges) {
52
+ if (now - change.timestamp > ANIMATION_DURATION) {
53
+ state.recentChanges.delete(key);
54
+ }
55
+ }
56
+ return state;
57
+ });
58
+ }, CLEANUP_INTERVAL);
59
+ }
60
+ function stopCleanup() {
61
+ if (cleanupInterval) {
62
+ clearInterval(cleanupInterval);
63
+ cleanupInterval = null;
64
+ }
65
+ }
66
+ return {
67
+ subscribe,
68
+ /**
69
+ * Detect action type from event type and changed fields.
70
+ * This is how we know what animation to play even though Supabase
71
+ * doesn't store the "action" - we infer it from what changed.
72
+ */
73
+ detectActionType(eventType, fields, valueDelta) {
74
+ if (eventType === 'INSERT')
75
+ return 'create';
76
+ if (eventType === 'DELETE')
77
+ return 'delete';
78
+ // For UPDATE, determine action from which fields changed
79
+ // Priority order matters - more specific actions first
80
+ // Toggle actions (completed, is_enabled)
81
+ if (fields.includes('completed') || fields.includes('is_enabled')) {
82
+ return 'toggle';
83
+ }
84
+ // Increment/decrement (current_value changed)
85
+ if (fields.includes('current_value')) {
86
+ if (valueDelta !== undefined) {
87
+ return valueDelta > 0 ? 'increment' : 'decrement';
88
+ }
89
+ return 'increment'; // Default to increment if delta unknown
90
+ }
91
+ // Reorder (order changed)
92
+ if (fields.includes('order') && fields.length === 1) {
93
+ return 'reorder';
94
+ }
95
+ // Rename or visual property change (name, color)
96
+ if ((fields.includes('name') || fields.includes('color')) && fields.length <= 2) {
97
+ return 'rename';
98
+ }
99
+ // Generic update for other changes
100
+ return 'update';
101
+ },
102
+ /**
103
+ * Record a remote change that just arrived.
104
+ * If the entity is being edited with a manual-save form, defer the change.
105
+ * Otherwise, mark it as a recent change for animation.
106
+ *
107
+ * @param eventType - Supabase event type (INSERT/UPDATE/DELETE)
108
+ * @param valueDelta - For increment/decrement, the change in value
109
+ */
110
+ recordRemoteChange(entityId, entityType, fields, applied, eventType = 'UPDATE', valueDelta) {
111
+ startCleanup();
112
+ const actionType = this.detectActionType(eventType, fields, valueDelta);
113
+ const change = {
114
+ entityId,
115
+ entityType,
116
+ fields,
117
+ actionType,
118
+ timestamp: Date.now(),
119
+ applied,
120
+ valueDelta
121
+ };
122
+ let deferred = false;
123
+ update((state) => {
124
+ const key = `${entityType}:${entityId}`;
125
+ const activeEdit = state.activeEdits.get(key);
126
+ if (activeEdit && activeEdit.formType === 'manual-save') {
127
+ // Entity is being edited in a form with Save button - defer the change
128
+ const existing = state.deferredChanges.get(key) || [];
129
+ existing.push(change);
130
+ state.deferredChanges.set(key, existing);
131
+ deferred = true;
132
+ }
133
+ else {
134
+ // Apply immediately (or already applied) - record for animation
135
+ state.recentChanges.set(key, change);
136
+ }
137
+ return state;
138
+ });
139
+ return { deferred, actionType };
140
+ },
141
+ /**
142
+ * Record a local change for animation purposes.
143
+ * Call this BEFORE the component mounts (e.g., right before adding to database)
144
+ * so that when the component mounts with remoteChangeAnimation, the create animation triggers.
145
+ *
146
+ * This is useful for local creates to animate the same way as remote creates.
147
+ */
148
+ recordLocalChange(entityId, entityType, actionType, fields = ['*']) {
149
+ startCleanup();
150
+ const change = {
151
+ entityId,
152
+ entityType,
153
+ fields,
154
+ actionType,
155
+ timestamp: Date.now(),
156
+ applied: true
157
+ };
158
+ update((state) => {
159
+ const key = `${entityType}:${entityId}`;
160
+ state.recentChanges.set(key, change);
161
+ return state;
162
+ });
163
+ },
164
+ /**
165
+ * Mark an entity as being actively edited.
166
+ * @param formType 'auto-save' for inline edits, 'manual-save' for modals with Save button
167
+ */
168
+ startEditing(entityId, entityType, formType, fields) {
169
+ update((state) => {
170
+ const key = `${entityType}:${entityId}`;
171
+ state.activeEdits.set(key, {
172
+ entityId,
173
+ entityType,
174
+ formType,
175
+ startedAt: Date.now(),
176
+ fields
177
+ });
178
+ return state;
179
+ });
180
+ },
181
+ /**
182
+ * Mark editing as complete. Returns any deferred changes that need to be processed.
183
+ */
184
+ stopEditing(entityId, entityType) {
185
+ let deferredChanges = [];
186
+ update((state) => {
187
+ const key = `${entityType}:${entityId}`;
188
+ state.activeEdits.delete(key);
189
+ // Return deferred changes for processing
190
+ if (state.deferredChanges.has(key)) {
191
+ deferredChanges = state.deferredChanges.get(key) || [];
192
+ state.deferredChanges.delete(key);
193
+ }
194
+ return state;
195
+ });
196
+ return deferredChanges;
197
+ },
198
+ /**
199
+ * Check if an entity is currently being edited.
200
+ */
201
+ isEditing(entityId, entityType) {
202
+ let editing = false;
203
+ const unsubscribe = subscribe((state) => {
204
+ editing = state.activeEdits.has(`${entityType}:${entityId}`);
205
+ });
206
+ unsubscribe();
207
+ return editing;
208
+ },
209
+ /**
210
+ * Clear deferred changes for an entity without stopping editing.
211
+ * Used when user dismisses or loads remote changes in the banner.
212
+ */
213
+ clearDeferredChanges(entityId, entityType) {
214
+ update((state) => {
215
+ const key = `${entityType}:${entityId}`;
216
+ state.deferredChanges.delete(key);
217
+ return state;
218
+ });
219
+ },
220
+ /**
221
+ * Check if an entity has deferred changes waiting.
222
+ */
223
+ hasDeferredChanges(entityId, entityType) {
224
+ let hasChanges = false;
225
+ const unsubscribe = subscribe((state) => {
226
+ const key = `${entityType}:${entityId}`;
227
+ const changes = state.deferredChanges.get(key);
228
+ hasChanges = !!changes && changes.length > 0;
229
+ });
230
+ unsubscribe();
231
+ return hasChanges;
232
+ },
233
+ /**
234
+ * Check if an entity was recently changed (for animation).
235
+ */
236
+ wasRecentlyChanged(entityId, entityType) {
237
+ let recent = false;
238
+ const unsubscribe = subscribe((state) => {
239
+ const key = `${entityType}:${entityId}`;
240
+ const change = state.recentChanges.get(key);
241
+ if (change && Date.now() - change.timestamp < ANIMATION_DURATION) {
242
+ recent = true;
243
+ }
244
+ });
245
+ unsubscribe();
246
+ return recent;
247
+ },
248
+ /**
249
+ * Get recent change details for an entity (for field-level animation).
250
+ */
251
+ getRecentChange(entityId, entityType) {
252
+ let change = null;
253
+ const unsubscribe = subscribe((state) => {
254
+ const key = `${entityType}:${entityId}`;
255
+ const c = state.recentChanges.get(key);
256
+ if (c && Date.now() - c.timestamp < ANIMATION_DURATION) {
257
+ change = c;
258
+ }
259
+ });
260
+ unsubscribe();
261
+ return change;
262
+ },
263
+ /**
264
+ * Mark an entity as pending delete (for delete animation).
265
+ * Returns a promise that resolves after the animation duration.
266
+ * The pending delete is cleared AFTER resolve so the caller can
267
+ * delete from DB first — this prevents a reactive flash where the
268
+ * item reappears between animation end and DOM removal.
269
+ */
270
+ markPendingDelete(entityId, entityType) {
271
+ update((state) => {
272
+ const key = `${entityType}:${entityId}`;
273
+ state.pendingDeletes.set(key, Date.now());
274
+ return state;
275
+ });
276
+ // Return promise that resolves after animation duration
277
+ return new Promise((resolve) => {
278
+ setTimeout(() => {
279
+ resolve();
280
+ // Clean up after a short delay — the caller deletes from DB on
281
+ // resolve which triggers DOM removal, so this is just housekeeping
282
+ setTimeout(() => {
283
+ update((state) => {
284
+ const key = `${entityType}:${entityId}`;
285
+ state.pendingDeletes.delete(key);
286
+ return state;
287
+ });
288
+ }, 100);
289
+ }, DELETE_ANIMATION_DURATION);
290
+ });
291
+ },
292
+ /**
293
+ * Check if an entity is pending deletion (for animation).
294
+ */
295
+ isPendingDelete(entityId, entityType) {
296
+ let pending = false;
297
+ const unsubscribe = subscribe((state) => {
298
+ const key = `${entityType}:${entityId}`;
299
+ pending = state.pendingDeletes.has(key);
300
+ });
301
+ unsubscribe();
302
+ return pending;
303
+ },
304
+ /**
305
+ * Clear all tracking (for logout).
306
+ */
307
+ clear() {
308
+ stopCleanup();
309
+ update(() => ({
310
+ recentChanges: new Map(),
311
+ activeEdits: new Map(),
312
+ deferredChanges: new Map(),
313
+ pendingDeletes: new Map()
314
+ }));
315
+ },
316
+ /**
317
+ * Stop the cleanup interval (for cleanup on unmount).
318
+ */
319
+ destroy() {
320
+ stopCleanup();
321
+ }
322
+ };
323
+ }
324
+ export const remoteChangesStore = createRemoteChangesStore();
325
+ // ============================================================
326
+ // DERIVED STORES FOR UI
327
+ // ============================================================
328
+ /**
329
+ * Derived store for components to check if a specific entity was recently updated remotely.
330
+ * Use this to trigger animations.
331
+ */
332
+ export function createRecentChangeIndicator(entityId, entityType) {
333
+ return derived(remoteChangesStore, ($state) => {
334
+ const key = `${entityType}:${entityId}`;
335
+ const change = $state.recentChanges.get(key);
336
+ if (!change)
337
+ return null;
338
+ if (Date.now() - change.timestamp > ANIMATION_DURATION)
339
+ return null;
340
+ return change;
341
+ });
342
+ }
343
+ /**
344
+ * Derived store for components to check if a specific entity is pending deletion.
345
+ * Use this to apply delete animation before removing from DOM.
346
+ */
347
+ export function createPendingDeleteIndicator(entityId, entityType) {
348
+ return derived(remoteChangesStore, ($state) => {
349
+ const key = `${entityType}:${entityId}`;
350
+ return $state.pendingDeletes.has(key);
351
+ });
352
+ }
353
+ //# sourceMappingURL=remoteChanges.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remoteChanges.js","sourceRoot":"","sources":["../../src/stores/remoteChanges.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import type { SyncStatus } from '../types';
2
+ export interface SyncError {
3
+ table: string;
4
+ operation: string;
5
+ entityId: string;
6
+ message: string;
7
+ timestamp: string;
8
+ }
9
+ export type RealtimeState = 'disconnected' | 'connecting' | 'connected' | 'error';
10
+ interface SyncState {
11
+ status: SyncStatus;
12
+ pendingCount: number;
13
+ lastError: string | null;
14
+ lastErrorDetails: string | null;
15
+ syncErrors: SyncError[];
16
+ lastSyncTime: string | null;
17
+ syncMessage: string | null;
18
+ isTabVisible: boolean;
19
+ realtimeState: RealtimeState;
20
+ }
21
+ export declare const syncStatusStore: {
22
+ subscribe: (this: void, run: import("svelte/store").Subscriber<SyncState>, invalidate?: () => void) => import("svelte/store").Unsubscriber;
23
+ setStatus: (status: SyncStatus) => void;
24
+ setPendingCount: (count: number) => void;
25
+ setError: (friendly: string | null, raw?: string | null) => void;
26
+ addSyncError: (error: SyncError) => void;
27
+ clearSyncErrors: () => void;
28
+ setLastSyncTime: (time: string) => void;
29
+ setSyncMessage: (message: string | null) => void;
30
+ setTabVisible: (visible: boolean) => void;
31
+ setRealtimeState: (realtimeState: RealtimeState) => void;
32
+ reset: () => void;
33
+ };
34
+ export {};
35
+ //# sourceMappingURL=sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/stores/sync.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAG3C,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAGD,MAAM,MAAM,aAAa,GAAG,cAAc,GAAG,YAAY,GAAG,WAAW,GAAG,OAAO,CAAC;AAElF,UAAU,SAAS;IACjB,MAAM,EAAE,UAAU,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,aAAa,CAAC;CAC9B;AA4HD,eAAO,MAAM,eAAe;;wBAhGJ,UAAU;6BAuDL,MAAM;yBACV,MAAM,GAAG,IAAI,QAAQ,MAAM,GAAG,IAAI;0BAMjC,SAAS;;4BAMP,MAAM;8BACJ,MAAM,GAAG,IAAI;6BAEd,OAAO;sCACE,aAAa;;CAwBG,CAAC"}
@@ -0,0 +1,115 @@
1
+ import { writable } from 'svelte/store';
2
+ // Minimum time to show 'syncing' state to prevent flickering (ms)
3
+ const MIN_SYNCING_TIME = 500;
4
+ // Max errors to keep in history
5
+ const MAX_ERROR_HISTORY = 10;
6
+ function createSyncStatusStore() {
7
+ const { subscribe, set, update } = writable({
8
+ status: 'idle',
9
+ pendingCount: 0,
10
+ lastError: null,
11
+ lastErrorDetails: null,
12
+ syncErrors: [],
13
+ lastSyncTime: null,
14
+ syncMessage: null,
15
+ isTabVisible: true,
16
+ realtimeState: 'disconnected'
17
+ });
18
+ let currentStatus = 'idle';
19
+ let syncingStartTime = null;
20
+ let pendingStatusChange = null;
21
+ return {
22
+ subscribe,
23
+ setStatus: (status) => {
24
+ // Ignore redundant status updates to prevent unnecessary re-renders
25
+ if (status === currentStatus && status !== 'syncing') {
26
+ return;
27
+ }
28
+ // Clear any pending status change
29
+ if (pendingStatusChange) {
30
+ clearTimeout(pendingStatusChange.timeout);
31
+ pendingStatusChange = null;
32
+ }
33
+ if (status === 'syncing') {
34
+ // Starting sync - record the time and clear previous errors
35
+ syncingStartTime = Date.now();
36
+ currentStatus = status;
37
+ update((state) => ({ ...state, status, lastError: null, syncErrors: [] }));
38
+ }
39
+ else if (syncingStartTime !== null) {
40
+ // Ending sync - ensure minimum display time
41
+ const elapsed = Date.now() - syncingStartTime;
42
+ const remaining = MIN_SYNCING_TIME - elapsed;
43
+ if (remaining > 0) {
44
+ // Delay the status change to prevent flickering
45
+ pendingStatusChange = {
46
+ status,
47
+ timeout: setTimeout(() => {
48
+ syncingStartTime = null;
49
+ pendingStatusChange = null;
50
+ currentStatus = status;
51
+ update((state) => ({
52
+ ...state,
53
+ status,
54
+ lastError: status === 'idle' ? null : state.lastError
55
+ }));
56
+ }, remaining)
57
+ };
58
+ }
59
+ else {
60
+ syncingStartTime = null;
61
+ currentStatus = status;
62
+ update((state) => ({
63
+ ...state,
64
+ status,
65
+ lastError: status === 'idle' ? null : state.lastError
66
+ }));
67
+ }
68
+ }
69
+ else {
70
+ currentStatus = status;
71
+ update((state) => ({
72
+ ...state,
73
+ status,
74
+ lastError: status === 'idle' ? null : state.lastError
75
+ }));
76
+ }
77
+ },
78
+ setPendingCount: (count) => update((state) => ({ ...state, pendingCount: count })),
79
+ setError: (friendly, raw) => update((state) => ({
80
+ ...state,
81
+ lastError: friendly,
82
+ lastErrorDetails: raw ?? null
83
+ })),
84
+ addSyncError: (error) => update((state) => ({
85
+ ...state,
86
+ syncErrors: [...state.syncErrors, error].slice(-MAX_ERROR_HISTORY)
87
+ })),
88
+ clearSyncErrors: () => update((state) => ({ ...state, syncErrors: [] })),
89
+ setLastSyncTime: (time) => update((state) => ({ ...state, lastSyncTime: time })),
90
+ setSyncMessage: (message) => update((state) => ({ ...state, syncMessage: message })),
91
+ setTabVisible: (visible) => update((state) => ({ ...state, isTabVisible: visible })),
92
+ setRealtimeState: (realtimeState) => update((state) => ({ ...state, realtimeState })),
93
+ reset: () => {
94
+ if (pendingStatusChange) {
95
+ clearTimeout(pendingStatusChange.timeout);
96
+ pendingStatusChange = null;
97
+ }
98
+ syncingStartTime = null;
99
+ currentStatus = 'idle';
100
+ set({
101
+ status: 'idle',
102
+ pendingCount: 0,
103
+ lastError: null,
104
+ lastErrorDetails: null,
105
+ syncErrors: [],
106
+ lastSyncTime: null,
107
+ syncMessage: null,
108
+ isTabVisible: true,
109
+ realtimeState: 'disconnected'
110
+ });
111
+ }
112
+ };
113
+ }
114
+ export const syncStatusStore = createSyncStatusStore();
115
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/stores/sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import type { User, Session } from '@supabase/supabase-js';
2
+ export interface AuthResponse {
3
+ user: User | null;
4
+ session: Session | null;
5
+ error: string | null;
6
+ }
7
+ export declare function signIn(email: string, password: string): Promise<AuthResponse>;
8
+ export declare function signUp(email: string, password: string, profileData: Record<string, unknown>): Promise<AuthResponse>;
9
+ export declare function signOut(options?: {
10
+ preserveOfflineCredentials?: boolean;
11
+ preserveLocalData?: boolean;
12
+ }): Promise<{
13
+ error: string | null;
14
+ }>;
15
+ /**
16
+ * Get current Supabase session
17
+ * When offline, returns the cached session from localStorage even if expired
18
+ * (the caller should handle offline mode appropriately)
19
+ */
20
+ export declare function getSession(): Promise<Session | null>;
21
+ /**
22
+ * Check if a session's access token is expired
23
+ */
24
+ export declare function isSessionExpired(session: Session | null): boolean;
25
+ export declare function getUserProfile(user: User | null): Record<string, unknown>;
26
+ /**
27
+ * Update user profile
28
+ * Also updates cached offline credentials
29
+ */
30
+ export declare function updateProfile(profile: Record<string, unknown>): Promise<{
31
+ error: string | null;
32
+ }>;
33
+ /**
34
+ * Change user password
35
+ * Verifies current password first, then updates
36
+ * Also updates cached offline credentials
37
+ */
38
+ export declare function changePassword(currentPassword: string, newPassword: string): Promise<{
39
+ error: string | null;
40
+ }>;
41
+ /**
42
+ * Resend confirmation email for signup
43
+ * Should be rate-limited on the client side (30 second cooldown)
44
+ */
45
+ export declare function resendConfirmationEmail(email: string): Promise<{
46
+ error: string | null;
47
+ }>;
48
+ /**
49
+ * Verify OTP token (for email confirmation).
50
+ * Absorbs confirm page's direct Supabase call.
51
+ */
52
+ export declare function verifyOtp(tokenHash: string, type: 'signup' | 'email'): Promise<{
53
+ error: string | null;
54
+ }>;
55
+ /**
56
+ * Get a valid (non-expired) session, or null.
57
+ * Merges getSession() + isSessionExpired() into a single call.
58
+ */
59
+ export declare function getValidSession(): Promise<Session | null>;
60
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/supabase/auth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AA0B3D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,wBAAsB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAqBnF;AAED,wBAAsB,MAAM,CAC1B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,OAAO,CAAC,YAAY,CAAC,CAoBvB;AAED,wBAAsB,OAAO,CAAC,OAAO,CAAC,EAAE;IACtC,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAyDpC;AAED;;;;GAIG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CA0C1D;AA+BD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,GAAG,OAAO,CAMjE;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAMzE;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAoBnC;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,eAAe,EAAE,MAAM,EACvB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAmCnC;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAU9F;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAC7B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,QAAQ,GAAG,OAAO,GACvB,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAOnC;AAED;;;GAGG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAK/D"}