@ttt-productions/auth-core 1.6.17 → 1.6.18

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.
@@ -1 +1 @@
1
- {"version":3,"file":"claims.js","sourceRoot":"","sources":["../../src/client/claims.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAiB;IACtD,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC/C,IAAI,IAAI,CAAC,aAAa,KAAK,IAAI,IAAI,GAAG,CAAC,MAAM,CAAC,cAAc,KAAK,IAAI,EAAE,CAAC;QACtE,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAChD,OAAO,KAAK,CAAC,MAAM,CAAC;IACtB,CAAC;IACD,OAAO,GAAG,CAAC,MAAM,CAAC;AACpB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAiB;IACnD,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAC9C,OAAO,GAAG,CAAC,MAAM,CAAC;AACpB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,IAAU;IACpD,OAAO,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAwC;IAClE,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,EAAE,CAAkB,CAAC;IAE5C,MAAM,UAAU,GAAI,GAAW,CAAC,KAAK,CAAC;IACtC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC;QACrC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC;QACjD,CAAC,CAAC,OAAO,UAAU,KAAK,QAAQ;YAC9B,CAAC,CAAC,CAAC,UAAU,CAAC;YACd,CAAC,CAAC,EAAE,CAAC;IAET,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;AACxB,CAAC","sourcesContent":["import type { Auth, User, IdTokenResult } from 'firebase/auth';\n\nexport type IdTokenClaims = IdTokenResult['claims'];\n\nexport type ParsedClaims = {\n roles: string[];\n raw: IdTokenClaims;\n};\n\nexport async function getIdTokenClaims(user: User | null): Promise<IdTokenClaims | null> {\n if (!user) return null;\n const res = await user.getIdTokenResult(false);\n if (user.emailVerified === true && res.claims.email_verified !== true) {\n const fresh = await user.getIdTokenResult(true);\n return fresh.claims;\n }\n return res.claims;\n}\n\nexport async function refreshClaims(user: User | null): Promise<IdTokenClaims | null> {\n if (!user) return null;\n const res = await user.getIdTokenResult(true);\n return res.claims;\n}\n\nexport async function refreshClaimsFromAuth(auth: Auth): Promise<IdTokenClaims | null> {\n return refreshClaims(auth.currentUser);\n}\n\nexport function parseClaims(claims: IdTokenClaims | null | undefined): ParsedClaims {\n const raw = (claims ?? {}) as IdTokenClaims;\n\n const rolesValue = (raw as any).roles;\n const roles = Array.isArray(rolesValue)\n ? rolesValue.filter((x) => typeof x === 'string')\n : typeof rolesValue === 'string'\n ? [rolesValue]\n : [];\n\n return { roles, raw };\n}\n"]}
1
+ {"version":3,"file":"claims.js","sourceRoot":"","sources":["../../src/client/claims.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAiB;IACtD,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC/C,IAAI,IAAI,CAAC,aAAa,KAAK,IAAI,IAAI,GAAG,CAAC,MAAM,CAAC,cAAc,KAAK,IAAI,EAAE,CAAC;QACtE,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAChD,OAAO,KAAK,CAAC,MAAM,CAAC;IACtB,CAAC;IACD,OAAO,GAAG,CAAC,MAAM,CAAC;AACpB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAiB;IACnD,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAC9C,OAAO,GAAG,CAAC,MAAM,CAAC;AACpB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,IAAU;IACpD,OAAO,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAwC;IAClE,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,EAAE,CAAkB,CAAC;IAE5C,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC;IAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC;QACrC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC;QACjD,CAAC,CAAC,OAAO,UAAU,KAAK,QAAQ;YAC9B,CAAC,CAAC,CAAC,UAAU,CAAC;YACd,CAAC,CAAC,EAAE,CAAC;IAET,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;AACxB,CAAC","sourcesContent":["import type { Auth, User, IdTokenResult } from 'firebase/auth';\n\nexport type IdTokenClaims = IdTokenResult['claims'];\n\nexport type ParsedClaims = {\n roles: string[];\n raw: IdTokenClaims;\n};\n\nexport async function getIdTokenClaims(user: User | null): Promise<IdTokenClaims | null> {\n if (!user) return null;\n const res = await user.getIdTokenResult(false);\n if (user.emailVerified === true && res.claims.email_verified !== true) {\n const fresh = await user.getIdTokenResult(true);\n return fresh.claims;\n }\n return res.claims;\n}\n\nexport async function refreshClaims(user: User | null): Promise<IdTokenClaims | null> {\n if (!user) return null;\n const res = await user.getIdTokenResult(true);\n return res.claims;\n}\n\nexport async function refreshClaimsFromAuth(auth: Auth): Promise<IdTokenClaims | null> {\n return refreshClaims(auth.currentUser);\n}\n\nexport function parseClaims(claims: IdTokenClaims | null | undefined): ParsedClaims {\n const raw = (claims ?? {}) as IdTokenClaims;\n\n const rolesValue = raw.roles;\n const roles = Array.isArray(rolesValue)\n ? rolesValue.filter((x) => typeof x === 'string')\n : typeof rolesValue === 'string'\n ? [rolesValue]\n : [];\n\n return { roles, raw };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GACrB,cAAc,GACd,oBAAoB,GACpB,wBAAwB,GACxB,mBAAmB,GACnB,oBAAoB,GACpB,gBAAgB,GAChB,oBAAoB,GACpB,qBAAqB,GACrB,qBAAqB,GACrB,oBAAoB,GACpB,2BAA2B,GAC3B,oBAAoB,GACpB,4BAA4B,GAC5B,yBAAyB,GACzB,+CAA+C,GAC/C,8BAA8B,GAC9B,gCAAgC,GAChC,0BAA0B,GAC1B,0BAA0B,CAAC;AAE/B,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC,CAAC;AAqFF,eAAO,MAAM,0BAA0B,4CAA4C,CAAC;AAEpF,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,OAAO,EACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,mBAAmB,CAoBrB;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEtD"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GACrB,cAAc,GACd,oBAAoB,GACpB,wBAAwB,GACxB,mBAAmB,GACnB,oBAAoB,GACpB,gBAAgB,GAChB,oBAAoB,GACpB,qBAAqB,GACrB,qBAAqB,GACrB,oBAAoB,GACpB,2BAA2B,GAC3B,oBAAoB,GACpB,4BAA4B,GAC5B,yBAAyB,GACzB,+CAA+C,GAC/C,8BAA8B,GAC9B,gCAAgC,GAChC,0BAA0B,GAC1B,0BAA0B,CAAC;AAE/B,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC,CAAC;AAoFF,eAAO,MAAM,0BAA0B,4CAA4C,CAAC;AAEpF,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,OAAO,EACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,mBAAmB,CAoBrB;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEtD"}
package/dist/errors.js CHANGED
@@ -1,8 +1,7 @@
1
1
  function pickFirebaseCode(err) {
2
2
  if (!err || typeof err !== 'object')
3
3
  return undefined;
4
- const anyErr = err;
5
- const c = anyErr.code;
4
+ const c = err.code;
6
5
  return typeof c === 'string' ? c : undefined;
7
6
  }
8
7
  const MAP = {
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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","sourcesContent":["export type AuthErrorCode =\n | 'AUTH_UNKNOWN'\n | 'AUTH_NETWORK_ERROR'\n | 'AUTH_TOO_MANY_REQUESTS'\n | 'AUTH_POPUP_CLOSED'\n | 'AUTH_POPUP_BLOCKED'\n | 'AUTH_CANCELLED'\n | 'AUTH_USER_DISABLED'\n | 'AUTH_USER_NOT_FOUND'\n | 'AUTH_WRONG_PASSWORD'\n | 'AUTH_INVALID_EMAIL'\n | 'AUTH_EMAIL_ALREADY_IN_USE'\n | 'AUTH_WEAK_PASSWORD'\n | 'AUTH_REQUIRES_RECENT_LOGIN'\n | 'AUTH_INVALID_CREDENTIAL'\n | 'AUTH_ACCOUNT_EXISTS_WITH_DIFFERENT_CREDENTIAL'\n | 'AUTH_PROVIDER_ALREADY_LINKED'\n | 'AUTH_CREDENTIAL_ALREADY_IN_USE'\n | 'AUTH_EXPIRED_ACTION_CODE'\n | 'AUTH_INVALID_ACTION_CODE';\n\nexport type NormalizedAuthError = {\n code: AuthErrorCode;\n message: string;\n firebaseCode?: string;\n details?: Record<string, unknown>;\n};\n\nfunction pickFirebaseCode(err: unknown): string | undefined {\n if (!err || typeof err !== 'object') return undefined;\n const anyErr = err as any;\n const c = anyErr.code;\n return typeof c === 'string' ? c : undefined;\n}\n\nconst MAP: Record<string, { code: AuthErrorCode; message: string }> = {\n 'auth/network-request-failed': {\n code: 'AUTH_NETWORK_ERROR',\n message: 'Network error. Please check your connection and try again.',\n },\n 'auth/too-many-requests': {\n code: 'AUTH_TOO_MANY_REQUESTS',\n message: 'Too many attempts. Please wait a moment and try again.',\n },\n 'auth/popup-closed-by-user': {\n code: 'AUTH_POPUP_CLOSED',\n message: 'Sign-in popup was closed.',\n },\n 'auth/popup-blocked': {\n code: 'AUTH_POPUP_BLOCKED',\n message: 'Sign-in popup was blocked by the browser.',\n },\n 'auth/cancelled-popup-request': {\n code: 'AUTH_CANCELLED',\n message: 'Sign-in was cancelled.',\n },\n 'auth/user-disabled': {\n code: 'AUTH_USER_DISABLED',\n message: 'This account has been disabled.',\n },\n 'auth/user-not-found': {\n code: 'AUTH_USER_NOT_FOUND',\n message: 'No account found with that email.',\n },\n 'auth/wrong-password': {\n code: 'AUTH_WRONG_PASSWORD',\n message: 'Incorrect password.',\n },\n 'auth/invalid-email': {\n code: 'AUTH_INVALID_EMAIL',\n message: 'Invalid email address.',\n },\n 'auth/email-already-in-use': {\n code: 'AUTH_EMAIL_ALREADY_IN_USE',\n message: 'That email is already in use.',\n },\n 'auth/weak-password': {\n code: 'AUTH_WEAK_PASSWORD',\n message: 'Password is too weak.',\n },\n 'auth/requires-recent-login': {\n code: 'AUTH_REQUIRES_RECENT_LOGIN',\n message: 'Please re-authenticate and try again.',\n },\n 'auth/invalid-credential': {\n code: 'AUTH_INVALID_CREDENTIAL',\n message: 'Invalid credentials. Please try again.',\n },\n 'auth/account-exists-with-different-credential': {\n code: 'AUTH_ACCOUNT_EXISTS_WITH_DIFFERENT_CREDENTIAL',\n message: 'An account already exists with a different sign-in method.',\n },\n 'auth/provider-already-linked': {\n code: 'AUTH_PROVIDER_ALREADY_LINKED',\n message: 'That provider is already linked to this account.',\n },\n 'auth/credential-already-in-use': {\n code: 'AUTH_CREDENTIAL_ALREADY_IN_USE',\n message: 'Those credentials are already associated with another account.',\n },\n 'auth/expired-action-code': {\n code: 'AUTH_EXPIRED_ACTION_CODE',\n message: 'This email action link has expired. Request a new link and try again.',\n },\n 'auth/invalid-action-code': {\n code: 'AUTH_INVALID_ACTION_CODE',\n message:\n 'This email action link is invalid or has already been used. Request a new link and try again.',\n },\n};\n\nexport const UNKNOWN_AUTH_ERROR_MESSAGE = 'Authentication error. Please try again.';\n\nexport function normalizeAuthError(\n err: unknown,\n details?: Record<string, unknown>,\n): NormalizedAuthError {\n const firebaseCode = pickFirebaseCode(err);\n\n const mapped = firebaseCode ? MAP[firebaseCode] : undefined;\n if (mapped) {\n return {\n code: mapped.code,\n message: mapped.message,\n firebaseCode,\n details,\n };\n }\n\n // Never the error's own message: for an unclassified failure it is the SDK's internal diagnostic.\n return {\n code: 'AUTH_UNKNOWN',\n message: UNKNOWN_AUTH_ERROR_MESSAGE,\n firebaseCode,\n details,\n };\n}\n\nexport function getErrorMessage(error: unknown): string {\n return normalizeAuthError(error).message;\n}\n"]}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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","sourcesContent":["export type AuthErrorCode =\n | 'AUTH_UNKNOWN'\n | 'AUTH_NETWORK_ERROR'\n | 'AUTH_TOO_MANY_REQUESTS'\n | 'AUTH_POPUP_CLOSED'\n | 'AUTH_POPUP_BLOCKED'\n | 'AUTH_CANCELLED'\n | 'AUTH_USER_DISABLED'\n | 'AUTH_USER_NOT_FOUND'\n | 'AUTH_WRONG_PASSWORD'\n | 'AUTH_INVALID_EMAIL'\n | 'AUTH_EMAIL_ALREADY_IN_USE'\n | 'AUTH_WEAK_PASSWORD'\n | 'AUTH_REQUIRES_RECENT_LOGIN'\n | 'AUTH_INVALID_CREDENTIAL'\n | 'AUTH_ACCOUNT_EXISTS_WITH_DIFFERENT_CREDENTIAL'\n | 'AUTH_PROVIDER_ALREADY_LINKED'\n | 'AUTH_CREDENTIAL_ALREADY_IN_USE'\n | 'AUTH_EXPIRED_ACTION_CODE'\n | 'AUTH_INVALID_ACTION_CODE';\n\nexport type NormalizedAuthError = {\n code: AuthErrorCode;\n message: string;\n firebaseCode?: string;\n details?: Record<string, unknown>;\n};\n\nfunction pickFirebaseCode(err: unknown): string | undefined {\n if (!err || typeof err !== 'object') return undefined;\n const c = (err as { code?: unknown }).code;\n return typeof c === 'string' ? c : undefined;\n}\n\nconst MAP: Record<string, { code: AuthErrorCode; message: string }> = {\n 'auth/network-request-failed': {\n code: 'AUTH_NETWORK_ERROR',\n message: 'Network error. Please check your connection and try again.',\n },\n 'auth/too-many-requests': {\n code: 'AUTH_TOO_MANY_REQUESTS',\n message: 'Too many attempts. Please wait a moment and try again.',\n },\n 'auth/popup-closed-by-user': {\n code: 'AUTH_POPUP_CLOSED',\n message: 'Sign-in popup was closed.',\n },\n 'auth/popup-blocked': {\n code: 'AUTH_POPUP_BLOCKED',\n message: 'Sign-in popup was blocked by the browser.',\n },\n 'auth/cancelled-popup-request': {\n code: 'AUTH_CANCELLED',\n message: 'Sign-in was cancelled.',\n },\n 'auth/user-disabled': {\n code: 'AUTH_USER_DISABLED',\n message: 'This account has been disabled.',\n },\n 'auth/user-not-found': {\n code: 'AUTH_USER_NOT_FOUND',\n message: 'No account found with that email.',\n },\n 'auth/wrong-password': {\n code: 'AUTH_WRONG_PASSWORD',\n message: 'Incorrect password.',\n },\n 'auth/invalid-email': {\n code: 'AUTH_INVALID_EMAIL',\n message: 'Invalid email address.',\n },\n 'auth/email-already-in-use': {\n code: 'AUTH_EMAIL_ALREADY_IN_USE',\n message: 'That email is already in use.',\n },\n 'auth/weak-password': {\n code: 'AUTH_WEAK_PASSWORD',\n message: 'Password is too weak.',\n },\n 'auth/requires-recent-login': {\n code: 'AUTH_REQUIRES_RECENT_LOGIN',\n message: 'Please re-authenticate and try again.',\n },\n 'auth/invalid-credential': {\n code: 'AUTH_INVALID_CREDENTIAL',\n message: 'Invalid credentials. Please try again.',\n },\n 'auth/account-exists-with-different-credential': {\n code: 'AUTH_ACCOUNT_EXISTS_WITH_DIFFERENT_CREDENTIAL',\n message: 'An account already exists with a different sign-in method.',\n },\n 'auth/provider-already-linked': {\n code: 'AUTH_PROVIDER_ALREADY_LINKED',\n message: 'That provider is already linked to this account.',\n },\n 'auth/credential-already-in-use': {\n code: 'AUTH_CREDENTIAL_ALREADY_IN_USE',\n message: 'Those credentials are already associated with another account.',\n },\n 'auth/expired-action-code': {\n code: 'AUTH_EXPIRED_ACTION_CODE',\n message: 'This email action link has expired. Request a new link and try again.',\n },\n 'auth/invalid-action-code': {\n code: 'AUTH_INVALID_ACTION_CODE',\n message:\n 'This email action link is invalid or has already been used. Request a new link and try again.',\n },\n};\n\nexport const UNKNOWN_AUTH_ERROR_MESSAGE = 'Authentication error. Please try again.';\n\nexport function normalizeAuthError(\n err: unknown,\n details?: Record<string, unknown>,\n): NormalizedAuthError {\n const firebaseCode = pickFirebaseCode(err);\n\n const mapped = firebaseCode ? MAP[firebaseCode] : undefined;\n if (mapped) {\n return {\n code: mapped.code,\n message: mapped.message,\n firebaseCode,\n details,\n };\n }\n\n // Never the error's own message: for an unclassified failure it is the SDK's internal diagnostic.\n return {\n code: 'AUTH_UNKNOWN',\n message: UNKNOWN_AUTH_ERROR_MESSAGE,\n firebaseCode,\n details,\n };\n}\n\nexport function getErrorMessage(error: unknown): string {\n return normalizeAuthError(error).message;\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import { type ReactNode } from 'react';
2
2
  import type { AuthProviderConfig, AuthContextValue } from './types.js';
3
- export declare const AuthContext: import("react").Context<AuthContextValue<any> | null>;
3
+ export declare const AuthContext: import("react").Context<AuthContextValue<unknown> | null>;
4
4
  interface AuthProviderProps<TClaims> {
5
5
  config: AuthProviderConfig<TClaims>;
6
6
  children: ReactNode;
@@ -1 +1 @@
1
- {"version":3,"file":"AuthProvider.d.ts","sourceRoot":"","sources":["../../src/react/AuthProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAQvE,eAAO,MAAM,WAAW,uDAAoD,CAAC;AAE7E,UAAU,iBAAiB,CAAC,OAAO;IACjC,MAAM,EAAE,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACpC,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,YAAY,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAC9D,MAAM,EACN,QAAQ,GACT,EAAE,iBAAiB,CAAC,OAAO,CAAC,+BAwG5B"}
1
+ {"version":3,"file":"AuthProvider.d.ts","sourceRoot":"","sources":["../../src/react/AuthProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAQvE,eAAO,MAAM,WAAW,2DAAwD,CAAC;AAEjF,UAAU,iBAAiB,CAAC,OAAO;IACjC,MAAM,EAAE,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACpC,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,YAAY,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAC9D,MAAM,EACN,QAAQ,GACT,EAAE,iBAAiB,CAAC,OAAO,CAAC,+BAwG5B"}
@@ -1 +1 @@
1
- {"version":3,"file":"AuthProvider.js","sourceRoot":"","sources":["../../src/react/AuthProvider.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EACL,aAAa,EACb,SAAS,EACT,MAAM,EACN,QAAQ,EACR,WAAW,EACX,OAAO,GAER,MAAM,OAAO,CAAC;AAEf,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AASvD,MAAM,CAAC,MAAM,WAAW,GAAG,aAAa,CAA+B,IAAI,CAAC,CAAC;AAO7E,MAAM,UAAU,YAAY,CAAoC,EAC9D,MAAM,EACN,QAAQ,GACmB;IAC3B,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAEjE,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAiC,IAAI,CAAC,CAAC;IAC/E,MAAM,aAAa,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAChC,MAAM,oBAAoB,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACvC,MAAM,cAAc,GAAG,MAAM,CAAc,IAAI,CAAC,CAAC;IACjD,cAAc,CAAC,OAAO,GAAG,IAAI,CAAC;IAE9B,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACjC,SAAS,CAAC,OAAO,GAAG,MAAM,CAAC;IAE3B,MAAM,UAAU,GAAG,WAAW,CAC5B,KAAK,EAAE,OAAa,EAAE,IAAmD,EAAE,OAAe,EAAE,EAAE;QAC5F,MAAM,UAAU,GAAG,EAAE,aAAa,CAAC,OAAO,CAAC;QAC3C,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,EAAE,CAAC;YACzB,IAAI,cAAc,CAAC,OAAO,KAAK,OAAO,IAAI,UAAU,IAAI,oBAAoB,CAAC,OAAO;gBAClF,OAAO;YACT,oBAAoB,CAAC,OAAO,GAAG,UAAU,CAAC;YAC1C,WAAW,CAAC;gBACV,IAAI,EAAE,OAAO;gBACb,UAAU;gBACV,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI,EAAE,CAAC;aACjD,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,cAAc,CAAC,OAAO,KAAK,OAAO;gBAAE,OAAO;YAC/C,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YAC1C,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CACnB,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO;gBAC3B,CAAC,CAAC,IAAI;gBACN,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,aAAa,EAAE,CAC3E,CAAC;QACJ,CAAC;IACH,CAAC,EACD,EAAE,CACH,CAAC;IAEF,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAClE,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC;QACzC,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,OAAO,CAAC,OAAO,EAAE;aACd,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC;aAClB,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;aAC7D,OAAO,CAAC,GAAG,EAAE;YACZ,IAAI,CAAC,SAAS;gBAAE,WAAW,CAAC,IAAI,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QACL,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,WAAW;YAAE,OAAO;QAExB,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,WAAW,CAAC,IAAI,CAAC,CAAC;YAClB,SAAS,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC,IAAI,CAAC,CAAC;YAC5C,OAAO;QACT,CAAC;QAED,SAAS,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC,IAAI,CAAC,CAAC;QAC5C,KAAK,UAAU,CACb,IAAI,EACJ,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAA4B,EAC7E,kBAAkB,CACnB,CAAC;IACJ,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC;IAEpC,MAAM,aAAa,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAC3C,2GAA2G;QAC3G,MAAM,QAAQ,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC;QACpD,IAAI,CAAC,QAAQ;YAAE,OAAO;QACtB,MAAM,UAAU,CACd,QAAQ,EACR,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAA4B,EAC7F,eAAe,CAChB,CAAC;IACJ,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IAEjB,MAAM,aAAa,GAAG,IAAI,IAAI,QAAQ,EAAE,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;IACxE,MAAM,aAAa,GAAG,WAAW,IAAI,CAAC,IAAI,KAAK,IAAI,IAAI,aAAa,KAAK,IAAI,CAAC,CAAC;IAE/E,MAAM,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3C,MAAM,MAAM,GAAG,WAAW,IAAI,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC;IAE1F,MAAM,OAAO,GAAG,WAAW,IAAI,aAAa,IAAI,CAAC,QAAQ,CAAC;IAE1D,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE,CAAC,CAAC;QACL,IAAI,EAAE,WAAW;QACjB,MAAM;QACN,OAAO;QACP,WAAW;QACX,aAAa;QACb,eAAe,EAAE,CAAC,CAAC,WAAW;QAC9B,aAAa;KACd,CAAC,EACF,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,CAAC,CAC1E,CAAC;IAEF,OAAO,KAAC,WAAW,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAAG,QAAQ,GAAwB,CAAC;AAC/E,CAAC","sourcesContent":["'use client';\n\nimport {\n createContext,\n useEffect,\n useRef,\n useState,\n useCallback,\n useMemo,\n type ReactNode,\n} from 'react';\nimport type { User } from 'firebase/auth';\nimport { useAuthState } from './useAuthState.js';\nimport { getIdTokenClaims } from '../client/claims.js';\nimport type { AuthProviderConfig, AuthContextValue } from './types.js';\n\ninterface ResolvedClaims<TClaims> {\n user: User;\n generation: number;\n claims: TClaims;\n}\n\nexport const AuthContext = createContext<AuthContextValue<any> | null>(null);\n\ninterface AuthProviderProps<TClaims> {\n config: AuthProviderConfig<TClaims>;\n children: ReactNode;\n}\n\nexport function AuthProvider<TClaims = Record<string, unknown>>({\n config,\n children,\n}: AuthProviderProps<TClaims>) {\n const { user, loading: authLoading } = useAuthState(config.auth);\n\n const [resolved, setResolved] = useState<ResolvedClaims<TClaims> | null>(null);\n const generationRef = useRef(0);\n const appliedGenerationRef = useRef(0);\n const currentUserRef = useRef<User | null>(user);\n currentUserRef.current = user;\n\n const configRef = useRef(config);\n configRef.current = config;\n\n const readClaims = useCallback(\n async (forUser: User, read: () => Promise<Record<string, unknown> | null>, context: string) => {\n const generation = ++generationRef.current;\n try {\n const raw = await read();\n if (currentUserRef.current !== forUser || generation <= appliedGenerationRef.current)\n return;\n appliedGenerationRef.current = generation;\n setResolved({\n user: forUser,\n generation,\n claims: configRef.current.parseClaims(raw ?? {}),\n });\n } catch (err) {\n if (currentUserRef.current !== forUser) return;\n configRef.current.onError?.(err, context);\n setResolved((prev) =>\n prev && prev.user === forUser\n ? prev\n : { user: forUser, generation, claims: configRef.current.defaultClaims },\n );\n }\n },\n [],\n );\n\n const [gateOpen, setGateOpen] = useState(() => !config.readyGate);\n useEffect(() => {\n const gate = configRef.current.readyGate;\n if (!gate) return;\n let cancelled = false;\n Promise.resolve()\n .then(() => gate())\n .catch((err) => configRef.current.onError?.(err, 'readyGate'))\n .finally(() => {\n if (!cancelled) setGateOpen(true);\n });\n return () => {\n cancelled = true;\n };\n }, []);\n\n useEffect(() => {\n if (authLoading) return;\n\n if (!user) {\n setResolved(null);\n configRef.current.onAuthStateChange?.(null);\n return;\n }\n\n configRef.current.onAuthStateChange?.(user);\n void readClaims(\n user,\n async () => ((await getIdTokenClaims(user)) ?? {}) as Record<string, unknown>,\n 'getIdTokenClaims',\n );\n }, [user, authLoading, readClaims]);\n\n const refreshClaims = useCallback(async () => {\n // `auth.currentUser`, not this render's user: a caller can hold this callback from before its own sign-in.\n const liveUser = configRef.current.auth.currentUser;\n if (!liveUser) return;\n await readClaims(\n liveUser,\n async () => ((await liveUser.getIdTokenResult(true)).claims ?? {}) as Record<string, unknown>,\n 'refreshClaims',\n );\n }, [readClaims]);\n\n const sessionClaims = user && resolved?.user === user ? resolved : null;\n const claimsLoading = authLoading || (user !== null && sessionClaims === null);\n\n const exposedUser = gateOpen ? user : null;\n const claims = exposedUser && sessionClaims ? sessionClaims.claims : config.defaultClaims;\n\n const loading = authLoading || claimsLoading || !gateOpen;\n\n const value = useMemo<AuthContextValue<TClaims>>(\n () => ({\n user: exposedUser,\n claims,\n loading,\n authLoading,\n claimsLoading,\n isAuthenticated: !!exposedUser,\n refreshClaims,\n }),\n [exposedUser, claims, loading, authLoading, claimsLoading, refreshClaims],\n );\n\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\n}\n"]}
1
+ {"version":3,"file":"AuthProvider.js","sourceRoot":"","sources":["../../src/react/AuthProvider.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport {\n createContext,\n useEffect,\n useRef,\n useState,\n useCallback,\n useMemo,\n type ReactNode,\n} from 'react';\nimport type { User } from 'firebase/auth';\nimport { useAuthState } from './useAuthState.js';\nimport { getIdTokenClaims } from '../client/claims.js';\nimport type { AuthProviderConfig, AuthContextValue } from './types.js';\n\ninterface ResolvedClaims<TClaims> {\n user: User;\n generation: number;\n claims: TClaims;\n}\n\nexport const AuthContext = createContext<AuthContextValue<unknown> | null>(null);\n\ninterface AuthProviderProps<TClaims> {\n config: AuthProviderConfig<TClaims>;\n children: ReactNode;\n}\n\nexport function AuthProvider<TClaims = Record<string, unknown>>({\n config,\n children,\n}: AuthProviderProps<TClaims>) {\n const { user, loading: authLoading } = useAuthState(config.auth);\n\n const [resolved, setResolved] = useState<ResolvedClaims<TClaims> | null>(null);\n const generationRef = useRef(0);\n const appliedGenerationRef = useRef(0);\n const currentUserRef = useRef<User | null>(user);\n currentUserRef.current = user;\n\n const configRef = useRef(config);\n configRef.current = config;\n\n const readClaims = useCallback(\n async (forUser: User, read: () => Promise<Record<string, unknown> | null>, context: string) => {\n const generation = ++generationRef.current;\n try {\n const raw = await read();\n if (currentUserRef.current !== forUser || generation <= appliedGenerationRef.current)\n return;\n appliedGenerationRef.current = generation;\n setResolved({\n user: forUser,\n generation,\n claims: configRef.current.parseClaims(raw ?? {}),\n });\n } catch (err) {\n if (currentUserRef.current !== forUser) return;\n configRef.current.onError?.(err, context);\n setResolved((prev) =>\n prev && prev.user === forUser\n ? prev\n : { user: forUser, generation, claims: configRef.current.defaultClaims },\n );\n }\n },\n [],\n );\n\n const [gateOpen, setGateOpen] = useState(() => !config.readyGate);\n useEffect(() => {\n const gate = configRef.current.readyGate;\n if (!gate) return;\n let cancelled = false;\n Promise.resolve()\n .then(() => gate())\n .catch((err) => configRef.current.onError?.(err, 'readyGate'))\n .finally(() => {\n if (!cancelled) setGateOpen(true);\n });\n return () => {\n cancelled = true;\n };\n }, []);\n\n useEffect(() => {\n if (authLoading) return;\n\n if (!user) {\n setResolved(null);\n configRef.current.onAuthStateChange?.(null);\n return;\n }\n\n configRef.current.onAuthStateChange?.(user);\n void readClaims(\n user,\n async () => ((await getIdTokenClaims(user)) ?? {}) as Record<string, unknown>,\n 'getIdTokenClaims',\n );\n }, [user, authLoading, readClaims]);\n\n const refreshClaims = useCallback(async () => {\n // `auth.currentUser`, not this render's user: a caller can hold this callback from before its own sign-in.\n const liveUser = configRef.current.auth.currentUser;\n if (!liveUser) return;\n await readClaims(\n liveUser,\n async () => ((await liveUser.getIdTokenResult(true)).claims ?? {}) as Record<string, unknown>,\n 'refreshClaims',\n );\n }, [readClaims]);\n\n const sessionClaims = user && resolved?.user === user ? resolved : null;\n const claimsLoading = authLoading || (user !== null && sessionClaims === null);\n\n const exposedUser = gateOpen ? user : null;\n const claims = exposedUser && sessionClaims ? sessionClaims.claims : config.defaultClaims;\n\n const loading = authLoading || claimsLoading || !gateOpen;\n\n const value = useMemo<AuthContextValue<TClaims>>(\n () => ({\n user: exposedUser,\n claims,\n loading,\n authLoading,\n claimsLoading,\n isAuthenticated: !!exposedUser,\n refreshClaims,\n }),\n [exposedUser, claims, loading, authLoading, claimsLoading, refreshClaims],\n );\n\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"redirect-storage.d.ts","sourceRoot":"","sources":["../../src/react/redirect-storage.ts"],"names":[],"mappings":"AAgBA,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAO3D;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAWhE;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAMnD"}
1
+ {"version":3,"file":"redirect-storage.d.ts","sourceRoot":"","sources":["../../src/react/redirect-storage.ts"],"names":[],"mappings":"AAoBA,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG3D;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAahE;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAInD"}
@@ -3,36 +3,35 @@ const memory = new Map();
3
3
  function inBrowser() {
4
4
  return typeof window !== 'undefined';
5
5
  }
6
- function storage() {
6
+ function attempt(access) {
7
7
  try {
8
- return window.localStorage;
8
+ return access();
9
9
  }
10
10
  catch {
11
- return null;
11
+ return undefined;
12
12
  }
13
13
  }
14
+ function storage() {
15
+ return attempt(() => window.localStorage);
16
+ }
14
17
  export function readRedirectPath(key) {
15
18
  if (!inBrowser())
16
19
  return null;
17
- try {
18
- const saved = storage()?.getItem(key) ?? null;
19
- if (saved !== null)
20
- return saved;
21
- }
22
- catch { }
23
- return memory.get(key) ?? null;
20
+ return attempt(() => storage()?.getItem(key)) ?? memory.get(key) ?? null;
24
21
  }
25
22
  export function saveRedirectPath(key, path) {
26
23
  if (!inBrowser())
27
24
  return;
28
- const store = storage();
29
- if (store) {
30
- try {
31
- store.setItem(key, path);
32
- memory.delete(key);
33
- return;
34
- }
35
- catch { }
25
+ const stored = attempt(() => {
26
+ const store = storage();
27
+ if (!store)
28
+ return false;
29
+ store.setItem(key, path);
30
+ return true;
31
+ });
32
+ if (stored) {
33
+ memory.delete(key);
34
+ return;
36
35
  }
37
36
  memory.set(key, path);
38
37
  }
@@ -40,9 +39,6 @@ export function clearRedirectPath(key) {
40
39
  if (!inBrowser())
41
40
  return;
42
41
  memory.delete(key);
43
- try {
44
- storage()?.removeItem(key);
45
- }
46
- catch { }
42
+ attempt(() => storage()?.removeItem(key));
47
43
  }
48
44
  //# sourceMappingURL=redirect-storage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"redirect-storage.js","sourceRoot":"","sources":["../../src/react/redirect-storage.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAE/F,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;AAEzC,SAAS,SAAS;IAChB,OAAO,OAAO,MAAM,KAAK,WAAW,CAAC;AACvC,CAAC;AAED,SAAS,OAAO;IACd,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,YAAY,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,IAAI,CAAC,SAAS,EAAE;QAAE,OAAO,IAAI,CAAC;IAC9B,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,OAAO,EAAE,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;QAC9C,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,KAAK,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IACV,OAAO,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAW,EAAE,IAAY;IACxD,IAAI,CAAC,SAAS,EAAE;QAAE,OAAO;IACzB,MAAM,KAAK,GAAG,OAAO,EAAE,CAAC;IACxB,IAAI,KAAK,EAAE,CAAC;QACV,IAAI,CAAC;YACH,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACzB,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACnB,OAAO;QACT,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACZ,CAAC;IACD,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,IAAI,CAAC,SAAS,EAAE;QAAE,OAAO;IACzB,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACnB,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;AACZ,CAAC","sourcesContent":["// A browser that blocks site data throws on the storage access itself (RULE-STD-FRONTEND-010).\n\nconst memory = new Map<string, string>();\n\nfunction inBrowser(): boolean {\n return typeof window !== 'undefined';\n}\n\nfunction storage(): Storage | null {\n try {\n return window.localStorage;\n } catch {\n return null;\n }\n}\n\nexport function readRedirectPath(key: string): string | null {\n if (!inBrowser()) return null;\n try {\n const saved = storage()?.getItem(key) ?? null;\n if (saved !== null) return saved;\n } catch {}\n return memory.get(key) ?? null;\n}\n\nexport function saveRedirectPath(key: string, path: string): void {\n if (!inBrowser()) return;\n const store = storage();\n if (store) {\n try {\n store.setItem(key, path);\n memory.delete(key);\n return;\n } catch {}\n }\n memory.set(key, path);\n}\n\nexport function clearRedirectPath(key: string): void {\n if (!inBrowser()) return;\n memory.delete(key);\n try {\n storage()?.removeItem(key);\n } catch {}\n}\n"]}
1
+ {"version":3,"file":"redirect-storage.js","sourceRoot":"","sources":["../../src/react/redirect-storage.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAE/F,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;AAEzC,SAAS,SAAS;IAChB,OAAO,OAAO,MAAM,KAAK,WAAW,CAAC;AACvC,CAAC;AAED,SAAS,OAAO,CAAI,MAAe;IACjC,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,CAAC;IAClB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,OAAO;IACd,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,IAAI,CAAC,SAAS,EAAE;QAAE,OAAO,IAAI,CAAC;IAC9B,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAW,EAAE,IAAY;IACxD,IAAI,CAAC,SAAS,EAAE;QAAE,OAAO;IACzB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE;QAC1B,MAAM,KAAK,GAAG,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;QACzB,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IACH,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACnB,OAAO;IACT,CAAC;IACD,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,IAAI,CAAC,SAAS,EAAE;QAAE,OAAO;IACzB,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;AAC5C,CAAC","sourcesContent":["// A browser that blocks site data throws on the storage access itself (RULE-STD-FRONTEND-010).\n\nconst memory = new Map<string, string>();\n\nfunction inBrowser(): boolean {\n return typeof window !== 'undefined';\n}\n\nfunction attempt<T>(access: () => T): T | undefined {\n try {\n return access();\n } catch {\n return undefined;\n }\n}\n\nfunction storage(): Storage | undefined {\n return attempt(() => window.localStorage);\n}\n\nexport function readRedirectPath(key: string): string | null {\n if (!inBrowser()) return null;\n return attempt(() => storage()?.getItem(key)) ?? memory.get(key) ?? null;\n}\n\nexport function saveRedirectPath(key: string, path: string): void {\n if (!inBrowser()) return;\n const stored = attempt(() => {\n const store = storage();\n if (!store) return false;\n store.setItem(key, path);\n return true;\n });\n if (stored) {\n memory.delete(key);\n return;\n }\n memory.set(key, path);\n}\n\nexport function clearRedirectPath(key: string): void {\n if (!inBrowser()) return;\n memory.delete(key);\n attempt(() => storage()?.removeItem(key));\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttt-productions/auth-core",
3
- "version": "1.6.17",
3
+ "version": "1.6.18",
4
4
  "description": "Shared Firebase authentication utilities and React hooks for TTT Productions apps",
5
5
  "repository": {
6
6
  "type": "git",