@flipboxlabs/aws-audit-sdk 1.1.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.
- package/LICENSE +21 -0
- package/README.md +30 -0
- package/dist/audits.d.ts +188 -0
- package/dist/audits.d.ts.map +1 -0
- package/dist/audits.js +225 -0
- package/dist/batch/batch-processor.d.ts +81 -0
- package/dist/batch/batch-processor.d.ts.map +1 -0
- package/dist/batch/batch-processor.js +102 -0
- package/dist/batch/index.d.ts +2 -0
- package/dist/batch/index.d.ts.map +1 -0
- package/dist/batch/index.js +1 -0
- package/dist/config.d.ts +65 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +44 -0
- package/dist/constants.d.ts +147 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +191 -0
- package/dist/events/batch-handler.d.ts +62 -0
- package/dist/events/batch-handler.d.ts.map +1 -0
- package/dist/events/batch-handler.js +92 -0
- package/dist/events/bus.d.ts +79 -0
- package/dist/events/bus.d.ts.map +1 -0
- package/dist/events/bus.js +86 -0
- package/dist/events/index.d.ts +3 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +2 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/middleware/middy.d.ts +66 -0
- package/dist/middleware/middy.d.ts.map +1 -0
- package/dist/middleware/middy.js +105 -0
- package/dist/repository.d.ts +421 -0
- package/dist/repository.d.ts.map +1 -0
- package/dist/repository.js +486 -0
- package/dist/repository.utils.d.ts +37 -0
- package/dist/repository.utils.d.ts.map +1 -0
- package/dist/repository.utils.js +70 -0
- package/dist/schema/audit.d.ts +202 -0
- package/dist/schema/audit.d.ts.map +1 -0
- package/dist/schema/audit.js +48 -0
- package/dist/schema/common.d.ts +128 -0
- package/dist/schema/common.d.ts.map +1 -0
- package/dist/schema/common.js +148 -0
- package/dist/schema/index.d.ts +27 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +26 -0
- package/dist/schema/log.d.ts +211 -0
- package/dist/schema/log.d.ts.map +1 -0
- package/dist/schema/log.js +179 -0
- package/dist/schema/model.d.ts +110 -0
- package/dist/schema/model.d.ts.map +1 -0
- package/dist/schema/model.js +86 -0
- package/dist/schema/service.d.ts +189 -0
- package/dist/schema/service.d.ts.map +1 -0
- package/dist/schema/service.js +89 -0
- package/dist/schema/storage.d.ts +105 -0
- package/dist/schema/storage.d.ts.map +1 -0
- package/dist/schema/storage.js +63 -0
- package/dist/service.d.ts +285 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +237 -0
- package/dist/test-config.d.ts +56 -0
- package/dist/test-config.d.ts.map +1 -0
- package/dist/test-config.js +24 -0
- package/dist/types.d.ts +40 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/dist/utils.d.ts +231 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +313 -0
- package/package.json +85 -0
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Input configuration for defining audit apps and resource types.
|
|
4
|
+
*/
|
|
5
|
+
export interface AuditConfigInput {
|
|
6
|
+
readonly apps: readonly string[];
|
|
7
|
+
readonly resourceTypes: readonly string[];
|
|
8
|
+
readonly service?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Creates an audit configuration object with typed schemas.
|
|
12
|
+
*
|
|
13
|
+
* The returned config object contains:
|
|
14
|
+
* - `service`: The service version (defaults to "v1")
|
|
15
|
+
* - `schemas.app`: Zod schema for validating app values
|
|
16
|
+
* - `schemas.resourceType`: Zod schema for validating resource type values
|
|
17
|
+
* - `schemas.resourceReference`: Zod schema for validating resource references
|
|
18
|
+
* - `_types`: Type helpers for extracting App and ResourceType union types
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* const config = defineAuditConfig({
|
|
23
|
+
* apps: ['Orders', 'Inventory'] as const,
|
|
24
|
+
* resourceTypes: ['Order', 'Product'] as const,
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* // Extract types for use in application code
|
|
28
|
+
* type App = typeof config._types.App; // 'Orders' | 'Inventory'
|
|
29
|
+
* type ResourceType = typeof config._types.ResourceType; // 'Order' | 'Product'
|
|
30
|
+
*
|
|
31
|
+
* // Use schemas for validation
|
|
32
|
+
* config.schemas.app.parse('Orders'); // ✅
|
|
33
|
+
* config.schemas.app.parse('Invalid'); // ❌ throws
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function defineAuditConfig<const C extends AuditConfigInput>(input: C): {
|
|
37
|
+
service: string | undefined;
|
|
38
|
+
} & C & {
|
|
39
|
+
schemas: {
|
|
40
|
+
app: z.ZodEnum<{
|
|
41
|
+
[x: string]: string;
|
|
42
|
+
}>;
|
|
43
|
+
resourceType: z.ZodEnum<{
|
|
44
|
+
[x: string]: string;
|
|
45
|
+
}>;
|
|
46
|
+
resourceReference: z.ZodObject<{
|
|
47
|
+
app: z.ZodEnum<{
|
|
48
|
+
[x: string]: string;
|
|
49
|
+
}>;
|
|
50
|
+
type: z.ZodEnum<{
|
|
51
|
+
[x: string]: string;
|
|
52
|
+
}>;
|
|
53
|
+
id: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
54
|
+
}, z.core.$strip>;
|
|
55
|
+
};
|
|
56
|
+
_types: {
|
|
57
|
+
App: C["apps"][number];
|
|
58
|
+
ResourceType: C["resourceTypes"][number];
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Type representing the return value of defineAuditConfig.
|
|
63
|
+
*/
|
|
64
|
+
export type AuditConfig = ReturnType<typeof defineAuditConfig>;
|
|
65
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,CAAC,CAAC,SAAS,gBAAgB,EAAE,KAAK,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;YAkB5D;QACb,GAAG,oBAAM;QACT,YAAY,6BAAe;KAC3B;EAEF;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Creates an audit configuration object with typed schemas.
|
|
4
|
+
*
|
|
5
|
+
* The returned config object contains:
|
|
6
|
+
* - `service`: The service version (defaults to "v1")
|
|
7
|
+
* - `schemas.app`: Zod schema for validating app values
|
|
8
|
+
* - `schemas.resourceType`: Zod schema for validating resource type values
|
|
9
|
+
* - `schemas.resourceReference`: Zod schema for validating resource references
|
|
10
|
+
* - `_types`: Type helpers for extracting App and ResourceType union types
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const config = defineAuditConfig({
|
|
15
|
+
* apps: ['Orders', 'Inventory'] as const,
|
|
16
|
+
* resourceTypes: ['Order', 'Product'] as const,
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* // Extract types for use in application code
|
|
20
|
+
* type App = typeof config._types.App; // 'Orders' | 'Inventory'
|
|
21
|
+
* type ResourceType = typeof config._types.ResourceType; // 'Order' | 'Product'
|
|
22
|
+
*
|
|
23
|
+
* // Use schemas for validation
|
|
24
|
+
* config.schemas.app.parse('Orders'); // ✅
|
|
25
|
+
* config.schemas.app.parse('Invalid'); // ❌ throws
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export function defineAuditConfig(input) {
|
|
29
|
+
const schemas = {
|
|
30
|
+
app: z.enum(input.apps),
|
|
31
|
+
resourceType: z.enum(input.resourceTypes),
|
|
32
|
+
resourceReference: z.object({
|
|
33
|
+
app: z.enum(input.apps),
|
|
34
|
+
type: z.enum(input.resourceTypes),
|
|
35
|
+
id: z.union([z.string(), z.number()]).optional(),
|
|
36
|
+
}),
|
|
37
|
+
};
|
|
38
|
+
return {
|
|
39
|
+
service: process.env.SERVICE,
|
|
40
|
+
...input,
|
|
41
|
+
schemas,
|
|
42
|
+
_types: {},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Identifier key used in CloudWatch structured logs to mark audit entries.
|
|
3
|
+
*
|
|
4
|
+
* When this key is present in a log object, it signals to log processors
|
|
5
|
+
* that the entry is an audit record that should be captured and stored.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* const logEntry = {
|
|
10
|
+
* [AUDIT_LOG_IDENTIFIER]: true,
|
|
11
|
+
* operation: 'createUser',
|
|
12
|
+
* // ...audit data
|
|
13
|
+
* };
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare const AUDIT_LOG_IDENTIFIER = "_audit";
|
|
17
|
+
/**
|
|
18
|
+
* SDK version string for debugging and compatibility checks.
|
|
19
|
+
*/
|
|
20
|
+
export declare const SDK_VERSION = "1.0.0";
|
|
21
|
+
/**
|
|
22
|
+
* Configuration for generating resource names.
|
|
23
|
+
*/
|
|
24
|
+
type NameConfig = {
|
|
25
|
+
/** Environment name (e.g., 'dev', 'staging', 'prod') */
|
|
26
|
+
env: string;
|
|
27
|
+
/** Service name used in naming resources */
|
|
28
|
+
service?: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Configuration for generating AWS resource ARNs.
|
|
32
|
+
* Extends NameConfig with AWS-specific identifiers.
|
|
33
|
+
*/
|
|
34
|
+
type ARNConfig = NameConfig & {
|
|
35
|
+
/** AWS account and region information */
|
|
36
|
+
aws: {
|
|
37
|
+
/** AWS region (e.g., 'us-east-1') */
|
|
38
|
+
region: string;
|
|
39
|
+
/** AWS account ID */
|
|
40
|
+
account: string;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* DynamoDB configuration constants for the audit table.
|
|
45
|
+
*
|
|
46
|
+
* Provides table naming, key definitions, index names, and attribute constants
|
|
47
|
+
* used throughout the audit SDK for DynamoDB operations.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* // Get table name for production
|
|
52
|
+
* const tableName = DynamoDB.Table.Name({ env: 'prod' });
|
|
53
|
+
* // Returns: "PROD-v1-Audit"
|
|
54
|
+
*
|
|
55
|
+
* // Access key names
|
|
56
|
+
* const pk = DynamoDB.Keys.PARTITION_KEY; // "PK"
|
|
57
|
+
* const sk = DynamoDB.Keys.SORT_KEY; // "SK"
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare const DynamoDB: {
|
|
61
|
+
/** Table name and ARN generators */
|
|
62
|
+
readonly Table: {
|
|
63
|
+
/** Generates the DynamoDB table name based on environment */
|
|
64
|
+
readonly Name: (config?: NameConfig) => string;
|
|
65
|
+
/** Generates the full DynamoDB table ARN */
|
|
66
|
+
readonly ARN: (config?: ARNConfig) => string;
|
|
67
|
+
};
|
|
68
|
+
/** DynamoDB key attribute names */
|
|
69
|
+
readonly Keys: {
|
|
70
|
+
/** Primary partition key */
|
|
71
|
+
readonly PARTITION_KEY: "PK";
|
|
72
|
+
/** Primary sort key */
|
|
73
|
+
readonly SORT_KEY: "SK";
|
|
74
|
+
/** GSI1 (String-String) partition key */
|
|
75
|
+
readonly GSI1_SS_PARTITION_KEY: "GSI1_SS_PK";
|
|
76
|
+
/** GSI1 (String-String) sort key */
|
|
77
|
+
readonly GSI1_SS_SORT_KEY: "GSI1_SS_SK";
|
|
78
|
+
/** GSI1 (String-Number) partition key */
|
|
79
|
+
readonly GSI1_SN_PARTITION_KEY: "GSI1_SN_PK";
|
|
80
|
+
/** GSI1 (String-Number) sort key */
|
|
81
|
+
readonly GSI1_SN_SORT_KEY: "GSI1_SN_SK";
|
|
82
|
+
/** LSI1 (String) sort key */
|
|
83
|
+
readonly LSI1_S_SORT_KEY: "LSI1_S_SK";
|
|
84
|
+
/** LSI1 (Numeric) sort key */
|
|
85
|
+
readonly LSI1_N_SORT_KEY: "LSI1_N_SK";
|
|
86
|
+
};
|
|
87
|
+
/** Secondary index names */
|
|
88
|
+
readonly Indexes: {
|
|
89
|
+
/** Global Secondary Index 1 - String partition, String sort */
|
|
90
|
+
readonly GSI1_SS: "GSI1_SS";
|
|
91
|
+
/** Global Secondary Index 1 - String partition, Numeric sort */
|
|
92
|
+
readonly GSI1_SN: "GSI1_SN";
|
|
93
|
+
/** Local Secondary Index 1 - String sort key */
|
|
94
|
+
readonly LSI1_S: "LSI1_S";
|
|
95
|
+
/** Local Secondary Index 1 - Numeric sort key */
|
|
96
|
+
readonly LSI1_N: "LSI1_N";
|
|
97
|
+
};
|
|
98
|
+
/** Special attribute names */
|
|
99
|
+
readonly Attributes: {
|
|
100
|
+
/** Time-to-live attribute for automatic item expiration */
|
|
101
|
+
readonly TTL: "ttl";
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* EventBridge configuration constants for the audit event bus.
|
|
106
|
+
*
|
|
107
|
+
* Provides bus naming, event source identifiers, and detail type constants
|
|
108
|
+
* used for publishing audit events to EventBridge.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```typescript
|
|
112
|
+
* // Get event bus name
|
|
113
|
+
* const busName = EventBridge.Bus.Name({ env: 'prod' });
|
|
114
|
+
* // Returns: "PROD-v1-Audit"
|
|
115
|
+
*
|
|
116
|
+
* // Use event types
|
|
117
|
+
* const event = {
|
|
118
|
+
* Source: EventBridge.Source,
|
|
119
|
+
* DetailType: EventBridge.DetailType.UPSERTED,
|
|
120
|
+
* Detail: JSON.stringify(auditData),
|
|
121
|
+
* };
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
export declare const EventBridge: {
|
|
125
|
+
/** Event bus name and ARN generators */
|
|
126
|
+
readonly Bus: {
|
|
127
|
+
/** Generates the EventBridge bus name based on environment */
|
|
128
|
+
readonly Name: (config?: NameConfig) => string;
|
|
129
|
+
/** Generates the full EventBridge bus ARN */
|
|
130
|
+
readonly ARN: (config?: ARNConfig) => string;
|
|
131
|
+
};
|
|
132
|
+
/** Source identifier for audit events */
|
|
133
|
+
readonly Source: "Audit";
|
|
134
|
+
/** Event detail types for different audit operations */
|
|
135
|
+
readonly DetailType: {
|
|
136
|
+
/** Emitted when an audit record is created or updated */
|
|
137
|
+
readonly UPSERTED: "Upserted";
|
|
138
|
+
/** Emitted when an audit record is deleted */
|
|
139
|
+
readonly DELETED: "Deleted";
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* Union type of all valid EventBridge detail types.
|
|
144
|
+
*/
|
|
145
|
+
export type AnyEventBridgeDetailType = (typeof EventBridge.DetailType)[keyof typeof EventBridge.DetailType];
|
|
146
|
+
export {};
|
|
147
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,WAAW,CAAC;AAE7C;;GAEG;AACH,eAAO,MAAM,WAAW,UAAU,CAAC;AAEnC;;GAEG;AACH,KAAK,UAAU,GAAG;IACjB,wDAAwD;IACxD,GAAG,EAAE,MAAM,CAAC;IAEZ,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;GAGG;AACH,KAAK,SAAS,GAAG,UAAU,GAAG;IAC7B,yCAAyC;IACzC,GAAG,EAAE;QACJ,qCAAqC;QACrC,MAAM,EAAE,MAAM,CAAC;QACf,qBAAqB;QACrB,OAAO,EAAE,MAAM,CAAC;KAChB,CAAC;CACF,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,QAAQ;IACpB,oCAAoC;;QAEnC,6DAA6D;iCAC7C,UAAU;QAC1B,4CAA4C;gCAC7B,SAAS;;IAEzB,mCAAmC;;QAElC,4BAA4B;;QAE5B,uBAAuB;;QAGvB,yCAAyC;;QAEzC,oCAAoC;;QAGpC,yCAAyC;;QAEzC,oCAAoC;;QAGpC,6BAA6B;;QAE7B,8BAA8B;;;IAG/B,4BAA4B;;QAE3B,+DAA+D;;QAE/D,gEAAgE;;QAGhE,gDAAgD;;QAEhD,iDAAiD;;;IAGlD,8BAA8B;;QAE7B,2DAA2D;;;CAGnD,CAAC;AA4CX;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,WAAW;IACvB,wCAAwC;;QAEvC,8DAA8D;iCAC9C,UAAU;QAC1B,6CAA6C;gCAC9B,SAAS;;IAEzB,yCAAyC;;IAEzC,wDAAwD;;QAEvD,yDAAyD;;QAEzD,8CAA8C;;;CAGtC,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,wBAAwB,GACnC,CAAC,OAAO,WAAW,CAAC,UAAU,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,UAAU,CAAC,CAAC"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Identifier key used in CloudWatch structured logs to mark audit entries.
|
|
3
|
+
*
|
|
4
|
+
* When this key is present in a log object, it signals to log processors
|
|
5
|
+
* that the entry is an audit record that should be captured and stored.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* const logEntry = {
|
|
10
|
+
* [AUDIT_LOG_IDENTIFIER]: true,
|
|
11
|
+
* operation: 'createUser',
|
|
12
|
+
* // ...audit data
|
|
13
|
+
* };
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export const AUDIT_LOG_IDENTIFIER = "_audit";
|
|
17
|
+
/**
|
|
18
|
+
* SDK version string for debugging and compatibility checks.
|
|
19
|
+
*/
|
|
20
|
+
export const SDK_VERSION = "1.0.0";
|
|
21
|
+
/**
|
|
22
|
+
* DynamoDB configuration constants for the audit table.
|
|
23
|
+
*
|
|
24
|
+
* Provides table naming, key definitions, index names, and attribute constants
|
|
25
|
+
* used throughout the audit SDK for DynamoDB operations.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* // Get table name for production
|
|
30
|
+
* const tableName = DynamoDB.Table.Name({ env: 'prod' });
|
|
31
|
+
* // Returns: "PROD-v1-Audit"
|
|
32
|
+
*
|
|
33
|
+
* // Access key names
|
|
34
|
+
* const pk = DynamoDB.Keys.PARTITION_KEY; // "PK"
|
|
35
|
+
* const sk = DynamoDB.Keys.SORT_KEY; // "SK"
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export const DynamoDB = {
|
|
39
|
+
/** Table name and ARN generators */
|
|
40
|
+
Table: {
|
|
41
|
+
/** Generates the DynamoDB table name based on environment */
|
|
42
|
+
Name: (config) => buildDynamoDBName(config),
|
|
43
|
+
/** Generates the full DynamoDB table ARN */
|
|
44
|
+
ARN: (config) => buildDynamoDBArn(config),
|
|
45
|
+
},
|
|
46
|
+
/** DynamoDB key attribute names */
|
|
47
|
+
Keys: {
|
|
48
|
+
/** Primary partition key */
|
|
49
|
+
PARTITION_KEY: "PK",
|
|
50
|
+
/** Primary sort key */
|
|
51
|
+
SORT_KEY: "SK",
|
|
52
|
+
/** GSI1 (String-String) partition key */
|
|
53
|
+
GSI1_SS_PARTITION_KEY: "GSI1_SS_PK",
|
|
54
|
+
/** GSI1 (String-String) sort key */
|
|
55
|
+
GSI1_SS_SORT_KEY: "GSI1_SS_SK",
|
|
56
|
+
/** GSI1 (String-Number) partition key */
|
|
57
|
+
GSI1_SN_PARTITION_KEY: "GSI1_SN_PK",
|
|
58
|
+
/** GSI1 (String-Number) sort key */
|
|
59
|
+
GSI1_SN_SORT_KEY: "GSI1_SN_SK",
|
|
60
|
+
/** LSI1 (String) sort key */
|
|
61
|
+
LSI1_S_SORT_KEY: "LSI1_S_SK",
|
|
62
|
+
/** LSI1 (Numeric) sort key */
|
|
63
|
+
LSI1_N_SORT_KEY: "LSI1_N_SK",
|
|
64
|
+
},
|
|
65
|
+
/** Secondary index names */
|
|
66
|
+
Indexes: {
|
|
67
|
+
/** Global Secondary Index 1 - String partition, String sort */
|
|
68
|
+
GSI1_SS: "GSI1_SS",
|
|
69
|
+
/** Global Secondary Index 1 - String partition, Numeric sort */
|
|
70
|
+
GSI1_SN: "GSI1_SN",
|
|
71
|
+
/** Local Secondary Index 1 - String sort key */
|
|
72
|
+
LSI1_S: "LSI1_S",
|
|
73
|
+
/** Local Secondary Index 1 - Numeric sort key */
|
|
74
|
+
LSI1_N: "LSI1_N",
|
|
75
|
+
},
|
|
76
|
+
/** Special attribute names */
|
|
77
|
+
Attributes: {
|
|
78
|
+
/** Time-to-live attribute for automatic item expiration */
|
|
79
|
+
TTL: "ttl",
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Builds a DynamoDB table name from service name and configuration.
|
|
84
|
+
*
|
|
85
|
+
* Format: `{ENV}-{service}-Audit` (e.g., "PROD-v1-Audit")
|
|
86
|
+
*
|
|
87
|
+
* @param name - Service name to include in table name
|
|
88
|
+
* @param config - Environment configuration (defaults to process.env.ENVIRONMENT)
|
|
89
|
+
* @returns Formatted table name string
|
|
90
|
+
* @internal
|
|
91
|
+
*/
|
|
92
|
+
function buildDynamoDBName(config = {
|
|
93
|
+
env: String(process.env.ENVIRONMENT),
|
|
94
|
+
service: process.env.SERVICE,
|
|
95
|
+
}) {
|
|
96
|
+
return [`${config.env.toUpperCase()}`, config.service, "Audit"]
|
|
97
|
+
.filter(Boolean)
|
|
98
|
+
.join("-");
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Builds a DynamoDB table ARN from service name and AWS configuration.
|
|
102
|
+
*
|
|
103
|
+
* @param name - Service name to include in table name
|
|
104
|
+
* @param config - AWS and environment configuration
|
|
105
|
+
* @returns Full DynamoDB table ARN
|
|
106
|
+
* @internal
|
|
107
|
+
*/
|
|
108
|
+
function buildDynamoDBArn(config = {
|
|
109
|
+
aws: {
|
|
110
|
+
region: String(process.env.AWS_REGION),
|
|
111
|
+
account: String(process.env.AWS_ACCOUNT),
|
|
112
|
+
},
|
|
113
|
+
env: String(process.env.ENVIRONMENT),
|
|
114
|
+
service: process.env.SERVICE,
|
|
115
|
+
}) {
|
|
116
|
+
return `arn:aws:dynamodb:${config.aws.region}:${config.aws.account}:table/${buildDynamoDBName({ env: config.env, service: config.service })}`;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* EventBridge configuration constants for the audit event bus.
|
|
120
|
+
*
|
|
121
|
+
* Provides bus naming, event source identifiers, and detail type constants
|
|
122
|
+
* used for publishing audit events to EventBridge.
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* // Get event bus name
|
|
127
|
+
* const busName = EventBridge.Bus.Name({ env: 'prod' });
|
|
128
|
+
* // Returns: "PROD-v1-Audit"
|
|
129
|
+
*
|
|
130
|
+
* // Use event types
|
|
131
|
+
* const event = {
|
|
132
|
+
* Source: EventBridge.Source,
|
|
133
|
+
* DetailType: EventBridge.DetailType.UPSERTED,
|
|
134
|
+
* Detail: JSON.stringify(auditData),
|
|
135
|
+
* };
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
export const EventBridge = {
|
|
139
|
+
/** Event bus name and ARN generators */
|
|
140
|
+
Bus: {
|
|
141
|
+
/** Generates the EventBridge bus name based on environment */
|
|
142
|
+
Name: (config) => buildEventBridgeName(config),
|
|
143
|
+
/** Generates the full EventBridge bus ARN */
|
|
144
|
+
ARN: (config) => buildEventBridgeArn(config),
|
|
145
|
+
},
|
|
146
|
+
/** Source identifier for audit events */
|
|
147
|
+
Source: "Audit",
|
|
148
|
+
/** Event detail types for different audit operations */
|
|
149
|
+
DetailType: {
|
|
150
|
+
/** Emitted when an audit record is created or updated */
|
|
151
|
+
UPSERTED: "Upserted",
|
|
152
|
+
/** Emitted when an audit record is deleted */
|
|
153
|
+
DELETED: "Deleted",
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
/**
|
|
157
|
+
* Builds an EventBridge bus name from service name and configuration.
|
|
158
|
+
*
|
|
159
|
+
* Format: `{ENV}-{service}-Audit` (e.g., "PROD-v1-Audit")
|
|
160
|
+
*
|
|
161
|
+
* @param name - Service name to include in bus name
|
|
162
|
+
* @param config - Environment configuration (defaults to process.env.ENVIRONMENT)
|
|
163
|
+
* @returns Formatted bus name string
|
|
164
|
+
* @internal
|
|
165
|
+
*/
|
|
166
|
+
function buildEventBridgeName(config = {
|
|
167
|
+
env: String(process.env.ENVIRONMENT),
|
|
168
|
+
service: process.env.SERVICE,
|
|
169
|
+
}) {
|
|
170
|
+
return [`${config.env.toUpperCase()}`, config.service, "Audit"]
|
|
171
|
+
.filter(Boolean)
|
|
172
|
+
.join("-");
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Builds an EventBridge bus ARN from service name and AWS configuration.
|
|
176
|
+
*
|
|
177
|
+
* @param name - Service name to include in bus name
|
|
178
|
+
* @param config - AWS and environment configuration
|
|
179
|
+
* @returns Full EventBridge bus ARN
|
|
180
|
+
* @internal
|
|
181
|
+
*/
|
|
182
|
+
function buildEventBridgeArn(config = {
|
|
183
|
+
aws: {
|
|
184
|
+
region: process.env.AWS_REGION ?? "us-east-1",
|
|
185
|
+
account: String(process.env.AWS_ACCOUNT),
|
|
186
|
+
},
|
|
187
|
+
env: String(process.env.ENVIRONMENT),
|
|
188
|
+
service: process.env.SERVICE,
|
|
189
|
+
}) {
|
|
190
|
+
return `arn:aws:events:${config.aws.region}:${config.aws.account}:event-bus/${buildEventBridgeName({ env: config.env, service: config.service })}`;
|
|
191
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { Logger } from "@aws-lambda-powertools/logger";
|
|
2
|
+
import { type EventBridgeClient, type PutEventsRequestEntry, type PutEventsResultEntry } from "@aws-sdk/client-eventbridge";
|
|
3
|
+
/**
|
|
4
|
+
* Handles batched EventBridge event publishing with automatic chunking.
|
|
5
|
+
*
|
|
6
|
+
* Provides a wrapper around the EventBridge PutEvents API that automatically
|
|
7
|
+
* splits large event arrays into compliant batch sizes and handles errors gracefully.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const handler = new BatchHandler(logger, eventBridgeClient);
|
|
12
|
+
*
|
|
13
|
+
* const results = await handler.putEvents([
|
|
14
|
+
* { DetailType: 'OrderCreated', Detail: '{"orderId":"123"}', Source: 'orders' },
|
|
15
|
+
* { DetailType: 'OrderCreated', Detail: '{"orderId":"456"}', Source: 'orders' },
|
|
16
|
+
* ]);
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export declare class BatchHandler {
|
|
20
|
+
private readonly logger;
|
|
21
|
+
private readonly client;
|
|
22
|
+
/**
|
|
23
|
+
* Creates a new BatchHandler instance.
|
|
24
|
+
*
|
|
25
|
+
* @param logger - Logger instance for debug and error logging
|
|
26
|
+
* @param client - EventBridge client for API calls
|
|
27
|
+
*/
|
|
28
|
+
constructor(logger: Logger, client: EventBridgeClient);
|
|
29
|
+
/**
|
|
30
|
+
* Publishes events to EventBridge with automatic batching and error handling.
|
|
31
|
+
*
|
|
32
|
+
* Events are automatically chunked into batches of the specified size
|
|
33
|
+
* (default 10, the EventBridge maximum). On success, logs the results
|
|
34
|
+
* at debug level. On failure, logs at critical level and returns an empty array.
|
|
35
|
+
*
|
|
36
|
+
* @param entries - Array of EventBridge event entries to publish
|
|
37
|
+
* @param chunk - Batch size for chunking (default: 10)
|
|
38
|
+
* @returns Array of result entries from EventBridge, or empty array on error
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const results = await handler.putEvents(events);
|
|
43
|
+
* console.log(`Published ${results.length} events`);
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
putEvents(entries: PutEventsRequestEntry[], chunk?: number): Promise<PutEventsResultEntry[]>;
|
|
47
|
+
/**
|
|
48
|
+
* Sends events to EventBridge in batches.
|
|
49
|
+
*
|
|
50
|
+
* Iterates through the entries array in chunks, sending each batch
|
|
51
|
+
* via the PutEvents API and collecting the results.
|
|
52
|
+
*
|
|
53
|
+
* @param client - EventBridge client for API calls
|
|
54
|
+
* @param entries - Array of event entries to send
|
|
55
|
+
* @param chunk - Number of entries per batch
|
|
56
|
+
* @returns Combined array of result entries from all batches
|
|
57
|
+
*
|
|
58
|
+
* @internal
|
|
59
|
+
*/
|
|
60
|
+
private sendEventsViaBatch;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=batch-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch-handler.d.ts","sourceRoot":"","sources":["../../src/events/batch-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EACN,KAAK,iBAAiB,EAEtB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,MAAM,6BAA6B,CAAC;AAQrC;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,YAAY;IAQvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IARxB;;;;;OAKG;gBAEe,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,iBAAiB;IAG3C;;;;;;;;;;;;;;;;OAgBG;IACU,SAAS,CACrB,OAAO,EAAE,qBAAqB,EAAE,EAChC,KAAK,GAAE,MAAmB,GACxB,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAgBlC;;;;;;;;;;;;OAYG;YACW,kBAAkB;CAsBhC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { PutEventsCommand, } from "@aws-sdk/client-eventbridge";
|
|
2
|
+
/**
|
|
3
|
+
* Default batch size for EventBridge PutEvents API calls.
|
|
4
|
+
* EventBridge allows a maximum of 10 entries per PutEvents call.
|
|
5
|
+
*/
|
|
6
|
+
const CHUNK_SIZE = 10;
|
|
7
|
+
/**
|
|
8
|
+
* Handles batched EventBridge event publishing with automatic chunking.
|
|
9
|
+
*
|
|
10
|
+
* Provides a wrapper around the EventBridge PutEvents API that automatically
|
|
11
|
+
* splits large event arrays into compliant batch sizes and handles errors gracefully.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const handler = new BatchHandler(logger, eventBridgeClient);
|
|
16
|
+
*
|
|
17
|
+
* const results = await handler.putEvents([
|
|
18
|
+
* { DetailType: 'OrderCreated', Detail: '{"orderId":"123"}', Source: 'orders' },
|
|
19
|
+
* { DetailType: 'OrderCreated', Detail: '{"orderId":"456"}', Source: 'orders' },
|
|
20
|
+
* ]);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export class BatchHandler {
|
|
24
|
+
logger;
|
|
25
|
+
client;
|
|
26
|
+
/**
|
|
27
|
+
* Creates a new BatchHandler instance.
|
|
28
|
+
*
|
|
29
|
+
* @param logger - Logger instance for debug and error logging
|
|
30
|
+
* @param client - EventBridge client for API calls
|
|
31
|
+
*/
|
|
32
|
+
constructor(logger, client) {
|
|
33
|
+
this.logger = logger;
|
|
34
|
+
this.client = client;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Publishes events to EventBridge with automatic batching and error handling.
|
|
38
|
+
*
|
|
39
|
+
* Events are automatically chunked into batches of the specified size
|
|
40
|
+
* (default 10, the EventBridge maximum). On success, logs the results
|
|
41
|
+
* at debug level. On failure, logs at critical level and returns an empty array.
|
|
42
|
+
*
|
|
43
|
+
* @param entries - Array of EventBridge event entries to publish
|
|
44
|
+
* @param chunk - Batch size for chunking (default: 10)
|
|
45
|
+
* @returns Array of result entries from EventBridge, or empty array on error
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* const results = await handler.putEvents(events);
|
|
50
|
+
* console.log(`Published ${results.length} events`);
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
async putEvents(entries, chunk = CHUNK_SIZE) {
|
|
54
|
+
try {
|
|
55
|
+
const result = await this.sendEventsViaBatch(this.client, entries, chunk);
|
|
56
|
+
this.logger.debug("Pushed event bridge events", {
|
|
57
|
+
events: result,
|
|
58
|
+
});
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
this.logger.critical("Error pushing event bridge events", error);
|
|
63
|
+
}
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Sends events to EventBridge in batches.
|
|
68
|
+
*
|
|
69
|
+
* Iterates through the entries array in chunks, sending each batch
|
|
70
|
+
* via the PutEvents API and collecting the results.
|
|
71
|
+
*
|
|
72
|
+
* @param client - EventBridge client for API calls
|
|
73
|
+
* @param entries - Array of event entries to send
|
|
74
|
+
* @param chunk - Number of entries per batch
|
|
75
|
+
* @returns Combined array of result entries from all batches
|
|
76
|
+
*
|
|
77
|
+
* @internal
|
|
78
|
+
*/
|
|
79
|
+
async sendEventsViaBatch(client, entries, chunk = CHUNK_SIZE) {
|
|
80
|
+
const result = [];
|
|
81
|
+
// Chunk into batches
|
|
82
|
+
for (let i = 0, j = entries.length; i < j; i += chunk) {
|
|
83
|
+
const output = await client.send(new PutEventsCommand({
|
|
84
|
+
Entries: entries.slice(i, i + chunk),
|
|
85
|
+
}));
|
|
86
|
+
if (output.Entries) {
|
|
87
|
+
result.concat(output.Entries);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
}
|