@rdlabo/workers-hono-kit 0.2.0 → 0.2.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.
Files changed (97) hide show
  1. package/README.md +126 -11
  2. package/dist/ai/gateway.d.ts +54 -16
  3. package/dist/ai/gateway.js +37 -12
  4. package/dist/aws/cloudfront.d.ts +23 -5
  5. package/dist/aws/cloudfront.js +45 -6
  6. package/dist/aws/secrets-manager.d.ts +38 -4
  7. package/dist/aws/secrets-manager.js +48 -3
  8. package/dist/cache/kv-cache.d.ts +173 -10
  9. package/dist/cache/kv-cache.js +139 -7
  10. package/dist/db/connection.d.ts +56 -14
  11. package/dist/db/connection.js +39 -13
  12. package/dist/db/database.d.ts +159 -23
  13. package/dist/db/database.js +49 -5
  14. package/dist/db/index.d.ts +11 -0
  15. package/dist/db/index.js +11 -2
  16. package/dist/db/jst.d.ts +89 -6
  17. package/dist/db/jst.js +89 -23
  18. package/dist/db/orm-config.d.ts +61 -19
  19. package/dist/db/orm-config.js +43 -14
  20. package/dist/db/retry.d.ts +25 -3
  21. package/dist/db/retry.js +25 -3
  22. package/dist/db/write-result.d.ts +27 -4
  23. package/dist/db/write-result.js +22 -1
  24. package/dist/firebase/firebase-verifier.d.ts +53 -4
  25. package/dist/firebase/identity-toolkit.d.ts +54 -5
  26. package/dist/firebase/identity-toolkit.js +51 -0
  27. package/dist/firebase/jose-firebase-verifier.d.ts +79 -7
  28. package/dist/firebase/jose-firebase-verifier.js +68 -7
  29. package/dist/firebase/remote-verifier.d.ts +42 -4
  30. package/dist/firebase/remote-verifier.js +58 -9
  31. package/dist/http/app-env.d.ts +41 -8
  32. package/dist/http/app-env.js +38 -8
  33. package/dist/http/app-info.d.ts +25 -3
  34. package/dist/http/app-info.js +16 -2
  35. package/dist/http/http-status.d.ts +12 -3
  36. package/dist/http/http-status.js +12 -3
  37. package/dist/http/nest-error.d.ts +90 -29
  38. package/dist/http/nest-error.js +59 -18
  39. package/dist/http/user-protocol.d.ts +23 -3
  40. package/dist/http/user-protocol.js +14 -2
  41. package/dist/index.d.ts +11 -0
  42. package/dist/index.js +11 -3
  43. package/dist/middleware/auth.d.ts +74 -13
  44. package/dist/middleware/auth.js +30 -6
  45. package/dist/middleware/finalize-response.d.ts +30 -0
  46. package/dist/middleware/finalize-response.js +41 -12
  47. package/dist/middleware/validation.d.ts +83 -9
  48. package/dist/middleware/validation.js +52 -9
  49. package/dist/middleware/zod-coerce.d.ts +56 -2
  50. package/dist/middleware/zod-coerce.js +68 -9
  51. package/dist/stripe/client.d.ts +46 -9
  52. package/dist/stripe/client.js +41 -3
  53. package/dist/testing/auth.d.ts +58 -10
  54. package/dist/testing/auth.js +58 -10
  55. package/dist/testing/configurable-fake.d.ts +20 -9
  56. package/dist/testing/configurable-fake.js +23 -11
  57. package/dist/testing/db.d.ts +81 -12
  58. package/dist/testing/db.js +23 -1
  59. package/dist/testing/fakes.d.ts +77 -9
  60. package/dist/testing/fakes.js +69 -7
  61. package/dist/testing/index.d.ts +7 -0
  62. package/dist/testing/index.js +10 -5
  63. package/dist/testing/stripe-fixtures.d.ts +93 -3
  64. package/dist/testing/stripe-fixtures.js +93 -3
  65. package/package.json +1 -1
  66. package/src/ai/gateway.ts +66 -27
  67. package/src/aws/cloudfront.ts +46 -6
  68. package/src/aws/secrets-manager.ts +56 -7
  69. package/src/cache/kv-cache.ts +194 -12
  70. package/src/db/connection.ts +56 -14
  71. package/src/db/database.ts +160 -24
  72. package/src/db/index.ts +11 -2
  73. package/src/db/jst.ts +89 -23
  74. package/src/db/orm-config.ts +61 -19
  75. package/src/db/retry.ts +25 -3
  76. package/src/db/write-result.ts +27 -4
  77. package/src/firebase/firebase-verifier.ts +53 -4
  78. package/src/firebase/identity-toolkit.ts +57 -5
  79. package/src/firebase/jose-firebase-verifier.ts +79 -9
  80. package/src/firebase/remote-verifier.ts +58 -9
  81. package/src/http/app-env.ts +41 -8
  82. package/src/http/app-info.ts +25 -3
  83. package/src/http/http-status.ts +12 -3
  84. package/src/http/nest-error.ts +106 -37
  85. package/src/http/user-protocol.ts +23 -3
  86. package/src/index.ts +11 -3
  87. package/src/middleware/auth.ts +77 -15
  88. package/src/middleware/finalize-response.ts +41 -12
  89. package/src/middleware/validation.ts +89 -15
  90. package/src/middleware/zod-coerce.ts +68 -9
  91. package/src/stripe/client.ts +46 -9
  92. package/src/testing/auth.ts +58 -10
  93. package/src/testing/configurable-fake.ts +23 -11
  94. package/src/testing/db.ts +82 -13
  95. package/src/testing/fakes.ts +77 -9
  96. package/src/testing/index.ts +10 -5
  97. package/src/testing/stripe-fixtures.ts +93 -3
@@ -1,32 +1,104 @@
1
1
  import type { CryptoKey, JWK, JWTVerifyGetKey, KeyObject } from 'jose';
2
2
  import type { DecodedIdToken, FirebaseVerifier } from './firebase-verifier.js';
3
3
  import type { IdentityToolkit } from './identity-toolkit.js';
4
- type KeyInput = CryptoKey | KeyObject | JWK | Uint8Array | JWTVerifyGetKey;
5
4
  /**
6
- * Replaces firebase-admin getAuth().verifyIdToken() with jose RS256 verification against
7
- * Google's securetoken JWKS. Mirrors the admin SDK's checks: issuer/audience = projectId,
8
- * RS256, a non-empty subject (the uid), and a valid auth_time.
5
+ * Union of every key shape `jose`'s `jwtVerify` accepts.
6
+ *
7
+ * @remarks
8
+ * `jose` v6 removed `KeyLike`, so the verification key is modelled here as either a static
9
+ * key (production uses `createRemoteJWKSet`, tests use a generated `CryptoKey`) or a dynamic
10
+ * `JWTVerifyGetKey` resolver function. This union covers both `jwtVerify` overloads' key
11
+ * parameters.
9
12
  *
10
- * - prod: keyResolver = createRemoteJWKSet(new URL(SECURETOKEN_JWK_URL)).
11
- * - test: keyResolver = the generated public key (offline, no network).
13
+ * @internal
14
+ */
15
+ type KeyInput = CryptoKey | KeyObject | JWK | Uint8Array | JWTVerifyGetKey;
16
+ /**
17
+ * URL of Google's securetoken JWKS endpoint, which serves the public keys used to sign
18
+ * Firebase ID tokens.
12
19
  *
13
- * getUser/deleteUser delegate to Identity Toolkit REST (network); absent it throws.
20
+ * @remarks
21
+ * Passed to `createRemoteJWKSet` (see `createRemoteFirebaseVerifier`) so RS256 signatures can
22
+ * be verified against Google's rotating public keys.
14
23
  */
15
24
  export declare const SECURETOKEN_JWK_URL = "https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com";
25
+ /**
26
+ * Verifies Firebase ID tokens with `jose` RS256 against Google's securetoken JWKS, and
27
+ * optionally looks up or deletes users via the Google Identity Toolkit REST API.
28
+ *
29
+ * This replaces the `firebase-admin` Auth surface (`verifyIdToken` / `getUser` /
30
+ * `deleteUser`) in environments where the Node SDK cannot run, such as Cloudflare Workers.
31
+ * Token verification mirrors the admin SDK's checks: issuer and audience equal to the
32
+ * project id, an RS256 signature, a non-empty subject (the uid), and a valid `auth_time`.
33
+ *
34
+ * @remarks
35
+ * The verification key is supplied as `keyResolver`:
36
+ * - Production: `createRemoteJWKSet(new URL(SECURETOKEN_JWK_URL))`, which fetches and caches
37
+ * Google's public keys.
38
+ * - Tests: a generated public key, allowing fully offline verification with no network.
39
+ *
40
+ * `getUser` / `deleteUser` delegate to {@link IdentityToolkit} (a network call); when no
41
+ * `IdentityToolkit` is configured they throw.
42
+ *
43
+ * @see {@link FirebaseVerifier} for the abstract boundary this implements.
44
+ */
16
45
  export declare class JoseFirebaseVerifier implements FirebaseVerifier {
17
46
  private readonly opts;
47
+ /**
48
+ * Create a verifier.
49
+ *
50
+ * @param opts - Verifier configuration.
51
+ * @param opts.projectId - The Firebase project id, used as both the expected token issuer
52
+ * (`https://securetoken.google.com/<projectId>`) and audience.
53
+ * @param opts.keyResolver - The RS256 verification key or a dynamic key resolver function.
54
+ * @param opts.identity - Optional Identity Toolkit client enabling `getUser` / `deleteUser`.
55
+ * @param opts.now - Optional clock returning the current time in seconds; injectable for
56
+ * deterministic tests. Defaults to the system clock.
57
+ */
18
58
  constructor(opts: {
19
59
  projectId: string;
20
60
  keyResolver: KeyInput;
21
61
  identity?: IdentityToolkit;
22
62
  now?: () => number;
23
63
  });
64
+ /**
65
+ * Verify a Firebase ID token and return its decoded payload.
66
+ *
67
+ * Checks the RS256 signature against the configured key, enforces the expected issuer and
68
+ * audience (the project id), and applies the admin SDK's extra checks: a non-empty string
69
+ * subject of at most 128 characters and an `auth_time` that is a number not in the future.
70
+ *
71
+ * @param idToken - The raw Firebase ID token (JWT) to verify.
72
+ * @returns The decoded payload, with `uid` set from `sub` and `email` lifted to a top-level field.
73
+ * @throws If the signature, issuer, audience, or expiry are invalid, if the subject is
74
+ * missing/non-string/too long, or if `auth_time` is missing or in the future.
75
+ */
24
76
  verifyIdToken(idToken: string): Promise<DecodedIdToken>;
77
+ /**
78
+ * Look up a user record by uid via the Identity Toolkit REST API.
79
+ *
80
+ * @param uid - The user's unique id.
81
+ * @returns The user's `uid` and optional `email`, or `null` when the user does not exist.
82
+ * @throws If no Identity Toolkit client was configured on this verifier.
83
+ */
25
84
  getUser(uid: string): Promise<{
26
85
  uid: string;
27
86
  email?: string;
28
87
  } | null>;
88
+ /**
89
+ * Delete a user by uid via the Identity Toolkit REST API.
90
+ *
91
+ * @param uid - The user's unique id.
92
+ * @returns A promise that resolves once the user has been deleted.
93
+ * @throws If no Identity Toolkit client was configured on this verifier, or the deletion fails.
94
+ */
29
95
  deleteUser(uid: string): Promise<void>;
96
+ /**
97
+ * Return the current time in seconds, using the injected clock when provided.
98
+ *
99
+ * @returns The current Unix time in seconds.
100
+ * @internal
101
+ */
30
102
  private nowSeconds;
31
103
  }
32
104
  export {};
@@ -1,20 +1,61 @@
1
1
  import { jwtVerify } from 'jose';
2
2
  /**
3
- * Replaces firebase-admin getAuth().verifyIdToken() with jose RS256 verification against
4
- * Google's securetoken JWKS. Mirrors the admin SDK's checks: issuer/audience = projectId,
5
- * RS256, a non-empty subject (the uid), and a valid auth_time.
3
+ * URL of Google's securetoken JWKS endpoint, which serves the public keys used to sign
4
+ * Firebase ID tokens.
6
5
  *
7
- * - prod: keyResolver = createRemoteJWKSet(new URL(SECURETOKEN_JWK_URL)).
8
- * - test: keyResolver = the generated public key (offline, no network).
9
- *
10
- * getUser/deleteUser delegate to Identity Toolkit REST (network); absent it throws.
6
+ * @remarks
7
+ * Passed to `createRemoteJWKSet` (see `createRemoteFirebaseVerifier`) so RS256 signatures can
8
+ * be verified against Google's rotating public keys.
11
9
  */
12
10
  export const SECURETOKEN_JWK_URL = 'https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com';
11
+ /**
12
+ * Verifies Firebase ID tokens with `jose` RS256 against Google's securetoken JWKS, and
13
+ * optionally looks up or deletes users via the Google Identity Toolkit REST API.
14
+ *
15
+ * This replaces the `firebase-admin` Auth surface (`verifyIdToken` / `getUser` /
16
+ * `deleteUser`) in environments where the Node SDK cannot run, such as Cloudflare Workers.
17
+ * Token verification mirrors the admin SDK's checks: issuer and audience equal to the
18
+ * project id, an RS256 signature, a non-empty subject (the uid), and a valid `auth_time`.
19
+ *
20
+ * @remarks
21
+ * The verification key is supplied as `keyResolver`:
22
+ * - Production: `createRemoteJWKSet(new URL(SECURETOKEN_JWK_URL))`, which fetches and caches
23
+ * Google's public keys.
24
+ * - Tests: a generated public key, allowing fully offline verification with no network.
25
+ *
26
+ * `getUser` / `deleteUser` delegate to {@link IdentityToolkit} (a network call); when no
27
+ * `IdentityToolkit` is configured they throw.
28
+ *
29
+ * @see {@link FirebaseVerifier} for the abstract boundary this implements.
30
+ */
13
31
  export class JoseFirebaseVerifier {
14
32
  opts;
33
+ /**
34
+ * Create a verifier.
35
+ *
36
+ * @param opts - Verifier configuration.
37
+ * @param opts.projectId - The Firebase project id, used as both the expected token issuer
38
+ * (`https://securetoken.google.com/<projectId>`) and audience.
39
+ * @param opts.keyResolver - The RS256 verification key or a dynamic key resolver function.
40
+ * @param opts.identity - Optional Identity Toolkit client enabling `getUser` / `deleteUser`.
41
+ * @param opts.now - Optional clock returning the current time in seconds; injectable for
42
+ * deterministic tests. Defaults to the system clock.
43
+ */
15
44
  constructor(opts) {
16
45
  this.opts = opts;
17
46
  }
47
+ /**
48
+ * Verify a Firebase ID token and return its decoded payload.
49
+ *
50
+ * Checks the RS256 signature against the configured key, enforces the expected issuer and
51
+ * audience (the project id), and applies the admin SDK's extra checks: a non-empty string
52
+ * subject of at most 128 characters and an `auth_time` that is a number not in the future.
53
+ *
54
+ * @param idToken - The raw Firebase ID token (JWT) to verify.
55
+ * @returns The decoded payload, with `uid` set from `sub` and `email` lifted to a top-level field.
56
+ * @throws If the signature, issuer, audience, or expiry are invalid, if the subject is
57
+ * missing/non-string/too long, or if `auth_time` is missing or in the future.
58
+ */
18
59
  async verifyIdToken(idToken) {
19
60
  const options = {
20
61
  issuer: `https://securetoken.google.com/${this.opts.projectId}`,
@@ -34,18 +75,38 @@ export class JoseFirebaseVerifier {
34
75
  }
35
76
  return { ...payload, uid: payload.sub, email: payload.email };
36
77
  }
78
+ /**
79
+ * Look up a user record by uid via the Identity Toolkit REST API.
80
+ *
81
+ * @param uid - The user's unique id.
82
+ * @returns The user's `uid` and optional `email`, or `null` when the user does not exist.
83
+ * @throws If no Identity Toolkit client was configured on this verifier.
84
+ */
37
85
  async getUser(uid) {
38
86
  if (!this.opts.identity) {
39
87
  throw new Error('Identity Toolkit not configured');
40
88
  }
41
89
  return this.opts.identity.lookup(uid, this.nowSeconds());
42
90
  }
91
+ /**
92
+ * Delete a user by uid via the Identity Toolkit REST API.
93
+ *
94
+ * @param uid - The user's unique id.
95
+ * @returns A promise that resolves once the user has been deleted.
96
+ * @throws If no Identity Toolkit client was configured on this verifier, or the deletion fails.
97
+ */
43
98
  async deleteUser(uid) {
44
99
  if (!this.opts.identity) {
45
100
  throw new Error('Identity Toolkit not configured');
46
101
  }
47
102
  await this.opts.identity.remove(uid, this.nowSeconds());
48
103
  }
104
+ /**
105
+ * Return the current time in seconds, using the injected clock when provided.
106
+ *
107
+ * @returns The current Unix time in seconds.
108
+ * @internal
109
+ */
49
110
  nowSeconds() {
50
111
  return this.opts.now ? this.opts.now() : Math.floor(Date.now() / 1000);
51
112
  }
@@ -1,9 +1,47 @@
1
1
  import { JoseFirebaseVerifier } from './jose-firebase-verifier.js';
2
+ /**
3
+ * Create a token-verification-only Firebase verifier for the given project.
4
+ *
5
+ * Uses `createRemoteJWKSet` to fetch Google's securetoken public keys and returns a
6
+ * {@link JoseFirebaseVerifier}. This factory is for token verification only; it configures no
7
+ * Identity Toolkit client, so `getUser` / `deleteUser` are unavailable.
8
+ *
9
+ * @remarks
10
+ * The remote JWKS is created once per isolate and shared, and the returned verifier is
11
+ * memoized per `projectId`. This preserves the caching behaviour of a module-level JWKS so
12
+ * repeated calls do not re-fetch keys or allocate new verifiers.
13
+ *
14
+ * @param projectId - The Firebase project id whose tokens will be verified.
15
+ * @returns A verifier that validates ID tokens for `projectId`.
16
+ * @example
17
+ * ```ts
18
+ * const verifier = createRemoteFirebaseVerifier('my-firebase-project');
19
+ * const decoded = await verifier.verifyIdToken(idToken);
20
+ * console.log(decoded.uid);
21
+ * ```
22
+ */
2
23
  export declare function createRemoteFirebaseVerifier(projectId: string): JoseFirebaseVerifier;
3
24
  /**
4
- * サービスアカウント JSON から検証器を作る便宜ファクトリ(receptray/tipsys hono `firebaseFor` 相当)。
5
- * `getUser`/`deleteUser` のため `IdentityToolkit` を内包する点が `createRemoteFirebaseVerifier` との違い。
6
- * SA JSON 文字列をキーに isolate 内で 1 つだけキャッシュ(秘密が変わったときだけ再生成)し、
7
- * JWKS `createRemoteFirebaseVerifier` と共有する。
25
+ * Create a Firebase verifier from a service-account JSON string.
26
+ *
27
+ * Unlike {@link createRemoteFirebaseVerifier}, the returned {@link JoseFirebaseVerifier}
28
+ * embeds an {@link IdentityToolkit} client, enabling `getUser` and `deleteUser` in addition to
29
+ * token verification.
30
+ *
31
+ * @remarks
32
+ * The verifier is cached for the lifetime of the isolate, keyed by the service-account JSON
33
+ * string, and is only rebuilt when that secret changes. The remote JWKS is shared with
34
+ * {@link createRemoteFirebaseVerifier}.
35
+ *
36
+ * @param serviceAccountJson - The service-account key as a JSON string (parsed into {@link ServiceAccount}).
37
+ * @returns A verifier that validates ID tokens and can look up or delete users.
38
+ * @throws If `serviceAccountJson` is not valid JSON.
39
+ * @example
40
+ * ```ts
41
+ * const verifier = createServiceAccountVerifier(env.FIREBASE_SERVICE_ACCOUNT);
42
+ * const decoded = await verifier.verifyIdToken(idToken);
43
+ * const user = await verifier.getUser(decoded.uid);
44
+ * await verifier.deleteUser(decoded.uid);
45
+ * ```
8
46
  */
9
47
  export declare function createServiceAccountVerifier(serviceAccountJson: string): JoseFirebaseVerifier;
@@ -2,15 +2,42 @@ import { createRemoteJWKSet } from 'jose';
2
2
  import { IdentityToolkit } from './identity-toolkit.js';
3
3
  import { JoseFirebaseVerifier, SECURETOKEN_JWK_URL } from './jose-firebase-verifier.js';
4
4
  /**
5
- * 本番用の便宜ファクトリ。`createRemoteJWKSet` Google securetoken の公開鍵を取り、
6
- * `JoseFirebaseVerifier` を返す。トークン検証のみ用途(getUser/deleteUser は不要 = Identity Toolkit 無し)。
5
+ * Shared remote JWKS for Google's securetoken keys.
7
6
  *
8
- * JWKS は URL 固定なので isolate 内で 1 度だけ生成して共有し(jose が内部メモリにキャッシュ)、
9
- * verifier projectId ごとにメモ化する。winecode の旧 `verifyFirebaseIdToken`(module-level JWKS)の
10
- * キャッシュ挙動を保つための置換。
7
+ * @remarks
8
+ * The JWKS URL is fixed, so the set is created once per isolate and shared across verifiers
9
+ * (`jose` caches the fetched keys internally). Lazily initialised on first use.
10
+ *
11
+ * @internal
11
12
  */
12
13
  let jwks;
14
+ /**
15
+ * Per-`projectId` cache of token-only verifiers, memoized for the lifetime of the isolate.
16
+ *
17
+ * @internal
18
+ */
13
19
  const verifiers = new Map();
20
+ /**
21
+ * Create a token-verification-only Firebase verifier for the given project.
22
+ *
23
+ * Uses `createRemoteJWKSet` to fetch Google's securetoken public keys and returns a
24
+ * {@link JoseFirebaseVerifier}. This factory is for token verification only; it configures no
25
+ * Identity Toolkit client, so `getUser` / `deleteUser` are unavailable.
26
+ *
27
+ * @remarks
28
+ * The remote JWKS is created once per isolate and shared, and the returned verifier is
29
+ * memoized per `projectId`. This preserves the caching behaviour of a module-level JWKS so
30
+ * repeated calls do not re-fetch keys or allocate new verifiers.
31
+ *
32
+ * @param projectId - The Firebase project id whose tokens will be verified.
33
+ * @returns A verifier that validates ID tokens for `projectId`.
34
+ * @example
35
+ * ```ts
36
+ * const verifier = createRemoteFirebaseVerifier('my-firebase-project');
37
+ * const decoded = await verifier.verifyIdToken(idToken);
38
+ * console.log(decoded.uid);
39
+ * ```
40
+ */
14
41
  export function createRemoteFirebaseVerifier(projectId) {
15
42
  jwks ??= createRemoteJWKSet(new URL(SECURETOKEN_JWK_URL));
16
43
  let verifier = verifiers.get(projectId);
@@ -20,12 +47,34 @@ export function createRemoteFirebaseVerifier(projectId) {
20
47
  }
21
48
  return verifier;
22
49
  }
50
+ /**
51
+ * Single-entry cache of the service-account verifier, keyed by the raw service-account JSON.
52
+ *
53
+ * @internal
54
+ */
23
55
  let saVerifierCache = null;
24
56
  /**
25
- * サービスアカウント JSON から検証器を作る便宜ファクトリ(receptray/tipsys hono `firebaseFor` 相当)。
26
- * `getUser`/`deleteUser` のため `IdentityToolkit` を内包する点が `createRemoteFirebaseVerifier` との違い。
27
- * SA JSON 文字列をキーに isolate 内で 1 つだけキャッシュ(秘密が変わったときだけ再生成)し、
28
- * JWKS `createRemoteFirebaseVerifier` と共有する。
57
+ * Create a Firebase verifier from a service-account JSON string.
58
+ *
59
+ * Unlike {@link createRemoteFirebaseVerifier}, the returned {@link JoseFirebaseVerifier}
60
+ * embeds an {@link IdentityToolkit} client, enabling `getUser` and `deleteUser` in addition to
61
+ * token verification.
62
+ *
63
+ * @remarks
64
+ * The verifier is cached for the lifetime of the isolate, keyed by the service-account JSON
65
+ * string, and is only rebuilt when that secret changes. The remote JWKS is shared with
66
+ * {@link createRemoteFirebaseVerifier}.
67
+ *
68
+ * @param serviceAccountJson - The service-account key as a JSON string (parsed into {@link ServiceAccount}).
69
+ * @returns A verifier that validates ID tokens and can look up or delete users.
70
+ * @throws If `serviceAccountJson` is not valid JSON.
71
+ * @example
72
+ * ```ts
73
+ * const verifier = createServiceAccountVerifier(env.FIREBASE_SERVICE_ACCOUNT);
74
+ * const decoded = await verifier.verifyIdToken(idToken);
75
+ * const user = await verifier.getUser(decoded.uid);
76
+ * await verifier.deleteUser(decoded.uid);
77
+ * ```
29
78
  */
30
79
  export function createServiceAccountVerifier(serviceAccountJson) {
31
80
  if (saVerifierCache?.key !== serviceAccountJson) {
@@ -1,19 +1,52 @@
1
+ /**
2
+ * The resolved runtime environment of the Worker.
3
+ */
1
4
  export type AppEnv = 'development' | 'production';
2
5
  /**
3
- * 実行環境(development / production)を解決する。フリート共通の判定。
6
+ * Resolve the runtime environment (development or production) from the Worker `env` binding.
7
+ *
8
+ * @remarks
9
+ * Cloudflare Workers have no filesystem or `child_process` at runtime, so the environment cannot be
10
+ * inferred from the presence of a `.git` directory the way a Node/NestJS process might. Instead, the
11
+ * development signal is carried in the committed launch command: `wrangler dev --var APP_ENV:development`
12
+ * injects `APP_ENV`, while `wrangler deploy` injects nothing. Only `env.APP_ENV === 'development'`
13
+ * resolves to `'development'`; every other case (including a missing binding, i.e. a production deploy)
14
+ * resolves to `'production'`. This "absence defaults to production" semantic keeps the safe side as the
15
+ * default.
16
+ *
17
+ * Because it reads from `env` rather than a request header, it works in both `fetch` and `scheduled`
18
+ * contexts and cannot be spoofed by an incoming request.
4
19
  *
5
- * NestJS `/api` は実行時 FS `.git` 有無で判定し「git throw catch → 本番」としていた。
6
- * Workers は実行時に FS / child_process が無いため同じ手は使えない。代わりに dev シグナルを
7
- * **コミット済みの起動コマンド**に置く: `wrangler dev --var APP_ENV:development`(`deploy` は無注入)。
8
- * よって `env.APP_ENV === 'development'` の時だけ development、それ以外(注入無し=本番デプロイ)は
9
- * production に倒す。これは `/api` の「absence/catch = 本番(安全側)」と同じ意味論。
20
+ * @param env - The Worker environment binding, or `null`/`undefined` when unavailable.
21
+ * @returns `'development'` only when `env.APP_ENV` is exactly `'development'`; otherwise `'production'`.
10
22
  *
11
- * `env` 由来なので fetch / scheduled どちらの文脈でも使え、リクエストヘッダ由来でないため詐称されない。
23
+ * @example
24
+ * ```ts
25
+ * export default {
26
+ * fetch(req, env) {
27
+ * if (resolveAppEnv(env) === 'development') {
28
+ * // enable verbose logging
29
+ * }
30
+ * },
31
+ * };
32
+ * ```
12
33
  */
13
34
  export declare function resolveAppEnv(env: {
14
35
  APP_ENV?: string;
15
36
  } | null | undefined): AppEnv;
16
- /** production 判定のショートハンド。 */
37
+ /**
38
+ * Shorthand for checking whether the resolved environment is production.
39
+ *
40
+ * @param env - The Worker environment binding, or `null`/`undefined` when unavailable.
41
+ * @returns `true` when {@link resolveAppEnv} resolves to `'production'`.
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * if (isProductionEnv(env)) {
46
+ * // skip dev-only diagnostics
47
+ * }
48
+ * ```
49
+ */
17
50
  export declare const isProductionEnv: (env: {
18
51
  APP_ENV?: string;
19
52
  } | null | undefined) => boolean;
@@ -1,16 +1,46 @@
1
1
  /**
2
- * 実行環境(development / production)を解決する。フリート共通の判定。
2
+ * Resolve the runtime environment (development or production) from the Worker `env` binding.
3
3
  *
4
- * NestJS `/api` は実行時 FS の `.git` 有無で判定し「git が throw → catch → 本番」としていた。
5
- * Workers は実行時に FS / child_process が無いため同じ手は使えない。代わりに dev シグナルを
6
- * **コミット済みの起動コマンド**に置く: `wrangler dev --var APP_ENV:development`(`deploy` は無注入)。
7
- * よって `env.APP_ENV === 'development'` の時だけ development、それ以外(注入無し=本番デプロイ)は
8
- * production に倒す。これは `/api` の「absence/catch = 本番(安全側)」と同じ意味論。
4
+ * @remarks
5
+ * Cloudflare Workers have no filesystem or `child_process` at runtime, so the environment cannot be
6
+ * inferred from the presence of a `.git` directory the way a Node/NestJS process might. Instead, the
7
+ * development signal is carried in the committed launch command: `wrangler dev --var APP_ENV:development`
8
+ * injects `APP_ENV`, while `wrangler deploy` injects nothing. Only `env.APP_ENV === 'development'`
9
+ * resolves to `'development'`; every other case (including a missing binding, i.e. a production deploy)
10
+ * resolves to `'production'`. This "absence defaults to production" semantic keeps the safe side as the
11
+ * default.
9
12
  *
10
- * `env` 由来なので fetch / scheduled どちらの文脈でも使え、リクエストヘッダ由来でないため詐称されない。
13
+ * Because it reads from `env` rather than a request header, it works in both `fetch` and `scheduled`
14
+ * contexts and cannot be spoofed by an incoming request.
15
+ *
16
+ * @param env - The Worker environment binding, or `null`/`undefined` when unavailable.
17
+ * @returns `'development'` only when `env.APP_ENV` is exactly `'development'`; otherwise `'production'`.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * export default {
22
+ * fetch(req, env) {
23
+ * if (resolveAppEnv(env) === 'development') {
24
+ * // enable verbose logging
25
+ * }
26
+ * },
27
+ * };
28
+ * ```
11
29
  */
12
30
  export function resolveAppEnv(env) {
13
31
  return env?.APP_ENV === 'development' ? 'development' : 'production';
14
32
  }
15
- /** production 判定のショートハンド。 */
33
+ /**
34
+ * Shorthand for checking whether the resolved environment is production.
35
+ *
36
+ * @param env - The Worker environment binding, or `null`/`undefined` when unavailable.
37
+ * @returns `true` when {@link resolveAppEnv} resolves to `'production'`.
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * if (isProductionEnv(env)) {
42
+ * // skip dev-only diagnostics
43
+ * }
44
+ * ```
45
+ */
16
46
  export const isProductionEnv = (env) => resolveAppEnv(env) === 'production';
@@ -1,11 +1,33 @@
1
1
  import type { Context } from 'hono';
2
- /** クライアントアプリのメタ情報(NestJS の x-amz-meta-* ヘッダ由来。3 repo 共通)。 */
2
+ /**
3
+ * Client application metadata derived from the `x-amz-meta-*` request headers.
4
+ *
5
+ * @remarks
6
+ * Reproduces the per-request app identity that a NestJS service would expose so a Hono app
7
+ * can read the same client-supplied version/uuid pair without changing the wire contract.
8
+ */
3
9
  export interface AppInfo {
10
+ /** Client application version from `x-amz-meta-version`, or `null` when the header is absent. */
4
11
  version: string | null;
12
+ /** Client installation identifier from `x-amz-meta-uuid`, or `null` when the header is absent. */
5
13
  uuid: string | null;
6
14
  }
7
15
  /**
8
- * `x-amz-meta-version` / `x-amz-meta-uuid` ヘッダから AppInfo を読む。
9
- * auth middleware が per-request で c.set('appInfo', ...) する値(3 repo で同一仕様)。
16
+ * Read {@link AppInfo} from the `x-amz-meta-version` / `x-amz-meta-uuid` request headers.
17
+ *
18
+ * @remarks
19
+ * Typically called by an auth middleware that stores the result per request via
20
+ * `c.set('appInfo', getAppInfo(c))`. Missing headers resolve to `null` rather than throwing.
21
+ *
22
+ * @param c - The Hono request context to read headers from.
23
+ * @returns The client application metadata for the current request.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * app.use(async (c, next) => {
28
+ * c.set('appInfo', getAppInfo(c));
29
+ * await next();
30
+ * });
31
+ * ```
10
32
  */
11
33
  export declare const getAppInfo: (c: Context) => AppInfo;
@@ -1,6 +1,20 @@
1
1
  /**
2
- * `x-amz-meta-version` / `x-amz-meta-uuid` ヘッダから AppInfo を読む。
3
- * auth middleware が per-request で c.set('appInfo', ...) する値(3 repo で同一仕様)。
2
+ * Read {@link AppInfo} from the `x-amz-meta-version` / `x-amz-meta-uuid` request headers.
3
+ *
4
+ * @remarks
5
+ * Typically called by an auth middleware that stores the result per request via
6
+ * `c.set('appInfo', getAppInfo(c))`. Missing headers resolve to `null` rather than throwing.
7
+ *
8
+ * @param c - The Hono request context to read headers from.
9
+ * @returns The client application metadata for the current request.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * app.use(async (c, next) => {
14
+ * c.set('appInfo', getAppInfo(c));
15
+ * await next();
16
+ * });
17
+ * ```
4
18
  */
5
19
  export const getAppInfo = (c) => ({
6
20
  version: c.req.header('x-amz-meta-version') ?? null,
@@ -1,7 +1,11 @@
1
1
  /**
2
- * NestJS `@nestjs/common` HttpStatus enum と同一。フリート(NestJS → Hono 移植)で
3
- * ステータスコードを Nest と同じ名前で参照するための共通定数。`/api` のレスポンス status と
4
- * バイト一致させる際の単一の参照元にする。
2
+ * HTTP status codes mirroring the `HttpStatus` enum from `@nestjs/common`.
3
+ *
4
+ * @remarks
5
+ * Provides a single source of truth for referencing status codes by the same names NestJS uses, so a
6
+ * Hono app can emit responses whose status matches a NestJS service byte-for-byte. The member set and
7
+ * numeric values intentionally track `@nestjs/common` rather than the IANA registry, including a few
8
+ * non-standard codes that NestJS ships.
5
9
  */
6
10
  export declare enum HttpStatus {
7
11
  CONTINUE = 100,
@@ -17,7 +21,9 @@ export declare enum HttpStatus {
17
21
  PARTIAL_CONTENT = 206,
18
22
  MULTI_STATUS = 207,
19
23
  ALREADY_REPORTED = 208,
24
+ /** Non-standard WebDAV extension carried over from NestJS. */
20
25
  CONTENT_DIFFERENT = 210,
26
+ /** Multiple Choices (300). Named `AMBIGUOUS` to match NestJS. */
21
27
  AMBIGUOUS = 300,
22
28
  MOVED_PERMANENTLY = 301,
23
29
  FOUND = 302,
@@ -43,13 +49,16 @@ export declare enum HttpStatus {
43
49
  UNSUPPORTED_MEDIA_TYPE = 415,
44
50
  REQUESTED_RANGE_NOT_SATISFIABLE = 416,
45
51
  EXPECTATION_FAILED = 417,
52
+ /** "I'm a teapot" (418), from RFC 2324. */
46
53
  I_AM_A_TEAPOT = 418,
54
+ /** Misdirected Request (421). Named `MISDIRECTED` to match NestJS. */
47
55
  MISDIRECTED = 421,
48
56
  UNPROCESSABLE_ENTITY = 422,
49
57
  LOCKED = 423,
50
58
  FAILED_DEPENDENCY = 424,
51
59
  PRECONDITION_REQUIRED = 428,
52
60
  TOO_MANY_REQUESTS = 429,
61
+ /** Non-standard code carried over from NestJS. */
53
62
  UNRECOVERABLE_ERROR = 456,
54
63
  INTERNAL_SERVER_ERROR = 500,
55
64
  NOT_IMPLEMENTED = 501,
@@ -1,7 +1,11 @@
1
1
  /**
2
- * NestJS `@nestjs/common` HttpStatus enum と同一。フリート(NestJS → Hono 移植)で
3
- * ステータスコードを Nest と同じ名前で参照するための共通定数。`/api` のレスポンス status と
4
- * バイト一致させる際の単一の参照元にする。
2
+ * HTTP status codes mirroring the `HttpStatus` enum from `@nestjs/common`.
3
+ *
4
+ * @remarks
5
+ * Provides a single source of truth for referencing status codes by the same names NestJS uses, so a
6
+ * Hono app can emit responses whose status matches a NestJS service byte-for-byte. The member set and
7
+ * numeric values intentionally track `@nestjs/common` rather than the IANA registry, including a few
8
+ * non-standard codes that NestJS ships.
5
9
  */
6
10
  export var HttpStatus;
7
11
  (function (HttpStatus) {
@@ -18,7 +22,9 @@ export var HttpStatus;
18
22
  HttpStatus[HttpStatus["PARTIAL_CONTENT"] = 206] = "PARTIAL_CONTENT";
19
23
  HttpStatus[HttpStatus["MULTI_STATUS"] = 207] = "MULTI_STATUS";
20
24
  HttpStatus[HttpStatus["ALREADY_REPORTED"] = 208] = "ALREADY_REPORTED";
25
+ /** Non-standard WebDAV extension carried over from NestJS. */
21
26
  HttpStatus[HttpStatus["CONTENT_DIFFERENT"] = 210] = "CONTENT_DIFFERENT";
27
+ /** Multiple Choices (300). Named `AMBIGUOUS` to match NestJS. */
22
28
  HttpStatus[HttpStatus["AMBIGUOUS"] = 300] = "AMBIGUOUS";
23
29
  HttpStatus[HttpStatus["MOVED_PERMANENTLY"] = 301] = "MOVED_PERMANENTLY";
24
30
  HttpStatus[HttpStatus["FOUND"] = 302] = "FOUND";
@@ -44,13 +50,16 @@ export var HttpStatus;
44
50
  HttpStatus[HttpStatus["UNSUPPORTED_MEDIA_TYPE"] = 415] = "UNSUPPORTED_MEDIA_TYPE";
45
51
  HttpStatus[HttpStatus["REQUESTED_RANGE_NOT_SATISFIABLE"] = 416] = "REQUESTED_RANGE_NOT_SATISFIABLE";
46
52
  HttpStatus[HttpStatus["EXPECTATION_FAILED"] = 417] = "EXPECTATION_FAILED";
53
+ /** "I'm a teapot" (418), from RFC 2324. */
47
54
  HttpStatus[HttpStatus["I_AM_A_TEAPOT"] = 418] = "I_AM_A_TEAPOT";
55
+ /** Misdirected Request (421). Named `MISDIRECTED` to match NestJS. */
48
56
  HttpStatus[HttpStatus["MISDIRECTED"] = 421] = "MISDIRECTED";
49
57
  HttpStatus[HttpStatus["UNPROCESSABLE_ENTITY"] = 422] = "UNPROCESSABLE_ENTITY";
50
58
  HttpStatus[HttpStatus["LOCKED"] = 423] = "LOCKED";
51
59
  HttpStatus[HttpStatus["FAILED_DEPENDENCY"] = 424] = "FAILED_DEPENDENCY";
52
60
  HttpStatus[HttpStatus["PRECONDITION_REQUIRED"] = 428] = "PRECONDITION_REQUIRED";
53
61
  HttpStatus[HttpStatus["TOO_MANY_REQUESTS"] = 429] = "TOO_MANY_REQUESTS";
62
+ /** Non-standard code carried over from NestJS. */
54
63
  HttpStatus[HttpStatus["UNRECOVERABLE_ERROR"] = 456] = "UNRECOVERABLE_ERROR";
55
64
  HttpStatus[HttpStatus["INTERNAL_SERVER_ERROR"] = 500] = "INTERNAL_SERVER_ERROR";
56
65
  HttpStatus[HttpStatus["NOT_IMPLEMENTED"] = 501] = "NOT_IMPLEMENTED";