@aurabase/core 0.7.0 → 0.7.1

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/dist/index.cjs CHANGED
@@ -96,8 +96,12 @@ var AuraError = class _AuraError extends Error {
96
96
  this.code = "SESSION_REVOKED";
97
97
  } else if (status === 401 && lowerMsg.includes("expired")) {
98
98
  this.code = "SESSION_EXPIRED";
99
- } else if (status === 400 && lowerMsg.includes("password")) {
99
+ } else if (status === 400 && (lowerMsg.includes("current password") || lowerMsg.includes("old password") || lowerMsg.includes("password") && lowerMsg.includes("required"))) {
100
+ this.code = lowerMsg.includes("incorrect") || lowerMsg.includes("invalid") ? "INVALID_CURRENT_PASSWORD" : "CURRENT_PASSWORD_REQUIRED";
101
+ } else if (status === 400 && lowerMsg.includes("password") && (lowerMsg.includes("weak") || lowerMsg.includes("length") || lowerMsg.includes("strength") || lowerMsg.includes("character") || lowerMsg.includes("digit") || lowerMsg.includes("pwned") || lowerMsg.includes("too short") || lowerMsg.includes("too common"))) {
100
102
  this.code = "WEAK_PASSWORD";
103
+ } else if (status === 400 && lowerMsg.includes("password")) {
104
+ this.code = "INVALID_PASSWORD";
101
105
  } else if (status === 409 && (lowerMsg.includes("already exists") || lowerMsg.includes("already in use") || lowerMsg.includes("email"))) {
102
106
  this.code = "EMAIL_ALREADY_IN_USE";
103
107
  } else if (status === 404 && lowerMsg.includes("user not found")) {
@@ -279,6 +283,33 @@ var AUTH_SETTINGS_WRITABLE_FIELDS = [
279
283
  "hook_secret"
280
284
  ];
281
285
 
286
+ // src/cookie-utils.ts
287
+ function parseCookieHeader(header) {
288
+ const result = {};
289
+ if (!header) return result;
290
+ for (const pair of header.split(";")) {
291
+ const idx = pair.indexOf("=");
292
+ if (idx === -1) continue;
293
+ const key = pair.slice(0, idx).trim();
294
+ const value = pair.slice(idx + 1).trim();
295
+ if (key) result[key] = decodeURIComponent(value);
296
+ }
297
+ return result;
298
+ }
299
+ function sameSiteAttribute(v) {
300
+ return v.charAt(0).toUpperCase() + v.slice(1);
301
+ }
302
+ function serializeCookieHeader(name, value, options = {}) {
303
+ const parts = [`${name}=${encodeURIComponent(value)}`];
304
+ if (options.path) parts.push(`Path=${options.path}`);
305
+ if (options.domain) parts.push(`Domain=${options.domain}`);
306
+ if (options.maxAge !== void 0) parts.push(`Max-Age=${options.maxAge}`);
307
+ if (options.secure) parts.push("Secure");
308
+ if (options.sameSite) parts.push(`SameSite=${sameSiteAttribute(options.sameSite)}`);
309
+ if (options.httpOnly) parts.push("HttpOnly");
310
+ return parts.join("; ");
311
+ }
312
+
282
313
  // src/stores/BaseAuthStore.ts
283
314
  function decodeJwtPayload(token) {
284
315
  try {
@@ -323,6 +354,7 @@ var BaseAuthStore = class {
323
354
  * le flux PKCE : le `code_verifier` doit survivre au redirect OAuth.
324
355
  */
325
356
  persistent = false;
357
+ key;
326
358
  _token = null;
327
359
  _refreshToken = null;
328
360
  _user = null;
@@ -333,6 +365,9 @@ var BaseAuthStore = class {
333
365
  /** Hook d'observabilité (LOT 3) — câblé par `AuraClient` via `setObservabilityHook`. */
334
366
  _onEvent;
335
367
  _debug = false;
368
+ constructor(key = "aura-auth") {
369
+ this.key = key;
370
+ }
336
371
  // -- Getters ----------------------------------------------------------------
337
372
  /** Compteur incrémenté à chaque `clear()` — sert au commit-guard anti-race du refresh. */
338
373
  get removalEpoch() {
@@ -394,6 +429,43 @@ var BaseAuthStore = class {
394
429
  _emitStorageBlocked(op) {
395
430
  emitAuraEvent(this._onEvent, this._debug, { kind: "storage-blocked", op });
396
431
  }
432
+ /**
433
+ * Populate the store from a raw `Cookie` header string (server-side).
434
+ * Looks for the key matching `this.key`.
435
+ */
436
+ loadFromCookie(cookieString) {
437
+ const prefix = `${this.key}=`;
438
+ const entry = cookieString.split(";").map((c) => c.trim()).find((c) => c.startsWith(prefix));
439
+ if (!entry) return;
440
+ try {
441
+ const raw = decodeURIComponent(entry.slice(prefix.length));
442
+ const parsed = JSON.parse(raw);
443
+ const user = parsed.token ? userFromAccessToken(parsed.token) : null;
444
+ if (parsed.token && parsed.refreshToken && user) {
445
+ this.save(parsed.token, parsed.refreshToken, user);
446
+ }
447
+ } catch {
448
+ }
449
+ }
450
+ /**
451
+ * Serialize the session tokens into a `Set-Cookie` value. The `user` object is NOT included: its
452
+ * `user_metadata` is already inside the access token.
453
+ */
454
+ exportToCookie(options = {}) {
455
+ const data = {
456
+ token: this.token,
457
+ refreshToken: this.refreshToken
458
+ };
459
+ const encoded = encodeURIComponent(JSON.stringify(data));
460
+ const parts = [`${this.key}=${encoded}`];
461
+ if (options.path) parts.push(`Path=${options.path}`);
462
+ if (options.domain) parts.push(`Domain=${options.domain}`);
463
+ if (options.maxAge !== void 0) parts.push(`Max-Age=${options.maxAge}`);
464
+ if (options.secure) parts.push("Secure");
465
+ if (options.sameSite) parts.push(`SameSite=${sameSiteAttribute(options.sameSite)}`);
466
+ if (options.httpOnly) parts.push("HttpOnly");
467
+ return parts.join("; ");
468
+ }
397
469
  // -- Event emitter ----------------------------------------------------------
398
470
  /**
399
471
  * Register a callback that fires whenever the auth state changes.
@@ -888,45 +960,16 @@ var BaseService = class {
888
960
  }
889
961
  };
890
962
 
891
- // src/cookie-utils.ts
892
- function parseCookieHeader(header) {
893
- const result = {};
894
- if (!header) return result;
895
- for (const pair of header.split(";")) {
896
- const idx = pair.indexOf("=");
897
- if (idx === -1) continue;
898
- const key = pair.slice(0, idx).trim();
899
- const value = pair.slice(idx + 1).trim();
900
- if (key) result[key] = decodeURIComponent(value);
901
- }
902
- return result;
903
- }
904
- function sameSiteAttribute(v) {
905
- return v.charAt(0).toUpperCase() + v.slice(1);
906
- }
907
- function serializeCookieHeader(name, value, options = {}) {
908
- const parts = [`${name}=${encodeURIComponent(value)}`];
909
- if (options.path) parts.push(`Path=${options.path}`);
910
- if (options.domain) parts.push(`Domain=${options.domain}`);
911
- if (options.maxAge !== void 0) parts.push(`Max-Age=${options.maxAge}`);
912
- if (options.secure) parts.push("Secure");
913
- if (options.sameSite) parts.push(`SameSite=${sameSiteAttribute(options.sameSite)}`);
914
- if (options.httpOnly) parts.push("HttpOnly");
915
- return parts.join("; ");
916
- }
917
-
918
963
  // src/stores/LocalAuthStore.ts
919
964
  var LocalAuthStore = class extends BaseAuthStore {
920
965
  /** Persiste en localStorage → survit au redirect pleine page (cf. PKCE). */
921
966
  persistent = true;
922
- key;
923
967
  /**
924
968
  * @param key Nom de l'entrée `localStorage` (et du cookie SSR). Scopez-le par projet :
925
969
  * `aura-${clientScope(baseUrl)}-auth`.
926
970
  */
927
971
  constructor(key) {
928
- super();
929
- this.key = key;
972
+ super(key);
930
973
  this._loadFromStorage();
931
974
  }
932
975
  // -- Overrides --------------------------------------------------------------
package/dist/index.d.cts CHANGED
@@ -203,6 +203,8 @@ interface User {
203
203
  last_sign_in_at?: string | null;
204
204
  }
205
205
  interface Session {
206
+ /** Identifiant unique de la session (UUID ou 'sess_...'), dérivé du claim `session_id` du JWT. */
207
+ id?: string;
206
208
  access_token: string;
207
209
  refresh_token: string;
208
210
  token_type: string;
@@ -267,6 +269,7 @@ interface SignUpRequest {
267
269
  options?: {
268
270
  emailRedirectTo?: string;
269
271
  data?: Record<string, unknown>;
272
+ preventEmailEnumeration?: boolean;
270
273
  };
271
274
  }
272
275
  interface SignInRequest {
@@ -369,14 +372,25 @@ interface MfaEnrollResponse {
369
372
  * Pour une passkey, utilisez `auth.mfa.webauthn.verify`.
370
373
  */
371
374
  type MfaVerifyRequest = {
372
- mfa_token: string;
375
+ mfa_token?: string;
376
+ mfaToken?: string;
377
+ challenge_id?: string;
378
+ challengeId?: string;
373
379
  code: string;
374
380
  } | {
375
- mfa_token: string;
381
+ mfa_token?: string;
382
+ mfaToken?: string;
383
+ challenge_id?: string;
384
+ challengeId?: string;
376
385
  recovery_code: string;
386
+ recoveryCode?: string;
377
387
  } | {
378
- mfa_token: string;
388
+ mfa_token?: string;
389
+ mfaToken?: string;
390
+ challenge_id?: string;
391
+ challengeId?: string;
379
392
  sms_code: string;
393
+ smsCode?: string;
380
394
  };
381
395
  /** Facteur MFA utilisable pour relever un défi (`auth.mfa.factors`). */
382
396
  type MfaFactorType = 'totp' | 'webauthn' | 'sms';
@@ -1839,6 +1853,19 @@ type AuthChangeCallback = (token: string | null, user: User | null) => void;
1839
1853
  * Check whether a JWT has expired (or will expire within `marginSec` seconds).
1840
1854
  */
1841
1855
  declare function isTokenExpired(token: string, marginSec?: number): boolean;
1856
+ interface CookieOptions {
1857
+ path?: string;
1858
+ domain?: string;
1859
+ maxAge?: number;
1860
+ secure?: boolean;
1861
+ sameSite?: 'strict' | 'lax' | 'none';
1862
+ httpOnly?: boolean;
1863
+ }
1864
+ interface StoredAuth {
1865
+ token: string | null;
1866
+ refreshToken: string | null;
1867
+ user: User | null;
1868
+ }
1842
1869
  /**
1843
1870
  * In-memory auth store with an event-emitter pattern.
1844
1871
  * Can be extended (see LocalAuthStore) for persistence.
@@ -1850,6 +1877,7 @@ declare class BaseAuthStore {
1850
1877
  * le flux PKCE : le `code_verifier` doit survivre au redirect OAuth.
1851
1878
  */
1852
1879
  readonly persistent: boolean;
1880
+ protected readonly key: string;
1853
1881
  private _token;
1854
1882
  private _refreshToken;
1855
1883
  private _user;
@@ -1860,6 +1888,7 @@ declare class BaseAuthStore {
1860
1888
  /** Hook d'observabilité (LOT 3) — câblé par `AuraClient` via `setObservabilityHook`. */
1861
1889
  private _onEvent?;
1862
1890
  private _debug;
1891
+ constructor(key?: string);
1863
1892
  /** Compteur incrémenté à chaque `clear()` — sert au commit-guard anti-race du refresh. */
1864
1893
  get removalEpoch(): number;
1865
1894
  get token(): string | null;
@@ -1881,6 +1910,16 @@ declare class BaseAuthStore {
1881
1910
  setObservabilityHook(onEvent: ((event: AuraObservabilityEvent) => void) | undefined, debug: boolean | undefined): void;
1882
1911
  /** Émet `{kind:'storage-blocked', op}` — ne throw jamais (voir `emitAuraEvent`). */
1883
1912
  protected _emitStorageBlocked(op: string): void;
1913
+ /**
1914
+ * Populate the store from a raw `Cookie` header string (server-side).
1915
+ * Looks for the key matching `this.key`.
1916
+ */
1917
+ loadFromCookie(cookieString: string): void;
1918
+ /**
1919
+ * Serialize the session tokens into a `Set-Cookie` value. The `user` object is NOT included: its
1920
+ * `user_metadata` is already inside the access token.
1921
+ */
1922
+ exportToCookie(options?: CookieOptions): string;
1884
1923
  /**
1885
1924
  * Register a callback that fires whenever the auth state changes.
1886
1925
  * Returns an unsubscribe function.
@@ -2038,14 +2077,6 @@ declare function clientScope(baseUrl: string): string;
2038
2077
  /** JSON.stringify avec support des bigint (sérialisés en string). */
2039
2078
  declare function serializeBody(body: unknown): string;
2040
2079
 
2041
- interface CookieOptions {
2042
- path?: string;
2043
- domain?: string;
2044
- maxAge?: number;
2045
- secure?: boolean;
2046
- sameSite?: 'strict' | 'lax' | 'none';
2047
- httpOnly?: boolean;
2048
- }
2049
2080
  /**
2050
2081
  * Auth store backed by `localStorage` (browser) with cookie helpers for SSR.
2051
2082
  *
@@ -2062,7 +2093,6 @@ interface CookieOptions {
2062
2093
  declare class LocalAuthStore extends BaseAuthStore {
2063
2094
  /** Persiste en localStorage → survit au redirect pleine page (cf. PKCE). */
2064
2095
  readonly persistent = true;
2065
- private readonly key;
2066
2096
  /**
2067
2097
  * @param key Nom de l'entrée `localStorage` (et du cookie SSR). Scopez-le par projet :
2068
2098
  * `aura-${clientScope(baseUrl)}-auth`.
@@ -2103,4 +2133,4 @@ declare class LocalAuthStore extends BaseAuthStore {
2103
2133
  private _removeStorage;
2104
2134
  }
2105
2135
 
2106
- export { AUTH_SETTINGS_WRITABLE_FIELDS, type AdminCreateUserRequest, type AdminSessionInfo, type AdminUpdateUserRequest, type AdminUser, type ApnsPublicSettings, type ApnsSettingsPatch, type AuditLogEntry, type AuraClientLike, type AuraClientOptions, AuraError, type AuraErrorCode, type AuraFailure, type AuraNoContent, type AuraObservabilityEvent, type AuraResponse, type AuraSuccess, type AuthChangePayload, type AuthEvent, type AuthSettings, type AuthSettingsUpdate, BaseAuthStore, BaseService, type BatchSendItemResult, type BatchSendResponse, type BroadcastAckMessage, type BroadcastFilter, type BroadcastPayload, type BroadcastSendStatus, type CdcPayload, type ChannelConfig, type ChatMessage, type ChatResponse, type CountMode, type CreateNotificationRuleRequest, type CreatePgFunctionRequest, type CreatePgTriggerRequest, type CronJob, DEFAULT_MAX_RETRIES, DEFAULT_REQUEST_TIMEOUT_MS, type EmailTemplateUpdate, type EmbedRequest, type EmbedResponse, type FcmPublicSettings, type FcmSettingsPatch, type FetchInit, type FileEntry, type FilterOp, type FunctionDef, type FunctionPermissions, type GenerateLinkResult, type GenerateLinkType, type GetClaimsResult, type IdentityInfo, type ImageTransform, type Job, type JwtClaims, LocalAuthStore, type LoginResponse, type MagicLinkRequest, type Meta, type MfaChallenge, type MfaEnrollResponse, type MfaFactorType, type MfaVerifyRequest, type Notification, type NotificationAttempt, type NotificationAttemptStatus, type NotificationChannel, type NotificationChannelStats, type NotificationDeadLetter, type NotificationEvent, type NotificationProviderLog, type NotificationQueueStats, type NotificationRule, type NotificationSettings, type NotificationSettingsPatch, type NotificationSettingsPublic, type NotificationStats, type NotificationStatsWindow, type NotificationStatus, type NotificationTemplate, type NotificationTemplatePreview, type OAuthProviderSetting, type OAuthSignInObjectOptions, type OAuthSignInOptions, type ObjectMeta, type PasskeyInfo, type PasskeyRegisterResult, type PasswordResetRequest, type PgExecutableRole, type PgFunctionInfo, type PgTriggerInfo, type PostgresChangesFilter, type PresenceFilter, type PresenceInfo, type PresenceState, type QueryFilter, type QueryOptions, type QuotaPublicSettings, type QuotaSettingsPatch, RETRYABLE_METHODS, RETRYABLE_STATUS, type RagIngestRequest, type RagIngestResponse, type RagRequest, type RagResponse, type RealtimeBroadcastEvent, type RealtimeEvent, type RealtimeListenType, type RealtimePostgresChangesBasePayload, type RealtimePostgresChangesPayload, type RealtimePostgresDeletePayload, type RealtimePostgresInsertPayload, type RealtimePostgresUpdatePayload, type RealtimeSubscribeStatus, type SchemaColumn, type SchemaEnum, type SchemaFunction, type SchemaFunctionArg, type SchemaIndex, type SchemaTable, type SemanticSearchResult, type SendNotificationItem, type SendNotificationOptions, type SendNotificationRequest, type SerializeCookieOptions, type ServerChannelRecoveredMsg, type ServerErrorMsg, type ServerEventMsg, type ServerMessage, type ServerPongMsg, type ServerPresenceStateMsg, type ServerSubscribedMsg, type ServerTokenRefreshedMsg, type Session, type SessionInfo, type SettingsSource, type SignInRequest, type SignUpRequest, type SmtpPublicSettings, type SmtpSettingsPatch, type StorageBucket, type SubscribeCallback, type TokenPair, type TwilioPublicSettings, type TwilioSettingsPatch, type UpdateNotificationRuleRequest, type UpdateUserRequest, type UploadResult, type User, type UserStats, type WebhookPublicSettings, type WebhookSettingsPatch, abortableSleep, clientScope, computeBackoff, emitAuraEvent, fetchWithAuth, isAbortError, isAuraError, isRetryableMethod, isRetryableStatus, isTokenExpired, parseCookieHeader, parseRetryAfter, refreshOnce, serializeBody, serializeCookieHeader };
2136
+ export { AUTH_SETTINGS_WRITABLE_FIELDS, type AdminCreateUserRequest, type AdminSessionInfo, type AdminUpdateUserRequest, type AdminUser, type ApnsPublicSettings, type ApnsSettingsPatch, type AuditLogEntry, type AuraClientLike, type AuraClientOptions, AuraError, type AuraErrorCode, type AuraFailure, type AuraNoContent, type AuraObservabilityEvent, type AuraResponse, type AuraSuccess, type AuthChangePayload, type AuthEvent, type AuthSettings, type AuthSettingsUpdate, BaseAuthStore, BaseService, type BatchSendItemResult, type BatchSendResponse, type BroadcastAckMessage, type BroadcastFilter, type BroadcastPayload, type BroadcastSendStatus, type CdcPayload, type ChannelConfig, type ChatMessage, type ChatResponse, type CookieOptions, type CountMode, type CreateNotificationRuleRequest, type CreatePgFunctionRequest, type CreatePgTriggerRequest, type CronJob, DEFAULT_MAX_RETRIES, DEFAULT_REQUEST_TIMEOUT_MS, type EmailTemplateUpdate, type EmbedRequest, type EmbedResponse, type FcmPublicSettings, type FcmSettingsPatch, type FetchInit, type FileEntry, type FilterOp, type FunctionDef, type FunctionPermissions, type GenerateLinkResult, type GenerateLinkType, type GetClaimsResult, type IdentityInfo, type ImageTransform, type Job, type JwtClaims, LocalAuthStore, type LoginResponse, type MagicLinkRequest, type Meta, type MfaChallenge, type MfaEnrollResponse, type MfaFactorType, type MfaVerifyRequest, type Notification, type NotificationAttempt, type NotificationAttemptStatus, type NotificationChannel, type NotificationChannelStats, type NotificationDeadLetter, type NotificationEvent, type NotificationProviderLog, type NotificationQueueStats, type NotificationRule, type NotificationSettings, type NotificationSettingsPatch, type NotificationSettingsPublic, type NotificationStats, type NotificationStatsWindow, type NotificationStatus, type NotificationTemplate, type NotificationTemplatePreview, type OAuthProviderSetting, type OAuthSignInObjectOptions, type OAuthSignInOptions, type ObjectMeta, type PasskeyInfo, type PasskeyRegisterResult, type PasswordResetRequest, type PgExecutableRole, type PgFunctionInfo, type PgTriggerInfo, type PostgresChangesFilter, type PresenceFilter, type PresenceInfo, type PresenceState, type QueryFilter, type QueryOptions, type QuotaPublicSettings, type QuotaSettingsPatch, RETRYABLE_METHODS, RETRYABLE_STATUS, type RagIngestRequest, type RagIngestResponse, type RagRequest, type RagResponse, type RealtimeBroadcastEvent, type RealtimeEvent, type RealtimeListenType, type RealtimePostgresChangesBasePayload, type RealtimePostgresChangesPayload, type RealtimePostgresDeletePayload, type RealtimePostgresInsertPayload, type RealtimePostgresUpdatePayload, type RealtimeSubscribeStatus, type SchemaColumn, type SchemaEnum, type SchemaFunction, type SchemaFunctionArg, type SchemaIndex, type SchemaTable, type SemanticSearchResult, type SendNotificationItem, type SendNotificationOptions, type SendNotificationRequest, type SerializeCookieOptions, type ServerChannelRecoveredMsg, type ServerErrorMsg, type ServerEventMsg, type ServerMessage, type ServerPongMsg, type ServerPresenceStateMsg, type ServerSubscribedMsg, type ServerTokenRefreshedMsg, type Session, type SessionInfo, type SettingsSource, type SignInRequest, type SignUpRequest, type SmtpPublicSettings, type SmtpSettingsPatch, type StorageBucket, type StoredAuth, type SubscribeCallback, type TokenPair, type TwilioPublicSettings, type TwilioSettingsPatch, type UpdateNotificationRuleRequest, type UpdateUserRequest, type UploadResult, type User, type UserStats, type WebhookPublicSettings, type WebhookSettingsPatch, abortableSleep, clientScope, computeBackoff, emitAuraEvent, fetchWithAuth, isAbortError, isAuraError, isRetryableMethod, isRetryableStatus, isTokenExpired, parseCookieHeader, parseRetryAfter, refreshOnce, serializeBody, serializeCookieHeader };
package/dist/index.d.ts CHANGED
@@ -203,6 +203,8 @@ interface User {
203
203
  last_sign_in_at?: string | null;
204
204
  }
205
205
  interface Session {
206
+ /** Identifiant unique de la session (UUID ou 'sess_...'), dérivé du claim `session_id` du JWT. */
207
+ id?: string;
206
208
  access_token: string;
207
209
  refresh_token: string;
208
210
  token_type: string;
@@ -267,6 +269,7 @@ interface SignUpRequest {
267
269
  options?: {
268
270
  emailRedirectTo?: string;
269
271
  data?: Record<string, unknown>;
272
+ preventEmailEnumeration?: boolean;
270
273
  };
271
274
  }
272
275
  interface SignInRequest {
@@ -369,14 +372,25 @@ interface MfaEnrollResponse {
369
372
  * Pour une passkey, utilisez `auth.mfa.webauthn.verify`.
370
373
  */
371
374
  type MfaVerifyRequest = {
372
- mfa_token: string;
375
+ mfa_token?: string;
376
+ mfaToken?: string;
377
+ challenge_id?: string;
378
+ challengeId?: string;
373
379
  code: string;
374
380
  } | {
375
- mfa_token: string;
381
+ mfa_token?: string;
382
+ mfaToken?: string;
383
+ challenge_id?: string;
384
+ challengeId?: string;
376
385
  recovery_code: string;
386
+ recoveryCode?: string;
377
387
  } | {
378
- mfa_token: string;
388
+ mfa_token?: string;
389
+ mfaToken?: string;
390
+ challenge_id?: string;
391
+ challengeId?: string;
379
392
  sms_code: string;
393
+ smsCode?: string;
380
394
  };
381
395
  /** Facteur MFA utilisable pour relever un défi (`auth.mfa.factors`). */
382
396
  type MfaFactorType = 'totp' | 'webauthn' | 'sms';
@@ -1839,6 +1853,19 @@ type AuthChangeCallback = (token: string | null, user: User | null) => void;
1839
1853
  * Check whether a JWT has expired (or will expire within `marginSec` seconds).
1840
1854
  */
1841
1855
  declare function isTokenExpired(token: string, marginSec?: number): boolean;
1856
+ interface CookieOptions {
1857
+ path?: string;
1858
+ domain?: string;
1859
+ maxAge?: number;
1860
+ secure?: boolean;
1861
+ sameSite?: 'strict' | 'lax' | 'none';
1862
+ httpOnly?: boolean;
1863
+ }
1864
+ interface StoredAuth {
1865
+ token: string | null;
1866
+ refreshToken: string | null;
1867
+ user: User | null;
1868
+ }
1842
1869
  /**
1843
1870
  * In-memory auth store with an event-emitter pattern.
1844
1871
  * Can be extended (see LocalAuthStore) for persistence.
@@ -1850,6 +1877,7 @@ declare class BaseAuthStore {
1850
1877
  * le flux PKCE : le `code_verifier` doit survivre au redirect OAuth.
1851
1878
  */
1852
1879
  readonly persistent: boolean;
1880
+ protected readonly key: string;
1853
1881
  private _token;
1854
1882
  private _refreshToken;
1855
1883
  private _user;
@@ -1860,6 +1888,7 @@ declare class BaseAuthStore {
1860
1888
  /** Hook d'observabilité (LOT 3) — câblé par `AuraClient` via `setObservabilityHook`. */
1861
1889
  private _onEvent?;
1862
1890
  private _debug;
1891
+ constructor(key?: string);
1863
1892
  /** Compteur incrémenté à chaque `clear()` — sert au commit-guard anti-race du refresh. */
1864
1893
  get removalEpoch(): number;
1865
1894
  get token(): string | null;
@@ -1881,6 +1910,16 @@ declare class BaseAuthStore {
1881
1910
  setObservabilityHook(onEvent: ((event: AuraObservabilityEvent) => void) | undefined, debug: boolean | undefined): void;
1882
1911
  /** Émet `{kind:'storage-blocked', op}` — ne throw jamais (voir `emitAuraEvent`). */
1883
1912
  protected _emitStorageBlocked(op: string): void;
1913
+ /**
1914
+ * Populate the store from a raw `Cookie` header string (server-side).
1915
+ * Looks for the key matching `this.key`.
1916
+ */
1917
+ loadFromCookie(cookieString: string): void;
1918
+ /**
1919
+ * Serialize the session tokens into a `Set-Cookie` value. The `user` object is NOT included: its
1920
+ * `user_metadata` is already inside the access token.
1921
+ */
1922
+ exportToCookie(options?: CookieOptions): string;
1884
1923
  /**
1885
1924
  * Register a callback that fires whenever the auth state changes.
1886
1925
  * Returns an unsubscribe function.
@@ -2038,14 +2077,6 @@ declare function clientScope(baseUrl: string): string;
2038
2077
  /** JSON.stringify avec support des bigint (sérialisés en string). */
2039
2078
  declare function serializeBody(body: unknown): string;
2040
2079
 
2041
- interface CookieOptions {
2042
- path?: string;
2043
- domain?: string;
2044
- maxAge?: number;
2045
- secure?: boolean;
2046
- sameSite?: 'strict' | 'lax' | 'none';
2047
- httpOnly?: boolean;
2048
- }
2049
2080
  /**
2050
2081
  * Auth store backed by `localStorage` (browser) with cookie helpers for SSR.
2051
2082
  *
@@ -2062,7 +2093,6 @@ interface CookieOptions {
2062
2093
  declare class LocalAuthStore extends BaseAuthStore {
2063
2094
  /** Persiste en localStorage → survit au redirect pleine page (cf. PKCE). */
2064
2095
  readonly persistent = true;
2065
- private readonly key;
2066
2096
  /**
2067
2097
  * @param key Nom de l'entrée `localStorage` (et du cookie SSR). Scopez-le par projet :
2068
2098
  * `aura-${clientScope(baseUrl)}-auth`.
@@ -2103,4 +2133,4 @@ declare class LocalAuthStore extends BaseAuthStore {
2103
2133
  private _removeStorage;
2104
2134
  }
2105
2135
 
2106
- export { AUTH_SETTINGS_WRITABLE_FIELDS, type AdminCreateUserRequest, type AdminSessionInfo, type AdminUpdateUserRequest, type AdminUser, type ApnsPublicSettings, type ApnsSettingsPatch, type AuditLogEntry, type AuraClientLike, type AuraClientOptions, AuraError, type AuraErrorCode, type AuraFailure, type AuraNoContent, type AuraObservabilityEvent, type AuraResponse, type AuraSuccess, type AuthChangePayload, type AuthEvent, type AuthSettings, type AuthSettingsUpdate, BaseAuthStore, BaseService, type BatchSendItemResult, type BatchSendResponse, type BroadcastAckMessage, type BroadcastFilter, type BroadcastPayload, type BroadcastSendStatus, type CdcPayload, type ChannelConfig, type ChatMessage, type ChatResponse, type CountMode, type CreateNotificationRuleRequest, type CreatePgFunctionRequest, type CreatePgTriggerRequest, type CronJob, DEFAULT_MAX_RETRIES, DEFAULT_REQUEST_TIMEOUT_MS, type EmailTemplateUpdate, type EmbedRequest, type EmbedResponse, type FcmPublicSettings, type FcmSettingsPatch, type FetchInit, type FileEntry, type FilterOp, type FunctionDef, type FunctionPermissions, type GenerateLinkResult, type GenerateLinkType, type GetClaimsResult, type IdentityInfo, type ImageTransform, type Job, type JwtClaims, LocalAuthStore, type LoginResponse, type MagicLinkRequest, type Meta, type MfaChallenge, type MfaEnrollResponse, type MfaFactorType, type MfaVerifyRequest, type Notification, type NotificationAttempt, type NotificationAttemptStatus, type NotificationChannel, type NotificationChannelStats, type NotificationDeadLetter, type NotificationEvent, type NotificationProviderLog, type NotificationQueueStats, type NotificationRule, type NotificationSettings, type NotificationSettingsPatch, type NotificationSettingsPublic, type NotificationStats, type NotificationStatsWindow, type NotificationStatus, type NotificationTemplate, type NotificationTemplatePreview, type OAuthProviderSetting, type OAuthSignInObjectOptions, type OAuthSignInOptions, type ObjectMeta, type PasskeyInfo, type PasskeyRegisterResult, type PasswordResetRequest, type PgExecutableRole, type PgFunctionInfo, type PgTriggerInfo, type PostgresChangesFilter, type PresenceFilter, type PresenceInfo, type PresenceState, type QueryFilter, type QueryOptions, type QuotaPublicSettings, type QuotaSettingsPatch, RETRYABLE_METHODS, RETRYABLE_STATUS, type RagIngestRequest, type RagIngestResponse, type RagRequest, type RagResponse, type RealtimeBroadcastEvent, type RealtimeEvent, type RealtimeListenType, type RealtimePostgresChangesBasePayload, type RealtimePostgresChangesPayload, type RealtimePostgresDeletePayload, type RealtimePostgresInsertPayload, type RealtimePostgresUpdatePayload, type RealtimeSubscribeStatus, type SchemaColumn, type SchemaEnum, type SchemaFunction, type SchemaFunctionArg, type SchemaIndex, type SchemaTable, type SemanticSearchResult, type SendNotificationItem, type SendNotificationOptions, type SendNotificationRequest, type SerializeCookieOptions, type ServerChannelRecoveredMsg, type ServerErrorMsg, type ServerEventMsg, type ServerMessage, type ServerPongMsg, type ServerPresenceStateMsg, type ServerSubscribedMsg, type ServerTokenRefreshedMsg, type Session, type SessionInfo, type SettingsSource, type SignInRequest, type SignUpRequest, type SmtpPublicSettings, type SmtpSettingsPatch, type StorageBucket, type SubscribeCallback, type TokenPair, type TwilioPublicSettings, type TwilioSettingsPatch, type UpdateNotificationRuleRequest, type UpdateUserRequest, type UploadResult, type User, type UserStats, type WebhookPublicSettings, type WebhookSettingsPatch, abortableSleep, clientScope, computeBackoff, emitAuraEvent, fetchWithAuth, isAbortError, isAuraError, isRetryableMethod, isRetryableStatus, isTokenExpired, parseCookieHeader, parseRetryAfter, refreshOnce, serializeBody, serializeCookieHeader };
2136
+ export { AUTH_SETTINGS_WRITABLE_FIELDS, type AdminCreateUserRequest, type AdminSessionInfo, type AdminUpdateUserRequest, type AdminUser, type ApnsPublicSettings, type ApnsSettingsPatch, type AuditLogEntry, type AuraClientLike, type AuraClientOptions, AuraError, type AuraErrorCode, type AuraFailure, type AuraNoContent, type AuraObservabilityEvent, type AuraResponse, type AuraSuccess, type AuthChangePayload, type AuthEvent, type AuthSettings, type AuthSettingsUpdate, BaseAuthStore, BaseService, type BatchSendItemResult, type BatchSendResponse, type BroadcastAckMessage, type BroadcastFilter, type BroadcastPayload, type BroadcastSendStatus, type CdcPayload, type ChannelConfig, type ChatMessage, type ChatResponse, type CookieOptions, type CountMode, type CreateNotificationRuleRequest, type CreatePgFunctionRequest, type CreatePgTriggerRequest, type CronJob, DEFAULT_MAX_RETRIES, DEFAULT_REQUEST_TIMEOUT_MS, type EmailTemplateUpdate, type EmbedRequest, type EmbedResponse, type FcmPublicSettings, type FcmSettingsPatch, type FetchInit, type FileEntry, type FilterOp, type FunctionDef, type FunctionPermissions, type GenerateLinkResult, type GenerateLinkType, type GetClaimsResult, type IdentityInfo, type ImageTransform, type Job, type JwtClaims, LocalAuthStore, type LoginResponse, type MagicLinkRequest, type Meta, type MfaChallenge, type MfaEnrollResponse, type MfaFactorType, type MfaVerifyRequest, type Notification, type NotificationAttempt, type NotificationAttemptStatus, type NotificationChannel, type NotificationChannelStats, type NotificationDeadLetter, type NotificationEvent, type NotificationProviderLog, type NotificationQueueStats, type NotificationRule, type NotificationSettings, type NotificationSettingsPatch, type NotificationSettingsPublic, type NotificationStats, type NotificationStatsWindow, type NotificationStatus, type NotificationTemplate, type NotificationTemplatePreview, type OAuthProviderSetting, type OAuthSignInObjectOptions, type OAuthSignInOptions, type ObjectMeta, type PasskeyInfo, type PasskeyRegisterResult, type PasswordResetRequest, type PgExecutableRole, type PgFunctionInfo, type PgTriggerInfo, type PostgresChangesFilter, type PresenceFilter, type PresenceInfo, type PresenceState, type QueryFilter, type QueryOptions, type QuotaPublicSettings, type QuotaSettingsPatch, RETRYABLE_METHODS, RETRYABLE_STATUS, type RagIngestRequest, type RagIngestResponse, type RagRequest, type RagResponse, type RealtimeBroadcastEvent, type RealtimeEvent, type RealtimeListenType, type RealtimePostgresChangesBasePayload, type RealtimePostgresChangesPayload, type RealtimePostgresDeletePayload, type RealtimePostgresInsertPayload, type RealtimePostgresUpdatePayload, type RealtimeSubscribeStatus, type SchemaColumn, type SchemaEnum, type SchemaFunction, type SchemaFunctionArg, type SchemaIndex, type SchemaTable, type SemanticSearchResult, type SendNotificationItem, type SendNotificationOptions, type SendNotificationRequest, type SerializeCookieOptions, type ServerChannelRecoveredMsg, type ServerErrorMsg, type ServerEventMsg, type ServerMessage, type ServerPongMsg, type ServerPresenceStateMsg, type ServerSubscribedMsg, type ServerTokenRefreshedMsg, type Session, type SessionInfo, type SettingsSource, type SignInRequest, type SignUpRequest, type SmtpPublicSettings, type SmtpSettingsPatch, type StorageBucket, type StoredAuth, type SubscribeCallback, type TokenPair, type TwilioPublicSettings, type TwilioSettingsPatch, type UpdateNotificationRuleRequest, type UpdateUserRequest, type UploadResult, type User, type UserStats, type WebhookPublicSettings, type WebhookSettingsPatch, abortableSleep, clientScope, computeBackoff, emitAuraEvent, fetchWithAuth, isAbortError, isAuraError, isRetryableMethod, isRetryableStatus, isTokenExpired, parseCookieHeader, parseRetryAfter, refreshOnce, serializeBody, serializeCookieHeader };
package/dist/index.js CHANGED
@@ -94,8 +94,12 @@ var AuraError = class _AuraError extends Error {
94
94
  this.code = "SESSION_REVOKED";
95
95
  } else if (status === 401 && lowerMsg.includes("expired")) {
96
96
  this.code = "SESSION_EXPIRED";
97
- } else if (status === 400 && lowerMsg.includes("password")) {
97
+ } else if (status === 400 && (lowerMsg.includes("current password") || lowerMsg.includes("old password") || lowerMsg.includes("password") && lowerMsg.includes("required"))) {
98
+ this.code = lowerMsg.includes("incorrect") || lowerMsg.includes("invalid") ? "INVALID_CURRENT_PASSWORD" : "CURRENT_PASSWORD_REQUIRED";
99
+ } else if (status === 400 && lowerMsg.includes("password") && (lowerMsg.includes("weak") || lowerMsg.includes("length") || lowerMsg.includes("strength") || lowerMsg.includes("character") || lowerMsg.includes("digit") || lowerMsg.includes("pwned") || lowerMsg.includes("too short") || lowerMsg.includes("too common"))) {
98
100
  this.code = "WEAK_PASSWORD";
101
+ } else if (status === 400 && lowerMsg.includes("password")) {
102
+ this.code = "INVALID_PASSWORD";
99
103
  } else if (status === 409 && (lowerMsg.includes("already exists") || lowerMsg.includes("already in use") || lowerMsg.includes("email"))) {
100
104
  this.code = "EMAIL_ALREADY_IN_USE";
101
105
  } else if (status === 404 && lowerMsg.includes("user not found")) {
@@ -277,6 +281,33 @@ var AUTH_SETTINGS_WRITABLE_FIELDS = [
277
281
  "hook_secret"
278
282
  ];
279
283
 
284
+ // src/cookie-utils.ts
285
+ function parseCookieHeader(header) {
286
+ const result = {};
287
+ if (!header) return result;
288
+ for (const pair of header.split(";")) {
289
+ const idx = pair.indexOf("=");
290
+ if (idx === -1) continue;
291
+ const key = pair.slice(0, idx).trim();
292
+ const value = pair.slice(idx + 1).trim();
293
+ if (key) result[key] = decodeURIComponent(value);
294
+ }
295
+ return result;
296
+ }
297
+ function sameSiteAttribute(v) {
298
+ return v.charAt(0).toUpperCase() + v.slice(1);
299
+ }
300
+ function serializeCookieHeader(name, value, options = {}) {
301
+ const parts = [`${name}=${encodeURIComponent(value)}`];
302
+ if (options.path) parts.push(`Path=${options.path}`);
303
+ if (options.domain) parts.push(`Domain=${options.domain}`);
304
+ if (options.maxAge !== void 0) parts.push(`Max-Age=${options.maxAge}`);
305
+ if (options.secure) parts.push("Secure");
306
+ if (options.sameSite) parts.push(`SameSite=${sameSiteAttribute(options.sameSite)}`);
307
+ if (options.httpOnly) parts.push("HttpOnly");
308
+ return parts.join("; ");
309
+ }
310
+
280
311
  // src/stores/BaseAuthStore.ts
281
312
  function decodeJwtPayload(token) {
282
313
  try {
@@ -321,6 +352,7 @@ var BaseAuthStore = class {
321
352
  * le flux PKCE : le `code_verifier` doit survivre au redirect OAuth.
322
353
  */
323
354
  persistent = false;
355
+ key;
324
356
  _token = null;
325
357
  _refreshToken = null;
326
358
  _user = null;
@@ -331,6 +363,9 @@ var BaseAuthStore = class {
331
363
  /** Hook d'observabilité (LOT 3) — câblé par `AuraClient` via `setObservabilityHook`. */
332
364
  _onEvent;
333
365
  _debug = false;
366
+ constructor(key = "aura-auth") {
367
+ this.key = key;
368
+ }
334
369
  // -- Getters ----------------------------------------------------------------
335
370
  /** Compteur incrémenté à chaque `clear()` — sert au commit-guard anti-race du refresh. */
336
371
  get removalEpoch() {
@@ -392,6 +427,43 @@ var BaseAuthStore = class {
392
427
  _emitStorageBlocked(op) {
393
428
  emitAuraEvent(this._onEvent, this._debug, { kind: "storage-blocked", op });
394
429
  }
430
+ /**
431
+ * Populate the store from a raw `Cookie` header string (server-side).
432
+ * Looks for the key matching `this.key`.
433
+ */
434
+ loadFromCookie(cookieString) {
435
+ const prefix = `${this.key}=`;
436
+ const entry = cookieString.split(";").map((c) => c.trim()).find((c) => c.startsWith(prefix));
437
+ if (!entry) return;
438
+ try {
439
+ const raw = decodeURIComponent(entry.slice(prefix.length));
440
+ const parsed = JSON.parse(raw);
441
+ const user = parsed.token ? userFromAccessToken(parsed.token) : null;
442
+ if (parsed.token && parsed.refreshToken && user) {
443
+ this.save(parsed.token, parsed.refreshToken, user);
444
+ }
445
+ } catch {
446
+ }
447
+ }
448
+ /**
449
+ * Serialize the session tokens into a `Set-Cookie` value. The `user` object is NOT included: its
450
+ * `user_metadata` is already inside the access token.
451
+ */
452
+ exportToCookie(options = {}) {
453
+ const data = {
454
+ token: this.token,
455
+ refreshToken: this.refreshToken
456
+ };
457
+ const encoded = encodeURIComponent(JSON.stringify(data));
458
+ const parts = [`${this.key}=${encoded}`];
459
+ if (options.path) parts.push(`Path=${options.path}`);
460
+ if (options.domain) parts.push(`Domain=${options.domain}`);
461
+ if (options.maxAge !== void 0) parts.push(`Max-Age=${options.maxAge}`);
462
+ if (options.secure) parts.push("Secure");
463
+ if (options.sameSite) parts.push(`SameSite=${sameSiteAttribute(options.sameSite)}`);
464
+ if (options.httpOnly) parts.push("HttpOnly");
465
+ return parts.join("; ");
466
+ }
395
467
  // -- Event emitter ----------------------------------------------------------
396
468
  /**
397
469
  * Register a callback that fires whenever the auth state changes.
@@ -886,45 +958,16 @@ var BaseService = class {
886
958
  }
887
959
  };
888
960
 
889
- // src/cookie-utils.ts
890
- function parseCookieHeader(header) {
891
- const result = {};
892
- if (!header) return result;
893
- for (const pair of header.split(";")) {
894
- const idx = pair.indexOf("=");
895
- if (idx === -1) continue;
896
- const key = pair.slice(0, idx).trim();
897
- const value = pair.slice(idx + 1).trim();
898
- if (key) result[key] = decodeURIComponent(value);
899
- }
900
- return result;
901
- }
902
- function sameSiteAttribute(v) {
903
- return v.charAt(0).toUpperCase() + v.slice(1);
904
- }
905
- function serializeCookieHeader(name, value, options = {}) {
906
- const parts = [`${name}=${encodeURIComponent(value)}`];
907
- if (options.path) parts.push(`Path=${options.path}`);
908
- if (options.domain) parts.push(`Domain=${options.domain}`);
909
- if (options.maxAge !== void 0) parts.push(`Max-Age=${options.maxAge}`);
910
- if (options.secure) parts.push("Secure");
911
- if (options.sameSite) parts.push(`SameSite=${sameSiteAttribute(options.sameSite)}`);
912
- if (options.httpOnly) parts.push("HttpOnly");
913
- return parts.join("; ");
914
- }
915
-
916
961
  // src/stores/LocalAuthStore.ts
917
962
  var LocalAuthStore = class extends BaseAuthStore {
918
963
  /** Persiste en localStorage → survit au redirect pleine page (cf. PKCE). */
919
964
  persistent = true;
920
- key;
921
965
  /**
922
966
  * @param key Nom de l'entrée `localStorage` (et du cookie SSR). Scopez-le par projet :
923
967
  * `aura-${clientScope(baseUrl)}-auth`.
924
968
  */
925
969
  constructor(key) {
926
- super();
927
- this.key = key;
970
+ super(key);
928
971
  this._loadFromStorage();
929
972
  }
930
973
  // -- Overrides --------------------------------------------------------------
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aurabase/core",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "description": "Cœur du SDK Aurabase : fetch résilient, erreurs, stores auth, types de réponse (infrastructure interne)",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",