@ttt-productions/auth-core 1.6.14 → 1.6.16

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 (73) hide show
  1. package/dist/acceptance.d.ts.map +1 -1
  2. package/dist/acceptance.js +6 -6
  3. package/dist/acceptance.js.map +1 -1
  4. package/dist/{auth.d.ts → client/auth.d.ts} +1 -1
  5. package/dist/client/auth.d.ts.map +1 -0
  6. package/dist/{auth.js → client/auth.js} +1 -1
  7. package/dist/client/auth.js.map +1 -0
  8. package/dist/{claims.d.ts → client/claims.d.ts} +2 -2
  9. package/dist/client/claims.d.ts.map +1 -0
  10. package/dist/{claims.js → client/claims.js} +5 -3
  11. package/dist/client/claims.js.map +1 -0
  12. package/dist/client/index.d.ts +3 -0
  13. package/dist/client/index.d.ts.map +1 -0
  14. package/dist/{client.js → client/index.js} +3 -2
  15. package/dist/client/index.js.map +1 -0
  16. package/dist/email-verification.js +3 -3
  17. package/dist/email-verification.js.map +1 -1
  18. package/dist/env.d.ts +1 -1
  19. package/dist/env.js +5 -5
  20. package/dist/env.js.map +1 -1
  21. package/dist/errors.d.ts +1 -1
  22. package/dist/errors.d.ts.map +1 -1
  23. package/dist/errors.js +61 -61
  24. package/dist/errors.js.map +1 -1
  25. package/dist/index.d.ts +4 -5
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +6 -7
  28. package/dist/index.js.map +1 -1
  29. package/dist/react/AuthProvider.d.ts +3 -3
  30. package/dist/react/AuthProvider.d.ts.map +1 -1
  31. package/dist/react/AuthProvider.js +25 -15
  32. package/dist/react/AuthProvider.js.map +1 -1
  33. package/dist/react/index.d.ts +8 -8
  34. package/dist/react/index.js +6 -6
  35. package/dist/react/index.js.map +1 -1
  36. package/dist/react/redirect-storage.js +1 -1
  37. package/dist/react/redirect-storage.js.map +1 -1
  38. package/dist/react/types.d.ts +4 -2
  39. package/dist/react/types.d.ts.map +1 -1
  40. package/dist/react/types.js.map +1 -1
  41. package/dist/react/useAuth.d.ts +1 -1
  42. package/dist/react/useAuth.js +4 -4
  43. package/dist/react/useAuth.js.map +1 -1
  44. package/dist/react/useAuthGuard.js +5 -5
  45. package/dist/react/useAuthGuard.js.map +1 -1
  46. package/dist/react/useAuthState.d.ts +1 -1
  47. package/dist/react/useAuthState.js +2 -2
  48. package/dist/react/useAuthState.js.map +1 -1
  49. package/dist/refusal.d.ts.map +1 -1
  50. package/dist/refusal.js +6 -4
  51. package/dist/refusal.js.map +1 -1
  52. package/dist/server/assertAuth.d.ts +1 -1
  53. package/dist/server/assertAuth.d.ts.map +1 -1
  54. package/dist/server/assertAuth.js +13 -16
  55. package/dist/server/assertAuth.js.map +1 -1
  56. package/dist/server/authError.d.ts +3 -3
  57. package/dist/server/authError.d.ts.map +1 -1
  58. package/dist/server/authError.js +1 -1
  59. package/dist/server/authError.js.map +1 -1
  60. package/dist/server/index.d.ts +4 -4
  61. package/dist/server/index.js +2 -2
  62. package/dist/server/index.js.map +1 -1
  63. package/dist/server/types.d.ts +4 -4
  64. package/dist/server/types.d.ts.map +1 -1
  65. package/dist/server/types.js.map +1 -1
  66. package/package.json +3 -3
  67. package/dist/auth.d.ts.map +0 -1
  68. package/dist/auth.js.map +0 -1
  69. package/dist/claims.d.ts.map +0 -1
  70. package/dist/claims.js.map +0 -1
  71. package/dist/client.d.ts +0 -2
  72. package/dist/client.d.ts.map +0 -1
  73. package/dist/client.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"authError.js","sourceRoot":"","sources":["../../src/server/authError.ts"],"names":[],"mappings":"AA2DA,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAClC,IAAI,CAAyB;IAC7B,OAAO,CAA6B;IAE7C,YAAY,IAA4B,EAAE,OAAe,EAAE,OAAmC;QAC5F,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,OAAO,KAAK,SAAS;YAAE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACpD,CAAC;CACF","sourcesContent":["import type { AcceptanceRequiredDetails } from \"../acceptance.js\";\nimport type { EmailVerificationRequiredDetails } from \"../email-verification.js\";\n\n/**\n * Typed failure channel for `createAssertAuth`.\n *\n * Every EXPECTED auth outcome (not signed in, email unverified, missing profile,\n * account not in good standing) throws an `AuthAssertionError` whose `code` is\n * deliberately the matching `HttpsError` code string, so a consuming Cloud\n * Function maps it 1:1 at the app boundary:\n *\n * catch (err) {\n * if (err instanceof AuthAssertionError) throw new HttpsError(err.code, err.message);\n * throw err;\n * }\n *\n * WHY THE PACKAGE MUST NOT BUILD THE HttpsError ITSELF: firebase-functions 7.2.5\n * ships TWO distinct `HttpsError` classes — the one\n * exported from the ESM entry `firebase-functions/v2/https`, and the one the CJS\n * callable runtime closes over and `instanceof`-checks at\n * `lib/common/providers/https.js`. An `HttpsError` constructed by this package's\n * ESM `dist` fails that identity check, so `onCall` logged \"Unhandled error\" and\n * replaced a correct 400 with `500 INTERNAL`. Measured:\n *\n * ESM class === CJS class ? false\n * esm-built error instanceof CJS class ? false\n * httpErrorCode.status: 400 (the error itself was correct)\n *\n * Because `assertAuth` is the first line of every callable, that turned EVERY auth\n * rejection — unauthenticated, unverified email, suspended, banned — into a generic\n * 500: users saw a generic error instead of the verify-email dialog, and monitoring\n * filled with 500s that were really expected answers. Constructing the HttpsError in\n * APP module space fixes the identity permanently and cannot regress when\n * firebase-functions repackages.\n *\n * This also brings auth-core in line with engineering-rules QUALITY-102 (generic\n * packages stay framework-agnostic; the consuming app's adapter binds the framework) and\n * mirrors `report-core`'s `ReportCoreTaskError`, which already works this way.\n */\nexport type AuthAssertionErrorCode =\n | \"unauthenticated\"\n | \"failed-precondition\"\n | \"not-found\"\n | \"permission-denied\";\n\n/**\n * Structured details an `AuthAssertionError` may carry — one per refusal the client answers\n * with a surface of its own, each told apart by `reason`: the email-verification refusal\n * (`reason: 'email-verification-required'`, recognized by `isEmailVerificationRequiredError`)\n * and the acceptance refusal (`reason: 'acceptance-required'`, recognized by\n * `isAcceptanceRequiredError`). The app forwards `details` as the `HttpsError` details so the\n * client can recognize them:\n *\n * throw new HttpsError(err.code, err.message, err.details);\n *\n * Every other rejection leaves `details` undefined.\n */\nexport type AuthAssertionErrorDetails = AcceptanceRequiredDetails | EmailVerificationRequiredDetails;\n\nexport class AuthAssertionError extends Error {\n readonly code: AuthAssertionErrorCode;\n readonly details?: AuthAssertionErrorDetails;\n\n constructor(code: AuthAssertionErrorCode, message: string, details?: AuthAssertionErrorDetails) {\n super(message);\n this.name = \"AuthAssertionError\";\n this.code = code;\n if (details !== undefined) this.details = details;\n }\n}\n"]}
1
+ {"version":3,"file":"authError.js","sourceRoot":"","sources":["../../src/server/authError.ts"],"names":[],"mappings":"AAyDA,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAClC,IAAI,CAAyB;IAC7B,OAAO,CAA6B;IAE7C,YAAY,IAA4B,EAAE,OAAe,EAAE,OAAmC;QAC5F,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,OAAO,KAAK,SAAS;YAAE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACpD,CAAC;CACF","sourcesContent":["import type { AcceptanceRequiredDetails } from '../acceptance.js';\nimport type { EmailVerificationRequiredDetails } from '../email-verification.js';\n\n/**\n * Typed failure channel for `createAssertAuth`.\n *\n * Every EXPECTED auth outcome (not signed in, email unverified, missing profile,\n * account not in good standing) throws an `AuthAssertionError` whose `code` is\n * deliberately the matching `HttpsError` code string, so a consuming Cloud\n * Function maps it 1:1 at the app boundary:\n *\n * catch (err) {\n * if (err instanceof AuthAssertionError) throw new HttpsError(err.code, err.message);\n * throw err;\n * }\n *\n * WHY THE PACKAGE MUST NOT BUILD THE HttpsError ITSELF: firebase-functions 7.2.5\n * ships TWO distinct `HttpsError` classes — the one\n * exported from the ESM entry `firebase-functions/v2/https`, and the one the CJS\n * callable runtime closes over and `instanceof`-checks at\n * `lib/common/providers/https.js`. An `HttpsError` constructed by this package's\n * ESM `dist` fails that identity check, so `onCall` logged \"Unhandled error\" and\n * replaced a correct 400 with `500 INTERNAL`. Measured:\n *\n * ESM class === CJS class ? false\n * esm-built error instanceof CJS class ? false\n * httpErrorCode.status: 400 (the error itself was correct)\n *\n * Because `assertAuth` is the first line of every callable, that turned EVERY auth\n * rejection — unauthenticated, unverified email, suspended, banned — into a generic\n * 500: users saw a generic error instead of the verify-email dialog, and monitoring\n * filled with 500s that were really expected answers. Constructing the HttpsError in\n * APP module space fixes the identity permanently and cannot regress when\n * firebase-functions repackages.\n *\n * This also brings auth-core in line with engineering-rules QUALITY-102 (generic\n * packages stay framework-agnostic; the consuming app's adapter binds the framework) and\n * mirrors `report-core`'s `ReportCoreTaskError`, which already works this way.\n */\nexport type AuthAssertionErrorCode =\n 'unauthenticated' | 'failed-precondition' | 'not-found' | 'permission-denied';\n\n/**\n * Structured details an `AuthAssertionError` may carry — one per refusal the client answers\n * with a surface of its own, each told apart by `reason`: the email-verification refusal\n * (`reason: 'email-verification-required'`, recognized by `isEmailVerificationRequiredError`)\n * and the acceptance refusal (`reason: 'acceptance-required'`, recognized by\n * `isAcceptanceRequiredError`). The app forwards `details` as the `HttpsError` details so the\n * client can recognize them:\n *\n * throw new HttpsError(err.code, err.message, err.details);\n *\n * Every other rejection leaves `details` undefined.\n */\nexport type AuthAssertionErrorDetails =\n AcceptanceRequiredDetails | EmailVerificationRequiredDetails;\n\nexport class AuthAssertionError extends Error {\n readonly code: AuthAssertionErrorCode;\n readonly details?: AuthAssertionErrorDetails;\n\n constructor(code: AuthAssertionErrorCode, message: string, details?: AuthAssertionErrorDetails) {\n super(message);\n this.name = 'AuthAssertionError';\n this.code = code;\n if (details !== undefined) this.details = details;\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
- export { createAssertAuth } from "./assertAuth.js";
2
- export { AuthAssertionError } from "./authError.js";
3
- export type { AuthAssertionErrorCode, AuthAssertionErrorDetails } from "./authError.js";
4
- export type { AcceptanceGateConfig, AssertAuthConfig, AssertAuthFn, AuthContext, AuthRequirements, AdminCheckOptions, UserStatus, } from "./types.js";
1
+ export { createAssertAuth } from './assertAuth.js';
2
+ export { AuthAssertionError } from './authError.js';
3
+ export type { AuthAssertionErrorCode, AuthAssertionErrorDetails } from './authError.js';
4
+ export type { AcceptanceGateConfig, AssertAuthConfig, AssertAuthFn, AuthContext, AuthRequirements, AdminCheckOptions, UserStatus, } from './types.js';
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1,4 +1,4 @@
1
1
  // Public surface of @ttt-productions/auth-core/server.
2
- export { createAssertAuth } from "./assertAuth.js";
3
- export { AuthAssertionError } from "./authError.js";
2
+ export { createAssertAuth } from './assertAuth.js';
3
+ export { AuthAssertionError } from './authError.js';
4
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAEvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC","sourcesContent":["// Public surface of @ttt-productions/auth-core/server.\n\nexport { createAssertAuth } from \"./assertAuth.js\";\nexport { AuthAssertionError } from \"./authError.js\";\nexport type { AuthAssertionErrorCode, AuthAssertionErrorDetails } from \"./authError.js\";\nexport type {\n AcceptanceGateConfig,\n AssertAuthConfig,\n AssertAuthFn,\n AuthContext,\n AuthRequirements,\n AdminCheckOptions,\n UserStatus,\n} from \"./types.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAEvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC","sourcesContent":["// Public surface of @ttt-productions/auth-core/server.\n\nexport { createAssertAuth } from './assertAuth.js';\nexport { AuthAssertionError } from './authError.js';\nexport type { AuthAssertionErrorCode, AuthAssertionErrorDetails } from './authError.js';\nexport type {\n AcceptanceGateConfig,\n AssertAuthConfig,\n AssertAuthFn,\n AuthContext,\n AuthRequirements,\n AdminCheckOptions,\n UserStatus,\n} from './types.js';\n"]}
@@ -1,6 +1,6 @@
1
- import type { CallableRequest } from "firebase-functions/v2/https";
2
- import type { DecodedIdToken } from "firebase-admin/auth";
3
- import type { Firestore } from "firebase-admin/firestore";
1
+ import type { CallableRequest } from 'firebase-functions/v2/https';
2
+ import type { DecodedIdToken } from 'firebase-admin/auth';
3
+ import type { Firestore } from 'firebase-admin/firestore';
4
4
  /**
5
5
  * Per-callable requirements passed at every assertAuth call site.
6
6
  * These are application-agnostic.
@@ -72,7 +72,7 @@ export interface AuthContext<TUser = unknown, TAdmin = void> {
72
72
  * Status the consuming app reports for a user doc. The package only
73
73
  * interprets these three values.
74
74
  */
75
- export type UserStatus = "active" | "suspended" | "banned";
75
+ export type UserStatus = 'active' | 'suspended' | 'banned';
76
76
  /**
77
77
  * Configuration for createAssertAuth. The consuming app supplies every
78
78
  * app-specific operation as a callback.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAE1D;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;;;OAIG;IACH,KAAK,CAAC,EAAE,iBAAiB,CAAC;CAC3B;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,IAAI;IACzD,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,cAAc,CAAC;IACtB,uEAAuE;IACvE,OAAO,CAAC,EAAE,KAAK,CAAC;IAChB,4IAA4I;IAC5I,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE3D;;;GAGG;AACH,MAAM,WAAW,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IACpD;;;;OAIG;IACH,SAAS,EAAE,MAAM,SAAS,CAAC;IAE3B;;;OAGG;IACH,eAAe,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IAEzC;;;;OAIG;IACH,aAAa,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,UAAU,CAAC;IAE3C;;;;OAIG;IACH,YAAY,EAAE,CACZ,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,iBAAiB,KACvB,OAAO,CAAC,MAAM,CAAC,CAAC;IAErB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,oBAAoB,CAAC;CACnC;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,wFAAwF;IACxF,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;;;OAKG;IACH,aAAa,EAAE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC/C;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,IAAI,CAC/C,OAAO,EAAE,eAAe,EACxB,YAAY,CAAC,EAAE,gBAAgB,KAC5B,OAAO,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAE1D;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;;;OAIG;IACH,KAAK,CAAC,EAAE,iBAAiB,CAAC;CAC3B;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,IAAI;IACzD,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,cAAc,CAAC;IACtB,uEAAuE;IACvE,OAAO,CAAC,EAAE,KAAK,CAAC;IAChB,4IAA4I;IAC5I,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE3D;;;GAGG;AACH,MAAM,WAAW,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IACpD;;;;OAIG;IACH,SAAS,EAAE,MAAM,SAAS,CAAC;IAE3B;;;OAGG;IACH,eAAe,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IAEzC;;;;OAIG;IACH,aAAa,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,UAAU,CAAC;IAE3C;;;;OAIG;IACH,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAElG;;;;;OAKG;IACH,UAAU,CAAC,EAAE,oBAAoB,CAAC;CACnC;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,wFAAwF;IACxF,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;;;OAKG;IACH,aAAa,EAAE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC/C;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,IAAI,CAC/C,OAAO,EAAE,eAAe,EACxB,YAAY,CAAC,EAAE,gBAAgB,KAC5B,OAAO,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,6EAA6E","sourcesContent":["// Types for the createAssertAuth factory. Fully generic over the consuming\n// app's user document shape. The package contains no app-specific knowledge.\n\nimport type { CallableRequest } from \"firebase-functions/v2/https\";\nimport type { DecodedIdToken } from \"firebase-admin/auth\";\nimport type { Firestore } from \"firebase-admin/firestore\";\n\n/**\n * Per-callable requirements passed at every assertAuth call site.\n * These are application-agnostic.\n */\nexport interface AuthRequirements {\n /**\n * Allow unverified email. Default: false.\n * If true, the emailVerified check is skipped entirely.\n * Special-case for system flows (e.g. user registration).\n */\n allowUnverified?: boolean;\n\n /**\n * Require email_verified=true on the auth token.\n * Default: false. Skipped when allowUnverified=true.\n */\n emailVerified?: boolean;\n\n /**\n * Skip the status check entirely. Special-case for flows where the\n * user doc may not exist yet (e.g. user registration).\n * Default: false.\n */\n allowAnyStatus?: boolean;\n\n /**\n * Allow suspended users to pass the status check. Banned users still fail.\n * Use ONLY for callables that are a suspended user's last recourse\n * (e.g. admin-support chat / ban appeal).\n * Default: false. Does NOT skip the existence check.\n */\n allowSuspended?: boolean;\n\n /**\n * Let a caller below the currently required acceptance level through. Meaningful only\n * when the factory was configured with `acceptance`; ignored otherwise.\n * Use ONLY for callables that must work before the caller accepts: the accept callable\n * itself, registration (a new account holds no accepted level yet), and last-recourse\n * paths such as sign-out, support, refunds, account deletion, and legally required\n * reporting. Default: false.\n */\n allowUnaccepted?: boolean;\n\n /**\n * Require admin status. Delegates to config.requireAdmin().\n * The shape of this object is forwarded verbatim to the consumer's\n * requireAdmin callback — the package does not interpret it.\n */\n admin?: AdminCheckOptions;\n}\n\n/**\n * Options forwarded to the consumer's requireAdmin callback. Generic shape.\n * Consuming apps may add their own fields; the package does not validate.\n */\nexport interface AdminCheckOptions {\n allowJrAdmin?: boolean;\n useFastCheck?: boolean;\n errorMessage?: string;\n [key: string]: unknown;\n}\n\n/**\n * Return value from assertAuth. Generic over the consuming app's user\n * document type.\n */\nexport interface AuthContext<TUser = unknown, TAdmin = void> {\n uid: string;\n token: DecodedIdToken;\n /** Populated when the user doc was read (default not-banned check). */\n userDoc?: TUser;\n /** Result returned by config.requireAdmin. Populated only when an admin check ran (AuthRequirements.admin was set). Undefined otherwise. */\n admin?: TAdmin;\n}\n\n/**\n * Status the consuming app reports for a user doc. The package only\n * interprets these three values.\n */\nexport type UserStatus = \"active\" | \"suspended\" | \"banned\";\n\n/**\n * Configuration for createAssertAuth. The consuming app supplies every\n * app-specific operation as a callback.\n */\nexport interface AssertAuthConfig<TUser, TAdmin = void> {\n /**\n * Returns the admin Firestore instance. Called every assertAuth invocation\n * that needs a Firestore read. Implementations typically return\n * `admin.firestore()` from a memoized handle.\n */\n firestore: () => Firestore;\n\n /**\n * Returns the Firestore document path for a user profile, given a uid.\n * Example: `userProfiles/${uid}`\n */\n userProfilePath: (uid: string) => string;\n\n /**\n * Returns the user's status given the user doc data. The package only\n * acts on 'active' | 'suspended' | 'banned'. Apps may store status in any\n * field; this callback interprets it.\n */\n getUserStatus: (user: TUser) => UserStatus;\n\n /**\n * Admin check. Called only when AuthRequirements.admin is set. The\n * package forwards uid, token, and the admin options verbatim. The\n * callback throws (typically HttpsError) on failure.\n */\n requireAdmin: (\n uid: string,\n token: DecodedIdToken,\n options: AdminCheckOptions\n ) => Promise<TAdmin>;\n\n /**\n * Optional acceptance-level gate. When set, every assertAuth call that does not pass\n * `allowUnaccepted` refuses a caller whose accepted level (read from the token claim\n * `claimKey`) is below the level `requiredLevel()` returns. Absent = no gate, exactly the\n * behavior before the gate existed.\n */\n acceptance?: AcceptanceGateConfig;\n}\n\n/**\n * The consuming app's acceptance-level wiring. The package holds no claim name and no\n * document knowledge: the app names the claim and supplies the current requirement.\n */\nexport interface AcceptanceGateConfig {\n /** The custom claim on the verified ID token that holds the caller's accepted level. */\n claimKey: string;\n\n /**\n * The level currently required. Runs on every gated assertAuth, so it must be cheap —\n * read it from a cached snapshot, never a fresh Firestore read per call. A non-finite or\n * non-positive result requires nothing (see `normalizeAcceptanceLevel`); a throw rejects\n * the call.\n */\n requiredLevel: () => number | Promise<number>;\n}\n\n/**\n * The function returned by createAssertAuth.\n */\nexport type AssertAuthFn<TUser, TAdmin = void> = (\n request: CallableRequest,\n requirements?: AuthRequirements\n) => Promise<AuthContext<TUser, TAdmin>>;\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,6EAA6E","sourcesContent":["// Types for the createAssertAuth factory. Fully generic over the consuming\n// app's user document shape. The package contains no app-specific knowledge.\n\nimport type { CallableRequest } from 'firebase-functions/v2/https';\nimport type { DecodedIdToken } from 'firebase-admin/auth';\nimport type { Firestore } from 'firebase-admin/firestore';\n\n/**\n * Per-callable requirements passed at every assertAuth call site.\n * These are application-agnostic.\n */\nexport interface AuthRequirements {\n /**\n * Allow unverified email. Default: false.\n * If true, the emailVerified check is skipped entirely.\n * Special-case for system flows (e.g. user registration).\n */\n allowUnverified?: boolean;\n\n /**\n * Require email_verified=true on the auth token.\n * Default: false. Skipped when allowUnverified=true.\n */\n emailVerified?: boolean;\n\n /**\n * Skip the status check entirely. Special-case for flows where the\n * user doc may not exist yet (e.g. user registration).\n * Default: false.\n */\n allowAnyStatus?: boolean;\n\n /**\n * Allow suspended users to pass the status check. Banned users still fail.\n * Use ONLY for callables that are a suspended user's last recourse\n * (e.g. admin-support chat / ban appeal).\n * Default: false. Does NOT skip the existence check.\n */\n allowSuspended?: boolean;\n\n /**\n * Let a caller below the currently required acceptance level through. Meaningful only\n * when the factory was configured with `acceptance`; ignored otherwise.\n * Use ONLY for callables that must work before the caller accepts: the accept callable\n * itself, registration (a new account holds no accepted level yet), and last-recourse\n * paths such as sign-out, support, refunds, account deletion, and legally required\n * reporting. Default: false.\n */\n allowUnaccepted?: boolean;\n\n /**\n * Require admin status. Delegates to config.requireAdmin().\n * The shape of this object is forwarded verbatim to the consumer's\n * requireAdmin callback — the package does not interpret it.\n */\n admin?: AdminCheckOptions;\n}\n\n/**\n * Options forwarded to the consumer's requireAdmin callback. Generic shape.\n * Consuming apps may add their own fields; the package does not validate.\n */\nexport interface AdminCheckOptions {\n allowJrAdmin?: boolean;\n useFastCheck?: boolean;\n errorMessage?: string;\n [key: string]: unknown;\n}\n\n/**\n * Return value from assertAuth. Generic over the consuming app's user\n * document type.\n */\nexport interface AuthContext<TUser = unknown, TAdmin = void> {\n uid: string;\n token: DecodedIdToken;\n /** Populated when the user doc was read (default not-banned check). */\n userDoc?: TUser;\n /** Result returned by config.requireAdmin. Populated only when an admin check ran (AuthRequirements.admin was set). Undefined otherwise. */\n admin?: TAdmin;\n}\n\n/**\n * Status the consuming app reports for a user doc. The package only\n * interprets these three values.\n */\nexport type UserStatus = 'active' | 'suspended' | 'banned';\n\n/**\n * Configuration for createAssertAuth. The consuming app supplies every\n * app-specific operation as a callback.\n */\nexport interface AssertAuthConfig<TUser, TAdmin = void> {\n /**\n * Returns the admin Firestore instance. Called every assertAuth invocation\n * that needs a Firestore read. Implementations typically return\n * `admin.firestore()` from a memoized handle.\n */\n firestore: () => Firestore;\n\n /**\n * Returns the Firestore document path for a user profile, given a uid.\n * Example: `userProfiles/${uid}`\n */\n userProfilePath: (uid: string) => string;\n\n /**\n * Returns the user's status given the user doc data. The package only\n * acts on 'active' | 'suspended' | 'banned'. Apps may store status in any\n * field; this callback interprets it.\n */\n getUserStatus: (user: TUser) => UserStatus;\n\n /**\n * Admin check. Called only when AuthRequirements.admin is set. The\n * package forwards uid, token, and the admin options verbatim. The\n * callback throws (typically HttpsError) on failure.\n */\n requireAdmin: (uid: string, token: DecodedIdToken, options: AdminCheckOptions) => Promise<TAdmin>;\n\n /**\n * Optional acceptance-level gate. When set, every assertAuth call that does not pass\n * `allowUnaccepted` refuses a caller whose accepted level (read from the token claim\n * `claimKey`) is below the level `requiredLevel()` returns. Absent = no gate, exactly the\n * behavior before the gate existed.\n */\n acceptance?: AcceptanceGateConfig;\n}\n\n/**\n * The consuming app's acceptance-level wiring. The package holds no claim name and no\n * document knowledge: the app names the claim and supplies the current requirement.\n */\nexport interface AcceptanceGateConfig {\n /** The custom claim on the verified ID token that holds the caller's accepted level. */\n claimKey: string;\n\n /**\n * The level currently required. Runs on every gated assertAuth, so it must be cheap —\n * read it from a cached snapshot, never a fresh Firestore read per call. A non-finite or\n * non-positive result requires nothing (see `normalizeAcceptanceLevel`); a throw rejects\n * the call.\n */\n requiredLevel: () => number | Promise<number>;\n}\n\n/**\n * The function returned by createAssertAuth.\n */\nexport type AssertAuthFn<TUser, TAdmin = void> = (\n request: CallableRequest,\n requirements?: AuthRequirements,\n) => Promise<AuthContext<TUser, TAdmin>>;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttt-productions/auth-core",
3
- "version": "1.6.14",
3
+ "version": "1.6.16",
4
4
  "description": "Shared Firebase authentication utilities and React hooks for TTT Productions apps",
5
5
  "repository": {
6
6
  "type": "git",
@@ -21,8 +21,8 @@
21
21
  "default": "./dist/index.js"
22
22
  },
23
23
  "./client": {
24
- "types": "./dist/client.d.ts",
25
- "default": "./dist/client.js"
24
+ "types": "./dist/client/index.d.ts",
25
+ "default": "./dist/client/index.js"
26
26
  },
27
27
  "./react": {
28
28
  "types": "./dist/react/index.d.ts",
@@ -1 +0,0 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAGhD,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AAErC,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAEnD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,IAAI,EACV,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI,EAC/B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GACjC,WAAW,CAEb"}
package/dist/auth.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,IAAI,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAI3E,MAAM,UAAU,WAAW,CAAC,IAAU;IACpC,OAAO,IAAI,CAAC,WAAW,CAAC;AAC1B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAAU,EACV,EAA+B,EAC/B,OAAkC;IAElC,OAAO,oBAAoB,CAAC,IAAI,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;AACjD,CAAC","sourcesContent":["import type { Auth, User } from \"firebase/auth\";\nimport { onAuthStateChanged as fbOnAuthStateChanged } from \"firebase/auth\";\n\nexport type Unsubscribe = () => void;\n\nexport function getAuthUser(auth: Auth): User | null {\n return auth.currentUser;\n}\n\n/**\n * Thin wrapper around Firebase onAuthStateChanged.\n * - always returns the unsubscribe function\n * - preserves Firebase callback signature\n */\nexport function onAuthStateChanged(\n auth: Auth,\n cb: (user: User | null) => void,\n onError?: (error: unknown) => void\n): Unsubscribe {\n return fbOnAuthStateChanged(auth, cb, onError);\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"claims.d.ts","sourceRoot":"","sources":["../src/claims.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE/D,MAAM,MAAM,aAAa,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;AAEpD,MAAM,MAAM,YAAY,GAAG;IAEzB,KAAK,EAAE,MAAM,EAAE,CAAC;IAEhB,GAAG,EAAE,aAAa,CAAC;CACpB,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAQvF;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAIpF;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAErF;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,GAAG,SAAS,GAAG,YAAY,CAUlF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"claims.js","sourceRoot":"","sources":["../src/claims.ts"],"names":[],"mappings":"AAWA;;;;;;;;;;;;;;GAcG;AACH,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;;;GAGG;AACH,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;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,IAAU;IACpD,OAAO,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;AACzC,CAAC;AAED;;;;GAIG;AACH,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,GACT,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC;QAC7E,OAAO,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;YAC/C,EAAE,CAAC;IAEL,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 // common defaults (kept generic)\n roles: string[];\n // raw claims for app-level decisions\n raw: IdTokenClaims;\n};\n\n/**\n * Get the current user's ID token claims.\n * Returns null if no current user.\n *\n * STALE-VERIFICATION RECONCILIATION: when the ACCOUNT says the email is\n * verified but the cached token claim still says it is not, force-mint a fresh\n * token and return ITS claims. Firebase ID tokens live for up to an hour and a\n * backend-side `emailVerified` flip (verification link applied elsewhere, or an\n * Admin SDK update) never invalidates them — without this, the UI (account\n * state) believes the user is verified while every backend call (token claim)\n * rejects with \"Email must be verified\" until the token happens to rotate.\n * One forced mint converges the two (the fresh token carries\n * `email_verified: true`); the check is directional, so an already-consistent\n * user never pays a forced refresh.\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\n/**\n * Forces refresh of ID token + claims.\n * Returns null if no current user.\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\n/**\n * Convenience helper when you only have Auth.\n */\nexport async function refreshClaimsFromAuth(auth: Auth): Promise<IdTokenClaims | null> {\n return refreshClaims(auth.currentUser);\n}\n\n/**\n * Keep parsing intentionally minimal and generic:\n * - normalize \"roles\" into string[]\n * - keep raw claims attached\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 =\n Array.isArray(rolesValue) ? rolesValue.filter((x) => typeof x === \"string\") :\n typeof rolesValue === \"string\" ? [rolesValue] :\n [];\n\n return { roles, raw };\n}\n"]}
package/dist/client.d.ts DELETED
@@ -1,2 +0,0 @@
1
- export * from "./auth.js";
2
- //# sourceMappingURL=client.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAGA,cAAc,WAAW,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,4EAA4E;AAC5E,iEAAiE;AACjE,cAAc,WAAW,CAAC","sourcesContent":["// Firebase *client* auth runtime. Importing this subpath pulls firebase/auth\n// at runtime (e.g. onAuthStateChanged), so it is intentionally kept off the\n// pure root. The pure root exposes only contracts/config/errors.\nexport * from \"./auth.js\";\n"]}