@prabhask5/stellar-engine 1.1.7 → 1.1.9
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 +12 -18
- package/dist/actions/remoteChange.d.ts +143 -18
- package/dist/actions/remoteChange.d.ts.map +1 -1
- package/dist/actions/remoteChange.js +182 -58
- package/dist/actions/remoteChange.js.map +1 -1
- package/dist/actions/truncateTooltip.d.ts +26 -12
- package/dist/actions/truncateTooltip.d.ts.map +1 -1
- package/dist/actions/truncateTooltip.js +89 -34
- package/dist/actions/truncateTooltip.js.map +1 -1
- package/dist/auth/crypto.d.ts +35 -8
- package/dist/auth/crypto.d.ts.map +1 -1
- package/dist/auth/crypto.js +38 -10
- package/dist/auth/crypto.js.map +1 -1
- package/dist/auth/deviceVerification.d.ts +236 -20
- package/dist/auth/deviceVerification.d.ts.map +1 -1
- package/dist/auth/deviceVerification.js +293 -40
- package/dist/auth/deviceVerification.js.map +1 -1
- package/dist/auth/displayUtils.d.ts +98 -0
- package/dist/auth/displayUtils.d.ts.map +1 -0
- package/dist/auth/displayUtils.js +133 -0
- package/dist/auth/displayUtils.js.map +1 -0
- package/dist/auth/loginGuard.d.ts +103 -16
- package/dist/auth/loginGuard.d.ts.map +1 -1
- package/dist/auth/loginGuard.js +163 -76
- package/dist/auth/loginGuard.js.map +1 -1
- package/dist/auth/offlineCredentials.d.ts +88 -24
- package/dist/auth/offlineCredentials.d.ts.map +1 -1
- package/dist/auth/offlineCredentials.js +114 -73
- package/dist/auth/offlineCredentials.js.map +1 -1
- package/dist/auth/offlineSession.d.ts +83 -9
- package/dist/auth/offlineSession.d.ts.map +1 -1
- package/dist/auth/offlineSession.js +104 -13
- package/dist/auth/offlineSession.js.map +1 -1
- package/dist/auth/resolveAuthState.d.ts +67 -9
- package/dist/auth/resolveAuthState.d.ts.map +1 -1
- package/dist/auth/resolveAuthState.js +125 -71
- package/dist/auth/resolveAuthState.js.map +1 -1
- package/dist/auth/singleUser.d.ts +390 -37
- package/dist/auth/singleUser.d.ts.map +1 -1
- package/dist/auth/singleUser.js +504 -103
- package/dist/auth/singleUser.js.map +1 -1
- package/dist/bin/install-pwa.d.ts +18 -2
- package/dist/bin/install-pwa.d.ts.map +1 -1
- package/dist/bin/install-pwa.js +2624 -77
- package/dist/bin/install-pwa.js.map +1 -1
- package/dist/config.d.ts +131 -15
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +87 -9
- package/dist/config.js.map +1 -1
- package/dist/conflicts.d.ts +246 -23
- package/dist/conflicts.d.ts.map +1 -1
- package/dist/conflicts.js +495 -46
- package/dist/conflicts.js.map +1 -1
- package/dist/data.d.ts +338 -18
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +385 -34
- package/dist/data.js.map +1 -1
- package/dist/database.d.ts +72 -14
- package/dist/database.d.ts.map +1 -1
- package/dist/database.js +120 -29
- package/dist/database.js.map +1 -1
- package/dist/debug.d.ts +77 -1
- package/dist/debug.d.ts.map +1 -1
- package/dist/debug.js +88 -1
- package/dist/debug.js.map +1 -1
- package/dist/deviceId.d.ts +38 -7
- package/dist/deviceId.d.ts.map +1 -1
- package/dist/deviceId.js +68 -10
- package/dist/deviceId.js.map +1 -1
- package/dist/engine.d.ts +175 -3
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +756 -109
- package/dist/engine.js.map +1 -1
- package/dist/entries/actions.d.ts +13 -0
- package/dist/entries/actions.d.ts.map +1 -1
- package/dist/entries/actions.js +26 -1
- package/dist/entries/actions.js.map +1 -1
- package/dist/entries/auth.d.ts +15 -4
- package/dist/entries/auth.d.ts.map +1 -1
- package/dist/entries/auth.js +47 -4
- package/dist/entries/auth.js.map +1 -1
- package/dist/entries/config.d.ts +12 -0
- package/dist/entries/config.d.ts.map +1 -1
- package/dist/entries/config.js +18 -1
- package/dist/entries/config.js.map +1 -1
- package/dist/entries/kit.d.ts +11 -0
- package/dist/entries/kit.d.ts.map +1 -1
- package/dist/entries/kit.js +52 -2
- package/dist/entries/kit.js.map +1 -1
- package/dist/entries/stores.d.ts +11 -0
- package/dist/entries/stores.d.ts.map +1 -1
- package/dist/entries/stores.js +43 -2
- package/dist/entries/stores.js.map +1 -1
- package/dist/entries/types.d.ts +10 -1
- package/dist/entries/types.d.ts.map +1 -1
- package/dist/entries/types.js +10 -0
- package/dist/entries/types.js.map +1 -1
- package/dist/entries/utils.d.ts +6 -0
- package/dist/entries/utils.d.ts.map +1 -1
- package/dist/entries/utils.js +22 -1
- package/dist/entries/utils.js.map +1 -1
- package/dist/entries/vite.d.ts +17 -0
- package/dist/entries/vite.d.ts.map +1 -1
- package/dist/entries/vite.js +24 -1
- package/dist/entries/vite.js.map +1 -1
- package/dist/index.d.ts +32 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +166 -23
- package/dist/index.js.map +1 -1
- package/dist/kit/auth.d.ts +60 -5
- package/dist/kit/auth.d.ts.map +1 -1
- package/dist/kit/auth.js +45 -4
- package/dist/kit/auth.js.map +1 -1
- package/dist/kit/confirm.d.ts +93 -12
- package/dist/kit/confirm.d.ts.map +1 -1
- package/dist/kit/confirm.js +103 -16
- package/dist/kit/confirm.js.map +1 -1
- package/dist/kit/loads.d.ts +148 -23
- package/dist/kit/loads.d.ts.map +1 -1
- package/dist/kit/loads.js +136 -28
- package/dist/kit/loads.js.map +1 -1
- package/dist/kit/server.d.ts +142 -10
- package/dist/kit/server.d.ts.map +1 -1
- package/dist/kit/server.js +158 -15
- package/dist/kit/server.js.map +1 -1
- package/dist/kit/sw.d.ts +152 -23
- package/dist/kit/sw.d.ts.map +1 -1
- package/dist/kit/sw.js +182 -26
- package/dist/kit/sw.js.map +1 -1
- package/dist/queue.d.ts +274 -0
- package/dist/queue.d.ts.map +1 -1
- package/dist/queue.js +556 -38
- package/dist/queue.js.map +1 -1
- package/dist/realtime.d.ts +241 -27
- package/dist/realtime.d.ts.map +1 -1
- package/dist/realtime.js +633 -109
- package/dist/realtime.js.map +1 -1
- package/dist/runtime/runtimeConfig.d.ts +91 -8
- package/dist/runtime/runtimeConfig.d.ts.map +1 -1
- package/dist/runtime/runtimeConfig.js +146 -19
- package/dist/runtime/runtimeConfig.js.map +1 -1
- package/dist/stores/authState.d.ts +150 -11
- package/dist/stores/authState.d.ts.map +1 -1
- package/dist/stores/authState.js +169 -17
- package/dist/stores/authState.js.map +1 -1
- package/dist/stores/network.d.ts +39 -0
- package/dist/stores/network.d.ts.map +1 -1
- package/dist/stores/network.js +169 -16
- package/dist/stores/network.js.map +1 -1
- package/dist/stores/remoteChanges.d.ts +327 -52
- package/dist/stores/remoteChanges.d.ts.map +1 -1
- package/dist/stores/remoteChanges.js +337 -75
- package/dist/stores/remoteChanges.js.map +1 -1
- package/dist/stores/sync.d.ts +130 -0
- package/dist/stores/sync.d.ts.map +1 -1
- package/dist/stores/sync.js +167 -7
- package/dist/stores/sync.js.map +1 -1
- package/dist/supabase/auth.d.ts +186 -46
- package/dist/supabase/auth.d.ts.map +1 -1
- package/dist/supabase/auth.js +238 -190
- package/dist/supabase/auth.js.map +1 -1
- package/dist/supabase/client.d.ts +79 -6
- package/dist/supabase/client.d.ts.map +1 -1
- package/dist/supabase/client.js +158 -15
- package/dist/supabase/client.js.map +1 -1
- package/dist/supabase/validate.d.ts +101 -7
- package/dist/supabase/validate.d.ts.map +1 -1
- package/dist/supabase/validate.js +117 -8
- package/dist/supabase/validate.js.map +1 -1
- package/dist/sw/build/vite-plugin.d.ts +55 -10
- package/dist/sw/build/vite-plugin.d.ts.map +1 -1
- package/dist/sw/build/vite-plugin.js +77 -18
- package/dist/sw/build/vite-plugin.js.map +1 -1
- package/dist/sw/sw.js +99 -44
- package/dist/types.d.ts +150 -26
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +12 -10
- package/dist/types.js.map +1 -1
- package/dist/utils.d.ts +55 -13
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +83 -22
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
- package/dist/auth/admin.d.ts +0 -12
- package/dist/auth/admin.d.ts.map +0 -1
- package/dist/auth/admin.js +0 -26
- package/dist/auth/admin.js.map +0 -1
- package/dist/auth/offlineLogin.d.ts +0 -34
- package/dist/auth/offlineLogin.d.ts.map +0 -1
- package/dist/auth/offlineLogin.js +0 -75
- package/dist/auth/offlineLogin.js.map +0 -1
|
@@ -1,35 +1,73 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Remote Changes Store
|
|
2
|
+
* @fileoverview Remote Changes Store
|
|
3
3
|
*
|
|
4
4
|
* Manages incoming realtime changes and active editing state to enable:
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* - Graceful UI animations when remote changes arrive
|
|
6
|
+
* - Protection of user edits from being overwritten by concurrent updates
|
|
7
|
+
* - Deferred change application for entities being edited in manual-save forms
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* **Entity Classification:**
|
|
10
|
+
* The store distinguishes between two types of editable entities:
|
|
11
|
+
* 1. **Auto-save entities** (toggles, quick actions) - Changes apply immediately
|
|
12
|
+
* with animation. No conflict risk since the user interaction is atomic.
|
|
13
|
+
* 2. **Form entities** (modals with a Save button) - Remote changes are deferred
|
|
14
|
+
* and queued until the form closes, preventing mid-edit data corruption.
|
|
12
15
|
*
|
|
13
|
-
* Action
|
|
14
|
-
* Since Supabase Realtime only sends INSERT/UPDATE/DELETE events
|
|
15
|
-
* the
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
16
|
+
* **Action Type Detection:**
|
|
17
|
+
* Since Supabase Realtime only sends INSERT/UPDATE/DELETE events (no semantic
|
|
18
|
+
* action type), this store infers the user-level action by analyzing which
|
|
19
|
+
* fields changed in the payload:
|
|
20
|
+
* - INSERT -> 'create' action
|
|
21
|
+
* - DELETE -> 'delete' action
|
|
22
|
+
* - UPDATE with 'completed' changed -> 'toggle' action
|
|
23
|
+
* - UPDATE with 'current_value' changed -> 'increment' or 'decrement' action
|
|
24
|
+
* - UPDATE with 'order' changed -> 'reorder' action
|
|
25
|
+
* - UPDATE with 'name' changed -> 'rename' action
|
|
26
|
+
* - UPDATE with 'is_enabled' changed -> 'toggle' action (for block lists)
|
|
27
|
+
* - UPDATE with other fields -> 'update' action
|
|
28
|
+
*
|
|
29
|
+
* **Svelte Store Pattern:**
|
|
30
|
+
* Uses a custom writable store with a `Map`-heavy internal state. Methods
|
|
31
|
+
* on the store provide imperative access for the sync engine, while derived
|
|
32
|
+
* store factories (`createRecentChangeIndicator`, `createPendingDeleteIndicator`)
|
|
33
|
+
* provide reactive per-entity subscriptions for UI components.
|
|
34
|
+
*
|
|
35
|
+
* **Reactive Architecture:**
|
|
36
|
+
* Components use the derived store factories to subscribe to changes for a
|
|
37
|
+
* specific entity, enabling fine-grained reactivity without re-rendering the
|
|
38
|
+
* entire list when a single item changes.
|
|
39
|
+
*
|
|
40
|
+
* @see {@link ./sync} for the sync store that triggers remote change recording
|
|
41
|
+
* @see {@link ./network} for connectivity state that gates realtime subscriptions
|
|
24
42
|
*/
|
|
25
43
|
import { writable, derived } from 'svelte/store';
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
|
|
44
|
+
// =============================================================================
|
|
45
|
+
// Constants
|
|
46
|
+
// =============================================================================
|
|
47
|
+
/** Duration (ms) to keep a change in the `recentChanges` map for animation purposes */
|
|
48
|
+
const ANIMATION_DURATION = 2000;
|
|
49
|
+
/** Interval (ms) at which stale entries are purged from `recentChanges` */
|
|
50
|
+
const CLEANUP_INTERVAL = 5000;
|
|
51
|
+
/** Duration (ms) to keep an entity in the `pendingDeletes` state for exit animation */
|
|
32
52
|
const DELETE_ANIMATION_DURATION = 500;
|
|
53
|
+
// =============================================================================
|
|
54
|
+
// Store Factory
|
|
55
|
+
// =============================================================================
|
|
56
|
+
/**
|
|
57
|
+
* Creates the singleton remote changes store.
|
|
58
|
+
*
|
|
59
|
+
* The store manages four concurrent concerns:
|
|
60
|
+
* 1. **Recent changes** - Short-lived entries that drive UI animations
|
|
61
|
+
* 2. **Active edits** - Tracks which entities the local user is editing
|
|
62
|
+
* 3. **Deferred changes** - Queues remote changes for entities in manual-save forms
|
|
63
|
+
* 4. **Pending deletes** - Coordinates delete animations with actual DB removal
|
|
64
|
+
*
|
|
65
|
+
* A periodic cleanup interval automatically purges stale `recentChanges` entries.
|
|
66
|
+
* The interval is lazily started on the first recorded change and can be stopped
|
|
67
|
+
* via `destroy()`.
|
|
68
|
+
*
|
|
69
|
+
* @returns A Svelte-compatible store with remote-change-specific methods
|
|
70
|
+
*/
|
|
33
71
|
function createRemoteChangesStore() {
|
|
34
72
|
const { subscribe, update } = writable({
|
|
35
73
|
recentChanges: new Map(),
|
|
@@ -37,8 +75,15 @@ function createRemoteChangesStore() {
|
|
|
37
75
|
deferredChanges: new Map(),
|
|
38
76
|
pendingDeletes: new Map()
|
|
39
77
|
});
|
|
40
|
-
//
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
// Cleanup Timer
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
/** Handle for the periodic cleanup interval; null when not running */
|
|
41
82
|
let cleanupInterval = null;
|
|
83
|
+
/**
|
|
84
|
+
* Lazily starts the periodic cleanup timer that purges stale entries
|
|
85
|
+
* from `recentChanges`. No-ops if already running or in SSR context.
|
|
86
|
+
*/
|
|
42
87
|
function startCleanup() {
|
|
43
88
|
if (cleanupInterval)
|
|
44
89
|
return;
|
|
@@ -48,7 +93,8 @@ function createRemoteChangesStore() {
|
|
|
48
93
|
const now = Date.now();
|
|
49
94
|
update((state) => {
|
|
50
95
|
const newRecentChanges = new Map(state.recentChanges);
|
|
51
|
-
|
|
96
|
+
/* Remove entries older than ANIMATION_DURATION so the animation
|
|
97
|
+
* CSS class is no longer applied on the next render cycle */
|
|
52
98
|
for (const [key, change] of newRecentChanges) {
|
|
53
99
|
if (now - change.timestamp > ANIMATION_DURATION) {
|
|
54
100
|
newRecentChanges.delete(key);
|
|
@@ -58,55 +104,102 @@ function createRemoteChangesStore() {
|
|
|
58
104
|
});
|
|
59
105
|
}, CLEANUP_INTERVAL);
|
|
60
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Stops the periodic cleanup timer. Called by `clear()` and `destroy()`.
|
|
109
|
+
*/
|
|
61
110
|
function stopCleanup() {
|
|
62
111
|
if (cleanupInterval) {
|
|
63
112
|
clearInterval(cleanupInterval);
|
|
64
113
|
cleanupInterval = null;
|
|
65
114
|
}
|
|
66
115
|
}
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
// Store Methods
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
67
119
|
return {
|
|
68
120
|
subscribe,
|
|
69
121
|
/**
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
122
|
+
* Infer the semantic action type from a Supabase realtime event.
|
|
123
|
+
*
|
|
124
|
+
* Since Supabase Realtime only provides INSERT/UPDATE/DELETE event types,
|
|
125
|
+
* this method analyzes the changed field names to determine the user-level
|
|
126
|
+
* action (toggle, increment, reorder, etc.) for animation purposes.
|
|
127
|
+
*
|
|
128
|
+
* Priority order matters: more specific field patterns are checked first
|
|
129
|
+
* to avoid false positives (e.g., an UPDATE that changes both 'completed'
|
|
130
|
+
* and 'name' is classified as 'toggle', not 'rename').
|
|
131
|
+
*
|
|
132
|
+
* @param eventType - The raw Supabase realtime event type
|
|
133
|
+
* @param fields - Array of field names that changed in this event
|
|
134
|
+
* @param valueDelta - Optional signed delta for numeric field changes
|
|
135
|
+
* @returns The inferred semantic action type
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```ts
|
|
139
|
+
* const action = remoteChangesStore.detectActionType('UPDATE', ['completed'], undefined);
|
|
140
|
+
* // Returns: 'toggle'
|
|
141
|
+
*
|
|
142
|
+
* const action2 = remoteChangesStore.detectActionType('UPDATE', ['current_value'], -1);
|
|
143
|
+
* // Returns: 'decrement'
|
|
144
|
+
* ```
|
|
73
145
|
*/
|
|
74
146
|
detectActionType(eventType, fields, valueDelta) {
|
|
75
147
|
if (eventType === 'INSERT')
|
|
76
148
|
return 'create';
|
|
77
149
|
if (eventType === 'DELETE')
|
|
78
150
|
return 'delete';
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
151
|
+
/* For UPDATE, determine action from which fields changed.
|
|
152
|
+
* Priority order matters - more specific actions first. */
|
|
153
|
+
/* Toggle actions (completed, is_enabled) */
|
|
82
154
|
if (fields.includes('completed') || fields.includes('is_enabled')) {
|
|
83
155
|
return 'toggle';
|
|
84
156
|
}
|
|
85
|
-
|
|
157
|
+
/* Increment/decrement (current_value changed) */
|
|
86
158
|
if (fields.includes('current_value')) {
|
|
87
159
|
if (valueDelta !== undefined) {
|
|
88
160
|
return valueDelta > 0 ? 'increment' : 'decrement';
|
|
89
161
|
}
|
|
90
|
-
return 'increment';
|
|
162
|
+
return 'increment'; /* Default to increment if delta is unknown */
|
|
91
163
|
}
|
|
92
|
-
|
|
164
|
+
/* Reorder - only when 'order' is the sole changed field */
|
|
93
165
|
if (fields.includes('order') && fields.length === 1) {
|
|
94
166
|
return 'reorder';
|
|
95
167
|
}
|
|
96
|
-
|
|
168
|
+
/* Rename or visual property change (name, color) with minimal other changes */
|
|
97
169
|
if ((fields.includes('name') || fields.includes('color')) && fields.length <= 2) {
|
|
98
170
|
return 'rename';
|
|
99
171
|
}
|
|
100
|
-
|
|
172
|
+
/* Generic update for any other combination of changed fields */
|
|
101
173
|
return 'update';
|
|
102
174
|
},
|
|
103
175
|
/**
|
|
104
|
-
* Record a remote change that just arrived.
|
|
105
|
-
*
|
|
106
|
-
*
|
|
176
|
+
* Record a remote change that just arrived via Supabase Realtime.
|
|
177
|
+
*
|
|
178
|
+
* Routing logic:
|
|
179
|
+
* - If the entity is being edited in a **manual-save** form, the change is
|
|
180
|
+
* deferred (queued) and will be returned when `stopEditing()` is called.
|
|
181
|
+
* - Otherwise, the change is stored in `recentChanges` for animation.
|
|
182
|
+
*
|
|
183
|
+
* @param entityId - Unique identifier of the changed entity
|
|
184
|
+
* @param entityType - Database table name
|
|
185
|
+
* @param fields - Array of field names that changed
|
|
186
|
+
* @param applied - Whether the change was already written to the local DB
|
|
187
|
+
* @param eventType - Supabase realtime event type (defaults to 'UPDATE')
|
|
188
|
+
* @param valueDelta - Signed delta for numeric changes (for animation direction)
|
|
189
|
+
* @returns Object indicating whether the change was deferred and the detected action type
|
|
107
190
|
*
|
|
108
|
-
* @
|
|
109
|
-
* @
|
|
191
|
+
* @see detectActionType for how the action type is inferred
|
|
192
|
+
* @see stopEditing for retrieving deferred changes
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* ```ts
|
|
196
|
+
* const result = remoteChangesStore.recordRemoteChange(
|
|
197
|
+
* 'abc-123', 'todos', ['completed'], true, 'UPDATE'
|
|
198
|
+
* );
|
|
199
|
+
* if (result.deferred) {
|
|
200
|
+
* console.log('Change queued - entity is being edited');
|
|
201
|
+
* }
|
|
202
|
+
* ```
|
|
110
203
|
*/
|
|
111
204
|
recordRemoteChange(entityId, entityType, fields, applied, eventType = 'UPDATE', valueDelta) {
|
|
112
205
|
startCleanup();
|
|
@@ -125,7 +218,8 @@ function createRemoteChangesStore() {
|
|
|
125
218
|
const key = `${entityType}:${entityId}`;
|
|
126
219
|
const activeEdit = state.activeEdits.get(key);
|
|
127
220
|
if (activeEdit && activeEdit.formType === 'manual-save') {
|
|
128
|
-
|
|
221
|
+
/* Entity is being edited in a form with a Save button - defer the change
|
|
222
|
+
* to prevent overwriting the user's in-progress edits */
|
|
129
223
|
const newDeferredChanges = new Map(state.deferredChanges);
|
|
130
224
|
const existing = [...(newDeferredChanges.get(key) || [])];
|
|
131
225
|
existing.push(change);
|
|
@@ -134,7 +228,7 @@ function createRemoteChangesStore() {
|
|
|
134
228
|
return { ...state, deferredChanges: newDeferredChanges };
|
|
135
229
|
}
|
|
136
230
|
else {
|
|
137
|
-
|
|
231
|
+
/* No conflicting edit in progress - record for immediate animation */
|
|
138
232
|
const newRecentChanges = new Map(state.recentChanges);
|
|
139
233
|
newRecentChanges.set(key, change);
|
|
140
234
|
return { ...state, recentChanges: newRecentChanges };
|
|
@@ -144,10 +238,26 @@ function createRemoteChangesStore() {
|
|
|
144
238
|
},
|
|
145
239
|
/**
|
|
146
240
|
* Record a local change for animation purposes.
|
|
147
|
-
* Call this BEFORE the component mounts (e.g., right before adding to database)
|
|
148
|
-
* so that when the component mounts with remoteChangeAnimation, the create animation triggers.
|
|
149
241
|
*
|
|
150
|
-
*
|
|
242
|
+
* Call this **before** the component mounts (e.g., right before inserting
|
|
243
|
+
* into the database) so that when the component renders with the
|
|
244
|
+
* `remoteChangeAnimation` directive, the create/update animation triggers
|
|
245
|
+
* on the initial mount.
|
|
246
|
+
*
|
|
247
|
+
* This ensures local creates animate identically to remote creates,
|
|
248
|
+
* providing a consistent visual experience.
|
|
249
|
+
*
|
|
250
|
+
* @param entityId - Unique identifier of the changed entity
|
|
251
|
+
* @param entityType - Database table name
|
|
252
|
+
* @param actionType - The semantic action type to animate
|
|
253
|
+
* @param fields - Array of changed field names (defaults to `['*']` for all)
|
|
254
|
+
*
|
|
255
|
+
* @example
|
|
256
|
+
* ```ts
|
|
257
|
+
* // Before inserting a new todo:
|
|
258
|
+
* remoteChangesStore.recordLocalChange(newId, 'todos', 'create');
|
|
259
|
+
* await db.todos.insert({ id: newId, name: 'New Todo' });
|
|
260
|
+
* ```
|
|
151
261
|
*/
|
|
152
262
|
recordLocalChange(entityId, entityType, actionType, fields = ['*']) {
|
|
153
263
|
startCleanup();
|
|
@@ -167,8 +277,24 @@ function createRemoteChangesStore() {
|
|
|
167
277
|
});
|
|
168
278
|
},
|
|
169
279
|
/**
|
|
170
|
-
* Mark an entity as being actively edited.
|
|
171
|
-
*
|
|
280
|
+
* Mark an entity as being actively edited by the local user.
|
|
281
|
+
*
|
|
282
|
+
* While an entity is marked as editing:
|
|
283
|
+
* - **auto-save**: Remote changes still apply immediately (no conflict risk)
|
|
284
|
+
* - **manual-save**: Remote changes are deferred until `stopEditing()` is called
|
|
285
|
+
*
|
|
286
|
+
* @param entityId - Unique identifier of the entity being edited
|
|
287
|
+
* @param entityType - Database table name
|
|
288
|
+
* @param formType - 'auto-save' for inline edits, 'manual-save' for modal/form edits
|
|
289
|
+
* @param fields - Optional list of specific fields being edited (for field-level tracking)
|
|
290
|
+
*
|
|
291
|
+
* @see stopEditing for completing the edit session and retrieving deferred changes
|
|
292
|
+
*
|
|
293
|
+
* @example
|
|
294
|
+
* ```ts
|
|
295
|
+
* // When opening a todo edit modal:
|
|
296
|
+
* remoteChangesStore.startEditing(todoId, 'todos', 'manual-save', ['name', 'description']);
|
|
297
|
+
* ```
|
|
172
298
|
*/
|
|
173
299
|
startEditing(entityId, entityType, formType, fields) {
|
|
174
300
|
update((state) => {
|
|
@@ -185,7 +311,26 @@ function createRemoteChangesStore() {
|
|
|
185
311
|
});
|
|
186
312
|
},
|
|
187
313
|
/**
|
|
188
|
-
* Mark editing as complete
|
|
314
|
+
* Mark editing as complete and return any deferred changes.
|
|
315
|
+
*
|
|
316
|
+
* The caller is responsible for processing the returned deferred changes
|
|
317
|
+
* (typically by refreshing the entity from the database or replaying
|
|
318
|
+
* the changes).
|
|
319
|
+
*
|
|
320
|
+
* @param entityId - Unique identifier of the entity
|
|
321
|
+
* @param entityType - Database table name
|
|
322
|
+
* @returns Array of deferred remote changes that arrived during the edit session
|
|
323
|
+
*
|
|
324
|
+
* @see startEditing for beginning an edit session
|
|
325
|
+
*
|
|
326
|
+
* @example
|
|
327
|
+
* ```ts
|
|
328
|
+
* // When closing a todo edit modal:
|
|
329
|
+
* const deferred = remoteChangesStore.stopEditing(todoId, 'todos');
|
|
330
|
+
* if (deferred.length > 0) {
|
|
331
|
+
* await refreshTodoFromServer(todoId);
|
|
332
|
+
* }
|
|
333
|
+
* ```
|
|
189
334
|
*/
|
|
190
335
|
stopEditing(entityId, entityType) {
|
|
191
336
|
let deferredChanges = [];
|
|
@@ -194,7 +339,7 @@ function createRemoteChangesStore() {
|
|
|
194
339
|
const newActiveEdits = new Map(state.activeEdits);
|
|
195
340
|
newActiveEdits.delete(key);
|
|
196
341
|
const newDeferredChanges = new Map(state.deferredChanges);
|
|
197
|
-
|
|
342
|
+
/* Extract deferred changes for the caller to process */
|
|
198
343
|
if (newDeferredChanges.has(key)) {
|
|
199
344
|
deferredChanges = newDeferredChanges.get(key) || [];
|
|
200
345
|
newDeferredChanges.delete(key);
|
|
@@ -204,7 +349,14 @@ function createRemoteChangesStore() {
|
|
|
204
349
|
return deferredChanges;
|
|
205
350
|
},
|
|
206
351
|
/**
|
|
207
|
-
*
|
|
352
|
+
* Synchronously check if an entity is currently being edited.
|
|
353
|
+
*
|
|
354
|
+
* Uses the subscribe-and-immediately-unsubscribe pattern to read the
|
|
355
|
+
* current store value imperatively (outside of a reactive context).
|
|
356
|
+
*
|
|
357
|
+
* @param entityId - Unique identifier of the entity
|
|
358
|
+
* @param entityType - Database table name
|
|
359
|
+
* @returns `true` if the entity has an active edit session
|
|
208
360
|
*/
|
|
209
361
|
isEditing(entityId, entityType) {
|
|
210
362
|
let editing = false;
|
|
@@ -215,8 +367,14 @@ function createRemoteChangesStore() {
|
|
|
215
367
|
return editing;
|
|
216
368
|
},
|
|
217
369
|
/**
|
|
218
|
-
* Clear deferred changes for an entity without
|
|
219
|
-
*
|
|
370
|
+
* Clear deferred changes for an entity without ending the edit session.
|
|
371
|
+
*
|
|
372
|
+
* Used when the user explicitly dismisses a "remote changes available"
|
|
373
|
+
* banner or loads the remote version, acknowledging the deferred changes
|
|
374
|
+
* without closing the form.
|
|
375
|
+
*
|
|
376
|
+
* @param entityId - Unique identifier of the entity
|
|
377
|
+
* @param entityType - Database table name
|
|
220
378
|
*/
|
|
221
379
|
clearDeferredChanges(entityId, entityType) {
|
|
222
380
|
update((state) => {
|
|
@@ -227,7 +385,14 @@ function createRemoteChangesStore() {
|
|
|
227
385
|
});
|
|
228
386
|
},
|
|
229
387
|
/**
|
|
230
|
-
*
|
|
388
|
+
* Synchronously check if an entity has deferred changes waiting.
|
|
389
|
+
*
|
|
390
|
+
* Typically used by edit forms to display a "remote changes available"
|
|
391
|
+
* indicator or banner.
|
|
392
|
+
*
|
|
393
|
+
* @param entityId - Unique identifier of the entity
|
|
394
|
+
* @param entityType - Database table name
|
|
395
|
+
* @returns `true` if one or more deferred changes exist for this entity
|
|
231
396
|
*/
|
|
232
397
|
hasDeferredChanges(entityId, entityType) {
|
|
233
398
|
let hasChanges = false;
|
|
@@ -240,7 +405,14 @@ function createRemoteChangesStore() {
|
|
|
240
405
|
return hasChanges;
|
|
241
406
|
},
|
|
242
407
|
/**
|
|
243
|
-
*
|
|
408
|
+
* Synchronously check if an entity was recently changed (within `ANIMATION_DURATION`).
|
|
409
|
+
*
|
|
410
|
+
* Used by components to determine whether to apply an animation CSS class
|
|
411
|
+
* on mount or re-render.
|
|
412
|
+
*
|
|
413
|
+
* @param entityId - Unique identifier of the entity
|
|
414
|
+
* @param entityType - Database table name
|
|
415
|
+
* @returns `true` if the entity has a recent change within the animation window
|
|
244
416
|
*/
|
|
245
417
|
wasRecentlyChanged(entityId, entityType) {
|
|
246
418
|
let recent = false;
|
|
@@ -255,7 +427,16 @@ function createRemoteChangesStore() {
|
|
|
255
427
|
return recent;
|
|
256
428
|
},
|
|
257
429
|
/**
|
|
258
|
-
*
|
|
430
|
+
* Synchronously retrieve the full `RemoteChange` details for a recently
|
|
431
|
+
* changed entity. Returns `null` if no recent change exists or the
|
|
432
|
+
* animation window has expired.
|
|
433
|
+
*
|
|
434
|
+
* Used for field-level animation where the component needs to know
|
|
435
|
+
* which specific fields changed and the action type.
|
|
436
|
+
*
|
|
437
|
+
* @param entityId - Unique identifier of the entity
|
|
438
|
+
* @param entityType - Database table name
|
|
439
|
+
* @returns The `RemoteChange` object if within the animation window, otherwise `null`
|
|
259
440
|
*/
|
|
260
441
|
getRecentChange(entityId, entityType) {
|
|
261
442
|
let change = null;
|
|
@@ -270,11 +451,28 @@ function createRemoteChangesStore() {
|
|
|
270
451
|
return change;
|
|
271
452
|
},
|
|
272
453
|
/**
|
|
273
|
-
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
*
|
|
454
|
+
* Initiate a delete animation for an entity.
|
|
455
|
+
*
|
|
456
|
+
* Returns a promise that resolves after `DELETE_ANIMATION_DURATION` ms,
|
|
457
|
+
* giving the UI time to play an exit animation. The caller should perform
|
|
458
|
+
* the actual database deletion **after** the promise resolves.
|
|
459
|
+
*
|
|
460
|
+
* The pending delete entry is cleaned up ~100ms after resolve, which is
|
|
461
|
+
* just housekeeping since the DB deletion (triggered on resolve) will
|
|
462
|
+
* cause the reactive DOM removal.
|
|
463
|
+
*
|
|
464
|
+
* @param entityId - Unique identifier of the entity to delete
|
|
465
|
+
* @param entityType - Database table name
|
|
466
|
+
* @returns A promise that resolves after the animation duration
|
|
467
|
+
*
|
|
468
|
+
* @see createPendingDeleteIndicator for the reactive per-entity derived store
|
|
469
|
+
*
|
|
470
|
+
* @example
|
|
471
|
+
* ```ts
|
|
472
|
+
* // Animate, then delete:
|
|
473
|
+
* await remoteChangesStore.markPendingDelete(todoId, 'todos');
|
|
474
|
+
* await db.todos.delete(todoId);
|
|
475
|
+
* ```
|
|
278
476
|
*/
|
|
279
477
|
markPendingDelete(entityId, entityType) {
|
|
280
478
|
update((state) => {
|
|
@@ -283,12 +481,13 @@ function createRemoteChangesStore() {
|
|
|
283
481
|
newPendingDeletes.set(key, Date.now());
|
|
284
482
|
return { ...state, pendingDeletes: newPendingDeletes };
|
|
285
483
|
});
|
|
286
|
-
|
|
484
|
+
/* Return a promise that resolves after the animation completes */
|
|
287
485
|
return new Promise((resolve) => {
|
|
288
486
|
setTimeout(() => {
|
|
289
487
|
resolve();
|
|
290
|
-
|
|
291
|
-
|
|
488
|
+
/* Clean up the pending delete entry after a short delay.
|
|
489
|
+
* The caller deletes from DB on resolve which triggers DOM removal,
|
|
490
|
+
* so this is just housekeeping to avoid stale map entries. */
|
|
292
491
|
setTimeout(() => {
|
|
293
492
|
update((state) => {
|
|
294
493
|
const key = `${entityType}:${entityId}`;
|
|
@@ -301,7 +500,12 @@ function createRemoteChangesStore() {
|
|
|
301
500
|
});
|
|
302
501
|
},
|
|
303
502
|
/**
|
|
304
|
-
*
|
|
503
|
+
* Synchronously check if an entity is currently pending deletion
|
|
504
|
+
* (i.e., its exit animation is in progress).
|
|
505
|
+
*
|
|
506
|
+
* @param entityId - Unique identifier of the entity
|
|
507
|
+
* @param entityType - Database table name
|
|
508
|
+
* @returns `true` if the entity is in the pending delete state
|
|
305
509
|
*/
|
|
306
510
|
isPendingDelete(entityId, entityType) {
|
|
307
511
|
let pending = false;
|
|
@@ -313,7 +517,12 @@ function createRemoteChangesStore() {
|
|
|
313
517
|
return pending;
|
|
314
518
|
},
|
|
315
519
|
/**
|
|
316
|
-
* Clear all tracking (
|
|
520
|
+
* Clear all tracking state (recent changes, active edits, deferred changes,
|
|
521
|
+
* pending deletes) and stop the cleanup timer.
|
|
522
|
+
*
|
|
523
|
+
* Called during logout to ensure no stale state carries over to the next session.
|
|
524
|
+
*
|
|
525
|
+
* @see destroy for cleanup without state reset (e.g., component unmount)
|
|
317
526
|
*/
|
|
318
527
|
clear() {
|
|
319
528
|
stopCleanup();
|
|
@@ -325,20 +534,53 @@ function createRemoteChangesStore() {
|
|
|
325
534
|
}));
|
|
326
535
|
},
|
|
327
536
|
/**
|
|
328
|
-
* Stop the cleanup interval
|
|
537
|
+
* Stop the periodic cleanup interval without resetting state.
|
|
538
|
+
*
|
|
539
|
+
* Called during component unmount or app teardown to prevent memory leaks
|
|
540
|
+
* from orphaned intervals.
|
|
541
|
+
*
|
|
542
|
+
* @see clear for full state reset including cleanup stop
|
|
329
543
|
*/
|
|
330
544
|
destroy() {
|
|
331
545
|
stopCleanup();
|
|
332
546
|
}
|
|
333
547
|
};
|
|
334
548
|
}
|
|
549
|
+
// =============================================================================
|
|
550
|
+
// Singleton Store Instance
|
|
551
|
+
// =============================================================================
|
|
552
|
+
/**
|
|
553
|
+
* Singleton remote changes store used throughout the application.
|
|
554
|
+
*
|
|
555
|
+
* @see {@link createRemoteChangesStore} for implementation details
|
|
556
|
+
*/
|
|
335
557
|
export const remoteChangesStore = createRemoteChangesStore();
|
|
336
|
-
//
|
|
337
|
-
//
|
|
338
|
-
//
|
|
558
|
+
// =============================================================================
|
|
559
|
+
// Derived Store Factories
|
|
560
|
+
// =============================================================================
|
|
339
561
|
/**
|
|
340
|
-
*
|
|
341
|
-
*
|
|
562
|
+
* Creates a derived store that reactively tracks whether a specific entity
|
|
563
|
+
* was recently changed remotely.
|
|
564
|
+
*
|
|
565
|
+
* The derived store emits the full `RemoteChange` object while the change
|
|
566
|
+
* is within the animation window, or `null` otherwise. Components use this
|
|
567
|
+
* to apply and remove animation CSS classes.
|
|
568
|
+
*
|
|
569
|
+
* @param entityId - Unique identifier of the entity to watch
|
|
570
|
+
* @param entityType - Database table name
|
|
571
|
+
* @returns A Svelte readable store that emits `RemoteChange | null`
|
|
572
|
+
*
|
|
573
|
+
* @see remoteChangesStore.recordRemoteChange for how changes enter the recent map
|
|
574
|
+
*
|
|
575
|
+
* @example
|
|
576
|
+
* ```svelte
|
|
577
|
+
* <script>
|
|
578
|
+
* const recentChange = createRecentChangeIndicator(todo.id, 'todos');
|
|
579
|
+
* </script>
|
|
580
|
+
* <div class:animate-pulse={$recentChange?.actionType === 'toggle'}>
|
|
581
|
+
* {todo.name}
|
|
582
|
+
* </div>
|
|
583
|
+
* ```
|
|
342
584
|
*/
|
|
343
585
|
export function createRecentChangeIndicator(entityId, entityType) {
|
|
344
586
|
return derived(remoteChangesStore, ($state) => {
|
|
@@ -352,8 +594,28 @@ export function createRecentChangeIndicator(entityId, entityType) {
|
|
|
352
594
|
});
|
|
353
595
|
}
|
|
354
596
|
/**
|
|
355
|
-
*
|
|
356
|
-
*
|
|
597
|
+
* Creates a derived store that reactively tracks whether a specific entity
|
|
598
|
+
* is pending deletion (i.e., its exit animation is in progress).
|
|
599
|
+
*
|
|
600
|
+
* The derived store emits `true` while the entity is in the pending delete
|
|
601
|
+
* state, and `false` otherwise. Components use this to apply exit animation
|
|
602
|
+
* CSS classes before the entity is removed from the DOM.
|
|
603
|
+
*
|
|
604
|
+
* @param entityId - Unique identifier of the entity to watch
|
|
605
|
+
* @param entityType - Database table name
|
|
606
|
+
* @returns A Svelte readable store that emits a boolean
|
|
607
|
+
*
|
|
608
|
+
* @see remoteChangesStore.markPendingDelete for how entities enter the pending state
|
|
609
|
+
*
|
|
610
|
+
* @example
|
|
611
|
+
* ```svelte
|
|
612
|
+
* <script>
|
|
613
|
+
* const isPending = createPendingDeleteIndicator(todo.id, 'todos');
|
|
614
|
+
* </script>
|
|
615
|
+
* <div class:opacity-0={$isPending} class:transition-opacity={$isPending}>
|
|
616
|
+
* {todo.name}
|
|
617
|
+
* </div>
|
|
618
|
+
* ```
|
|
357
619
|
*/
|
|
358
620
|
export function createPendingDeleteIndicator(entityId, entityType) {
|
|
359
621
|
return derived(remoteChangesStore, ($state) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remoteChanges.js","sourceRoot":"","sources":["../../src/stores/remoteChanges.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"remoteChanges.js","sourceRoot":"","sources":["../../src/stores/remoteChanges.ts"],"names":[],"mappings":"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"}
|