@aws-blocks/core 0.2.0 → 0.3.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/dist/cdk/blocks-backend.d.ts +35 -9
- package/dist/cdk/blocks-backend.d.ts.map +1 -1
- package/dist/cdk/blocks-backend.js +52 -69
- package/dist/cdk/blocks-backend.test.js +61 -69
- package/dist/cdk/blocks-defaults.d.ts +27 -1
- package/dist/cdk/blocks-defaults.d.ts.map +1 -1
- package/dist/cdk/blocks-defaults.js +5 -1
- package/dist/cdk/blocks-defaults.test.js +4 -2
- package/dist/cdk/blocks-stack.test.js +73 -37
- package/dist/cdk/compute/default-compute-factory.d.ts +33 -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/index.d.ts +46 -5
- package/dist/cdk/index.d.ts.map +1 -1
- package/dist/cdk/index.js +57 -7
- package/dist/cdk/internal.d.ts +1 -0
- package/dist/cdk/internal.d.ts.map +1 -1
- 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 +88 -6
- package/dist/hosting.d.ts.map +1 -1
- package/dist/hosting.js +83 -24
- package/dist/hosting.test.js +158 -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.test.js +66 -0
- 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.d.ts +52 -0
- package/dist/scripts/sandbox.d.ts.map +1 -1
- package/dist/scripts/sandbox.js +92 -15
- 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 +2 -1
- package/src/cdk/blocks-backend.test.ts +267 -272
- package/src/cdk/blocks-backend.ts +71 -79
- package/src/cdk/blocks-defaults.test.ts +4 -2
- package/src/cdk/blocks-defaults.ts +27 -1
- package/src/cdk/blocks-stack.test.ts +161 -118
- package/src/cdk/compute/default-compute-factory.ts +37 -0
- package/src/cdk/index.ts +84 -8
- package/src/cdk/internal.ts +1 -0
- package/src/hosting-secrets.test.ts +106 -0
- package/src/hosting-secrets.ts +106 -0
- package/src/hosting.test.ts +244 -63
- package/src/hosting.ts +180 -68
- package/src/index.cdk.ts +77 -38
- package/src/index.ts +35 -16
- package/src/lambda-handler.test.ts +74 -0
- 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.ts +102 -15
- 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
|
@@ -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,20 @@ 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;
|
|
56
73
|
/** Shared IAM role assumed by all Blocks compute. Building Blocks grant to this role. */
|
|
57
74
|
readonly executionRole: iam.IRole;
|
|
58
75
|
/** Infrastructure defaults for Building Blocks created under this backend. */
|
|
59
76
|
readonly defaults: BlocksDefaults;
|
|
77
|
+
/** The default compute (owns the Lambda function + API Gateway); set in `create()`. @internal */
|
|
78
|
+
_defaultCompute?: Compute;
|
|
79
|
+
/** The default compute's Lambda function. To be removed once consumers move to the multi-compute model. */
|
|
80
|
+
get handler(): cdk.aws_lambda_nodejs.NodejsFunction;
|
|
81
|
+
/** The default compute's API Gateway REST API. To be removed once consumers move to the multi-compute model. */
|
|
82
|
+
get gateway(): apigateway.RestApi;
|
|
83
|
+
/** The default compute's RPC endpoint URL. To be removed once consumers move to the multi-compute model. */
|
|
84
|
+
get apiUrl(): string;
|
|
85
|
+
private requireDefaultCompute;
|
|
60
86
|
/**
|
|
61
87
|
* The fullId used by child Scopes to compute their env var names,
|
|
62
88
|
* construct IDs, and physical resource names (e.g., DynamoDB table names).
|
|
@@ -78,6 +104,6 @@ export declare class BlocksBackend extends Construct {
|
|
|
78
104
|
*/
|
|
79
105
|
get fullId(): string;
|
|
80
106
|
private constructor();
|
|
81
|
-
static create(scope: Construct, id: string, props:
|
|
107
|
+
static create(scope: Construct, id: string, props: CoreBlocksBackendProps): Promise<BlocksBackend>;
|
|
82
108
|
}
|
|
83
109
|
//# 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;AACpD,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;;EAwFxF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,aAAc,SAAQ,SAAS;IAC1C,SAAgB,kBAAkB,EAAE,MAAM,CAAC;IAC3C,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;IAED,OAAO,CAAC,qBAAqB;IAO7B;;;;;;;;;;;;;;;;;;OAkBG;IACH,IAAI,MAAM,IAAI,MAAM,CAUnB;IAED,OAAO;WAmBM,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,sBAAsB;CA6BhF"}
|
|
@@ -1,17 +1,12 @@
|
|
|
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';
|
|
16
11
|
/**
|
|
17
12
|
* Validate that the Node.js process was started with `--conditions=cdk`.
|
|
@@ -35,7 +30,17 @@ export function assertCdkConditionActive() {
|
|
|
35
30
|
'Or use the Blocks CLI commands (npm run deploy / npm run sandbox) which set this automatically.');
|
|
36
31
|
}
|
|
37
32
|
}
|
|
38
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* Timeout of the shared Blocks handler Lambda, and therefore the ceiling on a
|
|
35
|
+
* single invocation. Exported because resources that feed the handler have to
|
|
36
|
+
* size their own timeouts against it (e.g. an SQS queue's visibility timeout).
|
|
37
|
+
*/
|
|
38
|
+
export const SHARED_HANDLER_TIMEOUT_SECONDS = 60 * 15;
|
|
39
|
+
/**
|
|
40
|
+
* Shared infra setup — provisions the stack-level resources that are NOT owned
|
|
41
|
+
* by a compute: the shared execution role, resource groups, and console-redirect
|
|
42
|
+
* routes.
|
|
43
|
+
*/
|
|
39
44
|
export function setupBlocksInfra(scope, props, id) {
|
|
40
45
|
// Fail fast with an actionable message at the create() call site if `defaults`
|
|
41
46
|
// is missing (e.g. a plain-JS caller, `as any`, or a dynamically-built props
|
|
@@ -45,12 +50,19 @@ export function setupBlocksInfra(scope, props, id) {
|
|
|
45
50
|
throw new Error('BlocksStack/BlocksBackend requires a `defaults` field. Pass a posture from ' +
|
|
46
51
|
'`@aws-blocks/core/cdk` — typically `defaults: sandboxMode ? BlocksPresets.sandbox : BlocksPresets.production`.');
|
|
47
52
|
}
|
|
48
|
-
// ── Shared execution role
|
|
53
|
+
// ── Shared execution role ───────────────────────────────────────────────
|
|
49
54
|
// A single IAM role that every Building Block grants to. Provisioned here so
|
|
50
55
|
// it exists before the backend module is imported (Building Blocks reach it
|
|
51
56
|
// via `scope.executionRole`). Block grants sit on the role's default (inline)
|
|
52
|
-
// policy. AWSLambdaBasicExecutionRole is attached so
|
|
57
|
+
// policy. AWSLambdaBasicExecutionRole is attached so compute functions retain
|
|
53
58
|
// CloudWatch Logs permissions.
|
|
59
|
+
//
|
|
60
|
+
// INVARIANT: this must be a mutable, framework-owned `iam.Role` — never an
|
|
61
|
+
// imported role (`Role.fromRoleArn`/`fromRoleName`), which is immutable by
|
|
62
|
+
// default. On an immutable role, every Building Block's `grant*()` /
|
|
63
|
+
// `addToPrincipalPolicy()` silently becomes a no-op (returns false, no error),
|
|
64
|
+
// so permissions would quietly vanish. If a bring-your-own-role option is ever
|
|
65
|
+
// added, it must resolve to a mutable role (`{ mutable: true }`).
|
|
54
66
|
const executionRole = new iam.Role(scope, 'BlocksRole', {
|
|
55
67
|
// CompositePrincipal (rather than a bare ServicePrincipal) so additional
|
|
56
68
|
// compute types can assume this same shared role as they are introduced
|
|
@@ -60,55 +72,7 @@ export function setupBlocksInfra(scope, props, id) {
|
|
|
60
72
|
iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole'),
|
|
61
73
|
],
|
|
62
74
|
});
|
|
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 ────────────────────────────────────────────────────
|
|
75
|
+
// ── Resource Groups ───────────────────────────────────────────────────
|
|
112
76
|
let rootStack = cdk.Stack.of(scope);
|
|
113
77
|
while (rootStack.nestedStackParent)
|
|
114
78
|
rootStack = rootStack.nestedStackParent;
|
|
@@ -142,7 +106,7 @@ export function setupBlocksInfra(scope, props, id) {
|
|
|
142
106
|
},
|
|
143
107
|
},
|
|
144
108
|
});
|
|
145
|
-
// ── Console redirect routes
|
|
109
|
+
// ── Console redirect routes ───────────────────────────────────────────
|
|
146
110
|
const region = cdk.Fn.ref('AWS::Region');
|
|
147
111
|
const resourcesUrl = cdk.Fn.join('', [
|
|
148
112
|
'https://', region, '.console.aws.amazon.com/resource-groups/group/',
|
|
@@ -155,7 +119,7 @@ export function setupBlocksInfra(scope, props, id) {
|
|
|
155
119
|
registerConfig(scope, 'BB_RESOURCES_GROUP_URL', resourcesUrl);
|
|
156
120
|
registerConfig(scope, 'BB_SETTINGS_GROUP_URL', settingsUrl);
|
|
157
121
|
registerBuiltinRoutes();
|
|
158
|
-
return {
|
|
122
|
+
return { executionRole };
|
|
159
123
|
}
|
|
160
124
|
/**
|
|
161
125
|
* Standalone CDK construct that provisions the Blocks backend: a single Lambda
|
|
@@ -175,14 +139,31 @@ export function setupBlocksInfra(scope, props, id) {
|
|
|
175
139
|
* ```
|
|
176
140
|
*/
|
|
177
141
|
export class BlocksBackend extends Construct {
|
|
178
|
-
apiUrl;
|
|
179
|
-
gateway;
|
|
180
|
-
handler;
|
|
181
142
|
backendHandlerPath;
|
|
182
143
|
/** Shared IAM role assumed by all Blocks compute. Building Blocks grant to this role. */
|
|
183
144
|
executionRole;
|
|
184
145
|
/** Infrastructure defaults for Building Blocks created under this backend. */
|
|
185
146
|
defaults;
|
|
147
|
+
/** The default compute (owns the Lambda function + API Gateway); set in `create()`. @internal */
|
|
148
|
+
_defaultCompute;
|
|
149
|
+
/** The default compute's Lambda function. To be removed once consumers move to the multi-compute model. */
|
|
150
|
+
get handler() {
|
|
151
|
+
return this.requireDefaultCompute().fn;
|
|
152
|
+
}
|
|
153
|
+
/** The default compute's API Gateway REST API. To be removed once consumers move to the multi-compute model. */
|
|
154
|
+
get gateway() {
|
|
155
|
+
return this.requireDefaultCompute().apiGateway;
|
|
156
|
+
}
|
|
157
|
+
/** The default compute's RPC endpoint URL. To be removed once consumers move to the multi-compute model. */
|
|
158
|
+
get apiUrl() {
|
|
159
|
+
return this.requireDefaultCompute().apiUrl;
|
|
160
|
+
}
|
|
161
|
+
requireDefaultCompute() {
|
|
162
|
+
if (!this._defaultCompute) {
|
|
163
|
+
throw new Error('Blocks backend not fully initialized — access .handler/.gateway/.apiUrl after BlocksBackend.create() resolves.');
|
|
164
|
+
}
|
|
165
|
+
return this._defaultCompute;
|
|
166
|
+
}
|
|
186
167
|
/**
|
|
187
168
|
* The fullId used by child Scopes to compute their env var names,
|
|
188
169
|
* construct IDs, and physical resource names (e.g., DynamoDB table names).
|
|
@@ -223,18 +204,20 @@ export class BlocksBackend extends Construct {
|
|
|
223
204
|
// walking up to their owning backend (see Scope.defaults).
|
|
224
205
|
this.defaults = props.defaults;
|
|
225
206
|
const infra = setupBlocksInfra(this, props, id);
|
|
226
|
-
this.handler = infra.handler;
|
|
227
|
-
this.gateway = infra.gateway;
|
|
228
|
-
this.apiUrl = infra.apiUrl;
|
|
229
207
|
this.executionRole = infra.executionRole;
|
|
230
|
-
//
|
|
231
|
-
//
|
|
232
|
-
// and are unique per deployment.
|
|
233
|
-
this.handler.addEnvironment('BLOCKS_STACK_NAME', this.fullId);
|
|
208
|
+
// The default compute (and thus handler/gateway) is created in create(),
|
|
209
|
+
// after construction — it derives BLOCKS_STACK_NAME from this.fullId.
|
|
234
210
|
}
|
|
235
211
|
static async create(scope, id, props) {
|
|
236
212
|
assertCdkConditionActive();
|
|
237
213
|
const backend = new BlocksBackend(scope, id, props);
|
|
214
|
+
// Create the default compute before importing the backend: it OWNS the
|
|
215
|
+
// Lambda function + API Gateway (which back .handler/.gateway/.apiUrl), and
|
|
216
|
+
// a block reading `this.compute` in its constructor (during that import)
|
|
217
|
+
// must resolve to it. The factory is supplied by the umbrella
|
|
218
|
+
// @aws-blocks/blocks (which injects LambdaCompute) via props, so core never
|
|
219
|
+
// imports the concrete compute class.
|
|
220
|
+
backend._defaultCompute = props.defaultComputeFactory(backend);
|
|
238
221
|
// file:// URL (not a raw path) so the cache-busting query works on Windows,
|
|
239
222
|
// where an absolute path like `D:\...` is rejected as URL scheme `d:`.
|
|
240
223
|
const backendUrl = pathToFileURL(props.backendCDKPath);
|
|
@@ -1,15 +1,52 @@
|
|
|
1
1
|
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
import { test, describe, before } from 'node:test';
|
|
4
3
|
import assert from 'node:assert';
|
|
5
|
-
import { fileURLToPath } from 'node:url';
|
|
6
4
|
import { dirname, join } from 'node:path';
|
|
5
|
+
import { before, describe, test } from 'node:test';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
7
|
import * as cdk from 'aws-cdk-lib';
|
|
8
|
-
import {
|
|
8
|
+
import { Match, Template } from 'aws-cdk-lib/assertions';
|
|
9
|
+
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
|
|
9
10
|
import { PolicyStatement } from 'aws-cdk-lib/aws-iam';
|
|
11
|
+
import * as lambda from 'aws-cdk-lib/aws-lambda-nodejs';
|
|
12
|
+
import { BLOCKS_RPC_PREFIX } from '../constants.js';
|
|
10
13
|
import { BlocksBackend } from './blocks-backend.js';
|
|
11
14
|
import { BlocksPresets } from './blocks-defaults.js';
|
|
15
|
+
import { Compute } from './compute/compute.js';
|
|
12
16
|
import { Scope } from './index.js';
|
|
17
|
+
// A real app gets its default compute from @aws-blocks/bb-lambda-compute (via
|
|
18
|
+
// @aws-blocks/blocks), which core's own tests can't depend on. Use an
|
|
19
|
+
// equivalent inline stub: a Compute that owns a NodejsFunction + API Gateway,
|
|
20
|
+
// so create() can build the default and the handler/gateway/apiUrl accessors
|
|
21
|
+
// and synth-shape assertions have something real to resolve to. It is passed to
|
|
22
|
+
// each create() via the internal `defaultComputeFactory` option (see
|
|
23
|
+
// makeBackend), exactly as @aws-blocks/blocks injects LambdaCompute.
|
|
24
|
+
class StubLambdaCompute extends Compute {
|
|
25
|
+
fn;
|
|
26
|
+
apiGateway;
|
|
27
|
+
apiUrl;
|
|
28
|
+
constructor(scope, id) {
|
|
29
|
+
super(id, { parent: scope });
|
|
30
|
+
this.fn = new lambda.NodejsFunction(this, 'Handler', {
|
|
31
|
+
entry: this.backendHandlerPath,
|
|
32
|
+
runtime: cdk.aws_lambda.Runtime.NODEJS_22_X,
|
|
33
|
+
handler: 'handler',
|
|
34
|
+
role: this.executionRole,
|
|
35
|
+
environment: { BLOCKS_STACK_NAME: this.backendStackName },
|
|
36
|
+
bundling: { minify: true, esbuildArgs: { '--conditions': 'aws-runtime' } },
|
|
37
|
+
});
|
|
38
|
+
this.apiGateway = new apigateway.RestApi(this, 'API', { restApiName: 'Blocks API' });
|
|
39
|
+
this.apiGateway.root.addProxy({
|
|
40
|
+
defaultIntegration: new apigateway.LambdaIntegration(this.fn),
|
|
41
|
+
anyMethod: true,
|
|
42
|
+
});
|
|
43
|
+
this.apiUrl = `${this.apiGateway.url}${BLOCKS_RPC_PREFIX.slice(1)}`;
|
|
44
|
+
}
|
|
45
|
+
setEnv(key, value) {
|
|
46
|
+
this.fn.addEnvironment(key, value);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const stubComputeFactory = (root) => new StubLambdaCompute(root, 'DefaultCompute');
|
|
13
50
|
// Simulate the CDK condition being active (tests import CDK files directly)
|
|
14
51
|
before(() => {
|
|
15
52
|
process.env.NODE_OPTIONS = (process.env.NODE_OPTIONS ?? '') + ' --conditions=cdk';
|
|
@@ -21,20 +58,15 @@ const factoryBackendPath = join(__dirname, '__fixtures__', 'factory-backend.js')
|
|
|
21
58
|
const fullIdConstructBackendPath = join(__dirname, '__fixtures__', 'fullid-construct-backend.js');
|
|
22
59
|
const EXECUTION_ROLE_MARKER_ACTION = 'blocks-test:MarkerAction';
|
|
23
60
|
const importMetaHandlerPath = join(__dirname, '__fixtures__', 'import-meta-handler.js');
|
|
61
|
+
// Wraps BlocksBackend.create, injecting the stub default-compute factory the way
|
|
62
|
+
// @aws-blocks/blocks injects LambdaCompute — so tests don't repeat it 15 times.
|
|
63
|
+
const makeBackend = (scope, id, backendCDKPath) => BlocksBackend.create(scope, id, { backendHandlerPath: handlerPath, backendCDKPath, defaults: BlocksPresets.production, defaultComputeFactory: stubComputeFactory });
|
|
24
64
|
describe('ESM cache-busting (multi-stage)', () => {
|
|
25
65
|
test('BlocksBackend.create() with same backendCDKPath but different IDs produces constructs in each', async () => {
|
|
26
66
|
const app = new cdk.App();
|
|
27
67
|
const stack = new cdk.Stack(app, 'TestStack');
|
|
28
|
-
const backend1 = await
|
|
29
|
-
|
|
30
|
-
backendCDKPath: sideEffectBackendPath,
|
|
31
|
-
defaults: BlocksPresets.production,
|
|
32
|
-
});
|
|
33
|
-
const backend2 = await BlocksBackend.create(stack, 'Stage2', {
|
|
34
|
-
backendHandlerPath: handlerPath,
|
|
35
|
-
backendCDKPath: sideEffectBackendPath,
|
|
36
|
-
defaults: BlocksPresets.production,
|
|
37
|
-
});
|
|
68
|
+
const backend1 = await makeBackend(stack, 'Stage1', sideEffectBackendPath);
|
|
69
|
+
const backend2 = await makeBackend(stack, 'Stage2', sideEffectBackendPath);
|
|
38
70
|
const findMarker = (scope) => scope.node.tryFindChild('SideEffectMarker');
|
|
39
71
|
assert.ok(findMarker(backend1), 'Stage1 backend should have SideEffectMarker construct from module side effect');
|
|
40
72
|
assert.ok(findMarker(backend2), 'Stage2 backend should have SideEffectMarker construct from re-executed module');
|
|
@@ -44,11 +76,7 @@ describe('synth shape (drop into existing stack)', () => {
|
|
|
44
76
|
test('BlocksBackend lives inside the parent stack and synthesizes Lambda + API Gateway', async () => {
|
|
45
77
|
const app = new cdk.App();
|
|
46
78
|
const parent = new cdk.Stack(app, 'MyExistingStack');
|
|
47
|
-
const backend = await
|
|
48
|
-
backendHandlerPath: handlerPath,
|
|
49
|
-
backendCDKPath: sideEffectBackendPath,
|
|
50
|
-
defaults: BlocksPresets.production,
|
|
51
|
-
});
|
|
79
|
+
const backend = await makeBackend(parent, 'Blocks', sideEffectBackendPath);
|
|
52
80
|
// Public surface mirrors BlocksStack.
|
|
53
81
|
assert.ok(backend.handler, 'BlocksBackend should expose .handler');
|
|
54
82
|
assert.ok(backend.gateway, 'BlocksBackend should expose .gateway');
|
|
@@ -62,16 +90,8 @@ describe('synth shape (drop into existing stack)', () => {
|
|
|
62
90
|
test('multiple BlocksBackends in the same parent stack do not collide', async () => {
|
|
63
91
|
const app = new cdk.App();
|
|
64
92
|
const parent = new cdk.Stack(app, 'MultiBackendStack');
|
|
65
|
-
await
|
|
66
|
-
|
|
67
|
-
backendCDKPath: sideEffectBackendPath,
|
|
68
|
-
defaults: BlocksPresets.production,
|
|
69
|
-
});
|
|
70
|
-
await BlocksBackend.create(parent, 'BackendB', {
|
|
71
|
-
backendHandlerPath: handlerPath,
|
|
72
|
-
backendCDKPath: sideEffectBackendPath,
|
|
73
|
-
defaults: BlocksPresets.production,
|
|
74
|
-
});
|
|
93
|
+
await makeBackend(parent, 'BackendA', sideEffectBackendPath);
|
|
94
|
+
await makeBackend(parent, 'BackendB', sideEffectBackendPath);
|
|
75
95
|
const template = Template.fromStack(parent);
|
|
76
96
|
template.resourceCountIs('AWS::ApiGateway::RestApi', 2);
|
|
77
97
|
});
|
|
@@ -80,21 +100,13 @@ describe('shared execution role', () => {
|
|
|
80
100
|
test('exposes executionRole on the backend', async () => {
|
|
81
101
|
const app = new cdk.App();
|
|
82
102
|
const parent = new cdk.Stack(app, 'RoleSurfaceStack');
|
|
83
|
-
const backend = await
|
|
84
|
-
backendHandlerPath: handlerPath,
|
|
85
|
-
backendCDKPath: sideEffectBackendPath,
|
|
86
|
-
defaults: BlocksPresets.production,
|
|
87
|
-
});
|
|
103
|
+
const backend = await makeBackend(parent, 'Blocks', sideEffectBackendPath);
|
|
88
104
|
assert.ok(backend.executionRole, 'BlocksBackend should expose .executionRole');
|
|
89
105
|
});
|
|
90
106
|
test('synth produces a Lambda-assumable role with basic execution, and the handler uses it', async () => {
|
|
91
107
|
const app = new cdk.App();
|
|
92
108
|
const parent = new cdk.Stack(app, 'RoleSynthStack');
|
|
93
|
-
await
|
|
94
|
-
backendHandlerPath: handlerPath,
|
|
95
|
-
backendCDKPath: sideEffectBackendPath,
|
|
96
|
-
defaults: BlocksPresets.production,
|
|
97
|
-
});
|
|
109
|
+
await makeBackend(parent, 'Blocks', sideEffectBackendPath);
|
|
98
110
|
const template = Template.fromStack(parent);
|
|
99
111
|
// The shared role (logical id derived from the 'BlocksRole' construct id)
|
|
100
112
|
// is assumable by Lambda and carries AWSLambdaBasicExecutionRole (so
|
|
@@ -102,7 +114,7 @@ describe('shared execution role', () => {
|
|
|
102
114
|
// roles exist (API Gateway CloudWatch role, config BucketDeployment role),
|
|
103
115
|
// so we target ours by logical id.
|
|
104
116
|
const roles = template.findResources('AWS::IAM::Role');
|
|
105
|
-
const blocksRoleId = Object.keys(roles).find(k => k.includes('BlocksRole'));
|
|
117
|
+
const blocksRoleId = Object.keys(roles).find((k) => k.includes('BlocksRole'));
|
|
106
118
|
assert.ok(blocksRoleId, 'expected a role from the BlocksRole construct');
|
|
107
119
|
const blocksRole = roles[blocksRoleId];
|
|
108
120
|
assert.deepStrictEqual(blocksRole.Properties.AssumeRolePolicyDocument.Statement[0], {
|
|
@@ -119,11 +131,7 @@ describe('shared execution role', () => {
|
|
|
119
131
|
test('a nested block resolves executionRole via the construct-tree walk', async () => {
|
|
120
132
|
const app = new cdk.App();
|
|
121
133
|
const parent = new cdk.Stack(app, 'RoleResolveStack');
|
|
122
|
-
const backend = await
|
|
123
|
-
backendHandlerPath: handlerPath,
|
|
124
|
-
backendCDKPath: sideEffectBackendPath,
|
|
125
|
-
defaults: BlocksPresets.production,
|
|
126
|
-
});
|
|
134
|
+
const backend = await makeBackend(parent, 'Blocks', sideEffectBackendPath);
|
|
127
135
|
// Build nested Scopes under the backend (outer → inner), the same shape a
|
|
128
136
|
// real Building Block tree has, and grant a uniquely-named marker action to
|
|
129
137
|
// `this.executionRole` from the innermost scope. If the getter's tree-walk
|
|
@@ -160,6 +168,7 @@ describe('CJS bundle: import.meta.url in the handler is shimmed (no Lambda-load
|
|
|
160
168
|
backendHandlerPath: importMetaHandlerPath,
|
|
161
169
|
backendCDKPath: sideEffectBackendPath,
|
|
162
170
|
defaults: BlocksPresets.production,
|
|
171
|
+
defaultComputeFactory: stubComputeFactory,
|
|
163
172
|
}));
|
|
164
173
|
});
|
|
165
174
|
});
|
|
@@ -167,11 +176,7 @@ describe('factory function support', () => {
|
|
|
167
176
|
test('BlocksBackend.create() calls default export function with the backend instance', async () => {
|
|
168
177
|
const app = new cdk.App();
|
|
169
178
|
const stack = new cdk.Stack(app, 'FactoryTestStack');
|
|
170
|
-
const backend = await
|
|
171
|
-
backendHandlerPath: handlerPath,
|
|
172
|
-
backendCDKPath: factoryBackendPath,
|
|
173
|
-
defaults: BlocksPresets.production,
|
|
174
|
-
});
|
|
179
|
+
const backend = await makeBackend(stack, 'FactoryStage', factoryBackendPath);
|
|
175
180
|
const marker = backend.node.tryFindChild('FactoryMarker');
|
|
176
181
|
assert.ok(marker, 'Factory function should have created FactoryMarker on the backend');
|
|
177
182
|
});
|
|
@@ -180,11 +185,7 @@ describe('fullId is token-free (construct IDs / env-var keys)', () => {
|
|
|
180
185
|
test('top-level stack: fullId is {stackName}-{id} and resolvable', async () => {
|
|
181
186
|
const app = new cdk.App();
|
|
182
187
|
const stack = new cdk.Stack(app, 'TopLevelStack');
|
|
183
|
-
const backend = await
|
|
184
|
-
backendHandlerPath: handlerPath,
|
|
185
|
-
backendCDKPath: sideEffectBackendPath,
|
|
186
|
-
defaults: BlocksPresets.production,
|
|
187
|
-
});
|
|
188
|
+
const backend = await makeBackend(stack, 'blocks', sideEffectBackendPath);
|
|
188
189
|
assert.strictEqual(backend.fullId, 'TopLevelStack-blocks');
|
|
189
190
|
assert.ok(!cdk.Token.isUnresolved(backend.fullId), 'fullId must not contain a token');
|
|
190
191
|
});
|
|
@@ -198,11 +199,7 @@ describe('fullId is token-free (construct IDs / env-var keys)', () => {
|
|
|
198
199
|
const nested = new cdk.NestedStack(parent, 'blocks');
|
|
199
200
|
// Sanity: the nested stack's own name really is a token.
|
|
200
201
|
assert.ok(cdk.Token.isUnresolved(nested.stackName), 'precondition: NestedStack.stackName should be an unresolved token');
|
|
201
|
-
const backend = await
|
|
202
|
-
backendHandlerPath: handlerPath,
|
|
203
|
-
backendCDKPath: sideEffectBackendPath,
|
|
204
|
-
defaults: BlocksPresets.production,
|
|
205
|
-
});
|
|
202
|
+
const backend = await makeBackend(nested, 'blocks', sideEffectBackendPath);
|
|
206
203
|
assert.ok(!cdk.Token.isUnresolved(backend.fullId), `fullId must be token-free inside a nested stack, got: ${backend.fullId}`);
|
|
207
204
|
// Falls back to the top-level (concrete) stack name, keeping uniqueness.
|
|
208
205
|
assert.strictEqual(backend.fullId, 'ParentStack-blocks');
|
|
@@ -213,11 +210,7 @@ describe('fullId is token-free (construct IDs / env-var keys)', () => {
|
|
|
213
210
|
const app = new cdk.App();
|
|
214
211
|
const parent = new cdk.Stack(app, 'Gen2ParentStack');
|
|
215
212
|
const nested = new cdk.NestedStack(parent, 'blocks');
|
|
216
|
-
const backend = await
|
|
217
|
-
backendHandlerPath: handlerPath,
|
|
218
|
-
backendCDKPath: fullIdConstructBackendPath,
|
|
219
|
-
defaults: BlocksPresets.production,
|
|
220
|
-
});
|
|
213
|
+
const backend = await makeBackend(nested, 'blocks', fullIdConstructBackendPath);
|
|
221
214
|
// The construct ID is `${scope.fullId}Marker` → `ParentStack-blocks-blocks-dbMarker`.
|
|
222
215
|
const expectedId = `${backend.fullId}-dbMarker`;
|
|
223
216
|
assert.ok(nested.node.tryFindChild(expectedId), `expected a child construct with id "${expectedId}"`);
|
|
@@ -234,11 +227,7 @@ describe('fullId is token-free (construct IDs / env-var keys)', () => {
|
|
|
234
227
|
const app = new cdk.App();
|
|
235
228
|
const parent = new cdk.Stack(app, 'InvariantParent');
|
|
236
229
|
const nested = new cdk.NestedStack(parent, 'blocks');
|
|
237
|
-
const backend = await
|
|
238
|
-
backendHandlerPath: handlerPath,
|
|
239
|
-
backendCDKPath: sideEffectBackendPath,
|
|
240
|
-
defaults: BlocksPresets.production,
|
|
241
|
-
});
|
|
230
|
+
const backend = await makeBackend(nested, 'blocks', sideEffectBackendPath);
|
|
242
231
|
const template = Template.fromStack(nested);
|
|
243
232
|
const fns = template.findResources('AWS::Lambda::Function');
|
|
244
233
|
const envValues = Object.values(fns)
|
|
@@ -259,11 +248,13 @@ describe('infrastructure defaults (backend-anchored)', () => {
|
|
|
259
248
|
backendHandlerPath: handlerPath,
|
|
260
249
|
backendCDKPath: sideEffectBackendPath,
|
|
261
250
|
defaults: BlocksPresets.production,
|
|
251
|
+
defaultComputeFactory: stubComputeFactory,
|
|
262
252
|
});
|
|
263
253
|
const b = await BlocksBackend.create(stack, 'B', {
|
|
264
254
|
backendHandlerPath: handlerPath,
|
|
265
255
|
backendCDKPath: sideEffectBackendPath,
|
|
266
256
|
defaults: BlocksPresets.sandbox,
|
|
257
|
+
defaultComputeFactory: stubComputeFactory,
|
|
267
258
|
});
|
|
268
259
|
// Two backends in one stack must NOT clobber each other — defaults are
|
|
269
260
|
// anchored on the backend, not the shared stack.
|
|
@@ -277,6 +268,7 @@ describe('infrastructure defaults (backend-anchored)', () => {
|
|
|
277
268
|
backendHandlerPath: handlerPath,
|
|
278
269
|
backendCDKPath: sideEffectBackendPath,
|
|
279
270
|
defaults: BlocksPresets.sandbox,
|
|
271
|
+
defaultComputeFactory: stubComputeFactory,
|
|
280
272
|
});
|
|
281
273
|
// A Scope under the backend resolves scope.defaults by walking up to it.
|
|
282
274
|
const outer = new Scope('outer');
|
|
@@ -20,6 +20,28 @@ export interface BlocksDefaults {
|
|
|
20
20
|
* well as the CLI, API, and AWS console — until it is turned off.
|
|
21
21
|
*/
|
|
22
22
|
deletionProtection: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* CORS origins the compute's API accepts, as regular-expression patterns
|
|
25
|
+
* matched against the request `Origin` header. Empty means no cross-origin
|
|
26
|
+
* requests are allowed. The `sandbox` preset allows localhost so a local dev
|
|
27
|
+
* frontend can reach a deployed API; `production` allows none by default.
|
|
28
|
+
*/
|
|
29
|
+
allowedOrigins: string[];
|
|
30
|
+
/**
|
|
31
|
+
* Whether stateful resources that support continuous backups keep them on by
|
|
32
|
+
* default — e.g. DynamoDB Point-in-Time Recovery, letting you restore to any
|
|
33
|
+
* second in the retention window. On in `production`, off in `sandbox` (where
|
|
34
|
+
* throwaway data isn't worth the backup-storage cost). Blocks whose service
|
|
35
|
+
* has no equivalent simply ignore it.
|
|
36
|
+
*
|
|
37
|
+
* `true` enables backups with the service's default window; `false` disables
|
|
38
|
+
* them; `{ retentionDays: n }` enables them and pins the window (a block
|
|
39
|
+
* clamps/validates `n` to its service's supported range — DynamoDB PITR is
|
|
40
|
+
* 1–35 days). Backups only have a window when on, so the two are one field.
|
|
41
|
+
*/
|
|
42
|
+
pointInTimeRecovery: boolean | {
|
|
43
|
+
retentionDays: number;
|
|
44
|
+
};
|
|
23
45
|
}
|
|
24
46
|
/**
|
|
25
47
|
* Prepared starting points for {@link BlocksDefaults}. Pick one and override
|
|
@@ -30,15 +52,19 @@ export interface BlocksDefaults {
|
|
|
30
52
|
* ```
|
|
31
53
|
*/
|
|
32
54
|
export declare const BlocksPresets: {
|
|
33
|
-
/** Disposable development stacks: tear down cleanly, no delete guard. */
|
|
55
|
+
/** Disposable development stacks: tear down cleanly, no delete guard, no backups. */
|
|
34
56
|
sandbox: {
|
|
35
57
|
removalPolicy: RemovalPolicy.DESTROY;
|
|
36
58
|
deletionProtection: false;
|
|
59
|
+
allowedOrigins: string[];
|
|
60
|
+
pointInTimeRecovery: false;
|
|
37
61
|
};
|
|
38
62
|
/** Durable, protected posture for permanent deployments. */
|
|
39
63
|
production: {
|
|
40
64
|
removalPolicy: RemovalPolicy.RETAIN;
|
|
41
65
|
deletionProtection: true;
|
|
66
|
+
allowedOrigins: never[];
|
|
67
|
+
pointInTimeRecovery: true;
|
|
42
68
|
};
|
|
43
69
|
};
|
|
44
70
|
//# sourceMappingURL=blocks-defaults.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blocks-defaults.d.ts","sourceRoot":"","sources":["../../src/cdk/blocks-defaults.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC9B;;;;;OAKG;IACH,aAAa,EAAE,aAAa,CAAC;IAE7B;;;;OAIG;IACH,kBAAkB,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"blocks-defaults.d.ts","sourceRoot":"","sources":["../../src/cdk/blocks-defaults.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC9B;;;;;OAKG;IACH,aAAa,EAAE,aAAa,CAAC;IAE7B;;;;OAIG;IACH,kBAAkB,EAAE,OAAO,CAAC;IAE5B;;;;;OAKG;IACH,cAAc,EAAE,MAAM,EAAE,CAAC;IAEzB;;;;;;;;;;;OAWG;IACH,mBAAmB,EAAE,OAAO,GAAG;QAAE,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;CACzD;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa;IACzB,qFAAqF;;;;;;;IAOrF,4DAA4D;;;;;;;CAOnB,CAAC"}
|
|
@@ -10,14 +10,18 @@ import { RemovalPolicy } from 'aws-cdk-lib';
|
|
|
10
10
|
* ```
|
|
11
11
|
*/
|
|
12
12
|
export const BlocksPresets = {
|
|
13
|
-
/** Disposable development stacks: tear down cleanly, no delete guard. */
|
|
13
|
+
/** Disposable development stacks: tear down cleanly, no delete guard, no backups. */
|
|
14
14
|
sandbox: {
|
|
15
15
|
removalPolicy: RemovalPolicy.DESTROY,
|
|
16
16
|
deletionProtection: false,
|
|
17
|
+
allowedOrigins: ['^https?://(localhost|127\\.0\\.0\\.1)(:\\d+)?$'],
|
|
18
|
+
pointInTimeRecovery: false,
|
|
17
19
|
},
|
|
18
20
|
/** Durable, protected posture for permanent deployments. */
|
|
19
21
|
production: {
|
|
20
22
|
removalPolicy: RemovalPolicy.RETAIN,
|
|
21
23
|
deletionProtection: true,
|
|
24
|
+
allowedOrigins: [],
|
|
25
|
+
pointInTimeRecovery: true,
|
|
22
26
|
},
|
|
23
27
|
};
|
|
@@ -11,12 +11,14 @@ import assert from 'node:assert';
|
|
|
11
11
|
import { RemovalPolicy } from 'aws-cdk-lib';
|
|
12
12
|
import { BlocksPresets } from './blocks-defaults.js';
|
|
13
13
|
describe('BlocksPresets', () => {
|
|
14
|
-
test('sandbox is disposable: DESTROY + deletion protection off', () => {
|
|
14
|
+
test('sandbox is disposable: DESTROY + deletion protection off + no PITR', () => {
|
|
15
15
|
assert.strictEqual(BlocksPresets.sandbox.removalPolicy, RemovalPolicy.DESTROY);
|
|
16
16
|
assert.strictEqual(BlocksPresets.sandbox.deletionProtection, false);
|
|
17
|
+
assert.strictEqual(BlocksPresets.sandbox.pointInTimeRecovery, false);
|
|
17
18
|
});
|
|
18
|
-
test('production is durable: RETAIN + deletion protection on', () => {
|
|
19
|
+
test('production is durable: RETAIN + deletion protection on + PITR on', () => {
|
|
19
20
|
assert.strictEqual(BlocksPresets.production.removalPolicy, RemovalPolicy.RETAIN);
|
|
20
21
|
assert.strictEqual(BlocksPresets.production.deletionProtection, true);
|
|
22
|
+
assert.strictEqual(BlocksPresets.production.pointInTimeRecovery, true);
|
|
21
23
|
});
|
|
22
24
|
});
|