@aws-blocks/core 0.2.0 → 0.4.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/README.md +13 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +32 -0
- package/dist/api.test.js +22 -0
- package/dist/bb-utils.d.ts +1 -0
- package/dist/bb-utils.d.ts.map +1 -1
- package/dist/bb-utils.js +3 -0
- package/dist/cdk/apigateway-account.d.ts +33 -0
- package/dist/cdk/apigateway-account.d.ts.map +1 -0
- package/dist/cdk/apigateway-account.js +60 -0
- package/dist/cdk/blocks-backend.d.ts +43 -9
- package/dist/cdk/blocks-backend.d.ts.map +1 -1
- package/dist/cdk/blocks-backend.js +69 -73
- package/dist/cdk/blocks-backend.test.js +78 -69
- package/dist/cdk/blocks-defaults.d.ts +92 -2
- package/dist/cdk/blocks-defaults.d.ts.map +1 -1
- package/dist/cdk/blocks-defaults.js +22 -2
- package/dist/cdk/blocks-defaults.test.js +21 -2
- package/dist/cdk/blocks-stack.test.js +94 -37
- package/dist/cdk/compute/compute-registry.d.ts +19 -0
- package/dist/cdk/compute/compute-registry.d.ts.map +1 -0
- package/dist/cdk/compute/compute-registry.js +38 -0
- package/dist/cdk/compute/compute.d.ts +2 -0
- package/dist/cdk/compute/compute.d.ts.map +1 -1
- package/dist/cdk/compute/compute.js +8 -0
- package/dist/cdk/compute/default-compute-factory.d.ts +34 -0
- package/dist/cdk/compute/default-compute-factory.d.ts.map +1 -0
- package/dist/cdk/compute/default-compute-factory.js +3 -0
- package/dist/cdk/config-registry.d.ts +34 -4
- package/dist/cdk/config-registry.d.ts.map +1 -1
- package/dist/cdk/config-registry.js +83 -25
- package/dist/cdk/config-registry.test.d.ts +2 -0
- package/dist/cdk/config-registry.test.d.ts.map +1 -0
- package/dist/cdk/config-registry.test.js +115 -0
- package/dist/cdk/index.d.ts +76 -7
- package/dist/cdk/index.d.ts.map +1 -1
- package/dist/cdk/index.js +99 -9
- package/dist/cdk/internal.d.ts +1 -0
- package/dist/cdk/internal.d.ts.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/common/config.d.ts +34 -0
- package/dist/common/config.d.ts.map +1 -1
- package/dist/common/config.js +45 -3
- package/dist/common/config.test.js +19 -0
- package/dist/common/index.d.ts +8 -0
- package/dist/common/index.d.ts.map +1 -1
- package/dist/errors.d.ts +16 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +20 -0
- package/dist/hosting-secrets.d.ts +48 -0
- package/dist/hosting-secrets.d.ts.map +1 -0
- package/dist/hosting-secrets.js +57 -0
- package/dist/hosting-secrets.test.d.ts +2 -0
- package/dist/hosting-secrets.test.d.ts.map +1 -0
- package/dist/hosting-secrets.test.js +81 -0
- package/dist/hosting.d.ts +97 -6
- package/dist/hosting.d.ts.map +1 -1
- package/dist/hosting.js +91 -23
- package/dist/hosting.test.js +182 -10
- package/dist/index.cdk.d.ts +13 -12
- package/dist/index.cdk.d.ts.map +1 -1
- package/dist/index.cdk.js +13 -9
- package/dist/index.d.ts +8 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -5
- package/dist/lambda-handler.d.ts +17 -0
- package/dist/lambda-handler.d.ts.map +1 -1
- package/dist/lambda-handler.js +52 -3
- package/dist/lambda-handler.test.js +196 -1
- package/dist/pipeline/index.d.ts +24 -2
- package/dist/pipeline/index.d.ts.map +1 -1
- package/dist/pipeline/index.js +41 -1
- package/dist/pipeline.test.d.ts +2 -0
- package/dist/pipeline.test.d.ts.map +1 -0
- package/dist/pipeline.test.js +47 -0
- package/dist/rpc.d.ts +21 -0
- package/dist/rpc.d.ts.map +1 -1
- package/dist/rpc.js +34 -0
- package/dist/rpc.test.js +38 -1
- package/dist/scripts/config.d.ts +15 -0
- package/dist/scripts/config.d.ts.map +1 -0
- package/dist/scripts/config.js +29 -0
- package/dist/scripts/deploy.d.ts.map +1 -1
- package/dist/scripts/deploy.js +4 -0
- package/dist/scripts/dev-server.d.ts +8 -0
- package/dist/scripts/dev-server.d.ts.map +1 -1
- package/dist/scripts/dev-server.js +31 -0
- package/dist/scripts/generate-client.d.ts.map +1 -1
- package/dist/scripts/generate-client.js +9 -4
- package/dist/scripts/generate-client.test.js +19 -4
- package/dist/scripts/index.d.ts +13 -10
- package/dist/scripts/index.d.ts.map +1 -1
- package/dist/scripts/index.js +11 -8
- package/dist/scripts/preflight-credentials.d.ts +30 -0
- package/dist/scripts/preflight-credentials.d.ts.map +1 -0
- package/dist/scripts/preflight-credentials.js +108 -0
- package/dist/scripts/preflight-credentials.test.d.ts +2 -0
- package/dist/scripts/preflight-credentials.test.d.ts.map +1 -0
- package/dist/scripts/preflight-credentials.test.js +77 -0
- package/dist/scripts/sandbox-args.test.d.ts +2 -0
- package/dist/scripts/sandbox-args.test.d.ts.map +1 -0
- package/dist/scripts/sandbox-args.test.js +77 -0
- package/dist/scripts/sandbox-empty-buckets.test.d.ts +2 -0
- package/dist/scripts/sandbox-empty-buckets.test.d.ts.map +1 -0
- package/dist/scripts/sandbox-empty-buckets.test.js +171 -0
- package/dist/scripts/sandbox.d.ts +106 -0
- package/dist/scripts/sandbox.d.ts.map +1 -1
- package/dist/scripts/sandbox.js +255 -40
- package/dist/scripts/secret.d.ts +15 -0
- package/dist/scripts/secret.d.ts.map +1 -0
- package/dist/scripts/secret.js +29 -0
- package/dist/scripts/secret.test.d.ts +2 -0
- package/dist/scripts/secret.test.d.ts.map +1 -0
- package/dist/scripts/secret.test.js +28 -0
- package/dist/scripts/typegen.d.ts +15 -0
- package/dist/scripts/typegen.d.ts.map +1 -0
- package/dist/scripts/typegen.js +16 -0
- package/dist/secret-naming.d.ts +58 -0
- package/dist/secret-naming.d.ts.map +1 -0
- package/dist/secret-naming.js +67 -0
- package/dist/secret-naming.test.d.ts +2 -0
- package/dist/secret-naming.test.d.ts.map +1 -0
- package/dist/secret-naming.test.js +40 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -1
- package/src/api.test.ts +25 -0
- package/src/api.ts +39 -0
- package/src/bb-utils.ts +3 -0
- package/src/cdk/apigateway-account.ts +66 -0
- package/src/cdk/blocks-backend.test.ts +291 -272
- package/src/cdk/blocks-backend.ts +88 -83
- package/src/cdk/blocks-defaults.test.ts +25 -2
- package/src/cdk/blocks-defaults.ts +94 -2
- package/src/cdk/blocks-stack.test.ts +186 -118
- package/src/cdk/compute/compute-registry.ts +45 -0
- package/src/cdk/compute/compute.ts +10 -0
- package/src/cdk/compute/default-compute-factory.ts +38 -0
- package/src/cdk/config-registry.test.ts +135 -0
- package/src/cdk/config-registry.ts +92 -34
- package/src/cdk/index.ts +129 -10
- package/src/cdk/internal.ts +1 -0
- package/src/client/index.ts +1 -1
- package/src/common/config.test.ts +21 -0
- package/src/common/config.ts +47 -3
- package/src/common/index.ts +8 -0
- package/src/errors.ts +21 -0
- package/src/hosting-secrets.test.ts +106 -0
- package/src/hosting-secrets.ts +106 -0
- package/src/hosting.test.ts +272 -63
- package/src/hosting.ts +200 -68
- package/src/index.cdk.ts +80 -38
- package/src/index.ts +35 -16
- package/src/lambda-handler.test.ts +215 -1
- package/src/lambda-handler.ts +54 -2
- package/src/pipeline/index.ts +64 -11
- package/src/pipeline.test.ts +55 -0
- package/src/rpc.test.ts +44 -1
- package/src/rpc.ts +41 -0
- package/src/scripts/config.ts +35 -0
- package/src/scripts/deploy.ts +5 -0
- package/src/scripts/dev-server.ts +40 -0
- package/src/scripts/generate-client.test.ts +43 -8
- package/src/scripts/generate-client.ts +70 -65
- package/src/scripts/index.ts +20 -17
- package/src/scripts/preflight-credentials.test.ts +110 -0
- package/src/scripts/preflight-credentials.ts +131 -0
- package/src/scripts/sandbox-args.test.ts +92 -0
- package/src/scripts/sandbox-empty-buckets.test.ts +191 -0
- package/src/scripts/sandbox.ts +287 -39
- package/src/scripts/secret.test.ts +35 -0
- package/src/scripts/secret.ts +35 -0
- package/src/scripts/typegen.ts +18 -0
- package/src/secret-naming.test.ts +59 -0
- package/src/secret-naming.ts +99 -0
- package/src/version.ts +1 -1
package/README.md
CHANGED
|
@@ -313,6 +313,19 @@ new Hosting(stack, 'Web', {
|
|
|
313
313
|
|
|
314
314
|
The `framework` option selects the frontend type: `'spa' | 'static' | 'nextjs'`. When omitted, the framework is auto-detected by reading your app's OWN `package.json` (not `node_modules`): a `next` dependency → `nextjs`; otherwise `spa`; and `static` when there is no `package.json`. Set `framework: 'spa'` explicitly to override auto-detection — e.g. when a stray `next` dependency would otherwise trigger an unwanted Next.js/OpenNext build. Full reference lives in the source JSDoc.
|
|
315
315
|
|
|
316
|
+
Old builds are retained for rollback and expired by an S3 lifecycle rule after `buildRetentionDays` (default **30**). The build currently being served is never expired regardless of deploy cadence — only superseded builds are cleaned up. Only builds superseded by a normal `Update` cutover are auto-tagged (and thus auto-expired): pre-existing/orphaned builds and aborted or rolled-back deploys are never tagged and need manual cleanup (e.g. an S3 inventory / Batch Operations sweep). Raise the window with `buildRetentionDays` (it must be ≥ `skewProtection.maxAge` in days):
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
new Hosting(stack, 'Web', {
|
|
320
|
+
root: join(__dirname, '..'),
|
|
321
|
+
api: blocksStack,
|
|
322
|
+
buildRetentionDays: 90,
|
|
323
|
+
});
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
Core's top-level `buildRetentionDays` maps to the L3 construct's `storage.buildRetentionDays`.
|
|
327
|
+
|
|
328
|
+
|
|
316
329
|
## Building Blocks
|
|
317
330
|
|
|
318
331
|
Import Building Blocks from their specific packages (or from the `@aws-blocks/blocks` umbrella):
|
package/dist/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE;QACP,OAAO,EAAE,OAAO,CAAC;QACjB,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;QACxC,IAAI,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;QAC5B;;;;;;;;;;WAUG;QACH,GAAG,EAAE,GAAG,CAAC;QACT;;;;;WAKG;QACH,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC/B;;;;;;;;;WASG;QACH,MAAM,CAAC,EAAE,WAAW,CAAC;KACtB,CAAC;IACF,QAAQ,EAAE;QACR,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;KAC3B,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,KAAK,CAAC,CAAC;AAG1G,KAAK,QAAQ,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC,IAAI;KAChE,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,MAAM,IAAI,KAAK,MAAM,CAAC,GACzD,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GACtC,KAAK;CACV,CAAC;AAEF,yEAAyE;AACzE,eAAO,MAAM,oBAAoB,eAAoC,CAAC;AAEtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE;QACP,OAAO,EAAE,OAAO,CAAC;QACjB,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;QACxC,IAAI,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;QAC5B;;;;;;;;;;WAUG;QACH,GAAG,EAAE,GAAG,CAAC;QACT;;;;;WAKG;QACH,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC/B;;;;;;;;;WASG;QACH,MAAM,CAAC,EAAE,WAAW,CAAC;KACtB,CAAC;IACF,QAAQ,EAAE;QACR,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;KAC3B,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,KAAK,CAAC,CAAC;AAG1G,KAAK,QAAQ,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC,IAAI;KAChE,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,MAAM,IAAI,KAAK,MAAM,CAAC,GACzD,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GACtC,KAAK;CACV,CAAC;AAEF,yEAAyE;AACzE,eAAO,MAAM,oBAAoB,eAAoC,CAAC;AAEtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAsCrD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0FG;AACH,MAAM,WAAW,uBAAuB;IACtC,KAAK,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;CAChI;AAED,eAAO,MAAM,YAAY,EAAE,uBAQnB,CAAC"}
|
package/dist/api.js
CHANGED
|
@@ -2,9 +2,41 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
/** Marker symbol to identify ApiNamespace instances during discovery. */
|
|
4
4
|
export const API_NAMESPACE_MARKER = Symbol.for('blocks:ApiNamespace');
|
|
5
|
+
/**
|
|
6
|
+
* Record this namespace on its resolved compute so request routing can later
|
|
7
|
+
* map a namespace to the compute that hosts it.
|
|
8
|
+
*
|
|
9
|
+
* CDK-synth concern only: in the CDK bundle `scope.compute` resolves to the
|
|
10
|
+
* namespace's compute (the stack default today), and we append the name to its
|
|
11
|
+
* `namespaces` list. In the mock/runtime bundles — or a scopeless test — the
|
|
12
|
+
* property is absent, so `scope.compute` is `undefined` and this is a silent
|
|
13
|
+
* no-op. The public `ApiNamespace` signature is unchanged; this is a purely
|
|
14
|
+
* internal side effect.
|
|
15
|
+
*
|
|
16
|
+
* No `try/catch`: `BlocksBackend.create()` initializes the default compute
|
|
17
|
+
* before it imports the backend module that constructs any `ApiNamespace`, so
|
|
18
|
+
* the `compute` getter always resolves at this call site. If it ever threw
|
|
19
|
+
* here it would signal a genuine lifecycle violation (an `ApiNamespace` built
|
|
20
|
+
* before `create()` resolved), which should surface rather than be swallowed.
|
|
21
|
+
*/
|
|
22
|
+
function recordNamespaceOnCompute(scope, name) {
|
|
23
|
+
// An API created without a Scope stays unrecorded and routes to the
|
|
24
|
+
// default compute.
|
|
25
|
+
if (!scope || typeof scope !== 'object')
|
|
26
|
+
return;
|
|
27
|
+
const compute = scope.compute;
|
|
28
|
+
// Guard against duplicates so `namespaces` stays a set of names: a namespace
|
|
29
|
+
// could otherwise be recorded twice (e.g. a re-imported module during synth).
|
|
30
|
+
if (compute && Array.isArray(compute.namespaces) && !compute.namespaces.includes(name)) {
|
|
31
|
+
compute.namespaces.push(name);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
5
34
|
export const ApiNamespace = class ApiNamespace {
|
|
6
35
|
constructor(scope, name, handler) {
|
|
7
36
|
handler[API_NAMESPACE_MARKER] = name;
|
|
37
|
+
// Record the namespace → compute association for per-compute routing.
|
|
38
|
+
// No-op outside CDK synth. Signature and returned handler are unchanged.
|
|
39
|
+
recordNamespaceOnCompute(scope, name);
|
|
8
40
|
return handler;
|
|
9
41
|
}
|
|
10
42
|
};
|
package/dist/api.test.js
CHANGED
|
@@ -17,3 +17,25 @@ test('Different ApiNamespace names should not collide', () => {
|
|
|
17
17
|
assert.strictEqual(api1[API_NAMESPACE_MARKER], 'api1');
|
|
18
18
|
assert.strictEqual(api2[API_NAMESPACE_MARKER], 'api2');
|
|
19
19
|
});
|
|
20
|
+
// ApiNamespace records its name on the scope's resolved compute (CDK
|
|
21
|
+
// synth), while staying a silent no-op where no compute is resolvable.
|
|
22
|
+
test('ApiNamespace records its name on a resolvable compute', () => {
|
|
23
|
+
const compute = { namespaces: [] };
|
|
24
|
+
new ApiNamespace({ id: 'app', compute }, 'myapi', () => ({ ping: () => 'ok' }));
|
|
25
|
+
assert.deepStrictEqual(compute.namespaces, ['myapi']);
|
|
26
|
+
});
|
|
27
|
+
test('ApiNamespace is a no-op recorder when the scope has no compute', () => {
|
|
28
|
+
// The common Scope (mock/runtime) has no `compute`; recording must not throw
|
|
29
|
+
// and the handler is still tagged and returned unchanged.
|
|
30
|
+
const handler = new ApiNamespace(new Scope('no-compute'), 'plainapi', () => ({ x: () => 1 }));
|
|
31
|
+
assert.strictEqual(handler[API_NAMESPACE_MARKER], 'plainapi');
|
|
32
|
+
});
|
|
33
|
+
test('ApiNamespace records a namespace at most once per compute', () => {
|
|
34
|
+
// `namespaces` is a set of names: recording the same name twice (e.g. a
|
|
35
|
+
// re-imported module during synth) must not append a duplicate.
|
|
36
|
+
const compute = { namespaces: [] };
|
|
37
|
+
const scopeLike = { id: 'app', compute };
|
|
38
|
+
new ApiNamespace(scopeLike, 'dup', () => ({ ping: () => 'ok' }));
|
|
39
|
+
new ApiNamespace(scopeLike, 'dup', () => ({ ping: () => 'ok' }));
|
|
40
|
+
assert.deepStrictEqual(compute.namespaces, ['dup']);
|
|
41
|
+
});
|
package/dist/bb-utils.d.ts
CHANGED
|
@@ -8,4 +8,5 @@ export { getMockDataDir } from './common/mock-data.js';
|
|
|
8
8
|
export { API_NAMESPACE_MARKER } from './api.js';
|
|
9
9
|
export { EventSourceMapping } from './lambda-handler.js';
|
|
10
10
|
export { constantTimeEquals } from './common/crypto.js';
|
|
11
|
+
export { sanitizeConfigKey } from './common/config.js';
|
|
11
12
|
//# sourceMappingURL=bb-utils.d.ts.map
|
package/dist/bb-utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bb-utils.d.ts","sourceRoot":"","sources":["../src/bb-utils.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"bb-utils.d.ts","sourceRoot":"","sources":["../src/bb-utils.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAGxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/bb-utils.js
CHANGED
|
@@ -10,3 +10,6 @@ export { getMockDataDir } from './common/mock-data.js';
|
|
|
10
10
|
export { API_NAMESPACE_MARKER } from './api.js';
|
|
11
11
|
export { EventSourceMapping } from './lambda-handler.js';
|
|
12
12
|
export { constantTimeEquals } from './common/crypto.js';
|
|
13
|
+
// Defined in the config module (it owns the config-key contract), re-exported
|
|
14
|
+
// here so BB authors get it alongside the other BB utilities.
|
|
15
|
+
export { sanitizeConfigKey } from './common/config.js';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type * as cdk from 'aws-cdk-lib';
|
|
2
|
+
import { CfnAccount } from 'aws-cdk-lib/aws-apigateway';
|
|
3
|
+
/**
|
|
4
|
+
* Ensure the account-level API Gateway CloudWatch Logs role exists on `stack`,
|
|
5
|
+
* creating it at most once per stack.
|
|
6
|
+
*
|
|
7
|
+
* API Gateway access logging — for both REST (v1) and WebSocket (v2) stages —
|
|
8
|
+
* requires an `AWS::ApiGateway::Account` whose `cloudWatchRoleArn` points at a
|
|
9
|
+
* role trusted by `apigateway.amazonaws.com` and carrying
|
|
10
|
+
* `AmazonAPIGatewayPushToCloudWatchLogs`. Nothing else in a Blocks stack
|
|
11
|
+
* provisions it, so a clean-account first deploy of any access-logging stage
|
|
12
|
+
* otherwise fails at CreateStage with "CloudWatch Logs role ARN must be set in
|
|
13
|
+
* account settings to enable logging".
|
|
14
|
+
*
|
|
15
|
+
* Callers should add their stage's dependency on the returned account so the
|
|
16
|
+
* account setting is applied before the stage is created.
|
|
17
|
+
*
|
|
18
|
+
* ⚠️ Single-Blocks-stack-per-region assumption. `AWS::ApiGateway::Account` is an
|
|
19
|
+
* account/region-level singleton (one effective `cloudWatchRoleArn` per region),
|
|
20
|
+
* but this provisions one per Blocks stack. If two Blocks stacks in the same
|
|
21
|
+
* account+region both enable access logging:
|
|
22
|
+
* - on deploy, the later stack's role wins (overwrites the account setting); and
|
|
23
|
+
* - on teardown of that later stack, its role is deleted and the account
|
|
24
|
+
* setting is left pointing at a now-deleted role — silently breaking access
|
|
25
|
+
* logging (or blocking `CreateStage`) for the surviving stack until it
|
|
26
|
+
* redeploys.
|
|
27
|
+
* Enabling `accessLogging` is therefore safe for one Blocks stack per region.
|
|
28
|
+
* Multi-stack support (a shared/imported account) is deferred; if you run
|
|
29
|
+
* multiple Blocks stacks per region, manage the account role out-of-band and
|
|
30
|
+
* leave `accessLogging` to a single owner.
|
|
31
|
+
*/
|
|
32
|
+
export declare function ensureApiGatewayAccount(stack: cdk.Stack): CfnAccount;
|
|
33
|
+
//# sourceMappingURL=apigateway-account.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apigateway-account.d.ts","sourceRoot":"","sources":["../../src/cdk/apigateway-account.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,GAAG,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAaxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,GAAG,CAAC,KAAK,GAAG,UAAU,CAmBpE"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { CfnAccount } from 'aws-cdk-lib/aws-apigateway';
|
|
4
|
+
import { ManagedPolicy, Role, ServicePrincipal } from 'aws-cdk-lib/aws-iam';
|
|
5
|
+
/**
|
|
6
|
+
* Global registry key for the per-stack API Gateway CloudWatch Logs account
|
|
7
|
+
* resource. Deliberately a `Symbol.for(...)` string key so the SAME symbol is
|
|
8
|
+
* shared across packages (core, hosting) — each package can carry its own copy
|
|
9
|
+
* of {@link ensureApiGatewayAccount} yet still find and reuse the one account a
|
|
10
|
+
* sibling package already created on the stack, instead of emitting a second
|
|
11
|
+
* `AWS::ApiGateway::Account` (which is account/region-level and would clash).
|
|
12
|
+
*/
|
|
13
|
+
const ACCOUNT_KEY = Symbol.for('BLOCKS_APIGATEWAY_ACCOUNT');
|
|
14
|
+
/**
|
|
15
|
+
* Ensure the account-level API Gateway CloudWatch Logs role exists on `stack`,
|
|
16
|
+
* creating it at most once per stack.
|
|
17
|
+
*
|
|
18
|
+
* API Gateway access logging — for both REST (v1) and WebSocket (v2) stages —
|
|
19
|
+
* requires an `AWS::ApiGateway::Account` whose `cloudWatchRoleArn` points at a
|
|
20
|
+
* role trusted by `apigateway.amazonaws.com` and carrying
|
|
21
|
+
* `AmazonAPIGatewayPushToCloudWatchLogs`. Nothing else in a Blocks stack
|
|
22
|
+
* provisions it, so a clean-account first deploy of any access-logging stage
|
|
23
|
+
* otherwise fails at CreateStage with "CloudWatch Logs role ARN must be set in
|
|
24
|
+
* account settings to enable logging".
|
|
25
|
+
*
|
|
26
|
+
* Callers should add their stage's dependency on the returned account so the
|
|
27
|
+
* account setting is applied before the stage is created.
|
|
28
|
+
*
|
|
29
|
+
* ⚠️ Single-Blocks-stack-per-region assumption. `AWS::ApiGateway::Account` is an
|
|
30
|
+
* account/region-level singleton (one effective `cloudWatchRoleArn` per region),
|
|
31
|
+
* but this provisions one per Blocks stack. If two Blocks stacks in the same
|
|
32
|
+
* account+region both enable access logging:
|
|
33
|
+
* - on deploy, the later stack's role wins (overwrites the account setting); and
|
|
34
|
+
* - on teardown of that later stack, its role is deleted and the account
|
|
35
|
+
* setting is left pointing at a now-deleted role — silently breaking access
|
|
36
|
+
* logging (or blocking `CreateStage`) for the surviving stack until it
|
|
37
|
+
* redeploys.
|
|
38
|
+
* Enabling `accessLogging` is therefore safe for one Blocks stack per region.
|
|
39
|
+
* Multi-stack support (a shared/imported account) is deferred; if you run
|
|
40
|
+
* multiple Blocks stacks per region, manage the account role out-of-band and
|
|
41
|
+
* leave `accessLogging` to a single owner.
|
|
42
|
+
*/
|
|
43
|
+
export function ensureApiGatewayAccount(stack) {
|
|
44
|
+
const existing = stack[ACCOUNT_KEY];
|
|
45
|
+
if (existing)
|
|
46
|
+
return existing;
|
|
47
|
+
const role = new Role(stack, 'BlocksApiGatewayCloudWatchRole', {
|
|
48
|
+
assumedBy: new ServicePrincipal('apigateway.amazonaws.com'),
|
|
49
|
+
managedPolicies: [
|
|
50
|
+
ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonAPIGatewayPushToCloudWatchLogs'),
|
|
51
|
+
],
|
|
52
|
+
});
|
|
53
|
+
// `cloudWatchRoleArn: role.roleArn` already gives CDK an implicit dependency
|
|
54
|
+
// on the role, so no explicit node.addDependency is needed.
|
|
55
|
+
const account = new CfnAccount(stack, 'BlocksApiGatewayAccount', {
|
|
56
|
+
cloudWatchRoleArn: role.roleArn,
|
|
57
|
+
});
|
|
58
|
+
stack[ACCOUNT_KEY] = account;
|
|
59
|
+
return account;
|
|
60
|
+
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import * as cdk from 'aws-cdk-lib';
|
|
2
|
-
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
|
|
2
|
+
import type * as apigateway from 'aws-cdk-lib/aws-apigateway';
|
|
3
3
|
import * as iam from 'aws-cdk-lib/aws-iam';
|
|
4
4
|
import { Construct } from 'constructs';
|
|
5
5
|
import type { BlocksDefaults } from './blocks-defaults.js';
|
|
6
|
+
import type { Compute } from './compute/compute.js';
|
|
7
|
+
import type { DefaultComputeFactory } from './compute/default-compute-factory.js';
|
|
6
8
|
/**
|
|
7
9
|
* Validate that the Node.js process was started with `--conditions=cdk`.
|
|
8
10
|
*
|
|
@@ -12,6 +14,12 @@ import type { BlocksDefaults } from './blocks-defaults.js';
|
|
|
12
14
|
* no real infrastructure (no tables, no IAM, no Lambda configs).
|
|
13
15
|
*/
|
|
14
16
|
export declare function assertCdkConditionActive(): void;
|
|
17
|
+
/**
|
|
18
|
+
* Timeout of the shared Blocks handler Lambda, and therefore the ceiling on a
|
|
19
|
+
* single invocation. Exported because resources that feed the handler have to
|
|
20
|
+
* size their own timeouts against it (e.g. an SQS queue's visibility timeout).
|
|
21
|
+
*/
|
|
22
|
+
export declare const SHARED_HANDLER_TIMEOUT_SECONDS: number;
|
|
15
23
|
export interface BlocksBackendProps {
|
|
16
24
|
backendHandlerPath: string;
|
|
17
25
|
backendCDKPath: string;
|
|
@@ -24,11 +32,23 @@ export interface BlocksBackendProps {
|
|
|
24
32
|
*/
|
|
25
33
|
defaults: BlocksDefaults;
|
|
26
34
|
}
|
|
27
|
-
/**
|
|
35
|
+
/**
|
|
36
|
+
* Core's `create()` props: the public {@link BlocksBackendProps} plus the
|
|
37
|
+
* required `defaultComputeFactory`, spread on by the umbrella (`@aws-blocks/blocks`).
|
|
38
|
+
* Customers use {@link BlocksBackendProps} and never set the factory.
|
|
39
|
+
*
|
|
40
|
+
* @internal
|
|
41
|
+
*/
|
|
42
|
+
export interface CoreBlocksBackendProps extends BlocksBackendProps {
|
|
43
|
+
/** Builds the backend's default compute. Injected by `@aws-blocks/blocks`. */
|
|
44
|
+
defaultComputeFactory: DefaultComputeFactory;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Shared infra setup — provisions the stack-level resources that are NOT owned
|
|
48
|
+
* by a compute: the shared execution role, resource groups, and console-redirect
|
|
49
|
+
* routes.
|
|
50
|
+
*/
|
|
28
51
|
export declare function setupBlocksInfra(scope: Construct, props: BlocksBackendProps, id?: string): {
|
|
29
|
-
handler: cdk.aws_lambda_nodejs.NodejsFunction;
|
|
30
|
-
gateway: cdk.aws_apigateway.RestApi;
|
|
31
|
-
apiUrl: string;
|
|
32
52
|
executionRole: cdk.aws_iam.Role;
|
|
33
53
|
};
|
|
34
54
|
/**
|
|
@@ -49,14 +69,28 @@ export declare function setupBlocksInfra(scope: Construct, props: BlocksBackendP
|
|
|
49
69
|
* ```
|
|
50
70
|
*/
|
|
51
71
|
export declare class BlocksBackend extends Construct {
|
|
52
|
-
readonly apiUrl: string;
|
|
53
|
-
readonly gateway: apigateway.RestApi;
|
|
54
|
-
readonly handler: cdk.aws_lambda_nodejs.NodejsFunction;
|
|
55
72
|
readonly backendHandlerPath: string;
|
|
73
|
+
/**
|
|
74
|
+
* Path to the app's backend module (`props.backendCDKPath`). Exposed so Building Blocks that
|
|
75
|
+
* co-bundle the backend at synth (e.g. the Agent BB's AgentCore Runtime) can discover it via
|
|
76
|
+
* `globalThis.CURRENT_BLOCKS_STACK.backendModulePath`.
|
|
77
|
+
*/
|
|
78
|
+
readonly backendModulePath: string;
|
|
56
79
|
/** Shared IAM role assumed by all Blocks compute. Building Blocks grant to this role. */
|
|
57
80
|
readonly executionRole: iam.IRole;
|
|
58
81
|
/** Infrastructure defaults for Building Blocks created under this backend. */
|
|
59
82
|
readonly defaults: BlocksDefaults;
|
|
83
|
+
/** The default compute (owns the Lambda function + API Gateway); set in `create()`. @internal */
|
|
84
|
+
_defaultCompute?: Compute;
|
|
85
|
+
/** The default compute's Lambda function. To be removed once consumers move to the multi-compute model. */
|
|
86
|
+
get handler(): cdk.aws_lambda_nodejs.NodejsFunction;
|
|
87
|
+
/** The default compute's API Gateway REST API. To be removed once consumers move to the multi-compute model. */
|
|
88
|
+
get gateway(): apigateway.RestApi;
|
|
89
|
+
/** The default compute's RPC endpoint URL. To be removed once consumers move to the multi-compute model. */
|
|
90
|
+
get apiUrl(): string;
|
|
91
|
+
/** The default compute's handler CloudWatch log group. `bb-logger` reconfigures its retention. */
|
|
92
|
+
get handlerLogGroup(): cdk.aws_logs.ILogGroup;
|
|
93
|
+
private requireDefaultCompute;
|
|
60
94
|
/**
|
|
61
95
|
* The fullId used by child Scopes to compute their env var names,
|
|
62
96
|
* construct IDs, and physical resource names (e.g., DynamoDB table names).
|
|
@@ -78,6 +112,6 @@ export declare class BlocksBackend extends Construct {
|
|
|
78
112
|
*/
|
|
79
113
|
get fullId(): string;
|
|
80
114
|
private constructor();
|
|
81
|
-
static create(scope: Construct, id: string, props:
|
|
115
|
+
static create(scope: Construct, id: string, props: CoreBlocksBackendProps): Promise<BlocksBackend>;
|
|
82
116
|
}
|
|
83
117
|
//# sourceMappingURL=blocks-backend.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blocks-backend.d.ts","sourceRoot":"","sources":["../../src/cdk/blocks-backend.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,GAAG,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"blocks-backend.d.ts","sourceRoot":"","sources":["../../src/cdk/blocks-backend.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,GAAG,MAAM,aAAa,CAAC;AACnC,OAAO,KAAK,KAAK,UAAU,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,GAAG,MAAM,qBAAqB,CAAC;AAE3C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAIvC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,KAAK,EAAE,qBAAqB,EAAuB,MAAM,sCAAsC,CAAC;AAEvG;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAkB/C;AAED;;;;GAIG;AACH,eAAO,MAAM,8BAA8B,QAAU,CAAC;AAEtD,MAAM,WAAW,kBAAkB;IACjC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB;;;;;;OAMG;IACH,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,sBAAuB,SAAQ,kBAAkB;IAChE,8EAA8E;IAC9E,qBAAqB,EAAE,qBAAqB,CAAC;CAC9C;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,kBAAkB,EAAE,EAAE,CAAC,EAAE,MAAM;;EAyFxF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,aAAc,SAAQ,SAAS;IAC1C,SAAgB,kBAAkB,EAAE,MAAM,CAAC;IAC3C;;;;OAIG;IACH,SAAgB,iBAAiB,EAAE,MAAM,CAAC;IAC1C,yFAAyF;IACzF,SAAgB,aAAa,EAAE,GAAG,CAAC,KAAK,CAAC;IACzC,8EAA8E;IAC9E,SAAgB,QAAQ,EAAE,cAAc,CAAC;IACzC,iGAAiG;IACjG,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B,2GAA2G;IAC3G,IAAI,OAAO,IAAI,GAAG,CAAC,iBAAiB,CAAC,cAAc,CAElD;IACD,gHAAgH;IAChH,IAAI,OAAO,IAAI,UAAU,CAAC,OAAO,CAEhC;IACD,4GAA4G;IAC5G,IAAI,MAAM,IAAI,MAAM,CAEnB;IACD,kGAAkG;IAClG,IAAI,eAAe,IAAI,GAAG,CAAC,QAAQ,CAAC,SAAS,CAE5C;IAED,OAAO,CAAC,qBAAqB;IAO7B;;;;;;;;;;;;;;;;;;OAkBG;IACH,IAAI,MAAM,IAAI,MAAM,CAUnB;IAED,OAAO;WAoBM,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,sBAAsB;CA6BhF"}
|
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import * as cdk from 'aws-cdk-lib';
|
|
4
|
-
import * as lambda from 'aws-cdk-lib/aws-lambda-nodejs';
|
|
5
|
-
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
|
|
6
4
|
import * as iam from 'aws-cdk-lib/aws-iam';
|
|
7
5
|
import { CfnGroup } from 'aws-cdk-lib/aws-resourcegroups';
|
|
8
6
|
import { Construct } from 'constructs';
|
|
9
7
|
import { pathToFileURL } from 'node:url';
|
|
10
|
-
import { DEFAULT_NODE_RUNTIME } from './node-version.js';
|
|
11
|
-
import { blocksNodejsBundling } from './bundling.js';
|
|
12
8
|
import { addBlocksStackMetadata } from './stack-metadata.js';
|
|
13
9
|
import { finalizeConfigRegistry, registerConfig } from './config-registry.js';
|
|
14
|
-
import { BLOCKS_NAMESPACE, BLOCKS_RPC_PREFIX } from '../constants.js';
|
|
15
10
|
import { registerBuiltinRoutes } from '../builtin-routes.js';
|
|
11
|
+
import { getComputes } from './compute/compute-registry.js';
|
|
16
12
|
/**
|
|
17
13
|
* Validate that the Node.js process was started with `--conditions=cdk`.
|
|
18
14
|
*
|
|
@@ -35,7 +31,17 @@ export function assertCdkConditionActive() {
|
|
|
35
31
|
'Or use the Blocks CLI commands (npm run deploy / npm run sandbox) which set this automatically.');
|
|
36
32
|
}
|
|
37
33
|
}
|
|
38
|
-
/**
|
|
34
|
+
/**
|
|
35
|
+
* Timeout of the shared Blocks handler Lambda, and therefore the ceiling on a
|
|
36
|
+
* single invocation. Exported because resources that feed the handler have to
|
|
37
|
+
* size their own timeouts against it (e.g. an SQS queue's visibility timeout).
|
|
38
|
+
*/
|
|
39
|
+
export const SHARED_HANDLER_TIMEOUT_SECONDS = 60 * 15;
|
|
40
|
+
/**
|
|
41
|
+
* Shared infra setup — provisions the stack-level resources that are NOT owned
|
|
42
|
+
* by a compute: the shared execution role, resource groups, and console-redirect
|
|
43
|
+
* routes.
|
|
44
|
+
*/
|
|
39
45
|
export function setupBlocksInfra(scope, props, id) {
|
|
40
46
|
// Fail fast with an actionable message at the create() call site if `defaults`
|
|
41
47
|
// is missing (e.g. a plain-JS caller, `as any`, or a dynamically-built props
|
|
@@ -45,70 +51,30 @@ export function setupBlocksInfra(scope, props, id) {
|
|
|
45
51
|
throw new Error('BlocksStack/BlocksBackend requires a `defaults` field. Pass a posture from ' +
|
|
46
52
|
'`@aws-blocks/core/cdk` — typically `defaults: sandboxMode ? BlocksPresets.sandbox : BlocksPresets.production`.');
|
|
47
53
|
}
|
|
48
|
-
// ── Shared execution role
|
|
54
|
+
// ── Shared execution role ───────────────────────────────────────────────
|
|
49
55
|
// A single IAM role that every Building Block grants to. Provisioned here so
|
|
50
56
|
// it exists before the backend module is imported (Building Blocks reach it
|
|
51
57
|
// via `scope.executionRole`). Block grants sit on the role's default (inline)
|
|
52
|
-
// policy. AWSLambdaBasicExecutionRole is attached so
|
|
58
|
+
// policy. AWSLambdaBasicExecutionRole is attached so compute functions retain
|
|
53
59
|
// CloudWatch Logs permissions.
|
|
60
|
+
//
|
|
61
|
+
// INVARIANT: this must be a mutable, framework-owned `iam.Role` — never an
|
|
62
|
+
// imported role (`Role.fromRoleArn`/`fromRoleName`), which is immutable by
|
|
63
|
+
// default. On an immutable role, every Building Block's `grant*()` /
|
|
64
|
+
// `addToPrincipalPolicy()` silently becomes a no-op (returns false, no error),
|
|
65
|
+
// so permissions would quietly vanish. If a bring-your-own-role option is ever
|
|
66
|
+
// added, it must resolve to a mutable role (`{ mutable: true }`).
|
|
54
67
|
const executionRole = new iam.Role(scope, 'BlocksRole', {
|
|
55
|
-
// CompositePrincipal (rather than a bare ServicePrincipal) so
|
|
56
|
-
// compute
|
|
57
|
-
// (e.g.
|
|
68
|
+
// CompositePrincipal (rather than a bare ServicePrincipal) so a Building Block
|
|
69
|
+
// whose compute runs AS this shared role can add its own trust principal here
|
|
70
|
+
// (e.g. the Agent BB adds bedrock-agentcore in its CDK construct) — core stays
|
|
71
|
+
// agnostic and only Lambda is trusted by default.
|
|
58
72
|
assumedBy: new iam.CompositePrincipal(new iam.ServicePrincipal('lambda.amazonaws.com')),
|
|
59
73
|
managedPolicies: [
|
|
60
74
|
iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole'),
|
|
61
75
|
],
|
|
62
76
|
});
|
|
63
|
-
|
|
64
|
-
entry: props.backendHandlerPath,
|
|
65
|
-
runtime: DEFAULT_NODE_RUNTIME,
|
|
66
|
-
handler: 'handler',
|
|
67
|
-
role: executionRole,
|
|
68
|
-
memorySize: 2048,
|
|
69
|
-
timeout: cdk.Duration.seconds(60 * 15),
|
|
70
|
-
environment: {
|
|
71
|
-
NODE_ENV: 'production',
|
|
72
|
-
/**
|
|
73
|
-
* BLOCKS_STACK_NAME is used at runtime to derive physical resource names
|
|
74
|
-
* (DynamoDB table names, env var prefixes). It must match the CDK-time
|
|
75
|
-
* fullId of the BlocksStack/BlocksBackend so resource lookups work correctly.
|
|
76
|
-
*
|
|
77
|
-
* For BlocksStack: this equals the stack name (id).
|
|
78
|
-
* For BlocksBackend: the caller overrides this after construction to include
|
|
79
|
-
* the parent stack name for deployment uniqueness.
|
|
80
|
-
*/
|
|
81
|
-
BLOCKS_STACK_NAME: id ?? cdk.Stack.of(scope).stackName,
|
|
82
|
-
},
|
|
83
|
-
// blocksNodejsBundling shims import.meta.* to CommonJS equivalents so a
|
|
84
|
-
// CJS-bundled `fileURLToPath(import.meta.url)` resolves instead of throwing at
|
|
85
|
-
// Lambda load. See ./bundling.ts.
|
|
86
|
-
bundling: blocksNodejsBundling({
|
|
87
|
-
minify: true,
|
|
88
|
-
esbuildArgs: { '--conditions': 'aws-runtime' },
|
|
89
|
-
}),
|
|
90
|
-
});
|
|
91
|
-
// In sandbox mode, allow localhost origins so the local dev frontend can
|
|
92
|
-
// reach the deployed Lambda API via CORS.
|
|
93
|
-
const isSandbox = scope.node.tryGetContext('sandboxMode') === 'true' ||
|
|
94
|
-
scope.node.tryGetContext('sandboxMode') === true;
|
|
95
|
-
if (isSandbox) {
|
|
96
|
-
handler.addEnvironment('CORS_ALLOWED_ORIGINS', '^https?://(localhost|127\\.0\\.0\\.1)(:\\d+)?$');
|
|
97
|
-
}
|
|
98
|
-
const api = new apigateway.RestApi(scope, 'API', {
|
|
99
|
-
restApiName: 'Blocks API',
|
|
100
|
-
deployOptions: { cachingEnabled: false },
|
|
101
|
-
});
|
|
102
|
-
const integration = new apigateway.LambdaIntegration(handler);
|
|
103
|
-
// Build the nested resource tree for /aws-blocks/api.
|
|
104
|
-
// Intermediate resource gets a proxy so sub-paths (RawRoutes) still reach Lambda.
|
|
105
|
-
const awsBlocksResource = api.root.addResource(BLOCKS_NAMESPACE.slice(1));
|
|
106
|
-
awsBlocksResource.addProxy({ defaultIntegration: integration, anyMethod: true });
|
|
107
|
-
const apiResource = awsBlocksResource.addResource('api');
|
|
108
|
-
apiResource.addMethod('POST', integration);
|
|
109
|
-
apiResource.addMethod('OPTIONS', integration);
|
|
110
|
-
api.root.addProxy({ defaultIntegration: integration, anyMethod: true });
|
|
111
|
-
// ── Resource Groups ────────────────────────────────────────────────────
|
|
77
|
+
// ── Resource Groups ───────────────────────────────────────────────────
|
|
112
78
|
let rootStack = cdk.Stack.of(scope);
|
|
113
79
|
while (rootStack.nestedStackParent)
|
|
114
80
|
rootStack = rootStack.nestedStackParent;
|
|
@@ -142,7 +108,7 @@ export function setupBlocksInfra(scope, props, id) {
|
|
|
142
108
|
},
|
|
143
109
|
},
|
|
144
110
|
});
|
|
145
|
-
// ── Console redirect routes
|
|
111
|
+
// ── Console redirect routes ───────────────────────────────────────────
|
|
146
112
|
const region = cdk.Fn.ref('AWS::Region');
|
|
147
113
|
const resourcesUrl = cdk.Fn.join('', [
|
|
148
114
|
'https://', region, '.console.aws.amazon.com/resource-groups/group/',
|
|
@@ -155,7 +121,7 @@ export function setupBlocksInfra(scope, props, id) {
|
|
|
155
121
|
registerConfig(scope, 'BB_RESOURCES_GROUP_URL', resourcesUrl);
|
|
156
122
|
registerConfig(scope, 'BB_SETTINGS_GROUP_URL', settingsUrl);
|
|
157
123
|
registerBuiltinRoutes();
|
|
158
|
-
return {
|
|
124
|
+
return { executionRole };
|
|
159
125
|
}
|
|
160
126
|
/**
|
|
161
127
|
* Standalone CDK construct that provisions the Blocks backend: a single Lambda
|
|
@@ -175,14 +141,41 @@ export function setupBlocksInfra(scope, props, id) {
|
|
|
175
141
|
* ```
|
|
176
142
|
*/
|
|
177
143
|
export class BlocksBackend extends Construct {
|
|
178
|
-
apiUrl;
|
|
179
|
-
gateway;
|
|
180
|
-
handler;
|
|
181
144
|
backendHandlerPath;
|
|
145
|
+
/**
|
|
146
|
+
* Path to the app's backend module (`props.backendCDKPath`). Exposed so Building Blocks that
|
|
147
|
+
* co-bundle the backend at synth (e.g. the Agent BB's AgentCore Runtime) can discover it via
|
|
148
|
+
* `globalThis.CURRENT_BLOCKS_STACK.backendModulePath`.
|
|
149
|
+
*/
|
|
150
|
+
backendModulePath;
|
|
182
151
|
/** Shared IAM role assumed by all Blocks compute. Building Blocks grant to this role. */
|
|
183
152
|
executionRole;
|
|
184
153
|
/** Infrastructure defaults for Building Blocks created under this backend. */
|
|
185
154
|
defaults;
|
|
155
|
+
/** The default compute (owns the Lambda function + API Gateway); set in `create()`. @internal */
|
|
156
|
+
_defaultCompute;
|
|
157
|
+
/** The default compute's Lambda function. To be removed once consumers move to the multi-compute model. */
|
|
158
|
+
get handler() {
|
|
159
|
+
return this.requireDefaultCompute().fn;
|
|
160
|
+
}
|
|
161
|
+
/** The default compute's API Gateway REST API. To be removed once consumers move to the multi-compute model. */
|
|
162
|
+
get gateway() {
|
|
163
|
+
return this.requireDefaultCompute().apiGateway;
|
|
164
|
+
}
|
|
165
|
+
/** The default compute's RPC endpoint URL. To be removed once consumers move to the multi-compute model. */
|
|
166
|
+
get apiUrl() {
|
|
167
|
+
return this.requireDefaultCompute().apiUrl;
|
|
168
|
+
}
|
|
169
|
+
/** The default compute's handler CloudWatch log group. `bb-logger` reconfigures its retention. */
|
|
170
|
+
get handlerLogGroup() {
|
|
171
|
+
return this.requireDefaultCompute().logGroup;
|
|
172
|
+
}
|
|
173
|
+
requireDefaultCompute() {
|
|
174
|
+
if (!this._defaultCompute) {
|
|
175
|
+
throw new Error('Blocks backend not fully initialized — access .handler/.gateway/.apiUrl after BlocksBackend.create() resolves.');
|
|
176
|
+
}
|
|
177
|
+
return this._defaultCompute;
|
|
178
|
+
}
|
|
186
179
|
/**
|
|
187
180
|
* The fullId used by child Scopes to compute their env var names,
|
|
188
181
|
* construct IDs, and physical resource names (e.g., DynamoDB table names).
|
|
@@ -216,6 +209,7 @@ export class BlocksBackend extends Construct {
|
|
|
216
209
|
constructor(scope, id, props) {
|
|
217
210
|
super(scope, id);
|
|
218
211
|
this.backendHandlerPath = props.backendHandlerPath;
|
|
212
|
+
this.backendModulePath = props.backendCDKPath;
|
|
219
213
|
// Expose self to Building Blocks at CDK time
|
|
220
214
|
globalThis.CURRENT_BLOCKS_STACK = this;
|
|
221
215
|
// Store defaults on the backend (not the stack) so several BlocksBackends
|
|
@@ -223,18 +217,20 @@ export class BlocksBackend extends Construct {
|
|
|
223
217
|
// walking up to their owning backend (see Scope.defaults).
|
|
224
218
|
this.defaults = props.defaults;
|
|
225
219
|
const infra = setupBlocksInfra(this, props, id);
|
|
226
|
-
this.handler = infra.handler;
|
|
227
|
-
this.gateway = infra.gateway;
|
|
228
|
-
this.apiUrl = infra.apiUrl;
|
|
229
220
|
this.executionRole = infra.executionRole;
|
|
230
|
-
//
|
|
231
|
-
//
|
|
232
|
-
// and are unique per deployment.
|
|
233
|
-
this.handler.addEnvironment('BLOCKS_STACK_NAME', this.fullId);
|
|
221
|
+
// The default compute (and thus handler/gateway) is created in create(),
|
|
222
|
+
// after construction — it derives BLOCKS_STACK_NAME from this.fullId.
|
|
234
223
|
}
|
|
235
224
|
static async create(scope, id, props) {
|
|
236
225
|
assertCdkConditionActive();
|
|
237
226
|
const backend = new BlocksBackend(scope, id, props);
|
|
227
|
+
// Create the default compute before importing the backend: it OWNS the
|
|
228
|
+
// Lambda function + API Gateway (which back .handler/.gateway/.apiUrl), and
|
|
229
|
+
// a block reading `this.compute` in its constructor (during that import)
|
|
230
|
+
// must resolve to it. The factory is supplied by the umbrella
|
|
231
|
+
// @aws-blocks/blocks (which injects LambdaCompute) via props, so core never
|
|
232
|
+
// imports the concrete compute class.
|
|
233
|
+
backend._defaultCompute = props.defaultComputeFactory(backend);
|
|
238
234
|
// file:// URL (not a raw path) so the cache-busting query works on Windows,
|
|
239
235
|
// where an absolute path like `D:\...` is rejected as URL scheme `d:`.
|
|
240
236
|
const backendUrl = pathToFileURL(props.backendCDKPath);
|
|
@@ -250,7 +246,7 @@ export class BlocksBackend extends Construct {
|
|
|
250
246
|
}
|
|
251
247
|
addBlocksStackMetadata(cdk.Stack.of(backend));
|
|
252
248
|
// Finalize BB config → S3 (after all BBs have registered their config)
|
|
253
|
-
finalizeConfigRegistry(backend, backend.
|
|
249
|
+
finalizeConfigRegistry(backend, backend.executionRole, getComputes(backend));
|
|
254
250
|
return backend;
|
|
255
251
|
}
|
|
256
252
|
}
|