@prabhask5/stellar-engine 1.1.8 → 1.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +19 -26
  2. package/dist/auth/crypto.d.ts +0 -23
  3. package/dist/auth/crypto.d.ts.map +1 -1
  4. package/dist/auth/crypto.js +0 -25
  5. package/dist/auth/crypto.js.map +1 -1
  6. package/dist/auth/deviceVerification.d.ts +2 -2
  7. package/dist/auth/deviceVerification.js +2 -2
  8. package/dist/auth/loginGuard.d.ts +7 -14
  9. package/dist/auth/loginGuard.d.ts.map +1 -1
  10. package/dist/auth/loginGuard.js +27 -62
  11. package/dist/auth/loginGuard.js.map +1 -1
  12. package/dist/auth/offlineCredentials.d.ts +6 -59
  13. package/dist/auth/offlineCredentials.d.ts.map +1 -1
  14. package/dist/auth/offlineCredentials.js +8 -111
  15. package/dist/auth/offlineCredentials.js.map +1 -1
  16. package/dist/auth/resolveAuthState.d.ts +14 -18
  17. package/dist/auth/resolveAuthState.d.ts.map +1 -1
  18. package/dist/auth/resolveAuthState.js +16 -58
  19. package/dist/auth/resolveAuthState.js.map +1 -1
  20. package/dist/auth/singleUser.js +4 -4
  21. package/dist/auth/singleUser.js.map +1 -1
  22. package/dist/bin/install-pwa.d.ts +4 -2
  23. package/dist/bin/install-pwa.d.ts.map +1 -1
  24. package/dist/bin/install-pwa.js +2289 -249
  25. package/dist/bin/install-pwa.js.map +1 -1
  26. package/dist/config.d.ts +3 -7
  27. package/dist/config.d.ts.map +1 -1
  28. package/dist/config.js +1 -1
  29. package/dist/config.js.map +1 -1
  30. package/dist/data.d.ts +105 -0
  31. package/dist/data.d.ts.map +1 -1
  32. package/dist/data.js +126 -0
  33. package/dist/data.js.map +1 -1
  34. package/dist/entries/auth.d.ts +8 -13
  35. package/dist/entries/auth.d.ts.map +1 -1
  36. package/dist/entries/auth.js +11 -40
  37. package/dist/entries/auth.js.map +1 -1
  38. package/dist/entries/stores.d.ts +2 -0
  39. package/dist/entries/stores.d.ts.map +1 -1
  40. package/dist/entries/stores.js +7 -0
  41. package/dist/entries/stores.js.map +1 -1
  42. package/dist/entries/types.d.ts +0 -1
  43. package/dist/entries/types.d.ts.map +1 -1
  44. package/dist/index.d.ts +6 -6
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +21 -18
  47. package/dist/index.js.map +1 -1
  48. package/dist/kit/loads.d.ts +3 -5
  49. package/dist/kit/loads.d.ts.map +1 -1
  50. package/dist/kit/loads.js +2 -10
  51. package/dist/kit/loads.js.map +1 -1
  52. package/dist/stores/authState.d.ts +2 -2
  53. package/dist/stores/authState.js +1 -1
  54. package/dist/stores/factories.d.ts +138 -0
  55. package/dist/stores/factories.d.ts.map +1 -0
  56. package/dist/stores/factories.js +154 -0
  57. package/dist/stores/factories.js.map +1 -0
  58. package/dist/supabase/auth.d.ts +14 -181
  59. package/dist/supabase/auth.d.ts.map +1 -1
  60. package/dist/supabase/auth.js +17 -317
  61. package/dist/supabase/auth.js.map +1 -1
  62. package/package.json +1 -1
  63. package/dist/auth/admin.d.ts +0 -49
  64. package/dist/auth/admin.d.ts.map +0 -1
  65. package/dist/auth/admin.js +0 -66
  66. package/dist/auth/admin.js.map +0 -1
  67. package/dist/auth/offlineLogin.d.ts +0 -120
  68. package/dist/auth/offlineLogin.d.ts.map +0 -1
  69. package/dist/auth/offlineLogin.js +0 -142
  70. package/dist/auth/offlineLogin.js.map +0 -1
package/README.md CHANGED
@@ -81,7 +81,6 @@ initEngine({
81
81
  tables: [/* ... */],
82
82
  database: {/* ... */},
83
83
  auth: {
84
- mode: 'single-user',
85
84
  singleUser: { gateType: 'code', codeLength: 4 },
86
85
  enableOfflineAuth: true,
87
86
  // emailConfirmation: { enabled: true }, // require email confirmation on setup
@@ -107,12 +106,14 @@ if (!auth.singleUserSetUp) {
107
106
 
108
107
  ## Install PWA Command
109
108
 
110
- Scaffold a complete offline-first PWA project:
109
+ Scaffold a complete offline-first PWA project with an interactive walkthrough:
111
110
 
112
111
  ```bash
113
- npx @prabhask5/stellar-engine install pwa --name "My App" --short_name "App" --prefix "myapp" [--description "..."]
112
+ npx @prabhask5/stellar-engine install pwa
114
113
  ```
115
114
 
115
+ The wizard guides you through each option (app name, short name, prefix, description), validates input inline, shows a confirmation summary, then scaffolds with animated progress.
116
+
116
117
  ### What it generates
117
118
 
118
119
  The command creates a full SvelteKit 2 + Svelte 5 project with:
@@ -134,7 +135,7 @@ The command creates a full SvelteKit 2 + Svelte 5 project with:
134
135
  | `src/routes/+layout.svelte` | Auth state hydration via `hydrateAuthState()` | App shell (navbar, tab bar, overlays) |
135
136
  | `src/routes/+page.svelte` | Imports `resolveFirstName`, `onSyncComplete`, `authState`; derives `firstName` reactively | Home page UI |
136
137
  | `src/routes/+error.svelte` | — | Error page UI |
137
- | `src/routes/setup/+page.ts` | Config check, session validation, admin check via `getConfig()`, `getValidSession()`, `isAdmin()` | — (fully managed) |
138
+ | `src/routes/setup/+page.ts` | Config check, session validation via `getConfig()`, `getValidSession()` | — (fully managed) |
138
139
  | `src/routes/setup/+page.svelte` | Imports `setConfig`, `isOnline`, `pollForNewServiceWorker` | Setup wizard UI |
139
140
  | `src/routes/policy/+page.svelte` | — | Privacy policy content |
140
141
  | `src/routes/login/+page.svelte` | All auth functions: `setupSingleUser`, `unlockSingleUser`, `getSingleUserInfo`, `completeSingleUserSetup`, `completeDeviceVerification`, `pollDeviceVerification`, `fetchRemoteGateConfig`, `linkSingleUserDevice`, `sendDeviceVerification` | Login page UI |
@@ -151,14 +152,14 @@ The command creates a full SvelteKit 2 + Svelte 5 project with:
151
152
 
152
153
  **Git hooks (1):** `.husky/pre-commit` with lint + format + validate
153
154
 
154
- ### Parameters
155
+ ### Interactive Prompts
155
156
 
156
- | Flag | Required | Description |
157
- |------|----------|-------------|
158
- | `--name` | Yes | Full app name (e.g., "My Stellar App") |
159
- | `--short_name` | Yes | Short name for PWA home screen |
160
- | `--prefix` | Yes | App prefix for localStorage keys, SW, debug utils |
161
- | `--description` | No | App description (default: "A self-hosted offline-first PWA") |
157
+ | Prompt | Required | Description |
158
+ |--------|----------|-------------|
159
+ | App Name | Yes | Full app name (e.g., "Stellar Planner") |
160
+ | Short Name | Yes | Short name for PWA home screen (under 12 chars) |
161
+ | Prefix | Yes | Lowercase key for localStorage, caches, SW (auto-suggested from name) |
162
+ | Description | No | App description (default: "A self-hosted offline-first PWA") |
162
163
 
163
164
  ## Subpath exports
164
165
 
@@ -168,7 +169,7 @@ Import only what you need via subpath exports:
168
169
  |---|---|
169
170
  | `@prabhask5/stellar-engine` | `initEngine`, `startSyncEngine`, `runFullSync`, `supabase`, `getDb`, `validateSupabaseCredentials`, `validateSchema` |
170
171
  | `@prabhask5/stellar-engine/data` | All engine CRUD + query operations (`engineCreate`, `engineUpdate`, etc.) |
171
- | `@prabhask5/stellar-engine/auth` | All auth functions (`signIn`, `signUp`, `resolveAuthState`, `isAdmin`, `changeEmail`, `completeEmailChange`, single-user: `setupSingleUser`, `unlockSingleUser`, `lockSingleUser`, `completeSingleUserSetup`, `completeDeviceVerification`, `changeSingleUserEmail`, `completeSingleUserEmailChange`, `padPin`, etc.) |
172
+ | `@prabhask5/stellar-engine/auth` | All auth functions (`resolveAuthState`, `signOut`, `setupSingleUser`, `unlockSingleUser`, `lockSingleUser`, `completeSingleUserSetup`, `completeDeviceVerification`, `changeSingleUserEmail`, `completeSingleUserEmailChange`, `padPin`, etc.) |
172
173
  | `@prabhask5/stellar-engine/stores` | Reactive stores + event subscriptions (`syncStatusStore`, `authState`, `onSyncComplete`, etc.) |
173
174
  | `@prabhask5/stellar-engine/types` | All type exports (`Session`, `SyncEngineConfig`, `BatchOperation`, `SingleUserConfig`, etc.) |
174
175
  | `@prabhask5/stellar-engine/utils` | Utility functions (`generateId`, `now`, `calculateNewOrder`, `snakeToCamel`, `debug`, etc.) |
@@ -300,30 +301,22 @@ Alternatively, you can provide a pre-created Dexie instance via the `db` config
300
301
  | `markEntityModified(table, id)` | Record that an entity was recently modified locally (prevents incoming realtime from overwriting). |
301
302
  | `onSyncComplete(callback)` | Register a callback invoked after each successful sync cycle. |
302
303
 
303
- ### Auth
304
+ ### Auth Utilities
304
305
 
305
306
  | Export | Description |
306
307
  |---|---|
307
- | `signIn` / `signUp` / `signOut` | Supabase auth wrappers that also manage offline credential caching. |
308
- | `getSession` / `isSessionExpired` | Session inspection helpers. |
309
- | `changePassword` / `resendConfirmationEmail` | Account management. |
310
- | `changeEmail(newEmail)` | Request email change (sends confirmation to new address). Returns `{ error, confirmationRequired }`. |
311
- | `completeEmailChange()` | Finalize email change after confirmation. Refreshes session and updates cached credentials. |
308
+ | `signOut` | Full teardown: stops sync, clears caches, signs out of Supabase. |
309
+ | `resendConfirmationEmail` | Resend signup confirmation email. |
312
310
  | `getUserProfile` / `updateProfile` | Profile read/write via Supabase user metadata. |
311
+ | `verifyOtp` | Verify OTP token hash from confirmation email links. |
312
+ | `getValidSession` | Get a non-expired Supabase session, or `null`. |
313
313
  | `resolveFirstName(session, offline, fallback?)` | Resolve display name from session or offline profile with configurable fallback. |
314
314
  | `resolveUserId(session, offline)` | Extract user UUID from session or offline credentials. |
315
315
  | `resolveAvatarInitial(session, offline, fallback?)` | Single uppercase initial for avatar display. |
316
316
 
317
- ### Offline auth
318
-
319
- | Export | Description |
320
- |---|---|
321
- | `cacheOfflineCredentials` / `getOfflineCredentials` / `verifyOfflineCredentials` / `clearOfflineCredentials` | Store and verify credentials locally for offline sign-in. |
322
- | `createOfflineSession` / `getValidOfflineSession` / `clearOfflineSession` | Manage offline session tokens in IndexedDB. |
323
-
324
317
  ### Single-user auth
325
318
 
326
- For personal apps that use a simplified PIN or password gate. Uses real Supabase email/password auth where the PIN is padded to meet minimum password length. Enable by setting `auth.mode: 'single-user'` in the engine config.
319
+ For personal apps that use a simplified PIN or password gate. Uses real Supabase email/password auth where the PIN is padded to meet minimum password length. Enable by setting `auth.singleUser` in the engine config.
327
320
 
328
321
  | Export | Description |
329
322
  |---|---|
@@ -17,10 +17,6 @@
17
17
  * password storage on its own. It is acceptable here because the hashed values
18
18
  * are only stored in the client-side IndexedDB for offline pre-checking and
19
19
  * are never transmitted to a server.
20
- * - The `isAlreadyHashed` helper uses a regex heuristic (64-char hex). If a
21
- * user's actual password happens to be a 64-char hex string, it will be
22
- * misidentified as already hashed. This is an acceptable edge case given the
23
- * vanishingly low probability and the local-only usage context.
24
20
  *
25
21
  * @module auth/crypto
26
22
  */
@@ -40,25 +36,6 @@
40
36
  * // hashed === 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' (example)
41
37
  * ```
42
38
  *
43
- * @see {@link isAlreadyHashed} to check whether a string is already a hex digest.
44
39
  */
45
40
  export declare function hashValue(value: string): Promise<string>;
46
- /**
47
- * Check if a stored value is already hashed (64-character hex string).
48
- *
49
- * Used to distinguish between legacy plaintext credentials and modern
50
- * SHA-256-hashed credentials in IndexedDB, enabling backward-compatible
51
- * verification without a migration step.
52
- *
53
- * @param value - The string to test.
54
- * @returns `true` if the value matches the pattern of a SHA-256 hex digest
55
- * (exactly 64 lowercase hexadecimal characters), `false` otherwise.
56
- *
57
- * @example
58
- * ```ts
59
- * isAlreadyHashed('abc123'); // false
60
- * isAlreadyHashed('e3b0c442...b855'); // true (64-char hex)
61
- * ```
62
- */
63
- export declare function isAlreadyHashed(value: string): boolean;
64
41
  //# sourceMappingURL=crypto.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/auth/crypto.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAMH;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAM9D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEtD"}
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/auth/crypto.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAMH;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAM9D"}
@@ -17,10 +17,6 @@
17
17
  * password storage on its own. It is acceptable here because the hashed values
18
18
  * are only stored in the client-side IndexedDB for offline pre-checking and
19
19
  * are never transmitted to a server.
20
- * - The `isAlreadyHashed` helper uses a regex heuristic (64-char hex). If a
21
- * user's actual password happens to be a 64-char hex string, it will be
22
- * misidentified as already hashed. This is an acceptable edge case given the
23
- * vanishingly low probability and the local-only usage context.
24
20
  *
25
21
  * @module auth/crypto
26
22
  */
@@ -43,7 +39,6 @@
43
39
  * // hashed === 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' (example)
44
40
  * ```
45
41
  *
46
- * @see {@link isAlreadyHashed} to check whether a string is already a hex digest.
47
42
  */
48
43
  export async function hashValue(value) {
49
44
  const encoder = new TextEncoder();
@@ -52,24 +47,4 @@ export async function hashValue(value) {
52
47
  const hashArray = Array.from(new Uint8Array(hashBuffer));
53
48
  return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
54
49
  }
55
- /**
56
- * Check if a stored value is already hashed (64-character hex string).
57
- *
58
- * Used to distinguish between legacy plaintext credentials and modern
59
- * SHA-256-hashed credentials in IndexedDB, enabling backward-compatible
60
- * verification without a migration step.
61
- *
62
- * @param value - The string to test.
63
- * @returns `true` if the value matches the pattern of a SHA-256 hex digest
64
- * (exactly 64 lowercase hexadecimal characters), `false` otherwise.
65
- *
66
- * @example
67
- * ```ts
68
- * isAlreadyHashed('abc123'); // false
69
- * isAlreadyHashed('e3b0c442...b855'); // true (64-char hex)
70
- * ```
71
- */
72
- export function isAlreadyHashed(value) {
73
- return /^[0-9a-f]{64}$/.test(value);
74
- }
75
50
  //# sourceMappingURL=crypto.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/auth/crypto.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,gFAAgF;AAChF,aAAa;AACb,gFAAgF;AAEhF;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAa;IAC3C,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC/D,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;IACzD,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACxE,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,OAAO,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACtC,CAAC"}
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/auth/crypto.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,gFAAgF;AAChF,aAAa;AACb,gFAAgF;AAEhF;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAa;IAC3C,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC/D,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;IACzD,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACxE,CAAC"}
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * @fileoverview Device Verification Module
3
3
  *
4
- * Manages the trusted device registry and email-based OTP verification flow
5
- * for both single-user and multi-user modes. When device verification is
4
+ * Manages the trusted device registry and email-based OTP verification flow.
5
+ * When device verification is
6
6
  * enabled, only devices present in the Supabase `trusted_devices` table (with
7
7
  * a recent `last_used_at` timestamp) are allowed to proceed after
8
8
  * authentication. Untrusted devices must complete an email OTP challenge.
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * @fileoverview Device Verification Module
3
3
  *
4
- * Manages the trusted device registry and email-based OTP verification flow
5
- * for both single-user and multi-user modes. When device verification is
4
+ * Manages the trusted device registry and email-based OTP verification flow.
5
+ * When device verification is
6
6
  * enabled, only devices present in the Supabase `trusted_devices` table (with
7
7
  * a recent `last_used_at` timestamp) are allowed to proceed after
8
8
  * authentication. Untrusted devices must complete an email OTP challenge.
@@ -57,25 +57,20 @@ export type PreCheckResult = {
57
57
  /**
58
58
  * Pre-check login credentials locally before calling Supabase.
59
59
  *
60
- * For single-user mode: reads `singleUserConfig.gateHash`, hashes input, compares.
61
- * For multi-user mode: reads offline credentials, matches email + hashes password, compares.
60
+ * Reads `singleUserConfig.gateHash`, hashes input, and compares.
62
61
  *
63
62
  * Returns `{ proceed: true, strategy }` to allow Supabase call,
64
63
  * or `{ proceed: false, error, retryAfterMs? }` to reject locally.
65
64
  *
66
65
  * @param input - The plaintext password or gate code entered by the user.
67
- * @param mode - The auth mode (`'single-user'` or `'multi-user'`), which
68
- * determines which IndexedDB table holds the cached hash.
69
- * @param email - (Multi-user only) The email address to match against cached
70
- * credentials. Ignored in single-user mode.
71
66
  * @returns A promise resolving to a {@link PreCheckResult}.
72
67
  *
73
68
  * @example
74
69
  * ```ts
75
- * const result = await preCheckLogin(password, 'multi-user', email);
70
+ * const result = await preCheckLogin(password);
76
71
  * if (result.proceed) {
77
72
  * const { error } = await supabase.auth.signInWithPassword({ email, password });
78
- * if (error) await onLoginFailure(result.strategy, 'multi-user');
73
+ * if (error) await onLoginFailure(result.strategy);
79
74
  * else onLoginSuccess();
80
75
  * } else {
81
76
  * showError(result.error);
@@ -85,7 +80,7 @@ export type PreCheckResult = {
85
80
  * @see {@link onLoginSuccess} -- must be called after a successful Supabase login.
86
81
  * @see {@link onLoginFailure} -- must be called after a failed Supabase login.
87
82
  */
88
- export declare function preCheckLogin(input: string, mode: 'single-user' | 'multi-user', email?: string): Promise<PreCheckResult>;
83
+ export declare function preCheckLogin(input: string): Promise<PreCheckResult>;
89
84
  /**
90
85
  * Called after a successful Supabase login.
91
86
  *
@@ -112,19 +107,17 @@ export declare function onLoginSuccess(): void;
112
107
  *
113
108
  * @param strategy - The {@link PreCheckStrategy} that was returned by
114
109
  * {@link preCheckLogin} for this attempt.
115
- * @param mode - The auth mode, used to determine which IndexedDB table to
116
- * invalidate if the hash is stale. Defaults to `'multi-user'`.
117
110
  *
118
111
  * @example
119
112
  * ```ts
120
- * const result = await preCheckLogin(password, 'multi-user', email);
113
+ * const result = await preCheckLogin(password);
121
114
  * if (result.proceed) {
122
115
  * const { error } = await supabase.auth.signInWithPassword({ email, password });
123
- * if (error) await onLoginFailure(result.strategy, 'multi-user');
116
+ * if (error) await onLoginFailure(result.strategy);
124
117
  * }
125
118
  * ```
126
119
  */
127
- export declare function onLoginFailure(strategy: PreCheckStrategy, mode?: 'single-user' | 'multi-user'): Promise<void>;
120
+ export declare function onLoginFailure(strategy: PreCheckStrategy): Promise<void>;
128
121
  /**
129
122
  * Full reset of all login guard state.
130
123
  *
@@ -1 +1 @@
1
- {"version":3,"file":"loginGuard.d.ts","sourceRoot":"","sources":["../../src/auth/loginGuard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAoDH;;;;;;;GAOG;AACH,MAAM,MAAM,gBAAgB,GAAG,aAAa,GAAG,UAAU,CAAC;AAE1D;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,gBAAgB,CAAA;CAAE,GAC7C;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAsE7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,aAAa,GAAG,YAAY,EAClC,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,cAAc,CAAC,CA8EzB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAKrC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,gBAAgB,EAC1B,IAAI,GAAE,aAAa,GAAG,YAA2B,GAChD,OAAO,CAAC,IAAI,CAAC,CAiBf;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAKtC"}
1
+ {"version":3,"file":"loginGuard.d.ts","sourceRoot":"","sources":["../../src/auth/loginGuard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAmDH;;;;;;;GAOG;AACH,MAAM,MAAM,gBAAgB,GAAG,aAAa,GAAG,UAAU,CAAC;AAE1D;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,gBAAgB,CAAA;CAAE,GAC7C;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAoD7D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAuE1E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAKrC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiB9E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAKtC"}
@@ -30,7 +30,6 @@
30
30
  * @module auth/loginGuard
31
31
  */
32
32
  import { hashValue } from './crypto';
33
- import { getOfflineCredentials } from './offlineCredentials';
34
33
  import { getEngineConfig } from '../config';
35
34
  import { debugLog, debugWarn } from '../debug';
36
35
  // =============================================================================
@@ -82,45 +81,26 @@ function checkRateLimit() {
82
81
  return { allowed: true };
83
82
  }
84
83
  /**
85
- * Invalidate the locally cached password/gate hash in IndexedDB.
84
+ * Invalidate the locally cached gate hash in IndexedDB.
86
85
  *
87
86
  * Called when the guard determines the cached hash is stale (e.g., the user
88
- * changed their password on another device, or too many consecutive local
87
+ * changed their PIN on another device, or too many consecutive local
89
88
  * mismatches have occurred).
90
89
  *
91
- * @param mode - Whether the app is running in single-user or multi-user mode,
92
- * which determines which IndexedDB table to update.
93
- *
94
90
  * @throws Never -- errors are caught and logged via `debugWarn`.
95
91
  */
96
- async function invalidateCachedHash(mode) {
92
+ async function invalidateCachedHash() {
97
93
  try {
98
- if (mode === 'single-user') {
99
- const config = getEngineConfig();
100
- const db = config.db;
101
- if (db) {
102
- const record = await db.table('singleUserConfig').get('config');
103
- if (record && record.gateHash) {
104
- await db.table('singleUserConfig').update('config', {
105
- gateHash: undefined,
106
- updatedAt: new Date().toISOString()
107
- });
108
- debugLog('[LoginGuard] Invalidated single-user gateHash');
109
- }
110
- }
111
- }
112
- else {
113
- const config = getEngineConfig();
114
- const db = config.db;
115
- if (db) {
116
- const record = await db.table('offlineCredentials').get('current_user');
117
- if (record && record.password) {
118
- await db.table('offlineCredentials').update('current_user', {
119
- password: undefined,
120
- cachedAt: new Date().toISOString()
121
- });
122
- debugLog('[LoginGuard] Invalidated offline credentials password hash');
123
- }
94
+ const config = getEngineConfig();
95
+ const db = config.db;
96
+ if (db) {
97
+ const record = await db.table('singleUserConfig').get('config');
98
+ if (record && record.gateHash) {
99
+ await db.table('singleUserConfig').update('config', {
100
+ gateHash: undefined,
101
+ updatedAt: new Date().toISOString()
102
+ });
103
+ debugLog('[LoginGuard] Invalidated single-user gateHash');
124
104
  }
125
105
  }
126
106
  }
@@ -134,25 +114,20 @@ async function invalidateCachedHash(mode) {
134
114
  /**
135
115
  * Pre-check login credentials locally before calling Supabase.
136
116
  *
137
- * For single-user mode: reads `singleUserConfig.gateHash`, hashes input, compares.
138
- * For multi-user mode: reads offline credentials, matches email + hashes password, compares.
117
+ * Reads `singleUserConfig.gateHash`, hashes input, and compares.
139
118
  *
140
119
  * Returns `{ proceed: true, strategy }` to allow Supabase call,
141
120
  * or `{ proceed: false, error, retryAfterMs? }` to reject locally.
142
121
  *
143
122
  * @param input - The plaintext password or gate code entered by the user.
144
- * @param mode - The auth mode (`'single-user'` or `'multi-user'`), which
145
- * determines which IndexedDB table holds the cached hash.
146
- * @param email - (Multi-user only) The email address to match against cached
147
- * credentials. Ignored in single-user mode.
148
123
  * @returns A promise resolving to a {@link PreCheckResult}.
149
124
  *
150
125
  * @example
151
126
  * ```ts
152
- * const result = await preCheckLogin(password, 'multi-user', email);
127
+ * const result = await preCheckLogin(password);
153
128
  * if (result.proceed) {
154
129
  * const { error } = await supabase.auth.signInWithPassword({ email, password });
155
- * if (error) await onLoginFailure(result.strategy, 'multi-user');
130
+ * if (error) await onLoginFailure(result.strategy);
156
131
  * else onLoginSuccess();
157
132
  * } else {
158
133
  * showError(result.error);
@@ -162,22 +137,14 @@ async function invalidateCachedHash(mode) {
162
137
  * @see {@link onLoginSuccess} -- must be called after a successful Supabase login.
163
138
  * @see {@link onLoginFailure} -- must be called after a failed Supabase login.
164
139
  */
165
- export async function preCheckLogin(input, mode, email) {
140
+ export async function preCheckLogin(input) {
166
141
  try {
167
142
  let cachedHash;
168
- if (mode === 'single-user') {
169
- const config = getEngineConfig();
170
- const db = config.db;
171
- if (db) {
172
- const record = await db.table('singleUserConfig').get('config');
173
- cachedHash = record?.gateHash;
174
- }
175
- }
176
- else {
177
- const creds = await getOfflineCredentials();
178
- if (creds && email && creds.email === email && creds.password) {
179
- cachedHash = creds.password;
180
- }
143
+ const config = getEngineConfig();
144
+ const db = config.db;
145
+ if (db) {
146
+ const record = await db.table('singleUserConfig').get('config');
147
+ cachedHash = record?.gateHash;
181
148
  }
182
149
  if (cachedHash) {
183
150
  /* We have a cached hash -- compare locally before touching the network. */
@@ -196,7 +163,7 @@ export async function preCheckLogin(input, mode, email) {
196
163
  on another device). Invalidate it so subsequent attempts go directly
197
164
  to Supabase in rate-limited mode. */
198
165
  debugWarn('[LoginGuard] Threshold exceeded, invalidating cached hash');
199
- await invalidateCachedHash(mode);
166
+ await invalidateCachedHash();
200
167
  consecutiveLocalFailures = 0;
201
168
  /* Fall through to rate-limited Supabase mode */
202
169
  const rateCheck = checkRateLimit();
@@ -262,24 +229,22 @@ export function onLoginSuccess() {
262
229
  *
263
230
  * @param strategy - The {@link PreCheckStrategy} that was returned by
264
231
  * {@link preCheckLogin} for this attempt.
265
- * @param mode - The auth mode, used to determine which IndexedDB table to
266
- * invalidate if the hash is stale. Defaults to `'multi-user'`.
267
232
  *
268
233
  * @example
269
234
  * ```ts
270
- * const result = await preCheckLogin(password, 'multi-user', email);
235
+ * const result = await preCheckLogin(password);
271
236
  * if (result.proceed) {
272
237
  * const { error } = await supabase.auth.signInWithPassword({ email, password });
273
- * if (error) await onLoginFailure(result.strategy, 'multi-user');
238
+ * if (error) await onLoginFailure(result.strategy);
274
239
  * }
275
240
  * ```
276
241
  */
277
- export async function onLoginFailure(strategy, mode = 'multi-user') {
242
+ export async function onLoginFailure(strategy) {
278
243
  if (strategy === 'local-match') {
279
244
  /* Stale hash: local match but Supabase rejected -- invalidate the cache
280
245
  so the user is not stuck in a loop of false local matches. */
281
246
  debugWarn('[LoginGuard] Stale hash detected, invalidating cached hash');
282
- await invalidateCachedHash(mode);
247
+ await invalidateCachedHash();
283
248
  }
284
249
  else {
285
250
  /* No-cache mode: apply exponential backoff to throttle brute-force
@@ -1 +1 @@
1
- {"version":3,"file":"loginGuard.js","sourceRoot":"","sources":["../../src/auth/loginGuard.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"loginGuard.js","sourceRoot":"","sources":["../../src/auth/loginGuard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE/C,gFAAgF;AAChF,YAAY;AACZ,gFAAgF;AAEhF;;;GAGG;AACH,MAAM,uBAAuB,GAAG,CAAC,CAAC;AAElC,qEAAqE;AACrE,MAAM,aAAa,GAAG,IAAI,CAAC;AAE3B,0EAA0E;AAC1E,MAAM,YAAY,GAAG,KAAK,CAAC;AAE3B,wEAAwE;AACxE,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAE7B,gFAAgF;AAChF,kBAAkB;AAClB,gFAAgF;AAEhF;;;GAGG;AACH,IAAI,wBAAwB,GAAG,CAAC,CAAC;AAEjC;;;GAGG;AACH,IAAI,iBAAiB,GAAG,CAAC,CAAC;AAE1B;;;GAGG;AACH,IAAI,kBAAkB,GAAG,CAAC,CAAC;AA4B3B,gFAAgF;AAChF,mBAAmB;AACnB,gFAAgF;AAEhF;;;;;GAKG;AACH,SAAS,cAAc;IACrB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,IAAI,kBAAkB,GAAG,GAAG,EAAE,CAAC;QAC7B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,kBAAkB,GAAG,GAAG,EAAE,CAAC;IACpE,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED;;;;;;;;GAQG;AACH,KAAK,UAAU,oBAAoB;IACjC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;QACjC,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC;QACrB,IAAI,EAAE,EAAE,CAAC;YACP,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAChE,IAAI,MAAM,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;gBAC9B,MAAM,EAAE,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE;oBAClD,QAAQ,EAAE,SAAS;oBACnB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;iBACpC,CAAC,CAAC;gBACH,QAAQ,CAAC,+CAA+C,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,SAAS,CAAC,gDAAgD,EAAE,CAAC,CAAC,CAAC;IACjE,CAAC;AACH,CAAC;AAED,gFAAgF;AAChF,aAAa;AACb,gFAAgF;AAEhF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAa;IAC/C,IAAI,CAAC;QACH,IAAI,UAA8B,CAAC;QAEnC,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;QACjC,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC;QACrB,IAAI,EAAE,EAAE,CAAC;YACP,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAChE,UAAU,GAAG,MAAM,EAAE,QAAQ,CAAC;QAChC,CAAC;QAED,IAAI,UAAU,EAAE,CAAC;YACf,2EAA2E;YAC3E,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,KAAK,CAAC,CAAC;YAEzC,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;gBAC7B;oFACoE;gBACpE,QAAQ,CAAC,uDAAuD,CAAC,CAAC;gBAClE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC;YACpD,CAAC;YAED,yEAAyE;YACzE,wBAAwB,EAAE,CAAC;YAC3B,SAAS,CACP,qCAAqC,wBAAwB,IAAI,uBAAuB,GAAG,CAC5F,CAAC;YAEF,IAAI,wBAAwB,IAAI,uBAAuB,EAAE,CAAC;gBACxD;;uDAEuC;gBACvC,SAAS,CAAC,2DAA2D,CAAC,CAAC;gBACvE,MAAM,oBAAoB,EAAE,CAAC;gBAC7B,wBAAwB,GAAG,CAAC,CAAC;gBAE7B,gDAAgD;gBAChD,MAAM,SAAS,GAAG,cAAc,EAAE,CAAC;gBACnC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;oBACvB,OAAO;wBACL,OAAO,EAAE,KAAK;wBACd,KAAK,EAAE,qDAAqD;wBAC5D,YAAY,EAAE,SAAS,CAAC,YAAY;qBACrC,CAAC;gBACJ,CAAC;gBAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;YACjD,CAAC;YAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,4BAA4B,EAAE,CAAC;QACjE,CAAC;QAED,kDAAkD;QAClD,MAAM,SAAS,GAAG,cAAc,EAAE,CAAC;QACnC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;YACvB,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,qDAAqD;gBAC5D,YAAY,EAAE,SAAS,CAAC,YAAY;aACrC,CAAC;QACJ,CAAC;QAED,QAAQ,CAAC,yEAAyE,CAAC,CAAC;QACpF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;IACjD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX;;6CAEqC;QACrC,SAAS,CAAC,4DAA4D,EAAE,CAAC,CAAC,CAAC;QAC3E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;IACjD,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc;IAC5B,wBAAwB,GAAG,CAAC,CAAC;IAC7B,iBAAiB,GAAG,CAAC,CAAC;IACtB,kBAAkB,GAAG,CAAC,CAAC;IACvB,QAAQ,CAAC,4CAA4C,CAAC,CAAC;AACzD,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,QAA0B;IAC7D,IAAI,QAAQ,KAAK,aAAa,EAAE,CAAC;QAC/B;wEACgE;QAChE,SAAS,CAAC,4DAA4D,CAAC,CAAC;QACxE,MAAM,oBAAoB,EAAE,CAAC;IAC/B,CAAC;SAAM,CAAC;QACN;uDAC+C;QAC/C,iBAAiB,EAAE,CAAC;QACpB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CACpB,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,kBAAkB,EAAE,iBAAiB,GAAG,CAAC,CAAC,EACnE,YAAY,CACb,CAAC;QACF,kBAAkB,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QACxC,SAAS,CAAC,oCAAoC,KAAK,qBAAqB,iBAAiB,GAAG,CAAC,CAAC;IAChG,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,eAAe;IAC7B,wBAAwB,GAAG,CAAC,CAAC;IAC7B,iBAAiB,GAAG,CAAC,CAAC;IACtB,kBAAkB,GAAG,CAAC,CAAC;IACvB,QAAQ,CAAC,0BAA0B,CAAC,CAAC;AACvC,CAAC"}
@@ -1,25 +1,22 @@
1
1
  /**
2
2
  * @fileoverview Offline Credentials Management
3
3
  *
4
- * Handles caching, retrieval, verification, and update of user credentials
5
- * in IndexedDB for offline login support. When the user successfully
6
- * authenticates online via Supabase, their credentials are cached locally
7
- * (with the password SHA-256-hashed) so they can log in again while offline.
4
+ * Handles caching, retrieval, and update of user credentials in IndexedDB
5
+ * for offline fallback support. When the user successfully authenticates
6
+ * online via Supabase, their credentials are cached locally (with the
7
+ * password SHA-256-hashed) so profile data is available while offline.
8
8
  *
9
9
  * Architecture:
10
10
  * - Credentials are stored as a singleton record (key: `'current_user'`) in the
11
11
  * `offlineCredentials` IndexedDB table.
12
- * - Only one set of credentials is cached at a time. In multi-user apps, the
13
- * last successfully authenticated user's credentials are stored.
12
+ * - Only one set of credentials is cached at a time.
14
13
  * - The profile blob is extracted via the host app's `profileExtractor` config
15
14
  * callback, or falls back to raw Supabase `user_metadata`.
16
15
  *
17
16
  * Security considerations:
18
17
  * - Passwords are **always** hashed with SHA-256 before storage. The plaintext
19
18
  * password is never persisted.
20
- * - Legacy plaintext credentials (from before the hashing migration) are
21
- * supported in `verifyOfflineCredentials` via the `isAlreadyHashed` check,
22
- * but new writes always hash.
19
+ * - New writes always hash the password before storage.
23
20
  * - A paranoid read-back verification is performed after `cacheOfflineCredentials`
24
21
  * to ensure the password was actually persisted (guards against silent
25
22
  * IndexedDB write failures).
@@ -75,56 +72,6 @@ export declare function cacheOfflineCredentials(email: string, password: string,
75
72
  * ```
76
73
  */
77
74
  export declare function getOfflineCredentials(): Promise<OfflineCredentials | null>;
78
- /**
79
- * Verify email and password against cached credentials.
80
- *
81
- * Performs a multi-field comparison:
82
- * 1. Checks that cached credentials exist.
83
- * 2. Verifies the `userId` matches (prevents cross-user attacks).
84
- * 3. Verifies the `email` matches (prevents credential reuse across accounts).
85
- * 4. Verifies the password by hashing the input and comparing against the
86
- * stored hash (or plaintext for legacy records).
87
- *
88
- * @param email - The email to verify against cached credentials.
89
- * @param password - The plaintext password to verify.
90
- * @param expectedUserId - The Supabase user ID that the credentials should belong to.
91
- * Prevents offline login with credentials cached from a
92
- * different user.
93
- * @returns An object with `valid: true` on success, or `valid: false` with a
94
- * `reason` string identifying which check failed.
95
- *
96
- * @example
97
- * ```ts
98
- * const result = await verifyOfflineCredentials(email, password, userId);
99
- * if (result.valid) {
100
- * await createOfflineSession(userId);
101
- * } else {
102
- * console.warn('Verification failed:', result.reason);
103
- * }
104
- * ```
105
- *
106
- * @see {@link cacheOfflineCredentials} for how credentials are stored.
107
- */
108
- export declare function verifyOfflineCredentials(email: string, password: string, expectedUserId: string): Promise<{
109
- valid: boolean;
110
- reason?: string;
111
- }>;
112
- /**
113
- * Update the cached password hash after an online password change.
114
- *
115
- * Should be called whenever the user changes their password while online,
116
- * so the offline cache stays in sync and the login guard does not flag
117
- * the old hash as stale.
118
- *
119
- * @param newPassword - The new plaintext password. Will be SHA-256-hashed before storage.
120
- *
121
- * @example
122
- * ```ts
123
- * await supabase.auth.updateUser({ password: newPassword });
124
- * await updateOfflineCredentialsPassword(newPassword);
125
- * ```
126
- */
127
- export declare function updateOfflineCredentialsPassword(newPassword: string): Promise<void>;
128
75
  /**
129
76
  * Update the user profile in cached credentials after an online profile update.
130
77
  *
@@ -1 +1 @@
1
- {"version":3,"file":"offlineCredentials.d.ts","sourceRoot":"","sources":["../../src/auth/offlineCredentials.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AACnD,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAmB3D;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,OAAO,GAChB,OAAO,CAAC,IAAI,CAAC,CAyCf;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAQhF;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAkD9C;AAMD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,gCAAgC,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYzF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,+BAA+B,CACnD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,IAAI,CAAC,CAWf;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,IAAI,CAAC,CAG7D"}
1
+ {"version":3,"file":"offlineCredentials.d.ts","sourceRoot":"","sources":["../../src/auth/offlineCredentials.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AACnD,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAmB3D;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,OAAO,GAChB,OAAO,CAAC,IAAI,CAAC,CAyCf;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAQhF;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,+BAA+B,CACnD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,IAAI,CAAC,CAWf;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,IAAI,CAAC,CAG7D"}