@rdlabo/workers-hono-kit 0.1.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 +160 -24
  13. package/dist/db/database.js +51 -7
  14. package/dist/db/index.d.ts +21 -10
  15. package/dist/db/index.js +17 -8
  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 +81 -9
  28. package/dist/firebase/jose-firebase-verifier.js +68 -7
  29. package/dist/firebase/remote-verifier.d.ts +43 -5
  30. package/dist/firebase/remote-verifier.js +60 -11
  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 +41 -30
  42. package/dist/index.js +29 -21
  43. package/dist/middleware/auth.d.ts +75 -14
  44. package/dist/middleware/auth.js +31 -7
  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 +60 -12
  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 +79 -11
  60. package/dist/testing/fakes.js +70 -8
  61. package/dist/testing/index.d.ts +15 -8
  62. package/dist/testing/index.js +15 -10
  63. package/dist/testing/stripe-fixtures.d.ts +93 -3
  64. package/dist/testing/stripe-fixtures.js +93 -3
  65. package/package.json +19 -9
  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 +163 -27
  72. package/src/db/index.ts +21 -12
  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 +81 -11
  80. package/src/firebase/remote-verifier.ts +61 -12
  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 +47 -33
  87. package/src/middleware/auth.ts +79 -17
  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 +60 -12
  93. package/src/testing/configurable-fake.ts +23 -11
  94. package/src/testing/db.ts +82 -13
  95. package/src/testing/fakes.ts +80 -12
  96. package/src/testing/index.ts +18 -13
  97. package/src/testing/stripe-fixtures.ts +93 -3
@@ -1,20 +1,43 @@
1
1
  import type { Pool } from 'mysql2/promise';
2
- import { databaseFrom } from '../db/database';
3
- import type { DisposableDatabase } from '../db/database';
4
- import type { DecodedIdToken, FirebaseVerifier } from '../firebase/firebase-verifier';
2
+ import { databaseFrom } from '../db/database.js';
3
+ import type { DisposableDatabase } from '../db/database.js';
4
+ import type { DecodedIdToken, FirebaseVerifier } from '../firebase/firebase-verifier.js';
5
5
 
6
6
  /**
7
- * オフライン route テスト用の in-memory FirebaseVerifier(4 repo 同一実装を集約)。
8
- * `register(token, { uid })` で偽 ID を仕込む。
7
+ * In-memory {@link FirebaseVerifier} implementation for offline route tests.
8
+ *
9
+ * Seed fake identities with {@link FakeFirebaseVerifier.register | register(token, { uid })}, then
10
+ * verification resolves the registered decoded token instead of calling a real Firebase backend.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * const firebase = new FakeFirebaseVerifier();
15
+ * firebase.register('tok-1', { uid: 'uid-1' });
16
+ * const decoded = await firebase.verifyIdToken('tok-1'); // { uid: 'uid-1' }
17
+ * ```
9
18
  */
10
19
  export class FakeFirebaseVerifier implements FirebaseVerifier {
11
20
  private readonly tokens = new Map<string, DecodedIdToken>();
21
+ /** UIDs passed to {@link FakeFirebaseVerifier.deleteUser}, in call order, for assertions. */
12
22
  readonly deleted: string[] = [];
13
23
 
24
+ /**
25
+ * Register a fake decoded token so that {@link FakeFirebaseVerifier.verifyIdToken} resolves it.
26
+ *
27
+ * @param token - Token string clients will present.
28
+ * @param record - Decoded token returned on verification (must include `uid`).
29
+ */
14
30
  register(token: string, record: DecodedIdToken): void {
15
31
  this.tokens.set(token, record);
16
32
  }
17
33
 
34
+ /**
35
+ * Resolve the decoded token previously registered for `idToken`.
36
+ *
37
+ * @param idToken - Token string to verify.
38
+ * @returns The registered decoded token.
39
+ * @throws Error if the token was never registered.
40
+ */
18
41
  async verifyIdToken(idToken: string): Promise<DecodedIdToken> {
19
42
  const record = this.tokens.get(idToken);
20
43
  if (!record) {
@@ -23,25 +46,57 @@ export class FakeFirebaseVerifier implements FirebaseVerifier {
23
46
  return record;
24
47
  }
25
48
 
49
+ /**
50
+ * Return a minimal user record echoing the requested UID.
51
+ *
52
+ * @param uid - UID to look up.
53
+ * @returns An object containing the `uid` (never `null` in this fake).
54
+ */
26
55
  async getUser(uid: string): Promise<{ uid: string; email?: string } | null> {
27
56
  return { uid };
28
57
  }
29
58
 
59
+ /**
60
+ * Record a user deletion by appending the UID to {@link FakeFirebaseVerifier.deleted}.
61
+ *
62
+ * @param uid - UID being deleted.
63
+ */
30
64
  async deleteUser(uid: string): Promise<void> {
31
65
  this.deleted.push(uid);
32
66
  }
33
67
  }
34
68
 
69
+ /**
70
+ * Options for {@link createPoolDatabase}.
71
+ *
72
+ * @typeParam TDrizzle - The Drizzle instance type, supplied by the consumer so that type identity is
73
+ * not coupled to this package's copy of `drizzle-orm`.
74
+ */
35
75
  export interface CreatePoolDatabaseOptions<TDrizzle> {
36
- /** テスト用プール(primary/replica 兼用)。 */
76
+ /** Test pool used as both primary and replica. */
37
77
  pool: Pool;
38
- /** 消費側の drizzle-orm `drizzle(pool, { schema, ... })` を作って渡す。 */
78
+ /** Drizzle instance built by the consumer with its own `drizzle-orm`, e.g. `drizzle(pool, { schema, ... })`. */
39
79
  orm: TDrizzle;
40
80
  }
41
81
 
42
82
  /**
43
- * テスト用にプール 1 本を primary/replica 兼用にした Database(foodlabel PoolDatabase 相当)。
44
- * `dispose()` はプールを閉じる。orm は消費側が自分の drizzle-orm で作って渡す(型同一性の分離)。
83
+ * Create a `Database` backed by a single pool used as both primary and replica, suitable for tests.
84
+ *
85
+ * @remarks
86
+ * `dispose()` ends the pool. The `orm` is provided by the caller (rather than constructed here) so
87
+ * the returned database uses the consumer's own `drizzle-orm` types, avoiding type-identity clashes
88
+ * across duplicated `drizzle-orm` installs.
89
+ *
90
+ * @typeParam TDrizzle - The Drizzle instance type provided by the consumer.
91
+ * @param options - Pool and Drizzle instance. See {@link CreatePoolDatabaseOptions}.
92
+ * @returns A {@link DisposableDatabase} whose `dispose()` closes the pool.
93
+ * @example
94
+ * ```ts
95
+ * const pool = testDb.createTestPool();
96
+ * const db = createPoolDatabase({ pool, orm: drizzle(pool, { schema }) });
97
+ * // ... run tests ...
98
+ * await db.dispose();
99
+ * ```
45
100
  */
46
101
  export function createPoolDatabase<TDrizzle>(
47
102
  options: CreatePoolDatabaseOptions<TDrizzle>,
@@ -57,9 +112,22 @@ export function createPoolDatabase<TDrizzle>(
57
112
  }
58
113
 
59
114
  /**
60
- * DB に触れない route(GET / 等)用の Database スタブ。write/transaction は誤用検知のため throw。
61
- * dispose は no-op(Hyperdrive/Pool 背面の DisposableDatabase を期待する repo でもそのまま使える)。
62
- * orm 型は呼び出し側が指定(既定 unknown)。
115
+ * Create a no-op `Database` stub for routes that never touch the database (e.g. plain GET handlers).
116
+ *
117
+ * @remarks
118
+ * `read` resolves to an empty array, while `write` and `transaction` throw so that any unexpected
119
+ * database access is caught as a misuse. `dispose` is a no-op, so this can stand in for a
120
+ * {@link DisposableDatabase} backing (e.g. a Hyperdrive- or pool-based one) without changes.
121
+ *
122
+ * @typeParam TDrizzle - The Drizzle instance type the consumer expects (defaults to `unknown`).
123
+ * @returns A {@link DisposableDatabase} that reads empty and throws on writes/transactions.
124
+ * @throws Error from `write`/`transaction` if they are accessed.
125
+ * @example
126
+ * ```ts
127
+ * const db = createNoopDatabase();
128
+ * await db.read('SELECT 1'); // []
129
+ * await db.write(async (dz) => dz); // throws: noopDatabase.write accessed unexpectedly
130
+ * ```
63
131
  */
64
132
  export function createNoopDatabase<TDrizzle = unknown>(): DisposableDatabase<TDrizzle> {
65
133
  return {
@@ -1,20 +1,25 @@
1
- // @rdlabo/workers-hono-kit/testing — フリート共通のテスト基盤(mysql2/drizzle 依存)。
2
- // 実行時には読み込まれないテスト専用ヘルパ。各 repo testing/db.ts・fakes.ts を集約。
1
+ /**
2
+ * Shared test infrastructure for Hono on Cloudflare Workers projects (depends on `mysql2`/`drizzle-orm`).
3
+ *
4
+ * Test-only helpers that are never loaded at runtime. This subpath consolidates the duplicated
5
+ * test boilerplate (test DB setup, in-memory fakes, auth header builders, Stripe fixtures) that
6
+ * tends to be copy-pasted across projects into a single, importable surface.
7
+ */
3
8
 
4
- export { createTestDb } from './db';
5
- export type { TestDb, CreateTestDbOptions, TestDbConnection } from './db';
9
+ export { createTestDb } from './db.js';
10
+ export type { TestDb, CreateTestDbOptions, TestDbConnection } from './db.js';
6
11
 
7
- export { FakeFirebaseVerifier, createPoolDatabase, createNoopDatabase } from './fakes';
8
- export type { CreatePoolDatabaseOptions } from './fakes';
9
- export type { Database, DisposableDatabase, QueryRunner, TxOf } from '../db/database';
12
+ export { FakeFirebaseVerifier, createPoolDatabase, createNoopDatabase } from './fakes.js';
13
+ export type { CreatePoolDatabaseOptions } from './fakes.js';
14
+ export type { Database, DisposableDatabase, QueryRunner, TxOf } from '../db/database.js';
10
15
 
11
- // 認証テストヘルパ(route spec のヘッダ生成・ユーザ provision を集約)。
12
- export { authHeaders, registerFirebaseToken, provisionUser } from './auth';
16
+ // Authentication test helpers (route-spec header builders and user provisioning).
17
+ export { authHeaders, registerFirebaseToken, provisionUser } from './auth.js';
13
18
 
14
- // test double ヘルパ(未設定メソッドで明示 throw する部分実装 fake)。
15
- export { configurableFake } from './configurable-fake';
19
+ // Test double helper (partial-implementation fake that throws explicitly on unconfigured members).
20
+ export { configurableFake } from './configurable-fake.js';
16
21
 
17
- // Stripe オブジェクトの test fixture factory。
22
+ // Test fixture factories for Stripe objects.
18
23
  export {
19
24
  fakeApiList,
20
25
  fakePaymentIntent,
@@ -23,4 +28,4 @@ export {
23
28
  fakeCustomer,
24
29
  fakePrice,
25
30
  fakeSubscription,
26
- } from './stripe-fixtures';
31
+ } from './stripe-fixtures.js';
@@ -1,11 +1,27 @@
1
1
  import type Stripe from 'stripe';
2
2
 
3
3
  /**
4
- * Stripe オブジェクトの test fixture factory。実 SDK 型は巨大なので、テストが参照する範囲だけを
5
- * 妥当な既定値で組み、`over` で上書きする(最後に 1 度だけ Stripe 型へキャスト)。fleet 各 repo の
6
- * 課金テストで同じダミー PaymentIntent/Event/... を手組みしていた重複を集約する。
4
+ * Test fixture factories for Stripe objects.
5
+ *
6
+ * The real SDK types are enormous, so each factory builds only the fields tests typically read,
7
+ * fills them with reasonable defaults, lets you override via `over`, and casts to the Stripe type
8
+ * once at the end. This consolidates the duplicated hand-built dummy `PaymentIntent`/`Event`/... that
9
+ * billing tests tend to reconstruct in every project.
7
10
  */
8
11
 
12
+ /**
13
+ * Build a fake Stripe `ApiList` wrapping the given data.
14
+ *
15
+ * @remarks Defaults: `object: 'list'`, `has_more: false`, `url: '/v1/_test'`.
16
+ * @typeParam T - Element type of the list.
17
+ * @param data - Items to place in `data`.
18
+ * @param over - Field overrides merged last.
19
+ * @returns A `Stripe.ApiList<T>` fixture.
20
+ * @example
21
+ * ```ts
22
+ * const list = fakeApiList([fakePaymentIntent()]);
23
+ * ```
24
+ */
9
25
  export function fakeApiList<T>(data: T[], over: Partial<Stripe.ApiList<T>> = {}): Stripe.ApiList<T> {
10
26
  return {
11
27
  object: 'list',
@@ -16,6 +32,18 @@ export function fakeApiList<T>(data: T[], over: Partial<Stripe.ApiList<T>> = {})
16
32
  };
17
33
  }
18
34
 
35
+ /**
36
+ * Build a fake Stripe `PaymentIntent`.
37
+ *
38
+ * @remarks Defaults: `id: 'pi_test_1'`, `object: 'payment_intent'`, `amount: 1000`, `currency: 'jpy'`,
39
+ * `status: 'succeeded'`, `created: 1_700_000_000`.
40
+ * @param over - Field overrides merged last.
41
+ * @returns A `Stripe.PaymentIntent` fixture.
42
+ * @example
43
+ * ```ts
44
+ * const pi = fakePaymentIntent({ status: 'requires_payment_method' });
45
+ * ```
46
+ */
19
47
  export function fakePaymentIntent(over: Partial<Stripe.PaymentIntent> = {}): Stripe.PaymentIntent {
20
48
  return {
21
49
  id: 'pi_test_1',
@@ -28,6 +56,20 @@ export function fakePaymentIntent(over: Partial<Stripe.PaymentIntent> = {}): Str
28
56
  } as Stripe.PaymentIntent;
29
57
  }
30
58
 
59
+ /**
60
+ * Build a fake Stripe webhook `Event` wrapping the given payload.
61
+ *
62
+ * @remarks Defaults: `id: 'evt_test_1'`, `object: 'event'`, `api_version: '2024-06-20'`,
63
+ * `created: 1_700_000_000`, `livemode: false`. The payload is placed at `data.object`.
64
+ * @param type - Event type (e.g. `'payment_intent.succeeded'`), assigned to `type`.
65
+ * @param dataObject - The object placed at `data.object`.
66
+ * @param over - Field overrides merged last.
67
+ * @returns A `Stripe.Event` fixture.
68
+ * @example
69
+ * ```ts
70
+ * const event = fakeStripeEvent('payment_intent.succeeded', fakePaymentIntent());
71
+ * ```
72
+ */
31
73
  export function fakeStripeEvent(type: string, dataObject: unknown, over: Partial<Stripe.Event> = {}): Stripe.Event {
32
74
  return {
33
75
  id: 'evt_test_1',
@@ -41,6 +83,18 @@ export function fakeStripeEvent(type: string, dataObject: unknown, over: Partial
41
83
  } as Stripe.Event;
42
84
  }
43
85
 
86
+ /**
87
+ * Build a fake Stripe `Checkout.Session`.
88
+ *
89
+ * @remarks Defaults: `id: 'cs_test_1'`, `object: 'checkout.session'`,
90
+ * `url: 'https://checkout.stripe.test/cs_test_1'`, `mode: 'subscription'`, `status: 'open'`.
91
+ * @param over - Field overrides merged last.
92
+ * @returns A `Stripe.Checkout.Session` fixture.
93
+ * @example
94
+ * ```ts
95
+ * const session = fakeCheckoutSession({ status: 'complete' });
96
+ * ```
97
+ */
44
98
  export function fakeCheckoutSession(over: Partial<Stripe.Checkout.Session> = {}): Stripe.Checkout.Session {
45
99
  return {
46
100
  id: 'cs_test_1',
@@ -52,6 +106,18 @@ export function fakeCheckoutSession(over: Partial<Stripe.Checkout.Session> = {})
52
106
  } as Stripe.Checkout.Session;
53
107
  }
54
108
 
109
+ /**
110
+ * Build a fake Stripe `Customer`.
111
+ *
112
+ * @remarks Defaults: `id: 'cus_test_1'`, `object: 'customer'`, `created: 1_700_000_000`,
113
+ * `livemode: false`.
114
+ * @param over - Field overrides merged last.
115
+ * @returns A `Stripe.Customer` fixture.
116
+ * @example
117
+ * ```ts
118
+ * const customer = fakeCustomer({ email: 'a@example.com' });
119
+ * ```
120
+ */
55
121
  export function fakeCustomer(over: Partial<Stripe.Customer> = {}): Stripe.Customer {
56
122
  return {
57
123
  id: 'cus_test_1',
@@ -62,6 +128,18 @@ export function fakeCustomer(over: Partial<Stripe.Customer> = {}): Stripe.Custom
62
128
  } as Stripe.Customer;
63
129
  }
64
130
 
131
+ /**
132
+ * Build a fake Stripe `Price`.
133
+ *
134
+ * @remarks Defaults: `id: 'price_test_1'`, `object: 'price'`, `active: true`, `currency: 'jpy'`,
135
+ * `unit_amount: 1000`.
136
+ * @param over - Field overrides merged last.
137
+ * @returns A `Stripe.Price` fixture.
138
+ * @example
139
+ * ```ts
140
+ * const price = fakePrice({ unit_amount: 2000 });
141
+ * ```
142
+ */
65
143
  export function fakePrice(over: Partial<Stripe.Price> = {}): Stripe.Price {
66
144
  return {
67
145
  id: 'price_test_1',
@@ -73,6 +151,18 @@ export function fakePrice(over: Partial<Stripe.Price> = {}): Stripe.Price {
73
151
  } as Stripe.Price;
74
152
  }
75
153
 
154
+ /**
155
+ * Build a fake Stripe `Subscription`.
156
+ *
157
+ * @remarks Defaults: `id: 'sub_test_1'`, `object: 'subscription'`, `status: 'active'`,
158
+ * `customer: 'cus_test_1'`, `created: 1_700_000_000`.
159
+ * @param over - Field overrides merged last.
160
+ * @returns A `Stripe.Subscription` fixture.
161
+ * @example
162
+ * ```ts
163
+ * const sub = fakeSubscription({ status: 'canceled' });
164
+ * ```
165
+ */
76
166
  export function fakeSubscription(over: Partial<Stripe.Subscription> = {}): Stripe.Subscription {
77
167
  return {
78
168
  id: 'sub_test_1',