@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
package/src/cdk/index.ts
CHANGED
|
@@ -16,8 +16,15 @@ import { setupBlocksInfra, BlocksBackend, assertCdkConditionActive } from './blo
|
|
|
16
16
|
import { addBlocksStackMetadata } from './stack-metadata.js';
|
|
17
17
|
import { finalizeConfigRegistry } from './config-registry.js';
|
|
18
18
|
import { type BlocksDefaults, BlocksPresets } from './blocks-defaults.js';
|
|
19
|
+
import type { Compute } from './compute/compute.js';
|
|
20
|
+
import type { DefaultComputeFactory, LambdaShapedCompute } from './compute/default-compute-factory.js';
|
|
19
21
|
|
|
20
|
-
export {
|
|
22
|
+
export {
|
|
23
|
+
BlocksBackend,
|
|
24
|
+
type BlocksBackendProps,
|
|
25
|
+
type CoreBlocksBackendProps,
|
|
26
|
+
SHARED_HANDLER_TIMEOUT_SECONDS,
|
|
27
|
+
} from './blocks-backend.js';
|
|
21
28
|
export { DEFAULT_NODE_RUNTIME } from './node-version.js';
|
|
22
29
|
export { blocksNodejsBundling } from './bundling.js';
|
|
23
30
|
export { SandboxDisableDeletionProtection } from './mixins.js';
|
|
@@ -30,16 +37,51 @@ export { synthGuard } from './synth-guard.js';
|
|
|
30
37
|
export type { ScopeOptions } from '../index.js';
|
|
31
38
|
export { ApiError, isBlocksError, hasAuthError, DEFAULT_API_ERROR_NAME } from '../errors.js';
|
|
32
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Core's `create()` props: the public {@link BlocksStackProps} plus the required
|
|
42
|
+
* `defaultComputeFactory`. The umbrella (`@aws-blocks/blocks`) supplies the
|
|
43
|
+
* factory (which builds a `LambdaCompute`) by spreading it onto the customer's
|
|
44
|
+
* props; customers use {@link BlocksStackProps} and never set the factory.
|
|
45
|
+
*
|
|
46
|
+
* Kept separate (rather than a `create()` argument) so the factory travels with
|
|
47
|
+
* the props object and core stays free of any concrete compute class.
|
|
48
|
+
*
|
|
49
|
+
* @internal
|
|
50
|
+
*/
|
|
51
|
+
export interface CoreBlocksStackProps extends BlocksStackProps {
|
|
52
|
+
/** Builds the stack's default compute. Injected by `@aws-blocks/blocks`. */
|
|
53
|
+
defaultComputeFactory: DefaultComputeFactory;
|
|
54
|
+
}
|
|
55
|
+
|
|
33
56
|
export class BlocksStack extends cdk.Stack implements BaseBlocksStack {
|
|
34
57
|
public readonly id: string;
|
|
35
|
-
public readonly apiUrl: string;
|
|
36
|
-
public readonly gateway: cdk.aws_apigateway.RestApi;
|
|
37
|
-
public readonly handler: cdk.aws_lambda_nodejs.NodejsFunction;
|
|
38
58
|
public readonly backendHandlerPath: string;
|
|
39
59
|
/** Shared IAM role assumed by all Blocks compute. Building Blocks grant to this role. */
|
|
40
60
|
public readonly executionRole: cdk.aws_iam.IRole;
|
|
41
61
|
/** Infrastructure defaults for Building Blocks created under this stack. */
|
|
42
62
|
public readonly defaults: BlocksDefaults;
|
|
63
|
+
/** The default compute (owns the Lambda function + API Gateway); set in `create()`. @internal */
|
|
64
|
+
_defaultCompute?: Compute;
|
|
65
|
+
|
|
66
|
+
/** The default compute's Lambda function. To be removed once consumers move to the multi-compute model. */
|
|
67
|
+
get handler(): cdk.aws_lambda_nodejs.NodejsFunction {
|
|
68
|
+
return this.requireDefaultCompute().fn;
|
|
69
|
+
}
|
|
70
|
+
/** The default compute's API Gateway REST API. To be removed once consumers move to the multi-compute model. */
|
|
71
|
+
get gateway(): cdk.aws_apigateway.RestApi {
|
|
72
|
+
return this.requireDefaultCompute().apiGateway;
|
|
73
|
+
}
|
|
74
|
+
/** The default compute's RPC endpoint URL. To be removed once consumers move to the multi-compute model. */
|
|
75
|
+
get apiUrl(): string {
|
|
76
|
+
return this.requireDefaultCompute().apiUrl;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private requireDefaultCompute(): LambdaShapedCompute {
|
|
80
|
+
if (!this._defaultCompute) {
|
|
81
|
+
throw new Error('Blocks stack not fully initialized — access .handler/.gateway/.apiUrl after BlocksStack.create() resolves.');
|
|
82
|
+
}
|
|
83
|
+
return this._defaultCompute as LambdaShapedCompute;
|
|
84
|
+
}
|
|
43
85
|
|
|
44
86
|
private constructor(scope: Construct, id: string, props: BlocksStackProps) {
|
|
45
87
|
super(scope, id, props);
|
|
@@ -51,13 +93,10 @@ export class BlocksStack extends cdk.Stack implements BaseBlocksStack {
|
|
|
51
93
|
(globalThis as any).CURRENT_BLOCKS_STACK = this;
|
|
52
94
|
|
|
53
95
|
const infra = setupBlocksInfra(this, props, id);
|
|
54
|
-
this.handler = infra.handler;
|
|
55
|
-
this.gateway = infra.gateway;
|
|
56
|
-
this.apiUrl = infra.apiUrl;
|
|
57
96
|
this.executionRole = infra.executionRole;
|
|
58
97
|
}
|
|
59
98
|
|
|
60
|
-
static async create(scope: Construct, id: string, props:
|
|
99
|
+
static async create(scope: Construct, id: string, props: CoreBlocksStackProps) {
|
|
61
100
|
assertCdkConditionActive();
|
|
62
101
|
|
|
63
102
|
// Detect ambient pipeline stage scope set by Pipeline appFile imports
|
|
@@ -65,6 +104,13 @@ export class BlocksStack extends cdk.Stack implements BaseBlocksStack {
|
|
|
65
104
|
const actualScope = pipelineScope || scope;
|
|
66
105
|
|
|
67
106
|
const stack = new BlocksStack(actualScope, id, props);
|
|
107
|
+
// Create the default compute before importing the backend: it OWNS the
|
|
108
|
+
// Lambda function + API Gateway (which back .handler/.gateway/.apiUrl), and
|
|
109
|
+
// a block reading `this.compute` in its constructor (during that import)
|
|
110
|
+
// must resolve to it. The factory is supplied by the umbrella
|
|
111
|
+
// @aws-blocks/blocks (which injects LambdaCompute) via props, so core never
|
|
112
|
+
// imports the concrete compute class.
|
|
113
|
+
stack._defaultCompute = props.defaultComputeFactory(stack);
|
|
68
114
|
// file:// URL (not a raw path) so the cache-busting query works on Windows,
|
|
69
115
|
// where an absolute path like `D:\...` is rejected as URL scheme `d:`.
|
|
70
116
|
const backendUrl = pathToFileURL(props.backendCDKPath);
|
|
@@ -104,6 +150,15 @@ export class Scope extends Construct {
|
|
|
104
150
|
*/
|
|
105
151
|
private readonly root: BlocksStack | BlocksBackend;
|
|
106
152
|
|
|
153
|
+
/**
|
|
154
|
+
* Compute assigned at this node. Applies to this block and is inherited by
|
|
155
|
+
* descendants (a nearer assignment wins). Covers both a handler assigned to a
|
|
156
|
+
* specific compute and a scope-level default for its subtree. Internal until
|
|
157
|
+
* the customer-facing surface exists.
|
|
158
|
+
* @internal
|
|
159
|
+
*/
|
|
160
|
+
_compute?: Compute;
|
|
161
|
+
|
|
107
162
|
constructor(id: string, options?: ScopeOptions) {
|
|
108
163
|
const parent = options?.parent || (globalThis as any).CURRENT_BLOCKS_STACK;
|
|
109
164
|
super(parent, id);
|
|
@@ -144,6 +199,27 @@ export class Scope extends Construct {
|
|
|
144
199
|
return this.root.executionRole;
|
|
145
200
|
}
|
|
146
201
|
|
|
202
|
+
/**
|
|
203
|
+
* The compute this block runs on: the nearest `_compute` assigned on this
|
|
204
|
+
* block or an ancestor scope, else the owning stack/backend's default compute.
|
|
205
|
+
*
|
|
206
|
+
* For any app that doesn't assign a compute, this always resolves to the
|
|
207
|
+
* default — so reads are a no-op refactor. `_compute` is internal
|
|
208
|
+
* (test/framework) until the customer-facing surface exists; there is no
|
|
209
|
+
* public option to set it yet.
|
|
210
|
+
*/
|
|
211
|
+
get compute(): Compute {
|
|
212
|
+
for (let current: ScopeParent | undefined = this; current; current = (current as Scope).parent) {
|
|
213
|
+
const assigned = (current as Scope)._compute;
|
|
214
|
+
if (assigned) return assigned;
|
|
215
|
+
}
|
|
216
|
+
const defaultCompute = this.root._defaultCompute;
|
|
217
|
+
if (!defaultCompute) {
|
|
218
|
+
throw new Error('Default compute not initialized — BlocksStack/BlocksBackend.create() must run before resolving `compute`.');
|
|
219
|
+
}
|
|
220
|
+
return defaultCompute;
|
|
221
|
+
}
|
|
222
|
+
|
|
147
223
|
/**
|
|
148
224
|
* The backend entry file the owning BlocksStack/BlocksBackend runs — the
|
|
149
225
|
* single handler entry shared across the whole app.
|
package/src/cdk/internal.ts
CHANGED
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
26
|
export { Compute } from './compute/compute.js';
|
|
27
|
+
export type { DefaultComputeFactory } from './compute/default-compute-factory.js';
|
|
27
28
|
// Reserved `/aws-blocks` path segment, needed by concrete computes (e.g.
|
|
28
29
|
// LambdaCompute in @aws-blocks/bb-lambda-compute) to build their API route tree.
|
|
29
30
|
export { BLOCKS_NAMESPACE } from '../constants.js';
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import assert from 'node:assert';
|
|
5
|
+
import { describe, it } from 'node:test';
|
|
6
|
+
import { config, secret } from '@aws-blocks/hosting';
|
|
7
|
+
import {
|
|
8
|
+
collectSynthMarkers,
|
|
9
|
+
partitionEnvironment,
|
|
10
|
+
resolveDomainNames,
|
|
11
|
+
resolveSecretsAtSynth,
|
|
12
|
+
} from './hosting-secrets.js';
|
|
13
|
+
|
|
14
|
+
void describe('partitionEnvironment()', () => {
|
|
15
|
+
void it('splits plain / managed (secret+config)', () => {
|
|
16
|
+
const { plain, managed } = partitionEnvironment({
|
|
17
|
+
FLAG: 'on',
|
|
18
|
+
STRIPE_KEY: secret('STRIPE_KEY'),
|
|
19
|
+
FEATURE_FLAGS: config('FEATURE_FLAGS'),
|
|
20
|
+
});
|
|
21
|
+
assert.deepStrictEqual(plain, { FLAG: 'on' });
|
|
22
|
+
assert.deepStrictEqual(managed.map((m) => `${m.key}:${m.kind}`).sort(), [
|
|
23
|
+
'FEATURE_FLAGS:config',
|
|
24
|
+
'STRIPE_KEY:secret',
|
|
25
|
+
]);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
void it('rejects env key / marker key mismatch', () => {
|
|
29
|
+
assert.throws(
|
|
30
|
+
() => partitionEnvironment({ STRIPE_KEY: secret('OTHER') }),
|
|
31
|
+
/must match the environment variable name/,
|
|
32
|
+
);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
void it('handles undefined', () => {
|
|
36
|
+
const { plain, managed, byo } = partitionEnvironment(undefined);
|
|
37
|
+
assert.deepStrictEqual(plain, {});
|
|
38
|
+
assert.strictEqual(managed.length, 0);
|
|
39
|
+
assert.strictEqual(byo.length, 0);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
void describe('collectSynthMarkers()', () => {
|
|
44
|
+
void it('gathers domain markers, deduped by key', () => {
|
|
45
|
+
const markers = collectSynthMarkers(['example.com', config('DOMAIN_PROD'), config('DOMAIN_PROD')]);
|
|
46
|
+
assert.deepStrictEqual(
|
|
47
|
+
markers.map((m) => m.key),
|
|
48
|
+
['DOMAIN_PROD'],
|
|
49
|
+
);
|
|
50
|
+
});
|
|
51
|
+
void it('returns nothing when no markers', () => {
|
|
52
|
+
assert.deepStrictEqual(collectSynthMarkers('example.com'), []);
|
|
53
|
+
assert.deepStrictEqual(collectSynthMarkers(undefined), []);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
void describe('resolveSecretsAtSynth() — Blocks namespaces', () => {
|
|
58
|
+
void it('config marker resolves under /blocks/config (SSM leading-slash)', async () => {
|
|
59
|
+
const seen: string[] = [];
|
|
60
|
+
const resolved = await resolveSecretsAtSynth([config('DOMAIN_PROD')], async (name) => {
|
|
61
|
+
seen.push(name);
|
|
62
|
+
return 'prod.example.com';
|
|
63
|
+
});
|
|
64
|
+
assert.deepStrictEqual(seen, ['/blocks/config/DOMAIN_PROD']);
|
|
65
|
+
assert.strictEqual(resolved.get('DOMAIN_PROD'), 'prod.example.com');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
void it('secret marker resolves under /blocks/secrets (Secrets Manager slash-free)', async () => {
|
|
69
|
+
const seen: string[] = [];
|
|
70
|
+
await resolveSecretsAtSynth([secret('API_KEY')], async (name) => {
|
|
71
|
+
seen.push(name);
|
|
72
|
+
return 'k';
|
|
73
|
+
});
|
|
74
|
+
assert.deepStrictEqual(seen, ['blocks/secrets/API_KEY']);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
void it('throws an actionable error when a value is not set', async () => {
|
|
78
|
+
await assert.rejects(
|
|
79
|
+
resolveSecretsAtSynth([config('DOMAIN_PROD')], async () => {
|
|
80
|
+
const e = new Error('not found');
|
|
81
|
+
e.name = 'ParameterNotFound';
|
|
82
|
+
throw e;
|
|
83
|
+
}),
|
|
84
|
+
/config 'DOMAIN_PROD' is referenced/,
|
|
85
|
+
);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
void describe('resolveDomainNames()', () => {
|
|
90
|
+
void it('replaces markers with resolved literals, preserving shape', () => {
|
|
91
|
+
const resolved = new Map([['DOMAIN_PROD', 'prod.example.com']]);
|
|
92
|
+
assert.strictEqual(resolveDomainNames(config('DOMAIN_PROD'), resolved), 'prod.example.com');
|
|
93
|
+
assert.deepStrictEqual(resolveDomainNames(['www.example.com', config('DOMAIN_PROD')], resolved), [
|
|
94
|
+
'www.example.com',
|
|
95
|
+
'prod.example.com',
|
|
96
|
+
]);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
void it('throws if a marker reached the sync path unresolved', () => {
|
|
100
|
+
assert.throws(() => resolveDomainNames(config('DOMAIN_PROD'), new Map()), /requires async resolution/);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
void it('passes literal domains through untouched', () => {
|
|
104
|
+
assert.strictEqual(resolveDomainNames('example.com', new Map()), 'example.com');
|
|
105
|
+
});
|
|
106
|
+
});
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Resolution glue between the dependency-free `secret()` / `config()` markers
|
|
6
|
+
* (defined in `@aws-blocks/hosting`) and the `Hosting` CDK block.
|
|
7
|
+
*
|
|
8
|
+
* Delegates to the shared `@aws-blocks/hosting` engine, pinning only the Blocks
|
|
9
|
+
* namespaces (`/blocks/secrets`, `/blocks/config`). The store is derived from the
|
|
10
|
+
* marker's kind (`secret` → Secrets Manager, `config` → SSM), and BYO
|
|
11
|
+
* `ISecret`/`IParameter` handles are wired identically.
|
|
12
|
+
*
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import type { ManagedValue } from '@aws-blocks/hosting';
|
|
17
|
+
import {
|
|
18
|
+
type ByoBinding,
|
|
19
|
+
type DomainNameInput as LeafDomainNameInput,
|
|
20
|
+
type EnvValue as LeafEnvValue,
|
|
21
|
+
assertMarkersExistAtSynth as leafAssertMarkersExistAtSynth,
|
|
22
|
+
collectSynthMarkers as leafCollectSynthMarkers,
|
|
23
|
+
partitionEnvironment as leafPartitionEnvironment,
|
|
24
|
+
resolveDomainNames as leafResolveDomainNames,
|
|
25
|
+
resolveSecretsAtSynth as leafResolveSecretsAtSynth,
|
|
26
|
+
type SecretFetcher,
|
|
27
|
+
type StoreConfig,
|
|
28
|
+
wireByo as leafWireByo,
|
|
29
|
+
wireManagedValue as leafWireManagedValue,
|
|
30
|
+
} from '@aws-blocks/hosting/constructs';
|
|
31
|
+
import type * as cdk from 'aws-cdk-lib';
|
|
32
|
+
import { blocksStoreConfig } from './secret-naming.js';
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Layer a caller's per-kind store config over the pinned Blocks defaults. Shallow
|
|
36
|
+
* and per-kind: the Blocks `/blocks/*` prefix stays the default, but any field the
|
|
37
|
+
* app sets (`prefix`, `stage`, `cacheTtlSeconds`) wins.
|
|
38
|
+
*/
|
|
39
|
+
function mergeBlocksStoreConfig(override?: StoreConfig): StoreConfig {
|
|
40
|
+
const base = blocksStoreConfig();
|
|
41
|
+
if (!override) return base;
|
|
42
|
+
return {
|
|
43
|
+
secretStore: { ...base.secretStore, ...override.secretStore },
|
|
44
|
+
configStore: { ...base.configStore, ...override.configStore },
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** A `compute.environment` value: a literal, a managed marker, or a BYO CDK handle. */
|
|
49
|
+
export type EnvValue = LeafEnvValue;
|
|
50
|
+
|
|
51
|
+
/** A custom-domain name: a literal, a managed marker, or a mix in an array. */
|
|
52
|
+
export type DomainNameInput = LeafDomainNameInput;
|
|
53
|
+
|
|
54
|
+
/** Split an environment map into plain literals, managed markers, and BYO handles. */
|
|
55
|
+
export function partitionEnvironment(environment: Record<string, EnvValue> | undefined): {
|
|
56
|
+
plain: Record<string, string>;
|
|
57
|
+
managed: ManagedValue[];
|
|
58
|
+
byo: ByoBinding[];
|
|
59
|
+
} {
|
|
60
|
+
return leafPartitionEnvironment(environment);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Every managed marker requiring a synth-time fetch (domain markers only). */
|
|
64
|
+
export function collectSynthMarkers(domainName: DomainNameInput | undefined): ManagedValue[] {
|
|
65
|
+
return leafCollectSynthMarkers(domainName);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Resolve managed markers to plaintext at synth time under the Blocks namespaces.
|
|
70
|
+
* Throws a clear, actionable error if a referenced value was never set. An optional
|
|
71
|
+
* `storeConfig` overrides the pinned Blocks prefix/stage per kind.
|
|
72
|
+
*/
|
|
73
|
+
export async function resolveSecretsAtSynth(
|
|
74
|
+
markers: ManagedValue[],
|
|
75
|
+
fetcher?: SecretFetcher,
|
|
76
|
+
storeConfig?: StoreConfig,
|
|
77
|
+
): Promise<Map<string, string>> {
|
|
78
|
+
return leafResolveSecretsAtSynth(markers, { ...mergeBlocksStoreConfig(storeConfig), fetcher });
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Resolve domain markers to literals using the synth-resolved value map. */
|
|
82
|
+
export function resolveDomainNames(domainName: DomainNameInput, resolved: Map<string, string>): string | string[] {
|
|
83
|
+
return leafResolveDomainNames(domainName, resolved);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Fail synth (deploy) when a referenced `environment` marker has no value set —
|
|
88
|
+
* existence only, never fetching the value. Uses the Blocks namespaces (with an
|
|
89
|
+
* optional per-kind `storeConfig` override), matching how the values are wired.
|
|
90
|
+
*/
|
|
91
|
+
export async function assertMarkersExistAtSynth(markers: ManagedValue[], storeConfig?: StoreConfig): Promise<void> {
|
|
92
|
+
return leafAssertMarkersExistAtSynth(markers, mergeBlocksStoreConfig(storeConfig));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Wire a runtime managed marker under the Blocks namespace (store from kind). An
|
|
97
|
+
* optional `storeConfig` overrides the pinned prefix/stage/cacheTtlSeconds per kind.
|
|
98
|
+
*/
|
|
99
|
+
export function wireManagedValue(fn: cdk.aws_lambda.Function, marker: ManagedValue, storeConfig?: StoreConfig): void {
|
|
100
|
+
leafWireManagedValue(fn, marker, mergeBlocksStoreConfig(storeConfig));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Wire a runtime BYO handle (grant + inject locator). Honors an optional `storeConfig`. */
|
|
104
|
+
export function wireByo(fn: cdk.aws_lambda.Function, binding: ByoBinding, storeConfig?: StoreConfig): void {
|
|
105
|
+
leafWireByo(fn, binding, mergeBlocksStoreConfig(storeConfig));
|
|
106
|
+
}
|