@exabugs/dynamodb-client 1.11.3 → 1.12.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 (67) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/client/Collection.d.ts.map +1 -1
  3. package/dist/client/Collection.js +10 -2
  4. package/dist/client/Collection.js.map +1 -1
  5. package/dist/integrations/react-admin/components/CloudWatchLog/CloudWatchLogButton.d.ts +14 -0
  6. package/dist/integrations/react-admin/components/CloudWatchLog/CloudWatchLogButton.d.ts.map +1 -0
  7. package/dist/integrations/react-admin/components/CloudWatchLog/CloudWatchLogButton.js +17 -0
  8. package/dist/integrations/react-admin/components/CloudWatchLog/CloudWatchLogButton.js.map +1 -0
  9. package/dist/integrations/react-admin/components/CloudWatchLog/cloudWatchLogUrl.d.ts +32 -0
  10. package/dist/integrations/react-admin/components/CloudWatchLog/cloudWatchLogUrl.d.ts.map +1 -0
  11. package/dist/integrations/react-admin/components/CloudWatchLog/cloudWatchLogUrl.js +63 -0
  12. package/dist/integrations/react-admin/components/CloudWatchLog/cloudWatchLogUrl.js.map +1 -0
  13. package/dist/integrations/react-admin/components/CloudWatchLog/index.d.ts +5 -0
  14. package/dist/integrations/react-admin/components/CloudWatchLog/index.d.ts.map +1 -0
  15. package/dist/integrations/react-admin/components/CloudWatchLog/index.js +3 -0
  16. package/dist/integrations/react-admin/components/CloudWatchLog/index.js.map +1 -0
  17. package/dist/integrations/react-admin/components/index.d.ts +3 -1
  18. package/dist/integrations/react-admin/components/index.d.ts.map +1 -1
  19. package/dist/integrations/react-admin/components/index.js +2 -1
  20. package/dist/integrations/react-admin/components/index.js.map +1 -1
  21. package/dist/integrations/react-admin/index.d.ts +2 -0
  22. package/dist/integrations/react-admin/index.d.ts.map +1 -1
  23. package/dist/integrations/react-admin/index.js +1 -0
  24. package/dist/integrations/react-admin/index.js.map +1 -1
  25. package/dist/notify/alerts.d.ts +145 -0
  26. package/dist/notify/alerts.d.ts.map +1 -0
  27. package/dist/notify/alerts.js +152 -0
  28. package/dist/notify/alerts.js.map +1 -0
  29. package/dist/notify/format.d.ts.map +1 -1
  30. package/dist/notify/format.js +2 -0
  31. package/dist/notify/format.js.map +1 -1
  32. package/dist/notify/handler.d.ts +63 -0
  33. package/dist/notify/handler.d.ts.map +1 -1
  34. package/dist/notify/handler.js +205 -3
  35. package/dist/notify/handler.js.map +1 -1
  36. package/dist/notify/index.d.ts +5 -2
  37. package/dist/notify/index.d.ts.map +1 -1
  38. package/dist/notify/index.js +2 -1
  39. package/dist/notify/index.js.map +1 -1
  40. package/dist/notify/normalize.d.ts +12 -1
  41. package/dist/notify/normalize.d.ts.map +1 -1
  42. package/dist/notify/normalize.js +73 -14
  43. package/dist/notify/normalize.js.map +1 -1
  44. package/dist/notify/store.d.ts +17 -3
  45. package/dist/notify/store.d.ts.map +1 -1
  46. package/dist/notify/store.js +87 -0
  47. package/dist/notify/store.js.map +1 -1
  48. package/dist/notify/types.d.ts +47 -0
  49. package/dist/notify/types.d.ts.map +1 -1
  50. package/dist/server/handler.cjs +105 -114
  51. package/dist/server/handler.cjs.map +3 -3
  52. package/dist/server/media-handler.cjs +2 -2
  53. package/dist/server/media-process-handler-dlq.cjs +2 -2
  54. package/dist/server/media-process-handler-dlq.cjs.map +1 -1
  55. package/dist/server/media-process-handler.cjs +2 -2
  56. package/dist/server/media-process-handler.cjs.map +1 -1
  57. package/dist/server/utils/errorHandler.d.ts +6 -0
  58. package/dist/server/utils/errorHandler.d.ts.map +1 -1
  59. package/dist/server/utils/errorHandler.js +9 -16
  60. package/dist/server/utils/errorHandler.js.map +1 -1
  61. package/dist/server/utils/responseBuilder.d.ts +8 -2
  62. package/dist/server/utils/responseBuilder.d.ts.map +1 -1
  63. package/dist/server/utils/responseBuilder.js +9 -5
  64. package/dist/server/utils/responseBuilder.js.map +1 -1
  65. package/dist/sharp-layer.zip +0 -0
  66. package/docs/NOTIFY.md +81 -1
  67. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.12.0] - 2026-10-15
11
+
12
+ ### Added
13
+
14
+ - **alerts(`@exabugs/dynamodb-client/notify`、任意)**: 通知を、指紋ごとに 1 件の `alerts` レコード(呼び出し側の Single-Table)として残し、通知の本文に管理画面の URL(`詳細: <adminBaseUrl>/alerts/<id>/show`)を足す(ADR 0003)。`createNotifyHandler` の任意の `recorder` / `adminBaseUrl` / `region` / `recordLimits` / `skipRecordEvents` / `skipRecordLogGroups`(Records のロググループを入れて、記録の失敗のループを防ぐ) / `recordBreaker`(記録の失敗が続いたら、コンテナごとに一定時間記録しない)、`createAlertRecorder`、`cleanupAlerts`(定時の削除)、`alertKeyOf`、`normalizeWithLogs`(ログ参照つきの正規化)、任意のインターフェース `AlertIndex`(`DynamoNoticeStore` / `MemoryNoticeStore` が実装。`al#` 行の `UpdateItem` だけ)。`recorder` を渡さなければ、挙動・出力は従来と同じ
15
+ - react-admin の共通部品 `cloudWatchLogUrl` / `CloudWatchLogButton`(ログ参照から CloudWatch コンソールを開く。URL の形式は、ap-northeast-1 の実機のコンソールで確認済み)
16
+ - `Notice.detailUrl`(任意)、`NotifyResult.recorded` / `unrecorded`(記録の単位 = alertKey の数。recorder があるときだけ) / `recordSuspended`、`LogRef`
17
+
18
+ ## [1.11.4] - 2026-10-14
19
+
20
+ ### Changed
21
+
22
+ - **`createErrorResponse`の第5引数`details`を`logContext`に改め、レスポンスボディから完全に除外した。** 例外オブジェクトは「何が起きたか」の診断情報を持つだけで、それを外部にどう見せるか(レスポンスの形)は呼び出し側の責務であり、例外から自動的に継承しない。`error.details`はこれまでもどこからも読まれていなかった(React Admin連携含め未使用)
23
+ - `errorHandler.ts`で個別に行っていたスタックトレースのログ出力を廃止し、`createErrorResponse`の`logContext`経由に統一(二重ログ・最終ステータス確定前のerror固定ログを防ぐ)
24
+
25
+ ### Fixed
26
+
27
+ - `client`(HTTPクライアント)がサーバーのエラーレスポンス(`{success:false, error:{code, message, statusCode}}`)を誤って平坦な形として読んでおり、常に`response.statusText`にフォールバックしていた。ネストを正しく読み、`code`/`statusCode`をスローするErrorのプロパティとして保持するようにした(呼び出し側が4xx/5xxを判別できるようになる)
28
+
10
29
  ## [1.11.3] - 2026-10-13
11
30
 
12
31
  ### Fixed
@@ -1 +1 @@
1
- {"version":3,"file":"Collection.d.ts","sourceRoot":"","sources":["../../src/client/Collection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Collection.d.ts","sourceRoot":"","sources":["../../src/client/Collection.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAEV,YAAY,EACZ,MAAM,EACN,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,YAAY,EACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C;;GAEG;AACH,MAAM,MAAM,iBAAiB,CAAC,YAAY,GAAG,OAAO,IAAI,CACtD,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,WAAW,CAAC,EAAE,YAAY,KACvB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAErC;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;;;GAQG;AACH,qBAAa,UAAU,CAAC,OAAO,SAAS,UAAU,GAAG,UAAU,EAAE,YAAY,GAAG,OAAO;IAEnF,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,cAAc;gBALd,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,WAAW,EAAE,YAAY,GAAG,SAAS,EACrC,aAAa,EAAE,aAAa,GAAG,SAAS,EACxC,cAAc,EAAE,iBAAiB,CAAC,YAAY,CAAC;IAGzD,OAAO,IAAI,MAAM;IAIjB,WAAW,IAAI,MAAM;IAIrB,YAAY,IAAI,MAAM,GAAG,SAAS;IAIlC,cAAc,IAAI,YAAY,GAAG,SAAS;IAI1C;;OAEG;YACW,OAAO;IAkErB,IAAI,CAAC,MAAM,GAAE,MAAM,CAAC,OAAO,CAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,UAAU,CAAC,OAAO,EAAE,YAAY,CAAC;IAatF,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAUzD,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAU3C,SAAS,CAAC,QAAQ,EAAE,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC;IAU9E,UAAU,CAAC,SAAS,EAAE,CAAC,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAqBrF,SAAS,CACb,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,EACvB,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,EAChC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAC7B,OAAO,CAAC,YAAY,CAAC;IAsBlB,UAAU,CACd,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,EACvB,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,EAChC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAC7B,OAAO,CAAC,YAAY,CAAC;IAoBlB,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC;IAUzD,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC;CAWjE"}
@@ -73,8 +73,16 @@ export class Collection {
73
73
  });
74
74
  clearTimeout(timeoutId);
75
75
  if (!response.ok) {
76
- const error = (await response.json().catch(() => ({ message: response.statusText })));
77
- throw new Error(`Request failed: ${error.message || response.statusText}`);
76
+ // サーバーのエラーレスポンスは { success: false, error: { code, message, statusCode } }
77
+ // というネスト構造。呼び出し元が4xx(想定内)か5xx(障害)かを判断できるように、
78
+ // code/statusCodeをErrorオブジェクトのプロパティとして保持する(messageに
79
+ // 埋め込むだけだと、呼び出し元は文字列マッチでしか判別できなくなる)
80
+ const body = (await response.json().catch(() => ({})));
81
+ const message = body.error?.message || response.statusText;
82
+ const err = new Error(`Request failed: ${message}`);
83
+ err.code = body.error?.code;
84
+ err.statusCode = body.error?.statusCode ?? response.status;
85
+ throw err;
78
86
  }
79
87
  const result = (await response.json());
80
88
  return result.data;
@@ -1 +1 @@
1
- {"version":3,"file":"Collection.js","sourceRoot":"","sources":["../../src/client/Collection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Collection.js","sourceRoot":"","sources":["../../src/client/Collection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { ReactElement } from 'react';
2
+ export interface CloudWatchLogButtonProps {
3
+ /** ログ参照の項目名。既定 'lastLog'('firstLog' も可) */
4
+ source?: string;
5
+ /** 既定 'CloudWatch で開く' */
6
+ label?: string;
7
+ }
8
+ /**
9
+ * alerts のレコードのログ参照を、CloudWatch のコンソールで開くボタン(AWS を操作できる人向けの補助)。
10
+ * ログ参照が無い(アラーム・直接呼び出しから来た)レコードでは、何も描画しない。
11
+ * リージョン・ドメイン・時間幅は、この部品が決める(呼び出し側は何も渡さない)
12
+ */
13
+ export declare const CloudWatchLogButton: (props: CloudWatchLogButtonProps) => ReactElement | null;
14
+ //# sourceMappingURL=CloudWatchLogButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CloudWatchLogButton.d.ts","sourceRoot":"","sources":["../../../../../src/integrations/react-admin/components/CloudWatchLog/CloudWatchLogButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAK1C,MAAM,WAAW,wBAAwB;IACvC,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0BAA0B;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAAI,OAAO,wBAAwB,KAAG,YAAY,GAAG,IAepF,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Button, useRecordContext } from 'react-admin';
3
+ import { cloudWatchLogUrl } from './cloudWatchLogUrl.js';
4
+ /**
5
+ * alerts のレコードのログ参照を、CloudWatch のコンソールで開くボタン(AWS を操作できる人向けの補助)。
6
+ * ログ参照が無い(アラーム・直接呼び出しから来た)レコードでは、何も描画しない。
7
+ * リージョン・ドメイン・時間幅は、この部品が決める(呼び出し側は何も渡さない)
8
+ */
9
+ export const CloudWatchLogButton = (props) => {
10
+ const { source = 'lastLog', label = 'CloudWatch で開く' } = props;
11
+ const record = useRecordContext();
12
+ const url = cloudWatchLogUrl(record?.[source]);
13
+ if (!url)
14
+ return null;
15
+ return (_jsx(Button, { component: "a", href: url, target: "_blank", rel: "noopener noreferrer", label: label, onClick: (e) => e.stopPropagation() }));
16
+ };
17
+ //# sourceMappingURL=CloudWatchLogButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CloudWatchLogButton.js","sourceRoot":"","sources":["../../../../../src/integrations/react-admin/components/CloudWatchLog/CloudWatchLogButton.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AASzD;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,KAA+B,EAAuB,EAAE;IAC1F,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,GAAG,gBAAgB,EAAE,GAAG,KAAK,CAAC;IAC/D,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;IAClC,MAAM,GAAG,GAAG,gBAAgB,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAC/C,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,OAAO,CACL,KAAC,MAAM,IACL,SAAS,EAAC,GAAG,EACb,IAAI,EAAE,GAAG,EACT,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,qBAAqB,EACzB,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,CAAC,CAAkC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,EAAE,GACpE,CACH,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * ログ参照(alerts の firstLog / lastLog)から、CloudWatch コンソールのログイベントの URL を作る。
3
+ *
4
+ * 形式(ap-northeast-1 の実機のコンソールで確認済み。aws-cn / aws-us-gov のドメインは未確認。docs/adr/0003-alerts.md):
5
+ * https://<コンソールのドメイン>/cloudwatch/home?region=<region>#logsV2:log-groups/log-group/<G>/log-events/<S><Q>
6
+ * - <G>・<S>: ロググループ名・ストリーム名に encodeURIComponent を 2 回かけ、`%` を `$` に置き換えたもの
7
+ * - <Q>: `?start=<ms>&end=<ms>` に encodeURIComponent を 1 回かけ、`%` を `$` に置き換えたもの
8
+ * リージョンからドメインを決める(aws / aws-cn / aws-us-gov)。呼び出し側は何も渡さない。
9
+ * それ以外のパーティション(`us-iso-east-1` などの ISO)や、形の不正なリージョンでは URL を作らない
10
+ * (ボタンを出さない)。
11
+ */
12
+ /** ログ参照(@exabugs/dynamodb-client/notify の LogRef と同じ形) */
13
+ export interface CloudWatchLogRef {
14
+ region: string;
15
+ logGroup: string;
16
+ logStream: string;
17
+ /** エポックミリ秒 */
18
+ timestamp: number;
19
+ requestId?: string;
20
+ }
21
+ export interface CloudWatchLogUrlOptions {
22
+ /** 発生時刻の前後に見る幅(ミリ秒)。既定 5 分 */
23
+ spanMs?: number;
24
+ }
25
+ /**
26
+ * リージョン → コンソールのドメイン。既知の形(商用・中国・GovCloud)でなければ undefined
27
+ * (入力をそのままドメインに埋め込まない)
28
+ */
29
+ export declare function consoleDomainOf(region: string): string | undefined;
30
+ /** ログ参照から URL を作る。参照が不正、または既知でないリージョン(ISO など)なら undefined */
31
+ export declare function cloudWatchLogUrl(ref: unknown, options?: CloudWatchLogUrlOptions): string | undefined;
32
+ //# sourceMappingURL=cloudWatchLogUrl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudWatchLogUrl.d.ts","sourceRoot":"","sources":["../../../../../src/integrations/react-admin/components/CloudWatchLog/cloudWatchLogUrl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,0DAA0D;AAC1D,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC,8BAA8B;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AASD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMlE;AAmBD,6DAA6D;AAC7D,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,OAAO,EACZ,OAAO,GAAE,uBAA4B,GACpC,MAAM,GAAG,SAAS,CAcpB"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * ログ参照(alerts の firstLog / lastLog)から、CloudWatch コンソールのログイベントの URL を作る。
3
+ *
4
+ * 形式(ap-northeast-1 の実機のコンソールで確認済み。aws-cn / aws-us-gov のドメインは未確認。docs/adr/0003-alerts.md):
5
+ * https://<コンソールのドメイン>/cloudwatch/home?region=<region>#logsV2:log-groups/log-group/<G>/log-events/<S><Q>
6
+ * - <G>・<S>: ロググループ名・ストリーム名に encodeURIComponent を 2 回かけ、`%` を `$` に置き換えたもの
7
+ * - <Q>: `?start=<ms>&end=<ms>` に encodeURIComponent を 1 回かけ、`%` を `$` に置き換えたもの
8
+ * リージョンからドメインを決める(aws / aws-cn / aws-us-gov)。呼び出し側は何も渡さない。
9
+ * それ以外のパーティション(`us-iso-east-1` などの ISO)や、形の不正なリージョンでは URL を作らない
10
+ * (ボタンを出さない)。
11
+ */
12
+ /** aws-us-gov(例: us-gov-west-1) */
13
+ const GOV_REGION = /^us-gov-[a-z]+-\d{1,2}$/;
14
+ /** aws-cn(例: cn-north-1) */
15
+ const CN_REGION = /^cn-[a-z]+-\d{1,2}$/;
16
+ /** aws(商用。例: ap-northeast-1)。ISO(us-iso-east-1、eu-isoe-west-1 など)は含めない */
17
+ const COMMERCIAL_REGION = /^(?!cn-)[a-z]{2}-(?!gov-|iso)[a-z]+-\d{1,2}$/;
18
+ /**
19
+ * リージョン → コンソールのドメイン。既知の形(商用・中国・GovCloud)でなければ undefined
20
+ * (入力をそのままドメインに埋め込まない)
21
+ */
22
+ export function consoleDomainOf(region) {
23
+ if (typeof region !== 'string')
24
+ return undefined;
25
+ if (GOV_REGION.test(region))
26
+ return 'console.amazonaws-us-gov.com';
27
+ if (CN_REGION.test(region))
28
+ return 'console.amazonaws.cn';
29
+ if (COMMERCIAL_REGION.test(region))
30
+ return `${region}.console.aws.amazon.com`;
31
+ return undefined;
32
+ }
33
+ /** CloudWatch の URL のフラグメントのエンコード(`%` を `$` に) */
34
+ const dollar = (s) => encodeURIComponent(s).replace(/%/g, '$');
35
+ function isRef(v) {
36
+ if (typeof v !== 'object' || v === null)
37
+ return false;
38
+ const r = v;
39
+ return (typeof r.region === 'string' &&
40
+ typeof r.logGroup === 'string' &&
41
+ r.logGroup !== '' &&
42
+ typeof r.logStream === 'string' &&
43
+ r.logStream !== '' &&
44
+ typeof r.timestamp === 'number' &&
45
+ Number.isFinite(r.timestamp));
46
+ }
47
+ /** ログ参照から URL を作る。参照が不正、または既知でないリージョン(ISO など)なら undefined */
48
+ export function cloudWatchLogUrl(ref, options = {}) {
49
+ if (!isRef(ref))
50
+ return undefined;
51
+ const domain = consoleDomainOf(ref.region);
52
+ if (!domain)
53
+ return undefined;
54
+ const span = Math.max(0, options.spanMs ?? 5 * 60 * 1000);
55
+ const start = Math.floor(ref.timestamp - span);
56
+ const end = Math.ceil(ref.timestamp + span);
57
+ const group = dollar(encodeURIComponent(ref.logGroup));
58
+ const stream = dollar(encodeURIComponent(ref.logStream));
59
+ const query = dollar(`?start=${start}&end=${end}`);
60
+ return (`https://${domain}/cloudwatch/home?region=${ref.region}` +
61
+ `#logsV2:log-groups/log-group/${group}/log-events/${stream}${query}`);
62
+ }
63
+ //# sourceMappingURL=cloudWatchLogUrl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudWatchLogUrl.js","sourceRoot":"","sources":["../../../../../src/integrations/react-admin/components/CloudWatchLog/cloudWatchLogUrl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAiBH,mCAAmC;AACnC,MAAM,UAAU,GAAG,yBAAyB,CAAC;AAC7C,4BAA4B;AAC5B,MAAM,SAAS,GAAG,qBAAqB,CAAC;AACxC,0EAA0E;AAC1E,MAAM,iBAAiB,GAAG,8CAA8C,CAAC;AAEzE;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IACjD,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,8BAA8B,CAAC;IACnE,IAAI,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,sBAAsB,CAAC;IAC1D,IAAI,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,GAAG,MAAM,yBAAyB,CAAC;IAC9E,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,kDAAkD;AAClD,MAAM,MAAM,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAE/E,SAAS,KAAK,CAAC,CAAU;IACvB,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,CAAC,GAAG,CAA4B,CAAC;IACvC,OAAO,CACL,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ;QAC5B,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ;QAC9B,CAAC,CAAC,QAAQ,KAAK,EAAE;QACjB,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ;QAC/B,CAAC,CAAC,SAAS,KAAK,EAAE;QAClB,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ;QAC/B,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAC7B,CAAC;AACJ,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,gBAAgB,CAC9B,GAAY,EACZ,UAAmC,EAAE;IAErC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAClC,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3C,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAC/C,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,MAAM,CAAC,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;IACvD,MAAM,MAAM,GAAG,MAAM,CAAC,kBAAkB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;IACzD,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,KAAK,QAAQ,GAAG,EAAE,CAAC,CAAC;IACnD,OAAO,CACL,WAAW,MAAM,2BAA2B,GAAG,CAAC,MAAM,EAAE;QACxD,gCAAgC,KAAK,eAAe,MAAM,GAAG,KAAK,EAAE,CACrE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { CloudWatchLogButton } from './CloudWatchLogButton.js';
2
+ export type { CloudWatchLogButtonProps } from './CloudWatchLogButton.js';
3
+ export { cloudWatchLogUrl, consoleDomainOf } from './cloudWatchLogUrl.js';
4
+ export type { CloudWatchLogRef, CloudWatchLogUrlOptions } from './cloudWatchLogUrl.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/integrations/react-admin/components/CloudWatchLog/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,YAAY,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC1E,YAAY,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { CloudWatchLogButton } from './CloudWatchLogButton.js';
2
+ export { cloudWatchLogUrl, consoleDomainOf } from './cloudWatchLogUrl.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/integrations/react-admin/components/CloudWatchLog/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
@@ -1,5 +1,7 @@
1
1
  /**
2
- * React-Admin 多対多関係コンポーネント
2
+ * React-Admin の共通部品(多対多関係、CloudWatch のログを開くボタン)
3
3
  */
4
4
  export { ReferenceManyToManyField, ReferenceManyToManyInput } from './ReferenceManyToMany/index.js';
5
+ export { CloudWatchLogButton, cloudWatchLogUrl, consoleDomainOf } from './CloudWatchLog/index.js';
6
+ export type { CloudWatchLogButtonProps, CloudWatchLogRef, CloudWatchLogUrlOptions, } from './CloudWatchLog/index.js';
5
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/integrations/react-admin/components/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/integrations/react-admin/components/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AACpG,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAClG,YAAY,EACV,wBAAwB,EACxB,gBAAgB,EAChB,uBAAuB,GACxB,MAAM,0BAA0B,CAAC"}
@@ -1,5 +1,6 @@
1
1
  /**
2
- * React-Admin 多対多関係コンポーネント
2
+ * React-Admin の共通部品(多対多関係、CloudWatch のログを開くボタン)
3
3
  */
4
4
  export { ReferenceManyToManyField, ReferenceManyToManyInput } from './ReferenceManyToMany/index.js';
5
+ export { CloudWatchLogButton, cloudWatchLogUrl, consoleDomainOf } from './CloudWatchLog/index.js';
5
6
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/integrations/react-admin/components/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/integrations/react-admin/components/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AACpG,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC"}
@@ -23,4 +23,6 @@ export { createDataProvider } from './dataProvider.js';
23
23
  export type { DynamoDataProvider } from './dataProvider.js';
24
24
  export type { DataProviderOptions, ReferenceManyToManyFieldProps, ReferenceManyToManyInputProps, TokenProvider, } from './types.js';
25
25
  export { ReferenceManyToManyField, ReferenceManyToManyInput } from './components/index.js';
26
+ export { CloudWatchLogButton, cloudWatchLogUrl, consoleDomainOf } from './components/index.js';
27
+ export type { CloudWatchLogButtonProps, CloudWatchLogRef, CloudWatchLogUrlOptions, } from './components/index.js';
26
28
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/integrations/react-admin/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,YAAY,EACV,mBAAmB,EACnB,6BAA6B,EAC7B,6BAA6B,EAC7B,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/integrations/react-admin/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,YAAY,EACV,mBAAmB,EACnB,6BAA6B,EAC7B,6BAA6B,EAC7B,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAC3F,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC/F,YAAY,EACV,wBAAwB,EACxB,gBAAgB,EAChB,uBAAuB,GACxB,MAAM,uBAAuB,CAAC"}
@@ -21,4 +21,5 @@
21
21
  */
22
22
  export { createDataProvider } from './dataProvider.js';
23
23
  export { ReferenceManyToManyField, ReferenceManyToManyInput } from './components/index.js';
24
+ export { CloudWatchLogButton, cloudWatchLogUrl, consoleDomainOf } from './components/index.js';
24
25
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/integrations/react-admin/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAQvD,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/integrations/react-admin/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAQvD,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAC3F,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,145 @@
1
+ import type { AlertIndex, LogRef, Notice } from './types.js';
2
+ /**
3
+ * alerts のリソース名。target が alerts の通知は記録しない。
4
+ * ただし Records の失敗ログの多く(`Request failed` など)には resource が出ないので、これだけでは
5
+ * ループを防げない。Records のロググループは skipRecordLogGroups に入れる(handler の遮断は最後の防壁)
6
+ */
7
+ export declare const ALERTS_RESOURCE = "alerts";
8
+ /** 保存期間(最後の発生から) */
9
+ export declare const ALERT_RETENTION_DAYS = 28;
10
+ /**
11
+ * alerts のキー。重複抑制の指紋(fingerprintOf)と同じだが、アラーム(`ALARM:` で始まる event)は
12
+ * level を除いて 1 件にまとめる(ALARM → OK を同じレコードの state で追う)
13
+ */
14
+ export declare function alertKeyOf(n: Pick<Notice, 'app' | 'env' | 'level' | 'event' | 'target'>): string;
15
+ /** 1 回の発生(最初・最後) */
16
+ export interface AlertOccurrence {
17
+ /** ISO 8601 */
18
+ occurredAt: string;
19
+ /** ログの購読から来た通知だけ */
20
+ log?: LogRef;
21
+ }
22
+ /** 記録する 1 件(同じ alertKey の、同じ呼び出しの中の発生をまとめたもの) */
23
+ export interface AlertInput {
24
+ /** 最後の発生の通知(level・message などは、これを写す) */
25
+ notice: Notice;
26
+ /** この呼び出しの中の発生の件数 */
27
+ count: number;
28
+ first: AlertOccurrence;
29
+ last: AlertOccurrence;
30
+ }
31
+ /** alerts のレコード(管理画面が読む形) */
32
+ export interface AlertRecord {
33
+ id: string;
34
+ level: Notice['level'];
35
+ event: string;
36
+ message: string;
37
+ target?: string;
38
+ action?: string;
39
+ /** alertKey */
40
+ fingerprint: string;
41
+ /** アラームだけ: 'ALARM' | 'OK' */
42
+ state?: 'ALARM' | 'OK';
43
+ /** 通知ストアの件数を写した目安 */
44
+ count: number;
45
+ firstSeenAt: string;
46
+ lastSeenAt: string;
47
+ firstLog?: LogRef;
48
+ lastLog?: LogRef;
49
+ createdAt?: string;
50
+ updatedAt?: string;
51
+ }
52
+ /**
53
+ * 書き込み先(`collection.updateOne` を持つもの。IAM クライアントの Collection がそのまま合う)。
54
+ * - upsert(`upsert: true`): 必ず `$set` と `$setOnInsert` を一緒に送る(`$setOnInsert` だけだと、
55
+ * キーがそのまま項目になる)。新規作成になりうるので、null を送らない(作成では null がそのまま保存される)
56
+ * - 項目の削除(`upsert: false`): `$set` に null だけを送る。既存のレコードにだけ効く(無ければ作らない)
57
+ */
58
+ export interface AlertsCollection {
59
+ updateOne(filter: {
60
+ id: string;
61
+ }, update: {
62
+ $set: Record<string, unknown>;
63
+ $setOnInsert?: Record<string, unknown>;
64
+ }, options: {
65
+ upsert: boolean;
66
+ }): Promise<unknown>;
67
+ }
68
+ export interface AlertRecorder {
69
+ record(input: AlertInput): Promise<{
70
+ id: string;
71
+ isNew: boolean;
72
+ count: number;
73
+ }>;
74
+ }
75
+ export interface AlertRecorderOptions {
76
+ collection: AlertsCollection;
77
+ /** 集計(通常は DynamoNoticeStore。UpdateItem だけを使う) */
78
+ index: AlertIndex;
79
+ /** 既定 28(cleanupAlerts の olderThanDays と揃える) */
80
+ retentionDays?: number;
81
+ now?: () => Date;
82
+ /** 既定 ULID */
83
+ newId?: () => string;
84
+ }
85
+ /**
86
+ * 通知 1 件を、alerts レコードに記録する部品。
87
+ * 集計(ID・件数・最初の時刻)を通知ストアで原子的に更新し、その結果を Records の upsert で写す。
88
+ *
89
+ * isNew が false でも、レコードがまだ無いことがある(前回の Records への書き込みが失敗・時間切れで、
90
+ * 通知ストアの行だけが進んだ)。そのため、どの回でも:
91
+ * - upsert には null を入れない(作成では null がそのまま保存される)
92
+ * - firstSeenAt は通知ストアの値(count と同じ行)を使う。firstLog は isNew のときだけ
93
+ * (isNew でないのに作成になったときは、firstLog の無いレコードになる。違う回のログを最初として残さない)
94
+ * - 無くなった任意の項目(action・lastLog.requestId。target は alertKey に含まれるので変わらない)は、upsert の後に、既存のレコードにだけ効く
95
+ * 更新(upsert: false。null は JSON Merge Patch の削除)で消す。isNew のときは消すものが無いので送らない
96
+ */
97
+ export declare function createAlertRecorder(options: AlertRecorderOptions): AlertRecorder;
98
+ /** 削除で使う形(`find` と `deleteMany` を持つもの。IAM クライアントの Collection がそのまま合う) */
99
+ export interface AlertsCleanupCollection {
100
+ find(filter: Record<string, never>, options: {
101
+ sort: {
102
+ lastSeenAt: 'asc';
103
+ };
104
+ limit: number;
105
+ }): {
106
+ toArray(): Promise<Array<{
107
+ id: string;
108
+ lastSeenAt?: unknown;
109
+ }>>;
110
+ };
111
+ deleteMany(filter: {
112
+ id: {
113
+ $in: string[];
114
+ };
115
+ }): Promise<{
116
+ deletedCount: number;
117
+ }>;
118
+ }
119
+ export interface CleanupAlertsOptions {
120
+ collection: AlertsCleanupCollection;
121
+ /** 既定 28 */
122
+ olderThanDays?: number;
123
+ /** 1 回の実行で消す上限(残りは次回)。既定 500 */
124
+ maxPerRun?: number;
125
+ now?: () => Date;
126
+ }
127
+ export interface CleanupAlertsResult {
128
+ /** 消した件数 */
129
+ deleted: number;
130
+ /** 消せなかった件数(deleteMany の結果が要求より少なかった分) */
131
+ failed: number;
132
+ /** 失敗の内容(握りつぶさない。呼び出し側がログ・例外にする) */
133
+ errors: string[];
134
+ /** 上限で止めた(古いものが残っているかもしれない) */
135
+ more: boolean;
136
+ }
137
+ /**
138
+ * 最後の発生から olderThanDays 日を過ぎた alerts を消す(アプリの定時 Lambda から呼ぶ)。
139
+ *
140
+ * `lastSeenAt: { $lt }` の範囲検索は、実際の DynamoDB では ValidationException になる(TODO.md)。
141
+ * そのため、条件なしに `lastSeenAt` 昇順で 1 ページずつ読み、期限内のものが出たら止める。
142
+ * 読んだら直ちに ID で消す(読み→削除の間を短くし、存在しない ID の削除で warn を出さない)
143
+ */
144
+ export declare function cleanupAlerts(options: CleanupAlertsOptions): Promise<CleanupAlertsResult>;
145
+ //# sourceMappingURL=alerts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alerts.d.ts","sourceRoot":"","sources":["../../src/notify/alerts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,152 @@
1
+ /**
2
+ * alerts(ADR 0003): 通知を、管理画面で見られるレコードとして残す。
3
+ *
4
+ * - 指紋(alertKey)ごとに 1 レコード。ID は ULID。集計(ID・件数)の正は通知ストアの行(AlertIndex)
5
+ * - レコードは、呼び出し側の Records(IAM の Function URL など)に `alerts` リソースとして書く。
6
+ * ライブラリはクライアントを import せず、構造的な型(AlertsCollection)で受け取る
7
+ * - 保存は最後の発生から 28 日。削除は、アプリの定時 Lambda が cleanupAlerts を呼ぶ(ネイティブ TTL は効かない)
8
+ */
9
+ import { ulid } from '../shared/utils/ulid.js';
10
+ /**
11
+ * alerts のリソース名。target が alerts の通知は記録しない。
12
+ * ただし Records の失敗ログの多く(`Request failed` など)には resource が出ないので、これだけでは
13
+ * ループを防げない。Records のロググループは skipRecordLogGroups に入れる(handler の遮断は最後の防壁)
14
+ */
15
+ export const ALERTS_RESOURCE = 'alerts';
16
+ /** 保存期間(最後の発生から) */
17
+ export const ALERT_RETENTION_DAYS = 28;
18
+ const isAlarm = (n) => n.event.startsWith('ALARM:');
19
+ /**
20
+ * alerts のキー。重複抑制の指紋(fingerprintOf)と同じだが、アラーム(`ALARM:` で始まる event)は
21
+ * level を除いて 1 件にまとめる(ALARM → OK を同じレコードの state で追う)
22
+ */
23
+ export function alertKeyOf(n) {
24
+ const level = isAlarm(n) ? 'alarm' : n.level;
25
+ return [n.app, n.env, level, n.event, n.target ?? ''].join('#').slice(0, 512);
26
+ }
27
+ /** undefined の項目を除く(JSON に出ない値を、送る前に落とす) */
28
+ function defined(o) {
29
+ return Object.fromEntries(Object.entries(o).filter(([, v]) => v !== undefined));
30
+ }
31
+ /**
32
+ * 通知 1 件を、alerts レコードに記録する部品。
33
+ * 集計(ID・件数・最初の時刻)を通知ストアで原子的に更新し、その結果を Records の upsert で写す。
34
+ *
35
+ * isNew が false でも、レコードがまだ無いことがある(前回の Records への書き込みが失敗・時間切れで、
36
+ * 通知ストアの行だけが進んだ)。そのため、どの回でも:
37
+ * - upsert には null を入れない(作成では null がそのまま保存される)
38
+ * - firstSeenAt は通知ストアの値(count と同じ行)を使う。firstLog は isNew のときだけ
39
+ * (isNew でないのに作成になったときは、firstLog の無いレコードになる。違う回のログを最初として残さない)
40
+ * - 無くなった任意の項目(action・lastLog.requestId。target は alertKey に含まれるので変わらない)は、upsert の後に、既存のレコードにだけ効く
41
+ * 更新(upsert: false。null は JSON Merge Patch の削除)で消す。isNew のときは消すものが無いので送らない
42
+ */
43
+ export function createAlertRecorder(options) {
44
+ const now = options.now ?? (() => new Date());
45
+ const newId = options.newId ?? ulid;
46
+ const keepSec = (options.retentionDays ?? ALERT_RETENTION_DAYS) * 86400;
47
+ return {
48
+ async record({ notice: n, count, first, last }) {
49
+ const key = alertKeyOf(n);
50
+ const t = await options.index.touchAlert(key, {
51
+ newId: newId(),
52
+ n: count,
53
+ nowSec: Math.floor(now().getTime() / 1000),
54
+ at: last.occurredAt,
55
+ firstAt: first.occurredAt,
56
+ keepSec,
57
+ });
58
+ // 既存のレコードの更新は JSON Merge Patch(入れ子は深くマージ)。lastLog は必須のキーを全部送る
59
+ const $set = defined({
60
+ level: n.level,
61
+ event: n.event,
62
+ message: n.message,
63
+ target: n.target,
64
+ action: n.action,
65
+ fingerprint: key,
66
+ state: isAlarm(n) ? (n.level === 'ok' ? 'OK' : 'ALARM') : undefined,
67
+ count: t.count,
68
+ lastSeenAt: last.occurredAt,
69
+ lastLog: last.log ? defined({ ...last.log }) : undefined,
70
+ });
71
+ const $setOnInsert = defined({
72
+ firstSeenAt: t.firstSeenAt,
73
+ firstLog: t.isNew ? first.log : undefined,
74
+ });
75
+ await options.collection.updateOne({ id: t.alertId }, { $set, $setOnInsert }, { upsert: true });
76
+ if (!t.isNew) {
77
+ // 直前の upsert でレコードは必ずある。lastLog も直前に書いたので、requestId だけを消せる
78
+ // target は alertKey に含まれるので、同じレコードでは変わらない(消すことは無い)
79
+ const unset = defined({
80
+ action: n.action === undefined ? null : undefined,
81
+ lastLog: last.log && last.log.requestId === undefined ? { requestId: null } : undefined,
82
+ });
83
+ if (Object.keys(unset).length > 0) {
84
+ await options.collection.updateOne({ id: t.alertId }, { $set: unset }, { upsert: false });
85
+ }
86
+ }
87
+ return { id: t.alertId, isNew: t.isNew, count: t.count };
88
+ },
89
+ };
90
+ }
91
+ /** Records の 1 ページの上限 */
92
+ const PAGE = 50;
93
+ /**
94
+ * 最後の発生から olderThanDays 日を過ぎた alerts を消す(アプリの定時 Lambda から呼ぶ)。
95
+ *
96
+ * `lastSeenAt: { $lt }` の範囲検索は、実際の DynamoDB では ValidationException になる(TODO.md)。
97
+ * そのため、条件なしに `lastSeenAt` 昇順で 1 ページずつ読み、期限内のものが出たら止める。
98
+ * 読んだら直ちに ID で消す(読み→削除の間を短くし、存在しない ID の削除で warn を出さない)
99
+ */
100
+ export async function cleanupAlerts(options) {
101
+ const now = options.now ?? (() => new Date());
102
+ const days = options.olderThanDays ?? ALERT_RETENTION_DAYS;
103
+ const maxPerRun = Math.max(1, options.maxPerRun ?? 500);
104
+ const cutoff = new Date(now().getTime() - days * 86400 * 1000).toISOString();
105
+ const result = { deleted: 0, failed: 0, errors: [], more: false };
106
+ while (result.deleted < maxPerRun) {
107
+ const limit = Math.min(PAGE, maxPerRun - result.deleted);
108
+ let page;
109
+ try {
110
+ page = await options.collection.find({}, { sort: { lastSeenAt: 'asc' }, limit }).toArray();
111
+ }
112
+ catch (e) {
113
+ result.errors.push(`取得に失敗しました: ${e instanceof Error ? e.message : String(e)}`);
114
+ return result;
115
+ }
116
+ const ids = [];
117
+ let reachedFresh = false;
118
+ for (const r of page) {
119
+ if (typeof r.lastSeenAt !== 'string') {
120
+ result.errors.push(`lastSeenAt が文字列でないレコードで止めました: ${r.id}`);
121
+ return result;
122
+ }
123
+ if (r.lastSeenAt >= cutoff) {
124
+ reachedFresh = true;
125
+ break;
126
+ }
127
+ ids.push(r.id);
128
+ }
129
+ if (ids.length > 0) {
130
+ try {
131
+ const r = await options.collection.deleteMany({ id: { $in: ids } });
132
+ result.deleted += r.deletedCount;
133
+ if (r.deletedCount < ids.length) {
134
+ // 同じものを読み直して回り続けないよう、ここで止める
135
+ result.failed += ids.length - r.deletedCount;
136
+ result.errors.push(`${ids.length} 件のうち ${ids.length - r.deletedCount} 件を消せませんでした`);
137
+ return result;
138
+ }
139
+ }
140
+ catch (e) {
141
+ result.failed += ids.length;
142
+ result.errors.push(`削除に失敗しました: ${e instanceof Error ? e.message : String(e)}`);
143
+ return result;
144
+ }
145
+ }
146
+ if (reachedFresh || page.length < limit)
147
+ return result;
148
+ }
149
+ result.more = true;
150
+ return result;
151
+ }
152
+ //# sourceMappingURL=alerts.js.map