@exabugs/dynamodb-client 1.21.0 → 1.23.0

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 (110) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +2 -1
  3. package/bin/dynamodb-admins.js +6 -0
  4. package/dist/admins/add.d.ts +60 -0
  5. package/dist/admins/add.d.ts.map +1 -0
  6. package/dist/admins/add.js +37 -0
  7. package/dist/admins/add.js.map +1 -0
  8. package/dist/admins/index.d.ts +12 -0
  9. package/dist/admins/index.d.ts.map +1 -0
  10. package/dist/admins/index.js +10 -0
  11. package/dist/admins/index.js.map +1 -0
  12. package/dist/admins/record.d.ts +44 -0
  13. package/dist/admins/record.d.ts.map +1 -0
  14. package/dist/admins/record.js +44 -0
  15. package/dist/admins/record.js.map +1 -0
  16. package/dist/integrations/react-admin/components/Admins/AdminDeleteButton.d.ts +12 -0
  17. package/dist/integrations/react-admin/components/Admins/AdminDeleteButton.d.ts.map +1 -0
  18. package/dist/integrations/react-admin/components/Admins/AdminDeleteButton.js +32 -0
  19. package/dist/integrations/react-admin/components/Admins/AdminDeleteButton.js.map +1 -0
  20. package/dist/integrations/react-admin/components/Admins/AdminsCreate.d.ts +12 -0
  21. package/dist/integrations/react-admin/components/Admins/AdminsCreate.d.ts.map +1 -0
  22. package/dist/integrations/react-admin/components/Admins/AdminsCreate.js +55 -0
  23. package/dist/integrations/react-admin/components/Admins/AdminsCreate.js.map +1 -0
  24. package/dist/integrations/react-admin/components/Admins/AdminsList.d.ts +19 -0
  25. package/dist/integrations/react-admin/components/Admins/AdminsList.d.ts.map +1 -0
  26. package/dist/integrations/react-admin/components/Admins/AdminsList.js +14 -0
  27. package/dist/integrations/react-admin/components/Admins/AdminsList.js.map +1 -0
  28. package/dist/integrations/react-admin/components/Admins/AdminsShow.d.ts +4 -0
  29. package/dist/integrations/react-admin/components/Admins/AdminsShow.d.ts.map +1 -0
  30. package/dist/integrations/react-admin/components/Admins/AdminsShow.js +11 -0
  31. package/dist/integrations/react-admin/components/Admins/AdminsShow.js.map +1 -0
  32. package/dist/integrations/react-admin/components/Admins/adminsResource.d.ts +21 -0
  33. package/dist/integrations/react-admin/components/Admins/adminsResource.d.ts.map +1 -0
  34. package/dist/integrations/react-admin/components/Admins/adminsResource.js +21 -0
  35. package/dist/integrations/react-admin/components/Admins/adminsResource.js.map +1 -0
  36. package/dist/integrations/react-admin/components/Admins/adminsView.d.ts +30 -0
  37. package/dist/integrations/react-admin/components/Admins/adminsView.d.ts.map +1 -0
  38. package/dist/integrations/react-admin/components/Admins/adminsView.js +38 -0
  39. package/dist/integrations/react-admin/components/Admins/adminsView.js.map +1 -0
  40. package/dist/integrations/react-admin/components/Admins/index.d.ts +13 -0
  41. package/dist/integrations/react-admin/components/Admins/index.d.ts.map +1 -0
  42. package/dist/integrations/react-admin/components/Admins/index.js +8 -0
  43. package/dist/integrations/react-admin/components/Admins/index.js.map +1 -0
  44. package/dist/integrations/react-admin/components/Admins/useAdminsMessages.d.ts +7 -0
  45. package/dist/integrations/react-admin/components/Admins/useAdminsMessages.d.ts.map +1 -0
  46. package/dist/integrations/react-admin/components/Admins/useAdminsMessages.js +20 -0
  47. package/dist/integrations/react-admin/components/Admins/useAdminsMessages.js.map +1 -0
  48. package/dist/integrations/react-admin/components/index.d.ts +2 -1
  49. package/dist/integrations/react-admin/components/index.d.ts.map +1 -1
  50. package/dist/integrations/react-admin/components/index.js +2 -1
  51. package/dist/integrations/react-admin/components/index.js.map +1 -1
  52. package/dist/integrations/react-admin/i18n/createI18nProvider.d.ts +27 -0
  53. package/dist/integrations/react-admin/i18n/createI18nProvider.d.ts.map +1 -0
  54. package/dist/integrations/react-admin/i18n/createI18nProvider.js +42 -0
  55. package/dist/integrations/react-admin/i18n/createI18nProvider.js.map +1 -0
  56. package/dist/integrations/react-admin/i18n/index.d.ts +11 -0
  57. package/dist/integrations/react-admin/i18n/index.d.ts.map +1 -0
  58. package/dist/integrations/react-admin/i18n/index.js +9 -0
  59. package/dist/integrations/react-admin/i18n/index.js.map +1 -0
  60. package/dist/integrations/react-admin/i18n/merge.d.ts +15 -0
  61. package/dist/integrations/react-admin/i18n/merge.d.ts.map +1 -0
  62. package/dist/integrations/react-admin/i18n/merge.js +31 -0
  63. package/dist/integrations/react-admin/i18n/merge.js.map +1 -0
  64. package/dist/integrations/react-admin/i18n/raJapaneseMessages.d.ts +194 -0
  65. package/dist/integrations/react-admin/i18n/raJapaneseMessages.d.ts.map +1 -0
  66. package/dist/integrations/react-admin/i18n/raJapaneseMessages.js +202 -0
  67. package/dist/integrations/react-admin/i18n/raJapaneseMessages.js.map +1 -0
  68. package/dist/integrations/react-admin/i18n/resources.d.ts +55 -0
  69. package/dist/integrations/react-admin/i18n/resources.d.ts.map +1 -0
  70. package/dist/integrations/react-admin/i18n/resources.js +49 -0
  71. package/dist/integrations/react-admin/i18n/resources.js.map +1 -0
  72. package/dist/integrations/react-admin/index.d.ts +1 -0
  73. package/dist/integrations/react-admin/index.d.ts.map +1 -1
  74. package/dist/integrations/react-admin/index.js +2 -0
  75. package/dist/integrations/react-admin/index.js.map +1 -1
  76. package/dist/notify/admins.d.ts.map +1 -1
  77. package/dist/notify/admins.js +3 -3
  78. package/dist/notify/admins.js.map +1 -1
  79. package/dist/notify/ops/index.d.ts +10 -0
  80. package/dist/notify/ops/index.d.ts.map +1 -0
  81. package/dist/notify/ops/index.js +9 -0
  82. package/dist/notify/ops/index.js.map +1 -0
  83. package/dist/notify/ops-notify.d.ts +106 -0
  84. package/dist/notify/ops-notify.d.ts.map +1 -0
  85. package/dist/notify/ops-notify.js +205 -0
  86. package/dist/notify/ops-notify.js.map +1 -0
  87. package/dist/notify/store.d.ts +5 -0
  88. package/dist/notify/store.d.ts.map +1 -1
  89. package/dist/notify/store.js +9 -2
  90. package/dist/notify/store.js.map +1 -1
  91. package/dist/server/handler.cjs +3 -3
  92. package/dist/server/media-handler.cjs +2 -2
  93. package/dist/server/media-process-handler-dlq.cjs +2 -2
  94. package/dist/server/media-process-handler.cjs +2 -2
  95. package/dist/tools/dynamodb-admins/cli.d.ts +39 -0
  96. package/dist/tools/dynamodb-admins/cli.d.ts.map +1 -0
  97. package/dist/tools/dynamodb-admins/cli.js +174 -0
  98. package/dist/tools/dynamodb-admins/cli.js.map +1 -0
  99. package/dist/tools/dynamodb-admins/index.d.ts +6 -0
  100. package/dist/tools/dynamodb-admins/index.d.ts.map +1 -0
  101. package/dist/tools/dynamodb-admins/index.js +5 -0
  102. package/dist/tools/dynamodb-admins/index.js.map +1 -0
  103. package/dist/tools/dynamodb-admins/run.d.ts +2 -0
  104. package/dist/tools/dynamodb-admins/run.d.ts.map +1 -0
  105. package/dist/tools/dynamodb-admins/run.js +11 -0
  106. package/dist/tools/dynamodb-admins/run.js.map +1 -0
  107. package/docs/ADMINS.md +57 -0
  108. package/docs/NOTIFY.md +51 -0
  109. package/package.json +28 -3
  110. package/terraform/ops-notify/README.md +2 -2
package/CHANGELOG.md CHANGED
@@ -7,6 +7,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.23.0] - 2026-10-25
11
+
12
+ ### Added
13
+
14
+ - **管理者(admins)**(新しいサブパス `@exabugs/dynamodb-client/admins`。共通化の段階 2 = A2、ADR 0007 §7): レコードの形 `AdminRecord`(`id` = `email` = 作成時の小文字のメール〔どちらも不変〕、`name` は必須)、`normalizeAdminEmail`(trim + 小文字)、`isAdminEmail`、`adminEmailOf`(`email` が無い既存のレコードは `id`)、`buildAdminRecord`(誤りは `AdminInputError`)、存在確認つきの作成 `addAdmin`(既にあれば書き込まない。Records は同じ `id` の insert を黙って上書きするため)、`adminWriterOf` / `findAdmin`(`find` + id の昇順 + 1 件。`findOne` を使わない)。使い方は `docs/ADMINS.md`
15
+ - **管理者の画面 `adminsResource`**(`@exabugs/dynamodb-client/integrations/react-admin`): 一覧(メールアドレス・名前・作成日時・削除)・作成(メールの正規化と形式の検査、名前は必須、保存の前に `getMany` で存在確認)・詳細・削除(確認つき)。編集は無い(`id`・`email` は不変)。自分自身の削除を防ぐ(`preventSelfDelete`、既定 true。自分かを確かめられないときも出さない)。オプションは `name`・`icon`・`messages`・`preventSelfDelete`・`sort`。文言は `messages` → i18n(`resources.<リソース名>.fields.*`・`.messages.*`)→ 既定の日本語の順に引く(言語の切り替えに追従する)。詳細のメールアドレスは `id`(`email` が違うときだけ併記)。部品 `AdminsList`・`AdminsCreate`・`AdminsShow`・`AdminDeleteButton`・`useAdminsMessages`・`ADMINS_MESSAGES_JA`・`ADMINS_I18N_KEYS`・`adminsMessagesOf`
16
+ - **CLI `dynamodb-admins add <email> --app --env --name [--dry-run] [--confirm <env>]`**: 最初の管理者の登録。Records の IAM 版 Function URL(SSM の `/<app>/<env>/infra/dynamodb-client-api-iam-url`)を利用者の AWS の認証情報で呼ぶ。既にあれば何も書かずに終了コード 3。`--env prd` で書き込むときは `--confirm prd` が要る(無ければ何も呼ばずに終了コード 2。`--dry-run` は不要)。出力に Records の URL のホストを出す
17
+ - **管理画面の日本語化**(新しいサブパス `@exabugs/dynamodb-client/integrations/react-admin/i18n`。A4): `createI18nProvider(messages?, { defaultLocale? })`(英語 ← `ra.*` の日本語 ← このライブラリの画面のリソース名 ← アプリの文言、を入れ子ごとに重ねる。既定の言語はブラウザの言語)、`raJapaneseMessages`(asanowa・asaichi の `ra.*` の日本語)、`LIBRARY_RESOURCE_MESSAGES_JA` / `_EN`(admins の項目名と画面の文言の日本語・英語を含む)、`availableLocales`、`i18nMessagesOf`、`mergeMessages`、`normalizeLocale`
18
+ - オプションの peer に `ra-i18n-polyglot`・`ra-language-english`(`^5.0.0`。i18n のサブパスだけが読む)
19
+
20
+ ### Changed
21
+
22
+ - `createAdminDirectory`(notify)の宛先の正規化を `normalizeAdminEmail` / `isAdminEmail` に寄せた(結果は同じ)
23
+
24
+ ## [1.22.0] - 2026-10-25
25
+
26
+ ### Added
27
+
28
+ - **運用通知 Lambda のエントリ `createOpsNotifyHandler`**(新しいサブパス `@exabugs/dynamodb-client/notify/ops`。共通化の段階 1 = A5、ADR 0006 の延長): asanowa・astro に複製されていた通知のエントリ(環境変数の読み取り、Slack〔SSM の Webhook。キャッシュ〕・メール〔SES v2〕のチャネル、通知ストア、管理者の一覧、alerts の記録の配線、`SKIP_RECORD_LOG_GROUPS` が空の警告)を 1 つにした。アプリのエントリは `export const handler = createOpsNotifyHandler();` だけになる。環境変数は `terraform/ops-notify`(1.21.0)の契約どおり(`PROJECT_NAME` も必須。`app` を渡せば不要)。両アプリの差は注入: `app`、`admins`(`recipientFields`・`sortById`・`maxAdmins`・`lister` = 読み取りを権限チェック層で包む)、`alertsCollection`(書き込みを包む)、`log`、`notify`(`createNotifyHandler` に渡す設定)、`overrides`(テスト用)。既定は両アプリの現行と同じ(`failOnAnyChannelError: true`、記録の上限・遮断、alerts の HTTP の時間切れ 2500 ms)。使い方は `docs/NOTIFY.md` の「通知 Lambda のエントリ」
29
+ - `readOpsNotifyConfig`、定数 `OPS_NOTIFY_RECORD_LIMITS`・`OPS_NOTIFY_RECORD_BREAKER`・`OPS_NOTIFY_RECORD_HTTP_TIMEOUT_MS`、型
30
+ - 依存に `@aws-sdk/client-sesv2`(3.946.0。他の AWS SDK と同じ版)を加えた。SSM・SES の SDK は `notify/ops` だけが静的に import する(`notify` 本体は読まない。`--external:@aws-sdk/*` の CJS バンドルでは `require` のまま残り、Lambda の実行環境の SDK で解決される)
31
+
10
32
  ## [1.21.0] - 2026-10-24
11
33
 
12
34
  ### Added
package/README.md CHANGED
@@ -197,8 +197,9 @@ const article = await articles.findOne({ title: 'Hello DynamoDB' });
197
197
  - **[Authorization & Secure Setup](docs/AUTHORIZATION.md)** - 認可モデルと安全な構成(必読。JWT の有効性しか検証しない/管理者専用ユーザープール/`aud` 検証)
198
198
  - **[疎な検索の警告と対応](docs/SCAN_WARNING.md)** - 検索を打ち切らず、警告(SPARSE_SCAN)で気づいてインデックス・スキーマ・ロジックを見直す
199
199
  - **[Records クライアントのヘルパー](docs/RECORDS_CLIENT.md)** - Lambda から Records を呼ぶ定型(`createRecordsClient` / `withCollection` / `lazyCollection`)
200
- - **[運用通知](docs/NOTIFY.md)** - ログ・アラームを、Slack・メールで管理者へ通知する部品(`@exabugs/dynamodb-client/notify`)
200
+ - **[運用通知](docs/NOTIFY.md)** - ログ・アラームを、Slack・メールで管理者へ通知する部品(`@exabugs/dynamodb-client/notify`。通知 Lambda のエントリは `@exabugs/dynamodb-client/notify/ops`)
201
201
  - **[システム変更履歴](docs/SYSTEM_CHANGES.md)** - インフラの変更・リリースを `systemChanges` に記録し、Slack に送る部品と記録 Lambda のハンドラ(`@exabugs/dynamodb-client/system-changes`)、terraform のラッパーから記録する CLI(`dynamodb-system-change`)
202
+ - **[管理者](docs/ADMINS.md)** - `admins` のレコードの形・メールの正規化・存在確認つきの作成(`@exabugs/dynamodb-client/admins`)、管理画面(`adminsResource`)、最初の管理者を登録する CLI(`dynamodb-admins add`)。管理画面の日本語化は `@exabugs/dynamodb-client/integrations/react-admin/i18n`([react-admin-integration.md](docs/react-admin-integration.md))
202
203
  - **[Deployment](docs/DEPLOYMENT.md)** - Production deployment guide
203
204
  - **[Terraform Modules](terraform/README.md)** - Infrastructure as Code
204
205
 
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * 管理者の登録(docs/ADMINS.md の「最初の管理者の登録」)
5
+ */
6
+ import '../dist/tools/dynamodb-admins/run.js';
@@ -0,0 +1,60 @@
1
+ /**
2
+ * 管理者の作成(存在確認つき。ADR 0007 §7)
3
+ *
4
+ * 同じ `id` で insert すると、Records は存在確認をせずに黙って上書きする(条件付き書き込みが無い既知の制約)。
5
+ * そのため作成の前に、必ず `id` で存在を確かめる。管理画面(`adminsResource`)と CLI(`dynamodb-admins add`)が、
6
+ * この 1 つの手順を使う(読み書きの方法だけを差し替える)。
7
+ */
8
+ import { type AdminInput, type AdminRecord } from './record.js';
9
+ /** 存在確認と書き込みの方法(管理画面は dataProvider、CLI は Records のコレクション) */
10
+ export interface AdminWriter<R = unknown> {
11
+ /** `id` のレコードがあるか */
12
+ exists(id: string): Promise<boolean>;
13
+ /** 作成する(存在確認の後にだけ呼ばれる) */
14
+ insert(record: AdminRecord): Promise<R>;
15
+ }
16
+ export type AddAdminResult<R = unknown> = {
17
+ status: 'created';
18
+ record: AdminRecord;
19
+ inserted: R;
20
+ } | {
21
+ status: 'exists';
22
+ record: AdminRecord;
23
+ } | {
24
+ status: 'dry-run';
25
+ record: AdminRecord;
26
+ };
27
+ export interface AddAdminOptions {
28
+ /** true なら存在確認だけして、書き込まない */
29
+ dryRun?: boolean;
30
+ }
31
+ /**
32
+ * 管理者を作成する。既にあれば書き込まずに `exists` を返す(上書きしない)。
33
+ * 入力の誤り(メールの形式・空の名前)は例外
34
+ */
35
+ export declare function addAdmin<R>(input: AdminInput, writer: AdminWriter<R>, options?: AddAdminOptions): Promise<AddAdminResult<R>>;
36
+ /** `adminWriterOf` が使うコレクションの操作(Records の `Collection` が満たす) */
37
+ export interface AdminsCollectionLike {
38
+ find(filter: {
39
+ id: string;
40
+ }): {
41
+ sort(sort: {
42
+ id: 'asc';
43
+ }): {
44
+ limit(n: number): {
45
+ toArray(): Promise<unknown[]>;
46
+ };
47
+ };
48
+ };
49
+ insertOne(document: AdminRecord & {
50
+ [key: string]: unknown;
51
+ }): Promise<unknown>;
52
+ }
53
+ /**
54
+ * `id` のレコードを 1 件読む(無ければ null)。
55
+ * `findOne` は、無い id で Records が 404 と ITEM_NOT_FOUND の警告を出すので使わない(`find` + id の昇順 + 1 件)
56
+ */
57
+ export declare function findAdmin(collection: Pick<AdminsCollectionLike, 'find'>, id: string): Promise<Record<string, unknown> | null>;
58
+ /** Records のコレクションでの存在確認と書き込み */
59
+ export declare function adminWriterOf(collection: AdminsCollectionLike): AdminWriter;
60
+ //# sourceMappingURL=add.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/admins/add.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,WAAW,EAAoB,MAAM,aAAa,CAAC;AAElF,6DAA6D;AAC7D,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,OAAO;IACtC,qBAAqB;IACrB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACrC,0BAA0B;IAC1B,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACzC;AAED,MAAM,MAAM,cAAc,CAAC,CAAC,GAAG,OAAO,IAClC;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,CAAC,CAAA;CAAE,GACvD;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GACzC;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,CAAC;AAE/C,MAAM,WAAW,eAAe;IAC9B,6BAA6B;IAC7B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,CAAC,EAC9B,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EACtB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAK5B;AAED,gEAAgE;AAChE,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG;QAC5B,IAAI,CAAC,IAAI,EAAE;YAAE,EAAE,EAAE,KAAK,CAAA;SAAE,GAAG;YAAE,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG;gBAAE,OAAO,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;aAAE,CAAA;SAAE,CAAC;KACpF,CAAC;IACF,SAAS,CAAC,QAAQ,EAAE,WAAW,GAAG;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACjF;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAC7B,UAAU,EAAE,IAAI,CAAC,oBAAoB,EAAE,MAAM,CAAC,EAC9C,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAIzC;AAED,iCAAiC;AACjC,wBAAgB,aAAa,CAAC,UAAU,EAAE,oBAAoB,GAAG,WAAW,CAK3E"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * 管理者の作成(存在確認つき。ADR 0007 §7)
3
+ *
4
+ * 同じ `id` で insert すると、Records は存在確認をせずに黙って上書きする(条件付き書き込みが無い既知の制約)。
5
+ * そのため作成の前に、必ず `id` で存在を確かめる。管理画面(`adminsResource`)と CLI(`dynamodb-admins add`)が、
6
+ * この 1 つの手順を使う(読み書きの方法だけを差し替える)。
7
+ */
8
+ import { buildAdminRecord } from './record.js';
9
+ /**
10
+ * 管理者を作成する。既にあれば書き込まずに `exists` を返す(上書きしない)。
11
+ * 入力の誤り(メールの形式・空の名前)は例外
12
+ */
13
+ export async function addAdmin(input, writer, options = {}) {
14
+ const record = buildAdminRecord(input);
15
+ if (await writer.exists(record.id))
16
+ return { status: 'exists', record };
17
+ if (options.dryRun)
18
+ return { status: 'dry-run', record };
19
+ return { status: 'created', record, inserted: await writer.insert(record) };
20
+ }
21
+ /**
22
+ * `id` のレコードを 1 件読む(無ければ null)。
23
+ * `findOne` は、無い id で Records が 404 と ITEM_NOT_FOUND の警告を出すので使わない(`find` + id の昇順 + 1 件)
24
+ */
25
+ export async function findAdmin(collection, id) {
26
+ const items = await collection.find({ id }).sort({ id: 'asc' }).limit(1).toArray();
27
+ const first = items[0];
28
+ return first && typeof first === 'object' ? first : null;
29
+ }
30
+ /** Records のコレクションでの存在確認と書き込み */
31
+ export function adminWriterOf(collection) {
32
+ return {
33
+ exists: async (id) => (await findAdmin(collection, id)) !== null,
34
+ insert: (record) => collection.insertOne({ ...record }),
35
+ };
36
+ }
37
+ //# sourceMappingURL=add.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/admins/add.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAqC,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAoBlF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,KAAiB,EACjB,MAAsB,EACtB,UAA2B,EAAE;IAE7B,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACvC,IAAI,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACxE,IAAI,OAAO,CAAC,MAAM;QAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IACzD,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;AAC9E,CAAC;AAUD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,UAA8C,EAC9C,EAAU;IAEV,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;IACnF,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACvB,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAE,KAAiC,CAAC,CAAC,CAAC,IAAI,CAAC;AACxF,CAAC;AAED,iCAAiC;AACjC,MAAM,UAAU,aAAa,CAAC,UAAgC;IAC5D,OAAO;QACL,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,SAAS,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI;QAChE,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC;KACxD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * 管理者(`@exabugs/dynamodb-client/admins`。ADR 0007 §7)
3
+ *
4
+ * admins のレコードの形、メールの正規化、存在確認つきの作成。管理画面は
5
+ * `@exabugs/dynamodb-client/integrations/react-admin` の `adminsResource`、初回の登録は CLI `dynamodb-admins add`。
6
+ * 使い方は docs/ADMINS.md
7
+ */
8
+ export { AdminInputError, adminEmailOf, buildAdminRecord, isAdminEmail, normalizeAdminEmail, } from './record.js';
9
+ export type { AdminInput, AdminRecord } from './record.js';
10
+ export { addAdmin, adminWriterOf, findAdmin } from './add.js';
11
+ export type { AddAdminOptions, AddAdminResult, AdminWriter, AdminsCollectionLike } from './add.js';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/admins/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,GACpB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC9D,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * 管理者(`@exabugs/dynamodb-client/admins`。ADR 0007 §7)
3
+ *
4
+ * admins のレコードの形、メールの正規化、存在確認つきの作成。管理画面は
5
+ * `@exabugs/dynamodb-client/integrations/react-admin` の `adminsResource`、初回の登録は CLI `dynamodb-admins add`。
6
+ * 使い方は docs/ADMINS.md
7
+ */
8
+ export { AdminInputError, adminEmailOf, buildAdminRecord, isAdminEmail, normalizeAdminEmail, } from './record.js';
9
+ export { addAdmin, adminWriterOf, findAdmin } from './add.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/admins/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * admins のレコードの形と、メールアドレスの正規化(ADR 0007 §7)
3
+ *
4
+ * 依存を持たない純粋なファイル(管理画面・CLI・通知の宛先が共有する。Pre Token Generation は ADR 0007 の段階 3 で
5
+ * これに揃える。現行の両アプリの Pre Token Generation は独自に小文字化している〔asanowa は trim なし〕)。
6
+ */
7
+ /**
8
+ * 管理者のレコード(`admins` コレクション)。
9
+ * - `id`: 不変。作成時の小文字のメール(主キーなので、同じメールで 2 件はできない)
10
+ * - `email`: 不変。常に `id` と同じ値。持たない既存のレコード(asanowa の `{ id, name }`)は `id` を使う
11
+ * - `name`: 表示名(必須。ただし astro の既存のレコードには無いので、読み取りでは欠けうる)
12
+ */
13
+ export interface AdminRecord {
14
+ id: string;
15
+ name: string;
16
+ email: string;
17
+ createdAt?: string;
18
+ updatedAt?: string;
19
+ }
20
+ /** 作成の入力(メールは正規化前でよい) */
21
+ export interface AdminInput {
22
+ email: string;
23
+ name: string;
24
+ }
25
+ /** メールアドレスの正規化(前後の空白を除き、小文字にする)。形式は検査しない */
26
+ export declare function normalizeAdminEmail(raw: string): string;
27
+ /** 正規化したメールアドレスが、メールの形式か */
28
+ export declare function isAdminEmail(normalized: string): boolean;
29
+ /** レコードのメールアドレス(`email` が無い既存のレコードは `id`) */
30
+ export declare function adminEmailOf(record: {
31
+ id: string;
32
+ email?: unknown;
33
+ }): string;
34
+ /** 作成の入力の誤り(どの項目かを `field` に持つ。画面はその項目のエラーとして出す) */
35
+ export declare class AdminInputError extends Error {
36
+ readonly field: keyof AdminInput;
37
+ constructor(field: keyof AdminInput, message: string);
38
+ }
39
+ /**
40
+ * 作成するレコード(`id` と `email` は正規化したメール、`name` は前後の空白を除く)。
41
+ * メールの形式が不正、または名前が空なら `AdminInputError`
42
+ */
43
+ export declare function buildAdminRecord(input: AdminInput): AdminRecord;
44
+ //# sourceMappingURL=record.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../../src/admins/record.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,yBAAyB;AACzB,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAID,4CAA4C;AAC5C,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,4BAA4B;AAC5B,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,6CAA6C;AAC7C,wBAAgB,YAAY,CAAC,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAE5E;AAED,oDAAoD;AACpD,qBAAa,eAAgB,SAAQ,KAAK;IAEtC,QAAQ,CAAC,KAAK,EAAE,MAAM,UAAU;gBAAvB,KAAK,EAAE,MAAM,UAAU,EAChC,OAAO,EAAE,MAAM;CAKlB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,CAU/D"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * admins のレコードの形と、メールアドレスの正規化(ADR 0007 §7)
3
+ *
4
+ * 依存を持たない純粋なファイル(管理画面・CLI・通知の宛先が共有する。Pre Token Generation は ADR 0007 の段階 3 で
5
+ * これに揃える。現行の両アプリの Pre Token Generation は独自に小文字化している〔asanowa は trim なし〕)。
6
+ */
7
+ const EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
8
+ /** メールアドレスの正規化(前後の空白を除き、小文字にする)。形式は検査しない */
9
+ export function normalizeAdminEmail(raw) {
10
+ return raw.trim().toLowerCase();
11
+ }
12
+ /** 正規化したメールアドレスが、メールの形式か */
13
+ export function isAdminEmail(normalized) {
14
+ return EMAIL_PATTERN.test(normalized);
15
+ }
16
+ /** レコードのメールアドレス(`email` が無い既存のレコードは `id`) */
17
+ export function adminEmailOf(record) {
18
+ return typeof record.email === 'string' && record.email !== '' ? record.email : record.id;
19
+ }
20
+ /** 作成の入力の誤り(どの項目かを `field` に持つ。画面はその項目のエラーとして出す) */
21
+ export class AdminInputError extends Error {
22
+ field;
23
+ constructor(field, message) {
24
+ super(message);
25
+ this.field = field;
26
+ this.name = 'AdminInputError';
27
+ }
28
+ }
29
+ /**
30
+ * 作成するレコード(`id` と `email` は正規化したメール、`name` は前後の空白を除く)。
31
+ * メールの形式が不正、または名前が空なら `AdminInputError`
32
+ */
33
+ export function buildAdminRecord(input) {
34
+ const email = normalizeAdminEmail(input.email);
35
+ if (!isAdminEmail(email)) {
36
+ throw new AdminInputError('email', `メールアドレスの形式が不正です: ${input.email}`);
37
+ }
38
+ const name = input.name.trim();
39
+ if (name === '') {
40
+ throw new AdminInputError('name', '名前(name)が要ります');
41
+ }
42
+ return { id: email, email, name };
43
+ }
44
+ //# sourceMappingURL=record.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"record.js","sourceRoot":"","sources":["../../src/admins/record.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAsBH,MAAM,aAAa,GAAG,4BAA4B,CAAC;AAEnD,4CAA4C;AAC5C,MAAM,UAAU,mBAAmB,CAAC,GAAW;IAC7C,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED,4BAA4B;AAC5B,MAAM,UAAU,YAAY,CAAC,UAAkB;IAC7C,OAAO,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AACxC,CAAC;AAED,6CAA6C;AAC7C,MAAM,UAAU,YAAY,CAAC,MAAuC;IAClE,OAAO,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;AAC5F,CAAC;AAED,oDAAoD;AACpD,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAE7B;IADX,YACW,KAAuB,EAChC,OAAe;QAEf,KAAK,CAAC,OAAO,CAAC,CAAC;QAHN,UAAK,GAAL,KAAK,CAAkB;QAIhC,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAiB;IAChD,MAAM,KAAK,GAAG,mBAAmB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC/C,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,eAAe,CAAC,OAAO,EAAE,oBAAoB,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;IACxE,CAAC;IACD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAC/B,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;QAChB,MAAM,IAAI,eAAe,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACpC,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { ReactElement } from 'react';
2
+ import { type DeleteButtonProps } from 'react-admin';
3
+ export interface AdminDeleteButtonProps extends Omit<DeleteButtonProps, 'mutationMode'> {
4
+ /** true なら、ログイン中の自分自身のレコードには削除ボタンを出さない(締め出しを防ぐ)。既定 true */
5
+ preventSelfDelete?: boolean;
6
+ }
7
+ /**
8
+ * 管理者の削除ボタン(確認つき・サーバーの応答を待つ)。
9
+ * `preventSelfDelete` では、自分自身かを確かめられないとき(identity の読み込み中・email が無い)も出さない(安全側)
10
+ */
11
+ export declare const AdminDeleteButton: ({ preventSelfDelete, ...props }: AdminDeleteButtonProps) => ReactElement | null;
12
+ //# sourceMappingURL=AdminDeleteButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AdminDeleteButton.d.ts","sourceRoot":"","sources":["../../../../../src/integrations/react-admin/components/Admins/AdminDeleteButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAEL,KAAK,iBAAiB,EAGvB,MAAM,aAAa,CAAC;AAIrB,MAAM,WAAW,sBAAuB,SAAQ,IAAI,CAAC,iBAAiB,EAAE,cAAc,CAAC;IACrF,2DAA2D;IAC3D,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAYD;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAAI,iCAG/B,sBAAsB,KAAG,YAAY,GAAG,IAW1C,CAAC"}
@@ -0,0 +1,32 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { DeleteButton, useGetIdentity, useRecordContext, } from 'react-admin';
3
+ import { adminEmailOf, normalizeAdminEmail } from '../../../../admins/record.js';
4
+ /** 自分のメールアドレス(identity の email。無い・読み込み中なら null) */
5
+ const useSelfEmail = () => {
6
+ const { identity, isPending } = useGetIdentity();
7
+ const email = identity?.email;
8
+ return {
9
+ pending: isPending,
10
+ email: typeof email === 'string' && email !== '' ? normalizeAdminEmail(email) : null,
11
+ };
12
+ };
13
+ /**
14
+ * 管理者の削除ボタン(確認つき・サーバーの応答を待つ)。
15
+ * `preventSelfDelete` では、自分自身かを確かめられないとき(identity の読み込み中・email が無い)も出さない(安全側)
16
+ */
17
+ export const AdminDeleteButton = ({ preventSelfDelete = true, ...props }) => {
18
+ const record = useRecordContext();
19
+ const self = useSelfEmail();
20
+ if (!record)
21
+ return null;
22
+ if (preventSelfDelete) {
23
+ if (self.pending || self.email === null)
24
+ return null;
25
+ // id と email は同じ値のはずだが、どちらかが一致すれば自分とみなす(安全側)
26
+ const mine = [String(record.id), adminEmailOf(record)].map(normalizeAdminEmail);
27
+ if (mine.includes(self.email))
28
+ return null;
29
+ }
30
+ return _jsx(DeleteButton, { mutationMode: "pessimistic", ...props });
31
+ };
32
+ //# sourceMappingURL=AdminDeleteButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AdminDeleteButton.js","sourceRoot":"","sources":["../../../../../src/integrations/react-admin/components/Admins/AdminDeleteButton.tsx"],"names":[],"mappings":";AACA,OAAO,EACL,YAAY,EAEZ,cAAc,EACd,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAOjF,mDAAmD;AACnD,MAAM,YAAY,GAAG,GAA+C,EAAE;IACpE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,cAAc,EAAE,CAAC;IACjD,MAAM,KAAK,GAAG,QAAQ,EAAE,KAAK,CAAC;IAC9B,OAAO;QACL,OAAO,EAAE,SAAS;QAClB,KAAK,EAAE,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI;KACrF,CAAC;AACJ,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,EAChC,iBAAiB,GAAG,IAAI,EACxB,GAAG,KAAK,EACe,EAAuB,EAAE;IAChD,MAAM,MAAM,GAAG,gBAAgB,EAAmC,CAAC;IACnE,MAAM,IAAI,GAAG,YAAY,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,IAAI,iBAAiB,EAAE,CAAC;QACtB,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QACrD,6CAA6C;QAC7C,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QAChF,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;IAC7C,CAAC;IACD,OAAO,KAAC,YAAY,IAAC,YAAY,EAAC,aAAa,KAAK,KAAK,GAAI,CAAC;AAChE,CAAC,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { ReactElement } from 'react';
2
+ import type { AdminsMessagesOverride } from './adminsView.js';
3
+ export interface AdminsCreateProps {
4
+ /** 文言の上書き(既定は日本語。ADMINS_MESSAGES_JA) */
5
+ messages?: AdminsMessagesOverride;
6
+ }
7
+ /**
8
+ * 管理者の作成(メールアドレス〔id になる。小文字に正規化〕と名前)。
9
+ * 作成の前に id で存在を確かめ、既にあれば保存せずにエラーを出す(Records は同じ id の insert を黙って上書きするため)
10
+ */
11
+ export declare const AdminsCreate: ({ messages: override }?: AdminsCreateProps) => ReactElement;
12
+ //# sourceMappingURL=AdminsCreate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AdminsCreate.d.ts","sourceRoot":"","sources":["../../../../../src/integrations/react-admin/components/Admins/AdminsCreate.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAgB1C,OAAO,KAAK,EAAkB,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAG9E,MAAM,WAAW,iBAAiB;IAChC,wCAAwC;IACxC,QAAQ,CAAC,EAAE,sBAAsB,CAAC;CACnC;AA4ED;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,yBAAwB,iBAAsB,KAAG,YAI7E,CAAC"}
@@ -0,0 +1,55 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Create, SimpleForm, TextInput, required, useDataProvider, useNotify, useResourceContext, useSaveContext, } from 'react-admin';
3
+ import { addAdmin } from '../../../../admins/add.js';
4
+ import { AdminInputError, isAdminEmail, normalizeAdminEmail } from '../../../../admins/record.js';
5
+ import { useAdminsMessages } from './useAdminsMessages.js';
6
+ /** dataProvider での存在確認(getMany。Records の findOne を使わない)と、保存(react-admin の save) */
7
+ const writerOf = (dataProvider, resource, save) => ({
8
+ exists: async (id) => {
9
+ const { data } = await dataProvider.getMany(resource, { ids: [id] });
10
+ return data.some((r) => String(r.id) === id);
11
+ },
12
+ insert: ({ id, email: mail, name }) => save({ id, email: mail, name }),
13
+ });
14
+ /** 入力の誤りを、項目のエラー(react-admin の送信のエラー)に変える */
15
+ const fieldErrorOf = (e, m) => e.field === 'email' ? { id: m.invalidEmail } : { name: m.nameRequired };
16
+ /** メールの形式の検査(正規化した後の値で見る。保存と同じ基準。前後の空白は弾かない) */
17
+ const adminEmailValidator = (message) => (value) => typeof value === 'string' && value.trim() !== '' && !isAdminEmail(normalizeAdminEmail(value))
18
+ ? message
19
+ : undefined;
20
+ /** フォーム(文言は Create のリソースの文脈で引く。i18n のキーにリソース名を使う) */
21
+ const AdminCreateForm = ({ override }) => {
22
+ const m = useAdminsMessages(override);
23
+ const dataProvider = useDataProvider();
24
+ const notify = useNotify();
25
+ const resource = useResourceContext() ?? 'admins';
26
+ const { save } = useSaveContext();
27
+ const onSubmit = async (values) => {
28
+ if (!save)
29
+ return undefined;
30
+ const writer = writerOf(dataProvider, resource, async (record) => (await save(record)) ?? undefined);
31
+ try {
32
+ const result = await addAdmin({ email: String(values.id ?? ''), name: String(values.name ?? '') }, writer);
33
+ if (result.status === 'exists')
34
+ return { id: m.duplicate };
35
+ return result.status === 'created' ? result.inserted : undefined;
36
+ }
37
+ catch (e) {
38
+ if (e instanceof AdminInputError)
39
+ return fieldErrorOf(e, m);
40
+ // 存在確認(getMany)の失敗など。保存はしていない
41
+ notify('ra.notification.http_error', { type: 'error' });
42
+ return undefined;
43
+ }
44
+ };
45
+ return (
46
+ // noValidate: ブラウザの検査(type="email" の吹き出し。ブラウザの言語で出る)ではなく、下の検査と文言で出す。
47
+ // type="email" はモバイルのキーボードのために残す
48
+ _jsxs(SimpleForm, { onSubmit: onSubmit, noValidate: true, children: [_jsx(TextInput, { source: "id", label: m.email, type: "email", validate: [required(), adminEmailValidator(m.invalidEmail)], helperText: m.emailHelper, fullWidth: true }), _jsx(TextInput, { source: "name", label: m.name, validate: required(), fullWidth: true })] }));
49
+ };
50
+ /**
51
+ * 管理者の作成(メールアドレス〔id になる。小文字に正規化〕と名前)。
52
+ * 作成の前に id で存在を確かめ、既にあれば保存せずにエラーを出す(Records は同じ id の insert を黙って上書きするため)
53
+ */
54
+ export const AdminsCreate = ({ messages: override } = {}) => (_jsx(Create, { redirect: "list", children: _jsx(AdminCreateForm, { override: override }) }));
55
+ //# sourceMappingURL=AdminsCreate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AdminsCreate.js","sourceRoot":"","sources":["../../../../../src/integrations/react-admin/components/Admins/AdminsCreate.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { ReactElement } from 'react';
2
+ import { type SortPayload } from 'react-admin';
3
+ import type { AdminsMessagesOverride } from './adminsView.js';
4
+ export interface AdminsScreenProps {
5
+ /** 文言の上書き(既定は日本語。ADMINS_MESSAGES_JA) */
6
+ messages?: AdminsMessagesOverride;
7
+ /** 自分自身の削除ボタンを出さない(締め出しを防ぐ)。既定 true */
8
+ preventSelfDelete?: boolean;
9
+ }
10
+ export interface AdminsListProps extends AdminsScreenProps {
11
+ /** 一覧の並び。既定は id(メールアドレス)の昇順 */
12
+ sort?: SortPayload;
13
+ }
14
+ /**
15
+ * 管理者の一覧(メールアドレス・名前・作成日時・削除)。一括操作・書き出しは無い
16
+ * (一括削除は、自分自身の削除を防ぐ検査を通らないため出さない)
17
+ */
18
+ export declare const AdminsList: ({ messages: override, preventSelfDelete, sort, }?: AdminsListProps) => ReactElement;
19
+ //# sourceMappingURL=AdminsList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AdminsList.d.ts","sourceRoot":"","sources":["../../../../../src/integrations/react-admin/components/Admins/AdminsList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAA6B,KAAK,WAAW,EAAa,MAAM,aAAa,CAAC;AAGrF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAG9D,MAAM,WAAW,iBAAiB;IAChC,wCAAwC;IACxC,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAClC,uCAAuC;IACvC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,eAAgB,SAAQ,iBAAiB;IACxD,+BAA+B;IAC/B,IAAI,CAAC,EAAE,WAAW,CAAC;CACpB;AAID;;;GAGG;AACH,eAAO,MAAM,UAAU,GAAI,mDAIxB,eAAoB,KAAG,YAYzB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Datagrid, DateField, List, TextField } from 'react-admin';
3
+ import { AdminDeleteButton } from './AdminDeleteButton.js';
4
+ import { useAdminsMessages } from './useAdminsMessages.js';
5
+ const DEFAULT_SORT = { field: 'id', order: 'ASC' };
6
+ /**
7
+ * 管理者の一覧(メールアドレス・名前・作成日時・削除)。一括操作・書き出しは無い
8
+ * (一括削除は、自分自身の削除を防ぐ検査を通らないため出さない)
9
+ */
10
+ export const AdminsList = ({ messages: override, preventSelfDelete = true, sort = DEFAULT_SORT, } = {}) => {
11
+ const m = useAdminsMessages(override);
12
+ return (_jsx(List, { sort: sort, exporter: false, children: _jsxs(Datagrid, { bulkActionButtons: false, rowClick: "show", children: [_jsx(TextField, { source: "id", label: m.email }), _jsx(TextField, { source: "name", label: m.name, emptyText: m.empty }), _jsx(DateField, { source: "createdAt", label: m.createdAt, showTime: true, emptyText: m.empty }), _jsx(AdminDeleteButton, { preventSelfDelete: preventSelfDelete })] }) }));
13
+ };
14
+ //# sourceMappingURL=AdminsList.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AdminsList.js","sourceRoot":"","sources":["../../../../../src/integrations/react-admin/components/Admins/AdminsList.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAoB,SAAS,EAAE,MAAM,aAAa,CAAC;AAErF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAc3D,MAAM,YAAY,GAAgB,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AAEhE;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,EACzB,QAAQ,EAAE,QAAQ,EAClB,iBAAiB,GAAG,IAAI,EACxB,IAAI,GAAG,YAAY,MACA,EAAE,EAAgB,EAAE;IACvC,MAAM,CAAC,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACtC,OAAO,CACL,KAAC,IAAI,IAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,YAC/B,MAAC,QAAQ,IAAC,iBAAiB,EAAE,KAAK,EAAE,QAAQ,EAAC,MAAM,aACjD,KAAC,SAAS,IAAC,MAAM,EAAC,IAAI,EAAC,KAAK,EAAE,CAAC,CAAC,KAAK,GAAI,EACzC,KAAC,SAAS,IAAC,MAAM,EAAC,MAAM,EAAC,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,KAAK,GAAI,EAC9D,KAAC,SAAS,IAAC,MAAM,EAAC,WAAW,EAAC,KAAK,EAAE,CAAC,CAAC,SAAS,EAAE,QAAQ,QAAC,SAAS,EAAE,CAAC,CAAC,KAAK,GAAI,EACjF,KAAC,iBAAiB,IAAC,iBAAiB,EAAE,iBAAiB,GAAI,IAClD,GACN,CACR,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { ReactElement } from 'react';
2
+ import type { AdminsScreenProps } from './AdminsList.js';
3
+ export declare const AdminsShow: ({ messages: override, preventSelfDelete, }?: AdminsScreenProps) => ReactElement;
4
+ //# sourceMappingURL=AdminsShow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AdminsShow.d.ts","sourceRoot":"","sources":["../../../../../src/integrations/react-admin/components/Admins/AdminsShow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAM1C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAUzD,eAAO,MAAM,UAAU,GAAI,6CAGxB,iBAAsB,KAAG,YAyB3B,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { DateField, Show, SimpleShowLayout, TextField, TopToolbar } from 'react-admin';
3
+ import { adminEmailOf } from '../../../../admins/record.js';
4
+ import { LabeledIf } from '../shared/LabeledIf.js';
5
+ import { AdminDeleteButton } from './AdminDeleteButton.js';
6
+ import { useAdminsMessages } from './useAdminsMessages.js';
7
+ export const AdminsShow = ({ messages: override, preventSelfDelete = true, } = {}) => {
8
+ const m = useAdminsMessages(override);
9
+ return (_jsx(Show, { actions: _jsx(TopToolbar, { children: _jsx(AdminDeleteButton, { preventSelfDelete: preventSelfDelete }) }), children: _jsxs(SimpleShowLayout, { children: [_jsx(TextField, { source: "id", label: m.email }), _jsx(LabeledIf, { label: false, title: m.emailMismatch, when: (r) => !!r && adminEmailOf(r) !== String(r.id), children: _jsx(TextField, { source: "email" }) }), _jsx(TextField, { source: "name", label: m.name, emptyText: m.empty }), _jsx(DateField, { source: "createdAt", label: m.createdAt, showTime: true, emptyText: m.empty }), _jsx(DateField, { source: "updatedAt", label: m.updatedAt, showTime: true, emptyText: m.empty })] }) }));
10
+ };
11
+ //# sourceMappingURL=AdminsShow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AdminsShow.js","sourceRoot":"","sources":["../../../../../src/integrations/react-admin/components/Admins/AdminsShow.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,gBAAgB,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEvF,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAS3D,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,EACzB,QAAQ,EAAE,QAAQ,EAClB,iBAAiB,GAAG,IAAI,MACH,EAAE,EAAgB,EAAE;IACzC,MAAM,CAAC,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACtC,OAAO,CACL,KAAC,IAAI,IACH,OAAO,EACL,KAAC,UAAU,cACT,KAAC,iBAAiB,IAAC,iBAAiB,EAAE,iBAAiB,GAAI,GAChD,YAGf,MAAC,gBAAgB,eACf,KAAC,SAAS,IAAC,MAAM,EAAC,IAAI,EAAC,KAAK,EAAE,CAAC,CAAC,KAAK,GAAI,EACzC,KAAC,SAAS,IACR,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,CAAC,CAAC,aAAa,EACtB,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,YAEpD,KAAC,SAAS,IAAC,MAAM,EAAC,OAAO,GAAG,GAClB,EACZ,KAAC,SAAS,IAAC,MAAM,EAAC,MAAM,EAAC,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,KAAK,GAAI,EAC9D,KAAC,SAAS,IAAC,MAAM,EAAC,WAAW,EAAC,KAAK,EAAE,CAAC,CAAC,SAAS,EAAE,QAAQ,QAAC,SAAS,EAAE,CAAC,CAAC,KAAK,GAAI,EACjF,KAAC,SAAS,IAAC,MAAM,EAAC,WAAW,EAAC,KAAK,EAAE,CAAC,CAAC,SAAS,EAAE,QAAQ,QAAC,SAAS,EAAE,CAAC,CAAC,KAAK,GAAI,IAChE,GACd,CACR,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { ComponentType } from 'react';
2
+ import type { ResourceProps, SortPayload } from 'react-admin';
3
+ import type { AdminsMessagesOverride } from './adminsView.js';
4
+ export interface AdminsResourceOptions {
5
+ /** リソース名(Records のコレクション名)。既定 'admins' */
6
+ name?: string;
7
+ /** メニューのアイコン(例: @mui/icons-material の AdminPanelSettings。本ライブラリは依存しない) */
8
+ icon?: ComponentType;
9
+ /** 文言の上書き(既定は日本語) */
10
+ messages?: AdminsMessagesOverride;
11
+ /** 自分自身の削除ボタンを出さない(締め出しを防ぐ)。既定 true */
12
+ preventSelfDelete?: boolean;
13
+ /** 一覧の並び。既定は id(メールアドレス)の昇順 */
14
+ sort?: SortPayload;
15
+ }
16
+ /**
17
+ * admins の `<Resource>` の props(一覧・作成・詳細・削除。編集は無い: id・email は不変)。
18
+ * `<Resource {...adminsResource({ icon: AdminPanelSettings })} />` と使う
19
+ */
20
+ export declare const adminsResource: (options?: AdminsResourceOptions) => ResourceProps;
21
+ //# sourceMappingURL=adminsResource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adminsResource.d.ts","sourceRoot":"","sources":["../../../../../src/integrations/react-admin/components/Admins/adminsResource.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAK9D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAE9D,MAAM,WAAW,qBAAqB;IACpC,0CAA0C;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAClC,uCAAuC;IACvC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,+BAA+B;IAC/B,IAAI,CAAC,EAAE,WAAW,CAAC;CACpB;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,UAAS,qBAA0B,KAAG,aAoBpE,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { AdminsCreate } from './AdminsCreate.js';
3
+ import { AdminsList } from './AdminsList.js';
4
+ import { AdminsShow } from './AdminsShow.js';
5
+ /**
6
+ * admins の `<Resource>` の props(一覧・作成・詳細・削除。編集は無い: id・email は不変)。
7
+ * `<Resource {...adminsResource({ icon: AdminPanelSettings })} />` と使う
8
+ */
9
+ export const adminsResource = (options = {}) => {
10
+ const { name = 'admins', icon, messages, preventSelfDelete, sort } = options;
11
+ const customized = messages !== undefined || preventSelfDelete !== undefined;
12
+ return {
13
+ name,
14
+ list: customized || sort ? (_jsx(AdminsList, { messages: messages, preventSelfDelete: preventSelfDelete, sort: sort })) : (AdminsList),
15
+ create: messages ? _jsx(AdminsCreate, { messages: messages }) : AdminsCreate,
16
+ show: customized ? (_jsx(AdminsShow, { messages: messages, preventSelfDelete: preventSelfDelete })) : (AdminsShow),
17
+ ...(icon ? { icon } : {}),
18
+ recordRepresentation: 'id',
19
+ };
20
+ };
21
+ //# sourceMappingURL=adminsResource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adminsResource.js","sourceRoot":"","sources":["../../../../../src/integrations/react-admin/components/Admins/adminsResource.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAgB7C;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,UAAiC,EAAE,EAAiB,EAAE;IACnF,MAAM,EAAE,IAAI,GAAG,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,iBAAiB,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IAC7E,MAAM,UAAU,GAAG,QAAQ,KAAK,SAAS,IAAI,iBAAiB,KAAK,SAAS,CAAC;IAC7E,OAAO;QACL,IAAI;QACJ,IAAI,EACF,UAAU,IAAI,IAAI,CAAC,CAAC,CAAC,CACnB,KAAC,UAAU,IAAC,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,IAAI,EAAE,IAAI,GAAI,CACrF,CAAC,CAAC,CAAC,CACF,UAAU,CACX;QACH,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAC,YAAY,IAAC,QAAQ,EAAE,QAAQ,GAAI,CAAC,CAAC,CAAC,YAAY;QACtE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,CACjB,KAAC,UAAU,IAAC,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,EAAE,iBAAiB,GAAI,CACzE,CAAC,CAAC,CAAC,CACF,UAAU,CACX;QACD,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzB,oBAAoB,EAAE,IAAI;KAC3B,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,30 @@
1
+ /** admins の画面の文言(既定は日本語。props の messages で一部を上書きする) */
2
+ export interface AdminsMessages {
3
+ /** メールアドレス(id。一覧・詳細・作成の見出し) */
4
+ email: string;
5
+ name: string;
6
+ createdAt: string;
7
+ updatedAt: string;
8
+ /** 作成の画面の、メールアドレスの補足 */
9
+ emailHelper: string;
10
+ /** 作成の画面で、同じメールアドレスの管理者が既にあるとき */
11
+ duplicate: string;
12
+ /** メールアドレスの形式が不正なとき(react-admin の email() の後の、正規化した値の検査) */
13
+ invalidEmail: string;
14
+ /** 名前が空白だけのとき */
15
+ nameRequired: string;
16
+ /** 詳細で、`email` が `id` と違うとき(本来は無い)の `email` の見出し */
17
+ emailMismatch: string;
18
+ /** 値の無い項目 */
19
+ empty: string;
20
+ }
21
+ export declare const ADMINS_MESSAGES_JA: Readonly<AdminsMessages>;
22
+ export type AdminsMessagesOverride = Partial<AdminsMessages>;
23
+ /** 既定の文言に、上書きを重ねる */
24
+ export declare const adminsMessagesOf: (override?: AdminsMessagesOverride) => AdminsMessages;
25
+ /**
26
+ * 文言ごとの i18n のキー(`resources.<リソース名>.` に続く部分)。
27
+ * messages で上書きしない文言は、react-admin の translate でこのキーを引き、無ければ既定の日本語にする
28
+ */
29
+ export declare const ADMINS_I18N_KEYS: Readonly<Record<keyof AdminsMessages, string>>;
30
+ //# sourceMappingURL=adminsView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adminsView.d.ts","sourceRoot":"","sources":["../../../../../src/integrations/react-admin/components/Admins/adminsView.ts"],"names":[],"mappings":"AAKA,uDAAuD;AACvD,MAAM,WAAW,cAAc;IAC7B,+BAA+B;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,wBAAwB;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,oDAAoD;IACpD,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CAAC,cAAc,CAYtD,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;AAE7D,qBAAqB;AACrB,eAAO,MAAM,gBAAgB,GAAI,WAAW,sBAAsB,KAAG,cAGnE,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,cAAc,EAAE,MAAM,CAAC,CAW1E,CAAC"}