@aws-blocks/bb-distributed-data 0.1.6 → 0.1.8

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cdk.d.ts","sourceRoot":"","sources":["../src/index.cdk.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,EAA0D,MAAM,sBAAsB,CAAC;AACrG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAQpD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAG7D,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,0BAA0B;IAgGhF;;;;;OAKG;IACH,SAAS,IAAI,KAAK;CAGnB;AAaD,OAAO,EAAE,GAAG,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.cdk.d.ts","sourceRoot":"","sources":["../src/index.cdk.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,EAA0E,MAAM,sBAAsB,CAAC;AACrH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AASpD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAG7D,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,0BAA0B;IAwGhF;;;;;OAKG;IACH,SAAS,IAAI,KAAK;CAGnB;AAaD,OAAO,EAAE,GAAG,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.cdk.js CHANGED
@@ -5,10 +5,11 @@
5
5
  * Provisions Aurora DSQL cluster via CloudFormation.
6
6
  * Optionally runs migrations via a CustomResource Lambda.
7
7
  */
8
- import { Scope, DEFAULT_NODE_RUNTIME, synthGuard, blocksNodejsBundling } from '@aws-blocks/core/cdk';
8
+ import { Scope, DEFAULT_NODE_RUNTIME, synthGuard, blocksNodejsBundling, registerConfig } from '@aws-blocks/core/cdk';
9
9
  import * as cdk from 'aws-cdk-lib';
10
10
  import * as iam from 'aws-cdk-lib/aws-iam';
11
11
  import * as lambda from 'aws-cdk-lib/aws-lambda-nodejs';
12
+ import { LogGroup } from 'aws-cdk-lib/aws-logs';
12
13
  import * as cr from 'aws-cdk-lib/custom-resources';
13
14
  import { createHash } from 'node:crypto';
14
15
  import { readdirSync, readFileSync } from 'node:fs';
@@ -39,17 +40,19 @@ export class DistributedDatabase extends Scope {
39
40
  });
40
41
  cluster.applyRemovalPolicy(removalPolicy);
41
42
  const endpoint = cluster.getAtt('Endpoint').toString();
42
- // Env vars for runtime
43
- this.handler.addEnvironment(`BLOCKS_${envName}_ENDPOINT`, endpoint);
44
- this.handler.addEnvironment(`BLOCKS_${envName}_REGION`, region);
45
- // IAM grant — app Lambda gets DML-only access via custom DB role (least privilege)
46
- this.handler.addToRolePolicy(new iam.PolicyStatement({
43
+ // Config for runtime — flows through S3 config (loaded into process.env at
44
+ // cold start) like every other block, instead of a direct env var.
45
+ registerConfig(this, `BLOCKS_${envName}_ENDPOINT`, endpoint);
46
+ registerConfig(this, `BLOCKS_${envName}_REGION`, region);
47
+ // IAM grant — the shared execution role gets DML-only access via custom DB
48
+ // role (least privilege).
49
+ this.executionRole.addToPrincipalPolicy(new iam.PolicyStatement({
47
50
  actions: ['dsql:DbConnect'],
48
51
  resources: [`arn:aws:dsql:${region}:${stack.account}:cluster/${cluster.ref}`],
49
52
  }));
50
53
  new cdk.CfnOutput(stack, `${this.fullId}DsqlEndpoint`, { value: endpoint });
51
- // The app Lambda's IAM role ARN is needed to map the custom DB role.
52
- const appRoleArn = this.handler.role.roleArn;
54
+ // The shared execution role ARN is mapped to the custom DB role.
55
+ const appRoleArn = this.executionRole.roleArn;
53
56
  // Resolve migrations path if provided
54
57
  const resolvedMigrationsPath = options?.migrationsPath ? resolve(options.migrationsPath) : undefined;
55
58
  const migrationsHash = resolvedMigrationsPath ? hashMigrationsDir(resolvedMigrationsPath) : 'no-migrations';
@@ -62,6 +65,12 @@ export class DistributedDatabase extends Scope {
62
65
  handler: 'handler',
63
66
  runtime: DEFAULT_NODE_RUNTIME,
64
67
  timeout: cdk.Duration.minutes(MIGRATION_LAMBDA_TIMEOUT_MINUTES),
68
+ // Own the migration Lambda's log group so its retention follows the
69
+ // stack-wide default instead of AWS's infinite retention.
70
+ logGroup: new LogGroup(stack, `${this.fullId}DsqlMigrationLogs`, {
71
+ retention: this.defaults.logRetention,
72
+ removalPolicy: cdk.RemovalPolicy.DESTROY,
73
+ }),
65
74
  environment: {
66
75
  DSQL_ENDPOINT: endpoint,
67
76
  DSQL_REGION: region,
@@ -18,12 +18,17 @@ const MIGRATIONS_DIR = '.bb-data/__test_cdk_migrations__';
18
18
  function synth(build) {
19
19
  const app = new cdk.App();
20
20
  const stack = new cdk.Stack(app, 'TestStack');
21
+ const executionRole = new cdk.aws_iam.Role(stack, 'BlocksRole', {
22
+ assumedBy: new cdk.aws_iam.ServicePrincipal('lambda.amazonaws.com'),
23
+ });
21
24
  const handler = new lambda.Function(stack, 'Handler', {
22
25
  runtime: DEFAULT_NODE_RUNTIME,
23
26
  handler: 'index.handler',
24
27
  code: lambda.Code.fromInline('exports.handler = async () => {};'),
28
+ role: executionRole,
25
29
  });
26
30
  stack.handler = handler;
31
+ stack.executionRole = executionRole;
27
32
  globalThis.CURRENT_BLOCKS_STACK = stack;
28
33
  try {
29
34
  build(stack);
@@ -59,13 +64,18 @@ test('CDK: per-block removalPolicy is independent of deletion protection', () =>
59
64
  // RETAINed on stack delete but not deletion-protected.
60
65
  const app = new cdk.App();
61
66
  const stack = new cdk.Stack(app, 'IndepStack');
67
+ const executionRole = new cdk.aws_iam.Role(stack, 'BlocksRole', {
68
+ assumedBy: new cdk.aws_iam.ServicePrincipal('lambda.amazonaws.com'),
69
+ });
62
70
  const handler = new lambda.Function(stack, 'Handler', {
63
71
  runtime: DEFAULT_NODE_RUNTIME,
64
72
  handler: 'index.handler',
65
73
  code: lambda.Code.fromInline('exports.handler = async () => {};'),
74
+ role: executionRole,
66
75
  });
67
76
  stack.handler = handler;
68
77
  stack.defaults = BlocksPresets.sandbox;
78
+ stack.executionRole = executionRole;
69
79
  globalThis.CURRENT_BLOCKS_STACK = stack;
70
80
  try {
71
81
  new DistributedDatabase(scope(stack), 'mydsql', { removalPolicy: 'retain' });
@@ -82,15 +92,20 @@ test('CDK: per-block removalPolicy is independent of deletion protection', () =>
82
92
  test('CDK: sandbox defaults disable deletion protection', () => {
83
93
  const app = new cdk.App();
84
94
  const stack = new cdk.Stack(app, 'SandboxStack');
95
+ const executionRole = new cdk.aws_iam.Role(stack, 'BlocksRole', {
96
+ assumedBy: new cdk.aws_iam.ServicePrincipal('lambda.amazonaws.com'),
97
+ });
85
98
  const handler = new lambda.Function(stack, 'Handler', {
86
99
  runtime: DEFAULT_NODE_RUNTIME,
87
100
  handler: 'index.handler',
88
101
  code: lambda.Code.fromInline('exports.handler = async () => {};'),
102
+ role: executionRole,
89
103
  });
90
104
  stack.handler = handler;
91
105
  // The cluster's removal/protection follows the stack-wide defaults (resolved
92
106
  // via the globalThis fallback here), not the sandboxMode context.
93
107
  stack.defaults = BlocksPresets.sandbox;
108
+ stack.executionRole = executionRole;
94
109
  globalThis.CURRENT_BLOCKS_STACK = stack;
95
110
  try {
96
111
  new DistributedDatabase(scope(stack), 'mydsql');
@@ -120,18 +135,36 @@ test('CDK: handler gets dsql:DbConnect policy (least privilege)', () => {
120
135
  },
121
136
  });
122
137
  });
123
- // --- Environment variables ---
124
- test('CDK: handler gets ENDPOINT and REGION env vars', () => {
125
- const template = synth((stack) => {
126
- new DistributedDatabase(scope(stack), 'mydsql');
138
+ // --- Runtime config (endpoint + region) ---
139
+ test('CDK: registers ENDPOINT and REGION via the config registry (not handler env vars)', () => {
140
+ const app = new cdk.App();
141
+ const stack = new cdk.Stack(app, 'TestStack');
142
+ const executionRole = new cdk.aws_iam.Role(stack, 'BlocksRole', {
143
+ assumedBy: new cdk.aws_iam.ServicePrincipal('lambda.amazonaws.com'),
127
144
  });
128
- const fns = template.findResources('AWS::Lambda::Function');
129
- const handlerFn = Object.entries(fns).find(([id]) => id.startsWith('Handler'));
130
- assert.ok(handlerFn, 'Handler Lambda should exist');
131
- const env = handlerFn[1].Properties?.Environment?.Variables ?? {};
132
- const envKeys = Object.keys(env);
133
- assert.ok(envKeys.some(k => k.includes('ENDPOINT')), `Expected ENDPOINT env var, got: ${envKeys}`);
134
- assert.ok(envKeys.some(k => k.includes('REGION')), `Expected REGION env var, got: ${envKeys}`);
145
+ const handler = new lambda.Function(stack, 'Handler', {
146
+ runtime: DEFAULT_NODE_RUNTIME,
147
+ handler: 'index.handler',
148
+ code: lambda.Code.fromInline('exports.handler = async () => {};'),
149
+ role: executionRole,
150
+ });
151
+ stack.handler = handler;
152
+ stack.executionRole = executionRole;
153
+ globalThis.CURRENT_BLOCKS_STACK = stack;
154
+ try {
155
+ new DistributedDatabase(scope(stack), 'mydsql');
156
+ // Endpoint + region now flow through the config registry (loaded into
157
+ // process.env at cold start) like every other block — not a direct env var
158
+ // on the handler.
159
+ const registry = stack[Symbol.for('BLOCKS_CONFIG_REGISTRY')];
160
+ assert.ok(registry, 'config registry exists on the stack');
161
+ const keys = [...registry.entries.keys()];
162
+ assert.ok(keys.some(k => k.includes('ENDPOINT')), `Expected an ENDPOINT config key, got: ${keys}`);
163
+ assert.ok(keys.some(k => k.includes('REGION')), `Expected a REGION config key, got: ${keys}`);
164
+ }
165
+ finally {
166
+ delete globalThis.CURRENT_BLOCKS_STACK;
167
+ }
135
168
  });
136
169
  // --- CfnOutput ---
137
170
  test('CDK: stack has endpoint output', () => {
@@ -156,6 +189,33 @@ test('CDK: migration/provisioning resources always created', () => {
156
189
  const hasDsqlGrant = policyValues.some((p) => JSON.stringify(p).includes('dsql:DbConnectAdmin'));
157
190
  assert.ok(hasDsqlGrant, 'Migration Lambda should have dsql:DbConnectAdmin');
158
191
  });
192
+ test('CDK: DSQL migration Lambda log group adopts defaults.logRetention', () => {
193
+ const app = new cdk.App();
194
+ const stack = new cdk.Stack(app, 'DsqlMigrationRetentionStack');
195
+ const executionRole = new cdk.aws_iam.Role(stack, 'BlocksRole', {
196
+ assumedBy: new cdk.aws_iam.ServicePrincipal('lambda.amazonaws.com'),
197
+ });
198
+ const handler = new lambda.Function(stack, 'Handler', {
199
+ runtime: DEFAULT_NODE_RUNTIME,
200
+ handler: 'index.handler',
201
+ code: lambda.Code.fromInline('exports.handler = async () => {};'),
202
+ role: executionRole,
203
+ });
204
+ stack.handler = handler;
205
+ stack.executionRole = executionRole;
206
+ stack.defaults = BlocksPresets.sandbox;
207
+ globalThis.CURRENT_BLOCKS_STACK = stack;
208
+ try {
209
+ new DistributedDatabase(scope(stack), 'mydsql');
210
+ const template = Template.fromStack(stack);
211
+ // The always-created migration Lambda now owns an explicit log group whose
212
+ // retention follows the stack-wide default (sandbox → one week).
213
+ template.hasResourceProperties('AWS::Logs::LogGroup', { RetentionInDays: 7 });
214
+ }
215
+ finally {
216
+ delete globalThis.CURRENT_BLOCKS_STACK;
217
+ }
218
+ });
159
219
  test('CDK: migration resources created when migrationsPath is provided', () => {
160
220
  rmSync(MIGRATIONS_DIR, { recursive: true, force: true });
161
221
  mkdirSync(MIGRATIONS_DIR, { recursive: true });
package/dist/version.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export declare const BB_NAME = "DistributedDatabase";
2
- export declare const BB_VERSION = "0.1.6";
2
+ export declare const BB_VERSION = "0.1.8";
3
3
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -1,3 +1,3 @@
1
1
  // Auto-generated by scripts/generate-version.mjs — do not edit manually
2
2
  export const BB_NAME = 'DistributedDatabase';
3
- export const BB_VERSION = '0.1.6';
3
+ export const BB_VERSION = '0.1.8';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aws-blocks/bb-distributed-data",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/aws-devtools-labs/aws-blocks.git",
@@ -37,9 +37,9 @@
37
37
  "test": "node --test 'dist/**/*.test.js'"
38
38
  },
39
39
  "dependencies": {
40
- "@aws-blocks/core": "^0.2.0",
40
+ "@aws-blocks/core": "^0.4.0",
41
41
  "@aws-blocks/data-common": "^0.1.4",
42
- "@aws-blocks/bb-logger": "^0.1.4",
42
+ "@aws-blocks/bb-logger": "^0.1.6",
43
43
  "@aws-sdk/dsql-signer": "^3.700.0",
44
44
  "@electric-sql/pglite": "^0.2.0",
45
45
  "pg": "^8.13.0"