@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,12 +1,49 @@
|
|
|
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 * as apigateway from 'aws-cdk-lib/aws-apigateway';
|
|
9
|
+
import * as lambda from 'aws-cdk-lib/aws-lambda-nodejs';
|
|
10
|
+
import { BLOCKS_RPC_PREFIX } from '../constants.js';
|
|
8
11
|
import { BlocksBackend } from './blocks-backend.js';
|
|
12
|
+
import { Compute } from './compute/compute.js';
|
|
9
13
|
import { BlocksStack, BlocksPresets, Scope } from './index.js';
|
|
14
|
+
// A real app gets its default compute from @aws-blocks/bb-lambda-compute (via
|
|
15
|
+
// @aws-blocks/blocks), which core's own tests can't depend on. Use an
|
|
16
|
+
// equivalent inline stub: a Compute that owns a NodejsFunction + API Gateway,
|
|
17
|
+
// so create() can build the default and the handler/gateway/apiUrl accessors
|
|
18
|
+
// and synth-shape assertions have something real to resolve to. It is passed to
|
|
19
|
+
// each create() via the internal `defaultComputeFactory` option (see makeStack /
|
|
20
|
+
// makeBackend), exactly as @aws-blocks/blocks injects LambdaCompute.
|
|
21
|
+
class StubLambdaCompute extends Compute {
|
|
22
|
+
fn;
|
|
23
|
+
apiGateway;
|
|
24
|
+
apiUrl;
|
|
25
|
+
constructor(scope, id) {
|
|
26
|
+
super(id, { parent: scope });
|
|
27
|
+
this.fn = new lambda.NodejsFunction(this, 'Handler', {
|
|
28
|
+
entry: this.backendHandlerPath,
|
|
29
|
+
runtime: cdk.aws_lambda.Runtime.NODEJS_22_X,
|
|
30
|
+
handler: 'handler',
|
|
31
|
+
role: this.executionRole,
|
|
32
|
+
environment: { BLOCKS_STACK_NAME: this.backendStackName },
|
|
33
|
+
bundling: { minify: true, esbuildArgs: { '--conditions': 'aws-runtime' } },
|
|
34
|
+
});
|
|
35
|
+
this.apiGateway = new apigateway.RestApi(this, 'API', { restApiName: 'Blocks API' });
|
|
36
|
+
this.apiGateway.root.addProxy({
|
|
37
|
+
defaultIntegration: new apigateway.LambdaIntegration(this.fn),
|
|
38
|
+
anyMethod: true,
|
|
39
|
+
});
|
|
40
|
+
this.apiUrl = `${this.apiGateway.url}${BLOCKS_RPC_PREFIX.slice(1)}`;
|
|
41
|
+
}
|
|
42
|
+
setEnv(key, value) {
|
|
43
|
+
this.fn.addEnvironment(key, value);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const stubComputeFactory = (root) => new StubLambdaCompute(root, 'DefaultCompute');
|
|
10
47
|
// Simulate the CDK condition being active (tests import CDK files directly)
|
|
11
48
|
before(() => {
|
|
12
49
|
process.env.NODE_OPTIONS = (process.env.NODE_OPTIONS ?? '') + ' --conditions=cdk';
|
|
@@ -15,19 +52,15 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
15
52
|
const handlerPath = join(__dirname, '__fixtures__', 'handler.js');
|
|
16
53
|
const sideEffectBackendPath = join(__dirname, '__fixtures__', 'side-effect-backend.js');
|
|
17
54
|
const factoryBackendPath = join(__dirname, '__fixtures__', 'factory-backend.js');
|
|
55
|
+
// Wrap create(), injecting the stub default-compute factory the way
|
|
56
|
+
// @aws-blocks/blocks injects LambdaCompute — so tests don't repeat it.
|
|
57
|
+
const makeStack = (scope, id, backendCDKPath) => BlocksStack.create(scope, id, { backendHandlerPath: handlerPath, backendCDKPath, defaults: BlocksPresets.production, defaultComputeFactory: stubComputeFactory });
|
|
58
|
+
const makeBackend = (scope, id, backendCDKPath) => BlocksBackend.create(scope, id, { backendHandlerPath: handlerPath, backendCDKPath, defaults: BlocksPresets.production, defaultComputeFactory: stubComputeFactory });
|
|
18
59
|
describe('ESM cache-busting (multi-stage)', () => {
|
|
19
60
|
test('BlocksStack.create() with same backendCDKPath but different IDs produces constructs in each', async () => {
|
|
20
61
|
const app = new cdk.App();
|
|
21
|
-
const stack1 = await
|
|
22
|
-
|
|
23
|
-
backendCDKPath: sideEffectBackendPath,
|
|
24
|
-
defaults: BlocksPresets.production,
|
|
25
|
-
});
|
|
26
|
-
const stack2 = await BlocksStack.create(app, 'PipelineStage2', {
|
|
27
|
-
backendHandlerPath: handlerPath,
|
|
28
|
-
backendCDKPath: sideEffectBackendPath,
|
|
29
|
-
defaults: BlocksPresets.production,
|
|
30
|
-
});
|
|
62
|
+
const stack1 = await makeStack(app, 'PipelineStage1', sideEffectBackendPath);
|
|
63
|
+
const stack2 = await makeStack(app, 'PipelineStage2', sideEffectBackendPath);
|
|
31
64
|
const findMarker = (scope) => scope.node.tryFindChild('SideEffectMarker');
|
|
32
65
|
assert.ok(findMarker(stack1), 'First stack should have SideEffectMarker from module side effect');
|
|
33
66
|
assert.ok(findMarker(stack2), 'Second stack should have SideEffectMarker from re-executed module (cache busted)');
|
|
@@ -36,11 +69,7 @@ describe('ESM cache-busting (multi-stage)', () => {
|
|
|
36
69
|
describe('factory function support', () => {
|
|
37
70
|
test('BlocksStack.create() calls default export function with the stack instance', async () => {
|
|
38
71
|
const app = new cdk.App();
|
|
39
|
-
const stack = await
|
|
40
|
-
backendHandlerPath: handlerPath,
|
|
41
|
-
backendCDKPath: factoryBackendPath,
|
|
42
|
-
defaults: BlocksPresets.production,
|
|
43
|
-
});
|
|
72
|
+
const stack = await makeStack(app, 'FactoryBlocksStack', factoryBackendPath);
|
|
44
73
|
const marker = stack.node.tryFindChild('FactoryMarker');
|
|
45
74
|
assert.ok(marker, 'Factory function should have created FactoryMarker on the stack');
|
|
46
75
|
});
|
|
@@ -49,11 +78,7 @@ describe('legacy side-effect mode (no default export)', () => {
|
|
|
49
78
|
test('module with only side effects still registers constructs via globalThis', async () => {
|
|
50
79
|
const app = new cdk.App();
|
|
51
80
|
const stack = new cdk.Stack(app, 'LegacyTestStack');
|
|
52
|
-
const backend = await
|
|
53
|
-
backendHandlerPath: handlerPath,
|
|
54
|
-
backendCDKPath: sideEffectBackendPath,
|
|
55
|
-
defaults: BlocksPresets.production,
|
|
56
|
-
});
|
|
81
|
+
const backend = await makeBackend(stack, 'LegacyStage', sideEffectBackendPath);
|
|
57
82
|
const marker = backend.node.tryFindChild('SideEffectMarker');
|
|
58
83
|
assert.ok(marker, 'Side-effect-only module should register construct via globalThis.CURRENT_BLOCKS_STACK');
|
|
59
84
|
});
|
|
@@ -65,22 +90,14 @@ describe('shared execution role (BlocksStack)', () => {
|
|
|
65
90
|
// executionRole — a separate code path from BlocksBackend's constructor.
|
|
66
91
|
test('BlocksStack wires executionRole via its constructor', async () => {
|
|
67
92
|
const app = new cdk.App();
|
|
68
|
-
const stack = await
|
|
69
|
-
backendHandlerPath: handlerPath,
|
|
70
|
-
backendCDKPath: sideEffectBackendPath,
|
|
71
|
-
defaults: BlocksPresets.production,
|
|
72
|
-
});
|
|
93
|
+
const stack = await makeStack(app, 'StackRoleStack', sideEffectBackendPath);
|
|
73
94
|
assert.ok(stack.executionRole, 'BlocksStack should expose a populated .executionRole');
|
|
74
95
|
});
|
|
75
96
|
});
|
|
76
97
|
describe('executionRole globalThis fallback', () => {
|
|
77
98
|
test('resolves via globalThis.CURRENT_BLOCKS_STACK when no owner is in the tree', async () => {
|
|
78
99
|
const app = new cdk.App();
|
|
79
|
-
const stack = await
|
|
80
|
-
backendHandlerPath: handlerPath,
|
|
81
|
-
backendCDKPath: sideEffectBackendPath,
|
|
82
|
-
defaults: BlocksPresets.production,
|
|
83
|
-
});
|
|
100
|
+
const stack = await makeStack(app, 'FallbackStack', sideEffectBackendPath);
|
|
84
101
|
// A Scope whose construct-tree ancestry has no BlocksStack/BlocksBackend
|
|
85
102
|
// (parented under a plain cdk.Stack) exhausts the tree-walk and falls back
|
|
86
103
|
// to globalThis.CURRENT_BLOCKS_STACK. The `as any` is test plumbing — a
|
|
@@ -91,6 +108,29 @@ describe('executionRole globalThis fallback', () => {
|
|
|
91
108
|
assert.strictEqual(orphan.executionRole, stack.executionRole, 'fallback resolves to the ambient stack role');
|
|
92
109
|
});
|
|
93
110
|
});
|
|
111
|
+
describe('root is bound to the owning stack (multi-stack synth)', () => {
|
|
112
|
+
test('a block under each of two stacks resolves its OWN stack, not the last globalThis', async () => {
|
|
113
|
+
// `root` is resolved once at Scope construction (not re-walked per getter),
|
|
114
|
+
// and `create()` mutates globalThis.CURRENT_BLOCKS_STACK for each stack it
|
|
115
|
+
// builds. With two stacks in one synth, a block constructed under the first
|
|
116
|
+
// must stay bound to the first even after the second stack is created and
|
|
117
|
+
// overwrites globalThis — otherwise its root-derived accessors (handler,
|
|
118
|
+
// executionRole, backendStackName) would silently point at the wrong stack.
|
|
119
|
+
const app = new cdk.App();
|
|
120
|
+
const stackA = await makeStack(app, 'RootBindingA', sideEffectBackendPath);
|
|
121
|
+
// A block explicitly parented under stackA (construct-tree walk resolves
|
|
122
|
+
// stackA regardless of the ambient globalThis).
|
|
123
|
+
const blockA = new Scope('blockA', { parent: stackA });
|
|
124
|
+
// Building the second stack overwrites globalThis.CURRENT_BLOCKS_STACK.
|
|
125
|
+
const stackB = await makeStack(app, 'RootBindingB', sideEffectBackendPath);
|
|
126
|
+
const blockB = new Scope('blockB', { parent: stackB });
|
|
127
|
+
assert.strictEqual(blockA.executionRole, stackA.executionRole, 'blockA stays bound to stackA');
|
|
128
|
+
assert.strictEqual(blockB.executionRole, stackB.executionRole, 'blockB binds to stackB');
|
|
129
|
+
assert.notStrictEqual(stackA.executionRole, stackB.executionRole, 'the two stacks have distinct roles');
|
|
130
|
+
assert.strictEqual(blockA.backendStackName, 'RootBindingA', 'blockA derives its own stack name');
|
|
131
|
+
assert.strictEqual(blockB.backendStackName, 'RootBindingB', 'blockB derives its own stack name');
|
|
132
|
+
});
|
|
133
|
+
});
|
|
94
134
|
describe('assertCdkConditionActive', () => {
|
|
95
135
|
test('BlocksStack.create() throws when --conditions=cdk is missing', async () => {
|
|
96
136
|
const origNodeOptions = process.env.NODE_OPTIONS;
|
|
@@ -99,11 +139,7 @@ describe('assertCdkConditionActive', () => {
|
|
|
99
139
|
process.execArgv = [];
|
|
100
140
|
try {
|
|
101
141
|
const app = new cdk.App();
|
|
102
|
-
await assert.rejects(
|
|
103
|
-
backendHandlerPath: handlerPath,
|
|
104
|
-
backendCDKPath: sideEffectBackendPath,
|
|
105
|
-
defaults: BlocksPresets.production,
|
|
106
|
-
}), (err) => {
|
|
142
|
+
await assert.rejects(makeStack(app, 'MissingConditionStack', sideEffectBackendPath), (err) => {
|
|
107
143
|
assert.ok(err.message.includes('Missing --conditions=cdk'), `Expected condition error, got: ${err.message}`);
|
|
108
144
|
return true;
|
|
109
145
|
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type * as cdk from 'aws-cdk-lib';
|
|
2
|
+
import type { Compute } from './compute.js';
|
|
3
|
+
import type { BlocksStack } from '../index.js';
|
|
4
|
+
import type { BlocksBackend } from '../blocks-backend.js';
|
|
5
|
+
/**
|
|
6
|
+
* Lambda-shaped surface of the default compute that the legacy
|
|
7
|
+
* `handler` / `gateway` / `apiUrl` accessors on BlocksStack/BlocksBackend read.
|
|
8
|
+
* The default compute (`LambdaCompute` from `@aws-blocks/bb-lambda-compute`)
|
|
9
|
+
* satisfies this structurally, so core exposes those accessors without
|
|
10
|
+
* importing the concrete class. To be removed with those accessors once
|
|
11
|
+
* consumers move to the multi-compute model.
|
|
12
|
+
*
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
export interface LambdaShapedCompute extends Compute {
|
|
16
|
+
readonly fn: cdk.aws_lambda_nodejs.NodejsFunction;
|
|
17
|
+
readonly apiGateway: cdk.aws_apigateway.RestApi;
|
|
18
|
+
readonly apiUrl: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Builds the default {@link Compute} for a stack/backend. `create()` reads it
|
|
22
|
+
* from its props (`CoreBlocksStackProps.defaultComputeFactory`) and calls it to
|
|
23
|
+
* build the default without importing a concrete compute class — the factory is
|
|
24
|
+
* supplied by whoever owns both core and a concrete compute package (the
|
|
25
|
+
* umbrella `@aws-blocks/blocks`, which injects `LambdaCompute`). It lives on
|
|
26
|
+
* `CoreBlocksStackProps`/`CoreBlocksBackendProps`, which the umbrella derives
|
|
27
|
+
* from the customer-facing props, so it is absent from `BlocksStackProps` and
|
|
28
|
+
* customers cannot set it.
|
|
29
|
+
*
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
export type DefaultComputeFactory = (root: BlocksStack | BlocksBackend) => Compute;
|
|
33
|
+
//# sourceMappingURL=default-compute-factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default-compute-factory.d.ts","sourceRoot":"","sources":["../../../src/cdk/compute/default-compute-factory.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,GAAG,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D;;;;;;;;;GASG;AACH,MAAM,WAAW,mBAAoB,SAAQ,OAAO;IACnD,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,iBAAiB,CAAC,cAAc,CAAC;IAClD,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,cAAc,CAAC,OAAO,CAAC;IAChD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,IAAI,EAAE,WAAW,GAAG,aAAa,KAAK,OAAO,CAAC"}
|
package/dist/cdk/index.d.ts
CHANGED
|
@@ -2,7 +2,9 @@ import * as cdk from 'aws-cdk-lib';
|
|
|
2
2
|
import { Construct } from 'constructs';
|
|
3
3
|
import { type BlocksStackProps, type BlocksStack as BaseBlocksStack, type ScopeParent, type ScopeOptions } from '../common/index.js';
|
|
4
4
|
import { type BlocksDefaults } from './blocks-defaults.js';
|
|
5
|
-
|
|
5
|
+
import type { Compute } from './compute/compute.js';
|
|
6
|
+
import type { DefaultComputeFactory } from './compute/default-compute-factory.js';
|
|
7
|
+
export { BlocksBackend, type BlocksBackendProps, type CoreBlocksBackendProps, SHARED_HANDLER_TIMEOUT_SECONDS, } from './blocks-backend.js';
|
|
6
8
|
export { DEFAULT_NODE_RUNTIME } from './node-version.js';
|
|
7
9
|
export { blocksNodejsBundling } from './bundling.js';
|
|
8
10
|
export { SandboxDisableDeletionProtection } from './mixins.js';
|
|
@@ -11,18 +13,39 @@ export { type BlocksDefaults, BlocksPresets, } from './blocks-defaults.js';
|
|
|
11
13
|
export { synthGuard } from './synth-guard.js';
|
|
12
14
|
export type { ScopeOptions } from '../index.js';
|
|
13
15
|
export { ApiError, isBlocksError, hasAuthError, DEFAULT_API_ERROR_NAME } from '../errors.js';
|
|
16
|
+
/**
|
|
17
|
+
* Core's `create()` props: the public {@link BlocksStackProps} plus the required
|
|
18
|
+
* `defaultComputeFactory`. The umbrella (`@aws-blocks/blocks`) supplies the
|
|
19
|
+
* factory (which builds a `LambdaCompute`) by spreading it onto the customer's
|
|
20
|
+
* props; customers use {@link BlocksStackProps} and never set the factory.
|
|
21
|
+
*
|
|
22
|
+
* Kept separate (rather than a `create()` argument) so the factory travels with
|
|
23
|
+
* the props object and core stays free of any concrete compute class.
|
|
24
|
+
*
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
export interface CoreBlocksStackProps extends BlocksStackProps {
|
|
28
|
+
/** Builds the stack's default compute. Injected by `@aws-blocks/blocks`. */
|
|
29
|
+
defaultComputeFactory: DefaultComputeFactory;
|
|
30
|
+
}
|
|
14
31
|
export declare class BlocksStack extends cdk.Stack implements BaseBlocksStack {
|
|
15
32
|
readonly id: string;
|
|
16
|
-
readonly apiUrl: string;
|
|
17
|
-
readonly gateway: cdk.aws_apigateway.RestApi;
|
|
18
|
-
readonly handler: cdk.aws_lambda_nodejs.NodejsFunction;
|
|
19
33
|
readonly backendHandlerPath: string;
|
|
20
34
|
/** Shared IAM role assumed by all Blocks compute. Building Blocks grant to this role. */
|
|
21
35
|
readonly executionRole: cdk.aws_iam.IRole;
|
|
22
36
|
/** Infrastructure defaults for Building Blocks created under this stack. */
|
|
23
37
|
readonly defaults: BlocksDefaults;
|
|
38
|
+
/** The default compute (owns the Lambda function + API Gateway); set in `create()`. @internal */
|
|
39
|
+
_defaultCompute?: Compute;
|
|
40
|
+
/** The default compute's Lambda function. To be removed once consumers move to the multi-compute model. */
|
|
41
|
+
get handler(): cdk.aws_lambda_nodejs.NodejsFunction;
|
|
42
|
+
/** The default compute's API Gateway REST API. To be removed once consumers move to the multi-compute model. */
|
|
43
|
+
get gateway(): cdk.aws_apigateway.RestApi;
|
|
44
|
+
/** The default compute's RPC endpoint URL. To be removed once consumers move to the multi-compute model. */
|
|
45
|
+
get apiUrl(): string;
|
|
46
|
+
private requireDefaultCompute;
|
|
24
47
|
private constructor();
|
|
25
|
-
static create(scope: Construct, id: string, props:
|
|
48
|
+
static create(scope: Construct, id: string, props: CoreBlocksStackProps): Promise<BlocksStack>;
|
|
26
49
|
}
|
|
27
50
|
export declare class Scope extends Construct {
|
|
28
51
|
readonly id: string;
|
|
@@ -37,6 +60,14 @@ export declare class Scope extends Construct {
|
|
|
37
60
|
* tree walk.
|
|
38
61
|
*/
|
|
39
62
|
private readonly root;
|
|
63
|
+
/**
|
|
64
|
+
* Compute assigned at this node. Applies to this block and is inherited by
|
|
65
|
+
* descendants (a nearer assignment wins). Covers both a handler assigned to a
|
|
66
|
+
* specific compute and a scope-level default for its subtree. Internal until
|
|
67
|
+
* the customer-facing surface exists.
|
|
68
|
+
* @internal
|
|
69
|
+
*/
|
|
70
|
+
_compute?: Compute;
|
|
40
71
|
constructor(id: string, options?: ScopeOptions);
|
|
41
72
|
/**
|
|
42
73
|
* Walk up the construct tree to the nearest owning BlocksStack/BlocksBackend;
|
|
@@ -51,6 +82,16 @@ export declare class Scope extends Construct {
|
|
|
51
82
|
* route those grants to the role's default (inline) policy.
|
|
52
83
|
*/
|
|
53
84
|
get executionRole(): cdk.aws_iam.IRole;
|
|
85
|
+
/**
|
|
86
|
+
* The compute this block runs on: the nearest `_compute` assigned on this
|
|
87
|
+
* block or an ancestor scope, else the owning stack/backend's default compute.
|
|
88
|
+
*
|
|
89
|
+
* For any app that doesn't assign a compute, this always resolves to the
|
|
90
|
+
* default — so reads are a no-op refactor. `_compute` is internal
|
|
91
|
+
* (test/framework) until the customer-facing surface exists; there is no
|
|
92
|
+
* public option to set it yet.
|
|
93
|
+
*/
|
|
94
|
+
get compute(): Compute;
|
|
54
95
|
/**
|
|
55
96
|
* The backend entry file the owning BlocksStack/BlocksBackend runs — the
|
|
56
97
|
* single handler entry shared across the whole app.
|
package/dist/cdk/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cdk/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,GAAG,MAAM,aAAa,CAAC;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,WAAW,IAAI,eAAe,EACnC,KAAK,WAAW,EAChB,KAAK,YAAY,EAElB,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAAE,KAAK,cAAc,EAAiB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cdk/index.ts"],"names":[],"mappings":"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"}
|
package/dist/cdk/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import { setupBlocksInfra, BlocksBackend, assertCdkConditionActive } from './blo
|
|
|
9
9
|
import { addBlocksStackMetadata } from './stack-metadata.js';
|
|
10
10
|
import { finalizeConfigRegistry } from './config-registry.js';
|
|
11
11
|
import { BlocksPresets } from './blocks-defaults.js';
|
|
12
|
-
export { BlocksBackend } from './blocks-backend.js';
|
|
12
|
+
export { BlocksBackend, SHARED_HANDLER_TIMEOUT_SECONDS, } from './blocks-backend.js';
|
|
13
13
|
export { DEFAULT_NODE_RUNTIME } from './node-version.js';
|
|
14
14
|
export { blocksNodejsBundling } from './bundling.js';
|
|
15
15
|
export { SandboxDisableDeletionProtection } from './mixins.js';
|
|
@@ -19,14 +19,31 @@ export { synthGuard } from './synth-guard.js';
|
|
|
19
19
|
export { ApiError, isBlocksError, hasAuthError, DEFAULT_API_ERROR_NAME } from '../errors.js';
|
|
20
20
|
export class BlocksStack extends cdk.Stack {
|
|
21
21
|
id;
|
|
22
|
-
apiUrl;
|
|
23
|
-
gateway;
|
|
24
|
-
handler;
|
|
25
22
|
backendHandlerPath;
|
|
26
23
|
/** Shared IAM role assumed by all Blocks compute. Building Blocks grant to this role. */
|
|
27
24
|
executionRole;
|
|
28
25
|
/** Infrastructure defaults for Building Blocks created under this stack. */
|
|
29
26
|
defaults;
|
|
27
|
+
/** The default compute (owns the Lambda function + API Gateway); set in `create()`. @internal */
|
|
28
|
+
_defaultCompute;
|
|
29
|
+
/** The default compute's Lambda function. To be removed once consumers move to the multi-compute model. */
|
|
30
|
+
get handler() {
|
|
31
|
+
return this.requireDefaultCompute().fn;
|
|
32
|
+
}
|
|
33
|
+
/** The default compute's API Gateway REST API. To be removed once consumers move to the multi-compute model. */
|
|
34
|
+
get gateway() {
|
|
35
|
+
return this.requireDefaultCompute().apiGateway;
|
|
36
|
+
}
|
|
37
|
+
/** The default compute's RPC endpoint URL. To be removed once consumers move to the multi-compute model. */
|
|
38
|
+
get apiUrl() {
|
|
39
|
+
return this.requireDefaultCompute().apiUrl;
|
|
40
|
+
}
|
|
41
|
+
requireDefaultCompute() {
|
|
42
|
+
if (!this._defaultCompute) {
|
|
43
|
+
throw new Error('Blocks stack not fully initialized — access .handler/.gateway/.apiUrl after BlocksStack.create() resolves.');
|
|
44
|
+
}
|
|
45
|
+
return this._defaultCompute;
|
|
46
|
+
}
|
|
30
47
|
constructor(scope, id, props) {
|
|
31
48
|
super(scope, id, props);
|
|
32
49
|
this.id = id;
|
|
@@ -35,9 +52,6 @@ export class BlocksStack extends cdk.Stack {
|
|
|
35
52
|
// Set globalThis so Building Blocks attach directly to this stack
|
|
36
53
|
globalThis.CURRENT_BLOCKS_STACK = this;
|
|
37
54
|
const infra = setupBlocksInfra(this, props, id);
|
|
38
|
-
this.handler = infra.handler;
|
|
39
|
-
this.gateway = infra.gateway;
|
|
40
|
-
this.apiUrl = infra.apiUrl;
|
|
41
55
|
this.executionRole = infra.executionRole;
|
|
42
56
|
}
|
|
43
57
|
static async create(scope, id, props) {
|
|
@@ -46,6 +60,13 @@ export class BlocksStack extends cdk.Stack {
|
|
|
46
60
|
const pipelineScope = globalThis[__PIPELINE_STAGE_SCOPE__];
|
|
47
61
|
const actualScope = pipelineScope || scope;
|
|
48
62
|
const stack = new BlocksStack(actualScope, id, props);
|
|
63
|
+
// Create the default compute before importing the backend: it OWNS the
|
|
64
|
+
// Lambda function + API Gateway (which back .handler/.gateway/.apiUrl), and
|
|
65
|
+
// a block reading `this.compute` in its constructor (during that import)
|
|
66
|
+
// must resolve to it. The factory is supplied by the umbrella
|
|
67
|
+
// @aws-blocks/blocks (which injects LambdaCompute) via props, so core never
|
|
68
|
+
// imports the concrete compute class.
|
|
69
|
+
stack._defaultCompute = props.defaultComputeFactory(stack);
|
|
49
70
|
// file:// URL (not a raw path) so the cache-busting query works on Windows,
|
|
50
71
|
// where an absolute path like `D:\...` is rejected as URL scheme `d:`.
|
|
51
72
|
const backendUrl = pathToFileURL(props.backendCDKPath);
|
|
@@ -79,6 +100,14 @@ export class Scope extends Construct {
|
|
|
79
100
|
* tree walk.
|
|
80
101
|
*/
|
|
81
102
|
root;
|
|
103
|
+
/**
|
|
104
|
+
* Compute assigned at this node. Applies to this block and is inherited by
|
|
105
|
+
* descendants (a nearer assignment wins). Covers both a handler assigned to a
|
|
106
|
+
* specific compute and a scope-level default for its subtree. Internal until
|
|
107
|
+
* the customer-facing surface exists.
|
|
108
|
+
* @internal
|
|
109
|
+
*/
|
|
110
|
+
_compute;
|
|
82
111
|
constructor(id, options) {
|
|
83
112
|
const parent = options?.parent || globalThis.CURRENT_BLOCKS_STACK;
|
|
84
113
|
super(parent, id);
|
|
@@ -115,6 +144,27 @@ export class Scope extends Construct {
|
|
|
115
144
|
get executionRole() {
|
|
116
145
|
return this.root.executionRole;
|
|
117
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* The compute this block runs on: the nearest `_compute` assigned on this
|
|
149
|
+
* block or an ancestor scope, else the owning stack/backend's default compute.
|
|
150
|
+
*
|
|
151
|
+
* For any app that doesn't assign a compute, this always resolves to the
|
|
152
|
+
* default — so reads are a no-op refactor. `_compute` is internal
|
|
153
|
+
* (test/framework) until the customer-facing surface exists; there is no
|
|
154
|
+
* public option to set it yet.
|
|
155
|
+
*/
|
|
156
|
+
get compute() {
|
|
157
|
+
for (let current = this; current; current = current.parent) {
|
|
158
|
+
const assigned = current._compute;
|
|
159
|
+
if (assigned)
|
|
160
|
+
return assigned;
|
|
161
|
+
}
|
|
162
|
+
const defaultCompute = this.root._defaultCompute;
|
|
163
|
+
if (!defaultCompute) {
|
|
164
|
+
throw new Error('Default compute not initialized — BlocksStack/BlocksBackend.create() must run before resolving `compute`.');
|
|
165
|
+
}
|
|
166
|
+
return defaultCompute;
|
|
167
|
+
}
|
|
118
168
|
/**
|
|
119
169
|
* The backend entry file the owning BlocksStack/BlocksBackend runs — the
|
|
120
170
|
* single handler entry shared across the whole app.
|
package/dist/cdk/internal.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../src/cdk/internal.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../src/cdk/internal.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,YAAY,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAGlF,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolution glue between the dependency-free `secret()` / `config()` markers
|
|
3
|
+
* (defined in `@aws-blocks/hosting`) and the `Hosting` CDK block.
|
|
4
|
+
*
|
|
5
|
+
* Delegates to the shared `@aws-blocks/hosting` engine, pinning only the Blocks
|
|
6
|
+
* namespaces (`/blocks/secrets`, `/blocks/config`). The store is derived from the
|
|
7
|
+
* marker's kind (`secret` → Secrets Manager, `config` → SSM), and BYO
|
|
8
|
+
* `ISecret`/`IParameter` handles are wired identically.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
import type { ManagedValue } from '@aws-blocks/hosting';
|
|
13
|
+
import { type ByoBinding, type DomainNameInput as LeafDomainNameInput, type EnvValue as LeafEnvValue, type SecretFetcher, type StoreConfig } from '@aws-blocks/hosting/constructs';
|
|
14
|
+
import type * as cdk from 'aws-cdk-lib';
|
|
15
|
+
/** A `compute.environment` value: a literal, a managed marker, or a BYO CDK handle. */
|
|
16
|
+
export type EnvValue = LeafEnvValue;
|
|
17
|
+
/** A custom-domain name: a literal, a managed marker, or a mix in an array. */
|
|
18
|
+
export type DomainNameInput = LeafDomainNameInput;
|
|
19
|
+
/** Split an environment map into plain literals, managed markers, and BYO handles. */
|
|
20
|
+
export declare function partitionEnvironment(environment: Record<string, EnvValue> | undefined): {
|
|
21
|
+
plain: Record<string, string>;
|
|
22
|
+
managed: ManagedValue[];
|
|
23
|
+
byo: ByoBinding[];
|
|
24
|
+
};
|
|
25
|
+
/** Every managed marker requiring a synth-time fetch (domain markers only). */
|
|
26
|
+
export declare function collectSynthMarkers(domainName: DomainNameInput | undefined): ManagedValue[];
|
|
27
|
+
/**
|
|
28
|
+
* Resolve managed markers to plaintext at synth time under the Blocks namespaces.
|
|
29
|
+
* Throws a clear, actionable error if a referenced value was never set. An optional
|
|
30
|
+
* `storeConfig` overrides the pinned Blocks prefix/stage per kind.
|
|
31
|
+
*/
|
|
32
|
+
export declare function resolveSecretsAtSynth(markers: ManagedValue[], fetcher?: SecretFetcher, storeConfig?: StoreConfig): Promise<Map<string, string>>;
|
|
33
|
+
/** Resolve domain markers to literals using the synth-resolved value map. */
|
|
34
|
+
export declare function resolveDomainNames(domainName: DomainNameInput, resolved: Map<string, string>): string | string[];
|
|
35
|
+
/**
|
|
36
|
+
* Fail synth (deploy) when a referenced `environment` marker has no value set —
|
|
37
|
+
* existence only, never fetching the value. Uses the Blocks namespaces (with an
|
|
38
|
+
* optional per-kind `storeConfig` override), matching how the values are wired.
|
|
39
|
+
*/
|
|
40
|
+
export declare function assertMarkersExistAtSynth(markers: ManagedValue[], storeConfig?: StoreConfig): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Wire a runtime managed marker under the Blocks namespace (store from kind). An
|
|
43
|
+
* optional `storeConfig` overrides the pinned prefix/stage/cacheTtlSeconds per kind.
|
|
44
|
+
*/
|
|
45
|
+
export declare function wireManagedValue(fn: cdk.aws_lambda.Function, marker: ManagedValue, storeConfig?: StoreConfig): void;
|
|
46
|
+
/** Wire a runtime BYO handle (grant + inject locator). Honors an optional `storeConfig`. */
|
|
47
|
+
export declare function wireByo(fn: cdk.aws_lambda.Function, binding: ByoBinding, storeConfig?: StoreConfig): void;
|
|
48
|
+
//# sourceMappingURL=hosting-secrets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hosting-secrets.d.ts","sourceRoot":"","sources":["../src/hosting-secrets.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EACN,KAAK,UAAU,EACf,KAAK,eAAe,IAAI,mBAAmB,EAC3C,KAAK,QAAQ,IAAI,YAAY,EAM7B,KAAK,aAAa,EAClB,KAAK,WAAW,EAGhB,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,KAAK,GAAG,MAAM,aAAa,CAAC;AAiBxC,uFAAuF;AACvF,MAAM,MAAM,QAAQ,GAAG,YAAY,CAAC;AAEpC,+EAA+E;AAC/E,MAAM,MAAM,eAAe,GAAG,mBAAmB,CAAC;AAElD,sFAAsF;AACtF,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,SAAS,GAAG;IACxF,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,GAAG,EAAE,UAAU,EAAE,CAAC;CAClB,CAEA;AAED,+EAA+E;AAC/E,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,eAAe,GAAG,SAAS,GAAG,YAAY,EAAE,CAE3F;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CAC1C,OAAO,EAAE,YAAY,EAAE,EACvB,OAAO,CAAC,EAAE,aAAa,EACvB,WAAW,CAAC,EAAE,WAAW,GACvB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAE9B;AAED,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,eAAe,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,GAAG,MAAM,EAAE,CAEhH;AAED;;;;GAIG;AACH,wBAAsB,yBAAyB,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAEjH;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,GAAG,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,CAAC,EAAE,WAAW,GAAG,IAAI,CAEnH;AAED,4FAA4F;AAC5F,wBAAgB,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,UAAU,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,WAAW,GAAG,IAAI,CAEzG"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { assertMarkersExistAtSynth as leafAssertMarkersExistAtSynth, collectSynthMarkers as leafCollectSynthMarkers, partitionEnvironment as leafPartitionEnvironment, resolveDomainNames as leafResolveDomainNames, resolveSecretsAtSynth as leafResolveSecretsAtSynth, wireByo as leafWireByo, wireManagedValue as leafWireManagedValue, } from '@aws-blocks/hosting/constructs';
|
|
4
|
+
import { blocksStoreConfig } from './secret-naming.js';
|
|
5
|
+
/**
|
|
6
|
+
* Layer a caller's per-kind store config over the pinned Blocks defaults. Shallow
|
|
7
|
+
* and per-kind: the Blocks `/blocks/*` prefix stays the default, but any field the
|
|
8
|
+
* app sets (`prefix`, `stage`, `cacheTtlSeconds`) wins.
|
|
9
|
+
*/
|
|
10
|
+
function mergeBlocksStoreConfig(override) {
|
|
11
|
+
const base = blocksStoreConfig();
|
|
12
|
+
if (!override)
|
|
13
|
+
return base;
|
|
14
|
+
return {
|
|
15
|
+
secretStore: { ...base.secretStore, ...override.secretStore },
|
|
16
|
+
configStore: { ...base.configStore, ...override.configStore },
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/** Split an environment map into plain literals, managed markers, and BYO handles. */
|
|
20
|
+
export function partitionEnvironment(environment) {
|
|
21
|
+
return leafPartitionEnvironment(environment);
|
|
22
|
+
}
|
|
23
|
+
/** Every managed marker requiring a synth-time fetch (domain markers only). */
|
|
24
|
+
export function collectSynthMarkers(domainName) {
|
|
25
|
+
return leafCollectSynthMarkers(domainName);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Resolve managed markers to plaintext at synth time under the Blocks namespaces.
|
|
29
|
+
* Throws a clear, actionable error if a referenced value was never set. An optional
|
|
30
|
+
* `storeConfig` overrides the pinned Blocks prefix/stage per kind.
|
|
31
|
+
*/
|
|
32
|
+
export async function resolveSecretsAtSynth(markers, fetcher, storeConfig) {
|
|
33
|
+
return leafResolveSecretsAtSynth(markers, { ...mergeBlocksStoreConfig(storeConfig), fetcher });
|
|
34
|
+
}
|
|
35
|
+
/** Resolve domain markers to literals using the synth-resolved value map. */
|
|
36
|
+
export function resolveDomainNames(domainName, resolved) {
|
|
37
|
+
return leafResolveDomainNames(domainName, resolved);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Fail synth (deploy) when a referenced `environment` marker has no value set —
|
|
41
|
+
* existence only, never fetching the value. Uses the Blocks namespaces (with an
|
|
42
|
+
* optional per-kind `storeConfig` override), matching how the values are wired.
|
|
43
|
+
*/
|
|
44
|
+
export async function assertMarkersExistAtSynth(markers, storeConfig) {
|
|
45
|
+
return leafAssertMarkersExistAtSynth(markers, mergeBlocksStoreConfig(storeConfig));
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Wire a runtime managed marker under the Blocks namespace (store from kind). An
|
|
49
|
+
* optional `storeConfig` overrides the pinned prefix/stage/cacheTtlSeconds per kind.
|
|
50
|
+
*/
|
|
51
|
+
export function wireManagedValue(fn, marker, storeConfig) {
|
|
52
|
+
leafWireManagedValue(fn, marker, mergeBlocksStoreConfig(storeConfig));
|
|
53
|
+
}
|
|
54
|
+
/** Wire a runtime BYO handle (grant + inject locator). Honors an optional `storeConfig`. */
|
|
55
|
+
export function wireByo(fn, binding, storeConfig) {
|
|
56
|
+
leafWireByo(fn, binding, mergeBlocksStoreConfig(storeConfig));
|
|
57
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hosting-secrets.test.d.ts","sourceRoot":"","sources":["../src/hosting-secrets.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import assert from 'node:assert';
|
|
4
|
+
import { describe, it } from 'node:test';
|
|
5
|
+
import { config, secret } from '@aws-blocks/hosting';
|
|
6
|
+
import { collectSynthMarkers, partitionEnvironment, resolveDomainNames, resolveSecretsAtSynth, } from './hosting-secrets.js';
|
|
7
|
+
void describe('partitionEnvironment()', () => {
|
|
8
|
+
void it('splits plain / managed (secret+config)', () => {
|
|
9
|
+
const { plain, managed } = partitionEnvironment({
|
|
10
|
+
FLAG: 'on',
|
|
11
|
+
STRIPE_KEY: secret('STRIPE_KEY'),
|
|
12
|
+
FEATURE_FLAGS: config('FEATURE_FLAGS'),
|
|
13
|
+
});
|
|
14
|
+
assert.deepStrictEqual(plain, { FLAG: 'on' });
|
|
15
|
+
assert.deepStrictEqual(managed.map((m) => `${m.key}:${m.kind}`).sort(), [
|
|
16
|
+
'FEATURE_FLAGS:config',
|
|
17
|
+
'STRIPE_KEY:secret',
|
|
18
|
+
]);
|
|
19
|
+
});
|
|
20
|
+
void it('rejects env key / marker key mismatch', () => {
|
|
21
|
+
assert.throws(() => partitionEnvironment({ STRIPE_KEY: secret('OTHER') }), /must match the environment variable name/);
|
|
22
|
+
});
|
|
23
|
+
void it('handles undefined', () => {
|
|
24
|
+
const { plain, managed, byo } = partitionEnvironment(undefined);
|
|
25
|
+
assert.deepStrictEqual(plain, {});
|
|
26
|
+
assert.strictEqual(managed.length, 0);
|
|
27
|
+
assert.strictEqual(byo.length, 0);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
void describe('collectSynthMarkers()', () => {
|
|
31
|
+
void it('gathers domain markers, deduped by key', () => {
|
|
32
|
+
const markers = collectSynthMarkers(['example.com', config('DOMAIN_PROD'), config('DOMAIN_PROD')]);
|
|
33
|
+
assert.deepStrictEqual(markers.map((m) => m.key), ['DOMAIN_PROD']);
|
|
34
|
+
});
|
|
35
|
+
void it('returns nothing when no markers', () => {
|
|
36
|
+
assert.deepStrictEqual(collectSynthMarkers('example.com'), []);
|
|
37
|
+
assert.deepStrictEqual(collectSynthMarkers(undefined), []);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
void describe('resolveSecretsAtSynth() — Blocks namespaces', () => {
|
|
41
|
+
void it('config marker resolves under /blocks/config (SSM leading-slash)', async () => {
|
|
42
|
+
const seen = [];
|
|
43
|
+
const resolved = await resolveSecretsAtSynth([config('DOMAIN_PROD')], async (name) => {
|
|
44
|
+
seen.push(name);
|
|
45
|
+
return 'prod.example.com';
|
|
46
|
+
});
|
|
47
|
+
assert.deepStrictEqual(seen, ['/blocks/config/DOMAIN_PROD']);
|
|
48
|
+
assert.strictEqual(resolved.get('DOMAIN_PROD'), 'prod.example.com');
|
|
49
|
+
});
|
|
50
|
+
void it('secret marker resolves under /blocks/secrets (Secrets Manager slash-free)', async () => {
|
|
51
|
+
const seen = [];
|
|
52
|
+
await resolveSecretsAtSynth([secret('API_KEY')], async (name) => {
|
|
53
|
+
seen.push(name);
|
|
54
|
+
return 'k';
|
|
55
|
+
});
|
|
56
|
+
assert.deepStrictEqual(seen, ['blocks/secrets/API_KEY']);
|
|
57
|
+
});
|
|
58
|
+
void it('throws an actionable error when a value is not set', async () => {
|
|
59
|
+
await assert.rejects(resolveSecretsAtSynth([config('DOMAIN_PROD')], async () => {
|
|
60
|
+
const e = new Error('not found');
|
|
61
|
+
e.name = 'ParameterNotFound';
|
|
62
|
+
throw e;
|
|
63
|
+
}), /config 'DOMAIN_PROD' is referenced/);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
void describe('resolveDomainNames()', () => {
|
|
67
|
+
void it('replaces markers with resolved literals, preserving shape', () => {
|
|
68
|
+
const resolved = new Map([['DOMAIN_PROD', 'prod.example.com']]);
|
|
69
|
+
assert.strictEqual(resolveDomainNames(config('DOMAIN_PROD'), resolved), 'prod.example.com');
|
|
70
|
+
assert.deepStrictEqual(resolveDomainNames(['www.example.com', config('DOMAIN_PROD')], resolved), [
|
|
71
|
+
'www.example.com',
|
|
72
|
+
'prod.example.com',
|
|
73
|
+
]);
|
|
74
|
+
});
|
|
75
|
+
void it('throws if a marker reached the sync path unresolved', () => {
|
|
76
|
+
assert.throws(() => resolveDomainNames(config('DOMAIN_PROD'), new Map()), /requires async resolution/);
|
|
77
|
+
});
|
|
78
|
+
void it('passes literal domains through untouched', () => {
|
|
79
|
+
assert.strictEqual(resolveDomainNames('example.com', new Map()), 'example.com');
|
|
80
|
+
});
|
|
81
|
+
});
|