@aws-blocks/core 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +32 -0
- package/dist/api.test.js +22 -0
- package/dist/bb-utils.d.ts +1 -0
- package/dist/bb-utils.d.ts.map +1 -1
- package/dist/bb-utils.js +3 -0
- package/dist/cdk/apigateway-account.d.ts +33 -0
- package/dist/cdk/apigateway-account.d.ts.map +1 -0
- package/dist/cdk/apigateway-account.js +60 -0
- package/dist/cdk/blocks-backend.d.ts +11 -0
- package/dist/cdk/blocks-backend.d.ts.map +1 -1
- package/dist/cdk/blocks-backend.js +72 -13
- package/dist/cdk/blocks-backend.test.js +88 -1
- package/dist/cdk/blocks-defaults.d.ts +76 -1
- package/dist/cdk/blocks-defaults.d.ts.map +1 -1
- package/dist/cdk/blocks-defaults.js +17 -1
- package/dist/cdk/blocks-defaults.test.js +17 -0
- package/dist/cdk/blocks-stack.test.js +44 -3
- package/dist/cdk/compute/compute-registry.d.ts +19 -0
- package/dist/cdk/compute/compute-registry.d.ts.map +1 -0
- package/dist/cdk/compute/compute-registry.js +38 -0
- package/dist/cdk/compute/compute.d.ts +82 -2
- package/dist/cdk/compute/compute.d.ts.map +1 -1
- package/dist/cdk/compute/compute.js +64 -2
- package/dist/cdk/compute/default-compute-factory.d.ts +1 -0
- package/dist/cdk/compute/default-compute-factory.d.ts.map +1 -1
- package/dist/cdk/config-registry.d.ts +34 -4
- package/dist/cdk/config-registry.d.ts.map +1 -1
- package/dist/cdk/config-registry.js +83 -25
- package/dist/cdk/config-registry.test.d.ts +2 -0
- package/dist/cdk/config-registry.test.d.ts.map +1 -0
- package/dist/cdk/config-registry.test.js +127 -0
- package/dist/cdk/dashboard-registry.d.ts +41 -0
- package/dist/cdk/dashboard-registry.d.ts.map +1 -0
- package/dist/cdk/dashboard-registry.js +61 -0
- package/dist/cdk/index.d.ts +90 -6
- package/dist/cdk/index.d.ts.map +1 -1
- package/dist/cdk/index.js +135 -13
- package/dist/cdk/internal.d.ts +3 -1
- package/dist/cdk/internal.d.ts.map +1 -1
- package/dist/cdk/internal.js +4 -1
- package/dist/cdk/tracer-registry.d.ts +31 -0
- package/dist/cdk/tracer-registry.d.ts.map +1 -0
- package/dist/cdk/tracer-registry.js +49 -0
- package/dist/cdk/vpc-requirements-registry.d.ts +33 -0
- package/dist/cdk/vpc-requirements-registry.d.ts.map +1 -0
- package/dist/cdk/vpc-requirements-registry.js +46 -0
- package/dist/cdk/vpc-types.d.ts +151 -0
- package/dist/cdk/vpc-types.d.ts.map +1 -0
- package/dist/cdk/vpc-types.js +3 -0
- package/dist/cdk/vpc.d.ts +59 -0
- package/dist/cdk/vpc.d.ts.map +1 -0
- package/dist/cdk/vpc.js +298 -0
- package/dist/cdk/vpc.test.d.ts +2 -0
- package/dist/cdk/vpc.test.d.ts.map +1 -0
- package/dist/cdk/vpc.test.js +285 -0
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/common/config.d.ts +34 -0
- package/dist/common/config.d.ts.map +1 -1
- package/dist/common/config.js +45 -3
- package/dist/common/config.test.js +19 -0
- package/dist/common/index.d.ts +8 -0
- package/dist/common/index.d.ts.map +1 -1
- package/dist/errors.d.ts +21 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +25 -0
- package/dist/hosting.d.ts +9 -0
- package/dist/hosting.d.ts.map +1 -1
- package/dist/hosting.js +12 -1
- package/dist/hosting.test.js +63 -1
- package/dist/index.cdk.d.ts +3 -2
- package/dist/index.cdk.d.ts.map +1 -1
- package/dist/index.cdk.js +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/lambda-handler.d.ts +17 -0
- package/dist/lambda-handler.d.ts.map +1 -1
- package/dist/lambda-handler.js +61 -5
- package/dist/lambda-handler.test.js +191 -2
- package/dist/raw-route.d.ts +15 -1
- package/dist/raw-route.d.ts.map +1 -1
- package/dist/raw-route.js +96 -12
- package/dist/raw-route.test.js +332 -1
- package/dist/scripts/dev-server.d.ts.map +1 -1
- package/dist/scripts/dev-server.js +11 -0
- package/dist/scripts/extract-ts-types.d.ts.map +1 -1
- package/dist/scripts/extract-ts-types.js +107 -23
- package/dist/scripts/extract-ts-types.test.js +225 -26
- package/dist/scripts/generate-spec.d.ts.map +1 -1
- package/dist/scripts/generate-spec.js +14 -5
- package/dist/scripts/generate-spec.test.js +93 -0
- package/dist/scripts/sandbox-empty-buckets.test.d.ts +2 -0
- package/dist/scripts/sandbox-empty-buckets.test.d.ts.map +1 -0
- package/dist/scripts/sandbox-empty-buckets.test.js +171 -0
- package/dist/scripts/sandbox.d.ts +54 -0
- package/dist/scripts/sandbox.d.ts.map +1 -1
- package/dist/scripts/sandbox.js +163 -25
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +10 -1
- package/src/api.test.ts +25 -0
- package/src/api.ts +39 -0
- package/src/bb-utils.ts +3 -0
- package/src/cdk/apigateway-account.ts +66 -0
- package/src/cdk/blocks-backend.test.ts +168 -60
- package/src/cdk/blocks-backend.ts +299 -227
- package/src/cdk/blocks-defaults.test.ts +21 -0
- package/src/cdk/blocks-defaults.ts +79 -1
- package/src/cdk/blocks-stack.test.ts +57 -13
- package/src/cdk/compute/compute-registry.ts +45 -0
- package/src/cdk/compute/compute.ts +114 -2
- package/src/cdk/compute/default-compute-factory.ts +1 -0
- package/src/cdk/config-registry.test.ts +149 -0
- package/src/cdk/config-registry.ts +92 -34
- package/src/cdk/dashboard-registry.ts +68 -0
- package/src/cdk/index.ts +427 -256
- package/src/cdk/internal.ts +6 -2
- package/src/cdk/tracer-registry.ts +54 -0
- package/src/cdk/vpc-requirements-registry.ts +63 -0
- package/src/cdk/vpc-types.ts +158 -0
- package/src/cdk/vpc.test.ts +348 -0
- package/src/cdk/vpc.ts +336 -0
- package/src/client/index.ts +1 -1
- package/src/common/config.test.ts +21 -0
- package/src/common/config.ts +47 -3
- package/src/common/index.ts +8 -0
- package/src/errors.ts +26 -0
- package/src/hosting.test.ts +87 -1
- package/src/hosting.ts +24 -1
- package/src/index.cdk.ts +11 -1
- package/src/index.ts +1 -1
- package/src/lambda-handler.test.ts +220 -2
- package/src/lambda-handler.ts +65 -4
- package/src/raw-route.test.ts +427 -1
- package/src/raw-route.ts +125 -12
- package/src/scripts/dev-server.ts +12 -1
- package/src/scripts/extract-ts-types.test.ts +228 -26
- package/src/scripts/extract-ts-types.ts +104 -20
- package/src/scripts/generate-spec.test.ts +101 -0
- package/src/scripts/generate-spec.ts +15 -5
- package/src/scripts/sandbox-empty-buckets.test.ts +191 -0
- package/src/scripts/sandbox.ts +185 -24
- package/src/version.ts +1 -1
package/dist/common/config.js
CHANGED
|
@@ -53,9 +53,13 @@ async function loadConfigFromS3() {
|
|
|
53
53
|
|| error?.Code === 'NoSuchKey'
|
|
54
54
|
|| error?.$metadata?.httpStatusCode === 404;
|
|
55
55
|
if (isNotFound) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
// Do NOT cache the empty result: a 404 right after deploy is usually the config file
|
|
57
|
+
// not being readable yet (the transient window before the BucketDeployment settles), not
|
|
58
|
+
// a genuinely config-less app. Caching {} here would poison the container for its whole
|
|
59
|
+
// lifetime. Returning without caching lets the next invocation re-fetch and pick up the
|
|
60
|
+
// real config once it's present. (Apps that truly have no config just re-check cheaply.)
|
|
61
|
+
console.warn(`[Blocks] Config file not found in S3 (${bucket}/${key}), proceeding with empty config (will retry on next request)`);
|
|
62
|
+
return {};
|
|
59
63
|
}
|
|
60
64
|
const msg = error instanceof Error ? error.message : String(error);
|
|
61
65
|
throw new Error(`[Blocks] Failed to load config from S3 (${bucket}/${key}): ${msg}`);
|
|
@@ -138,6 +142,44 @@ export async function loadConfigToProcessEnv() {
|
|
|
138
142
|
}
|
|
139
143
|
}
|
|
140
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* Whether a config load has resolved and cached a result.
|
|
147
|
+
*
|
|
148
|
+
* Returns `true` once `loadConfigFromS3()` has cached a config object — either a
|
|
149
|
+
* successful S3 load, a genuinely-empty `{}` config, or the no-bucket local-dev
|
|
150
|
+
* path (both of which cache `{}`). Returns `false` in the initial state AND
|
|
151
|
+
* after a transient not-found miss: the 404 path deliberately does NOT cache its
|
|
152
|
+
* empty result (see `loadConfigFromS3`), so a `false` return immediately after
|
|
153
|
+
* awaiting a load uniquely identifies the post-deploy S3 window where
|
|
154
|
+
* blocks-config.json isn't readable yet.
|
|
155
|
+
*
|
|
156
|
+
* Callers use this to tell a transient-empty load (retry on the next request)
|
|
157
|
+
* apart from a legitimately-config-less app (do nothing) without reaching into
|
|
158
|
+
* the module's private cache.
|
|
159
|
+
*/
|
|
160
|
+
export function isConfigResolved() {
|
|
161
|
+
return configCache !== null;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Sanitize a Blocks identifier into a valid config/env-var key segment:
|
|
165
|
+
* uppercase, with every non-alphanumeric character replaced by `_`.
|
|
166
|
+
*
|
|
167
|
+
* Config entries are loaded into `process.env` at runtime (see
|
|
168
|
+
* {@link loadConfigToProcessEnv}), so a key must be a valid env-var name. This
|
|
169
|
+
* is the single rule both sides of a key share: whoever *writes* a config key
|
|
170
|
+
* (`registerConfig(\`PREFIX_${sanitizeConfigKey(id)}\`, …)`) and whoever *reads*
|
|
171
|
+
* it (`getConfigSync(\`PREFIX_${sanitizeConfigKey(id)}\`)`) MUST go through this
|
|
172
|
+
* function so they reconstruct a byte-identical key — a hand-inlined variant
|
|
173
|
+
* that drifts silently misses the lookup at runtime.
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```typescript
|
|
177
|
+
* registerConfig(this, `BLOCKS_QUEUE_URL_${sanitizeConfigKey(this.fullId)}`, url);
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
export function sanitizeConfigKey(id) {
|
|
181
|
+
return id.toUpperCase().replace(/[^A-Z0-9]/g, '_');
|
|
182
|
+
}
|
|
141
183
|
/**
|
|
142
184
|
* Reset the config cache. **For testing only.**
|
|
143
185
|
*/
|
|
@@ -101,6 +101,25 @@ describe('config — S3 errors', () => {
|
|
|
101
101
|
const result = await getConfig('ANY_KEY');
|
|
102
102
|
assert.strictEqual(result, '', 'Should return empty string (empty config) on 404');
|
|
103
103
|
});
|
|
104
|
+
it('does not cache a not-found result — a later call re-fetches once the config exists', async () => {
|
|
105
|
+
process.env.BLOCKS_CONFIG_BUCKET = 'test-bucket';
|
|
106
|
+
process.env.BLOCKS_CONFIG_KEY = 'blocks-config.json';
|
|
107
|
+
// Simulate the transient post-deploy window: the object isn't written yet on the first
|
|
108
|
+
// fetch, then becomes available. A not-found result must NOT be cached, or the container
|
|
109
|
+
// would be poisoned with empty config for its lifetime.
|
|
110
|
+
let call = 0;
|
|
111
|
+
const notFound = new Error('The specified key does not exist.');
|
|
112
|
+
notFound.name = 'NoSuchKey';
|
|
113
|
+
_setS3Fetcher(async () => {
|
|
114
|
+
call++;
|
|
115
|
+
if (call === 1)
|
|
116
|
+
throw notFound;
|
|
117
|
+
return JSON.stringify({ READY_KEY: 'ready-value' });
|
|
118
|
+
});
|
|
119
|
+
assert.strictEqual(await getConfig('READY_KEY'), '', 'first call sees the not-yet-written config as empty');
|
|
120
|
+
assert.strictEqual(await getConfig('READY_KEY'), 'ready-value', 'later call re-fetches once the config exists');
|
|
121
|
+
assert.strictEqual(call, 2, 'a not-found result must not be cached — S3 is retried');
|
|
122
|
+
});
|
|
104
123
|
it('throws with clear message on S3 network error', async () => {
|
|
105
124
|
process.env.BLOCKS_CONFIG_BUCKET = 'test-bucket';
|
|
106
125
|
process.env.BLOCKS_CONFIG_KEY = 'blocks-config.json';
|
package/dist/common/index.d.ts
CHANGED
|
@@ -224,6 +224,14 @@ export interface BlocksStackProps extends StackProps {
|
|
|
224
224
|
}
|
|
225
225
|
export declare class BlocksStack {
|
|
226
226
|
readonly id: string;
|
|
227
|
+
/**
|
|
228
|
+
* Path to the app's backend module (`props.backendCDKPath`). A typed contract for Building
|
|
229
|
+
* Blocks that co-bundle the backend at synth time and read it off
|
|
230
|
+
* `globalThis.CURRENT_BLOCKS_STACK` (the CDK `BlocksStack` / `BlocksBackend` set it). Declared
|
|
231
|
+
* here so those consumers can type against this shared `BlocksStack` contract — which the CDK
|
|
232
|
+
* `BlocksStack` / `BlocksBackend` implements — instead of `any`.
|
|
233
|
+
*/
|
|
234
|
+
readonly backendModulePath: string;
|
|
227
235
|
constructor(scope: Construct, id: string, props: BlocksStackProps);
|
|
228
236
|
}
|
|
229
237
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/common/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAGhE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAErE,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsGG;AAEH;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IACjC,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC3B;AAED,qBAAa,KAAK;IAChB,SAAgB,EAAE,EAAE,MAAM,CAAC;IAC3B,SAAgB,MAAM,EAAE,WAAW,CAAC;IAEpC,qEAAqE;IACrE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,2EAA2E;IAC3E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAE5B,kEAAkE;IAClE,OAAO,CAAC,MAAM,CAAC,WAAW,CAA8D;gBAE5E,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;IAiB9C;;;;;;;;OAQG;IACH,MAAM,CAAC,mBAAmB,IAAI;QAAE,MAAM,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAA;KAAE;IAejI,2CAA2C;IAC3C,MAAM,CAAC,cAAc,IAAI,IAAI;IAI7B,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED;;;;;;;;;;OAUG;IACH,0BAA0B,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAOlH;;;;OAIG;IACH,wBAAwB,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI;IAIxD;;;;;;;;;;OAUG;IACH,qBAAqB,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI;IAIrD;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,SAAS,CAAC,mBAAmB,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE;CAapD;AA0CD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,GAAG,CAAA;CAAE,UAUrE;AAED,MAAM,WAAW,gBAAiB,SAAQ,UAAU;IAClD,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB;;;;;;OAMG;IACH,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAED,qBAAa,WAAW;IACvB,SAAgB,EAAE,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/common/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAGhE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAErE,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsGG;AAEH;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IACjC,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC3B;AAED,qBAAa,KAAK;IAChB,SAAgB,EAAE,EAAE,MAAM,CAAC;IAC3B,SAAgB,MAAM,EAAE,WAAW,CAAC;IAEpC,qEAAqE;IACrE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,2EAA2E;IAC3E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAE5B,kEAAkE;IAClE,OAAO,CAAC,MAAM,CAAC,WAAW,CAA8D;gBAE5E,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;IAiB9C;;;;;;;;OAQG;IACH,MAAM,CAAC,mBAAmB,IAAI;QAAE,MAAM,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAA;KAAE;IAejI,2CAA2C;IAC3C,MAAM,CAAC,cAAc,IAAI,IAAI;IAI7B,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED;;;;;;;;;;OAUG;IACH,0BAA0B,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAOlH;;;;OAIG;IACH,wBAAwB,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI;IAIxD;;;;;;;;;;OAUG;IACH,qBAAqB,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI;IAIrD;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,SAAS,CAAC,mBAAmB,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE;CAapD;AA0CD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,GAAG,CAAA;CAAE,UAUrE;AAED,MAAM,WAAW,gBAAiB,SAAQ,UAAU;IAClD,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB;;;;;;OAMG;IACH,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAED,qBAAa,WAAW;IACvB,SAAgB,EAAE,EAAE,MAAM,CAAC;IAC3B;;;;;;OAMG;IACH,SAAiB,iBAAiB,EAAE,MAAM,CAAC;gBAC/B,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB;CAGjE"}
|
package/dist/errors.d.ts
CHANGED
|
@@ -44,6 +44,11 @@ export declare class ApiError extends Error {
|
|
|
44
44
|
* when `retriable === true`; non-retriable errors (expired session,
|
|
45
45
|
* tampered envelope, too-many-attempts lockouts) require restarting the
|
|
46
46
|
* flow. Defaults to `false` when unspecified.
|
|
47
|
+
*
|
|
48
|
+
* This marks whether the *kind* of failure is retriable in principle, not a
|
|
49
|
+
* guarantee that a given retry will succeed — e.g. an optimistic-lock
|
|
50
|
+
* conflict against a missing row is flagged retriable, yet a blind retry
|
|
51
|
+
* fails identically.
|
|
47
52
|
*/
|
|
48
53
|
readonly retriable: boolean;
|
|
49
54
|
constructor(message: string, status: number, options?: {
|
|
@@ -70,6 +75,22 @@ export declare class ApiError extends Error {
|
|
|
70
75
|
export declare function isBlocksError<N extends string>(e: unknown, name: N): e is Error & {
|
|
71
76
|
name: N;
|
|
72
77
|
};
|
|
78
|
+
/**
|
|
79
|
+
* Build a named `Error` whose `name` is a BB error constant, so it is matchable
|
|
80
|
+
* with {@link isBlocksError} on both server and client. The name is also
|
|
81
|
+
* prefixed into the message for readable logs.
|
|
82
|
+
*
|
|
83
|
+
* This is the producer half of the {@link isBlocksError} contract: throw via
|
|
84
|
+
* this helper so the `name` a consumer matches on is set consistently. It has
|
|
85
|
+
* no runtime dependencies, so it is safe to use in every bundle — mock,
|
|
86
|
+
* aws-runtime, and CDK synth.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```typescript
|
|
90
|
+
* throw blocksError(KVStoreErrors.ConditionalCheckFailed, 'Key already exists');
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
export declare function blocksError(name: string, message: string): Error;
|
|
73
94
|
/**
|
|
74
95
|
* Type guard for branching on a failed `AuthState` (the recommended
|
|
75
96
|
* `setAuthState` client path) by its structured `errorName`.
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,aAAa,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,QAAS,SAAQ,KAAK;IAClC,wBAAwB;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,aAAa,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,QAAS,SAAQ,KAAK;IAClC,wBAAwB;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;gBAEhB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE;CAM9G;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,GAAG;IAAE,IAAI,EAAE,CAAC,CAAA;CAAE,CAE7F;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,KAAK,CAIhE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,SAAS,MAAM,EAC9E,KAAK,EAAE,CAAC,GAAG,IAAI,GAAG,SAAS,EAC3B,IAAI,EAAE,CAAC,GACL,KAAK,IAAI,CAAC,GAAG;IAAE,SAAS,EAAE,CAAC,CAAA;CAAE,CAE/B"}
|
package/dist/errors.js
CHANGED
|
@@ -46,6 +46,11 @@ export class ApiError extends Error {
|
|
|
46
46
|
* when `retriable === true`; non-retriable errors (expired session,
|
|
47
47
|
* tampered envelope, too-many-attempts lockouts) require restarting the
|
|
48
48
|
* flow. Defaults to `false` when unspecified.
|
|
49
|
+
*
|
|
50
|
+
* This marks whether the *kind* of failure is retriable in principle, not a
|
|
51
|
+
* guarantee that a given retry will succeed — e.g. an optimistic-lock
|
|
52
|
+
* conflict against a missing row is flagged retriable, yet a blind retry
|
|
53
|
+
* fails identically.
|
|
49
54
|
*/
|
|
50
55
|
retriable;
|
|
51
56
|
constructor(message, status, options) {
|
|
@@ -73,6 +78,26 @@ export class ApiError extends Error {
|
|
|
73
78
|
export function isBlocksError(e, name) {
|
|
74
79
|
return e instanceof Error && e.name === name;
|
|
75
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Build a named `Error` whose `name` is a BB error constant, so it is matchable
|
|
83
|
+
* with {@link isBlocksError} on both server and client. The name is also
|
|
84
|
+
* prefixed into the message for readable logs.
|
|
85
|
+
*
|
|
86
|
+
* This is the producer half of the {@link isBlocksError} contract: throw via
|
|
87
|
+
* this helper so the `name` a consumer matches on is set consistently. It has
|
|
88
|
+
* no runtime dependencies, so it is safe to use in every bundle — mock,
|
|
89
|
+
* aws-runtime, and CDK synth.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```typescript
|
|
93
|
+
* throw blocksError(KVStoreErrors.ConditionalCheckFailed, 'Key already exists');
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
export function blocksError(name, message) {
|
|
97
|
+
const err = new Error(`${name}: ${message}`);
|
|
98
|
+
err.name = name;
|
|
99
|
+
return err;
|
|
100
|
+
}
|
|
76
101
|
/**
|
|
77
102
|
* Type guard for branching on a failed `AuthState` (the recommended
|
|
78
103
|
* `setAuthState` client path) by its structured `errorName`.
|
package/dist/hosting.d.ts
CHANGED
|
@@ -209,6 +209,15 @@ export interface HostingProps {
|
|
|
209
209
|
waf?: HostingWafConfig;
|
|
210
210
|
/** Retain the S3 bucket when the stack is deleted. Default: false. */
|
|
211
211
|
retainOnDelete?: boolean;
|
|
212
|
+
/**
|
|
213
|
+
* Days to retain SUPERSEDED build artifacts in S3 before they are expired.
|
|
214
|
+
* Default: 30. The build currently referenced by CloudFront KVS (`meta.b`)
|
|
215
|
+
* is NEVER expired regardless of this value — only builds that have been
|
|
216
|
+
* replaced by a newer deploy are cleaned up (issue #480). Raise this to keep
|
|
217
|
+
* a longer rollback window. Must be at least `skewProtection.maxAge`
|
|
218
|
+
* (converted to days), or synth throws `InvalidSkewProtectionMaxAgeError`.
|
|
219
|
+
*/
|
|
220
|
+
buildRetentionDays?: number;
|
|
212
221
|
/** Custom Content-Security-Policy header value. */
|
|
213
222
|
contentSecurityPolicy?: string;
|
|
214
223
|
/** CloudFront price class. Default: PRICE_CLASS_100. */
|
package/dist/hosting.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hosting.d.ts","sourceRoot":"","sources":["../src/hosting.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"hosting.d.ts","sourceRoot":"","sources":["../src/hosting.ts"],"names":[],"mappings":"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"}
|
package/dist/hosting.js
CHANGED
|
@@ -267,7 +267,16 @@ export class Hosting extends Construct {
|
|
|
267
267
|
environment: Object.keys(plainEnv).length ? plainEnv : undefined,
|
|
268
268
|
domain: resolvedDomain,
|
|
269
269
|
waf: props.waf,
|
|
270
|
-
storage: props.retainOnDelete != null
|
|
270
|
+
storage: props.retainOnDelete != null || props.buildRetentionDays != null
|
|
271
|
+
? {
|
|
272
|
+
...(props.retainOnDelete != null
|
|
273
|
+
? { retainOnDelete: props.retainOnDelete }
|
|
274
|
+
: {}),
|
|
275
|
+
...(props.buildRetentionDays != null
|
|
276
|
+
? { buildRetentionDays: props.buildRetentionDays }
|
|
277
|
+
: {}),
|
|
278
|
+
}
|
|
279
|
+
: undefined,
|
|
271
280
|
cdn: props.contentSecurityPolicy || props.priceClass || props.geoRestriction || props.quotas
|
|
272
281
|
? {
|
|
273
282
|
contentSecurityPolicy: props.contentSecurityPolicy,
|
|
@@ -356,6 +365,8 @@ export class Hosting extends Construct {
|
|
|
356
365
|
for (const dep of assetDeployments) {
|
|
357
366
|
configDeployment.node.addDependency(dep);
|
|
358
367
|
}
|
|
368
|
+
// Delay route cutover until resolved config replaces the static placeholder.
|
|
369
|
+
hosting.addBuildAssetDependency(configDeployment);
|
|
359
370
|
}
|
|
360
371
|
// ── 9. Register public origin + CORS hosting origin into S3 config ──
|
|
361
372
|
// The Handler no longer depends on the BucketDeployment, so including
|
package/dist/hosting.test.js
CHANGED
|
@@ -12,7 +12,7 @@ import { App, Duration, Stack } from 'aws-cdk-lib';
|
|
|
12
12
|
import { Match, Template } from 'aws-cdk-lib/assertions';
|
|
13
13
|
import { BLOCKS_RPC_PREFIX } from './constants.js';
|
|
14
14
|
import { Hosting } from './hosting.js';
|
|
15
|
-
import { clearRouteRegistry, registerRoute } from './raw-route.js';
|
|
15
|
+
import { clearRouteRegistry, compilePath, registerRoute } from './raw-route.js';
|
|
16
16
|
// ================================================================
|
|
17
17
|
// Hosting construct tests
|
|
18
18
|
//
|
|
@@ -372,6 +372,30 @@ describe('Hosting', () => {
|
|
|
372
372
|
}
|
|
373
373
|
assert.ok(foundRetain, 'At least one bucket should have Retain deletion policy');
|
|
374
374
|
});
|
|
375
|
+
it('forwards buildRetentionDays to the hosting bucket lifecycle rule (#480)', () => {
|
|
376
|
+
createSpaBuildOutput(tmpDir);
|
|
377
|
+
const app = new App();
|
|
378
|
+
const stack = new Stack(app, 'RetentionStack');
|
|
379
|
+
new Hosting(stack, 'Hosting', {
|
|
380
|
+
root: tmpDir,
|
|
381
|
+
api: MOCK_API,
|
|
382
|
+
buildRetentionDays: 90,
|
|
383
|
+
});
|
|
384
|
+
const template = Template.fromStack(stack);
|
|
385
|
+
// Before the fix, core dropped buildRetentionDays (only retainOnDelete was
|
|
386
|
+
// forwarded), so this asserted 30. It must now reach the DeleteOldBuilds
|
|
387
|
+
// rule as 90.
|
|
388
|
+
template.hasResourceProperties('AWS::S3::Bucket', {
|
|
389
|
+
LifecycleConfiguration: Match.objectLike({
|
|
390
|
+
Rules: Match.arrayWith([
|
|
391
|
+
Match.objectLike({
|
|
392
|
+
Id: 'DeleteOldBuilds',
|
|
393
|
+
ExpirationInDays: 90,
|
|
394
|
+
}),
|
|
395
|
+
]),
|
|
396
|
+
}),
|
|
397
|
+
});
|
|
398
|
+
});
|
|
375
399
|
});
|
|
376
400
|
// ── API integration tests ────────────────────────────────────
|
|
377
401
|
describe('API integration', () => {
|
|
@@ -528,6 +552,38 @@ describe('Hosting', () => {
|
|
|
528
552
|
assert.ok(patterns.includes('/health'), 'Should have /health behavior for RawRoute');
|
|
529
553
|
assert.ok(patterns.includes('/users/*'), 'Should have /users/* behavior for parameterized RawRoute');
|
|
530
554
|
});
|
|
555
|
+
it('adds a CloudFront behavior for a route another core copy registered', () => {
|
|
556
|
+
createSpaBuildOutput(tmpDir);
|
|
557
|
+
// Synth has the same split as dispatch: a bundle can hold more than one
|
|
558
|
+
// copy of @aws-blocks/core, and this loop reads whichever route table
|
|
559
|
+
// its own copy owns. Register the way a second copy would — straight
|
|
560
|
+
// into the shared state, not through this copy's registerRoute() — and
|
|
561
|
+
// the behavior must still be emitted. With a module-local registry it
|
|
562
|
+
// never is, and the route 404s at CloudFront before Lambda is reached.
|
|
563
|
+
const REGISTRY_KEY = '__AWS_BLOCKS_RAW_ROUTE_REGISTRY_V1__';
|
|
564
|
+
const state = globalThis[REGISTRY_KEY];
|
|
565
|
+
assert.ok(state, `route registry state must live on globalThis['${REGISTRY_KEY}']`);
|
|
566
|
+
const { pattern, paramNames } = compilePath('/from-other-copy');
|
|
567
|
+
state.routes.push({
|
|
568
|
+
method: 'GET',
|
|
569
|
+
path: '/from-other-copy',
|
|
570
|
+
pattern,
|
|
571
|
+
paramNames,
|
|
572
|
+
handler: async () => { },
|
|
573
|
+
});
|
|
574
|
+
const app = new App();
|
|
575
|
+
const stack = new Stack(app, 'ForeignRouteBehaviorStack');
|
|
576
|
+
new Hosting(stack, 'Hosting', {
|
|
577
|
+
root: tmpDir,
|
|
578
|
+
api: MOCK_API,
|
|
579
|
+
});
|
|
580
|
+
const template = Template.fromStack(stack);
|
|
581
|
+
const distributions = template.findResources('AWS::CloudFront::Distribution');
|
|
582
|
+
const distKeys = Object.keys(distributions);
|
|
583
|
+
const distConfig = distributions[distKeys[0]].Properties.DistributionConfig;
|
|
584
|
+
const patterns = (distConfig.CacheBehaviors ?? []).map((b) => b.PathPattern);
|
|
585
|
+
assert.ok(patterns.includes('/from-other-copy'), `synth must see routes from every core copy, got: ${JSON.stringify(patterns)}`);
|
|
586
|
+
});
|
|
531
587
|
it('proxies the reserved /aws-blocks/auth subtree with a single behavior', () => {
|
|
532
588
|
createSpaBuildOutput(tmpDir);
|
|
533
589
|
// A route under the auth subtree (as the auth runtime would mount) must
|
|
@@ -1158,6 +1214,12 @@ describe('Hosting', () => {
|
|
|
1158
1214
|
const assetDeps = dependsOn.filter((d) => /AssetDeployment/.test(d));
|
|
1159
1215
|
assert.ok(assetDeps.length >= 1, `BlocksConfigDeployment must DependsOn the asset deployment(s); ` +
|
|
1160
1216
|
`found DependsOn=${JSON.stringify(dependsOn)}`);
|
|
1217
|
+
const routeCutoverId = Object.entries(tpl.Resources).find(([id, resource]) => resource.Type === 'AWS::CloudFormation::CustomResource' &&
|
|
1218
|
+
/RouteStoreKeys/.test(id))?.[0];
|
|
1219
|
+
assert.ok(routeCutoverId, 'expected a RouteStoreKeys cutover resource');
|
|
1220
|
+
const routeCutoverDeps = tpl.Resources[routeCutoverId].DependsOn ?? [];
|
|
1221
|
+
assert.ok(routeCutoverDeps.includes(configId), `RouteStoreKeys must DependsOn BlocksConfigDeployment; ` +
|
|
1222
|
+
`found DependsOn=${JSON.stringify(routeCutoverDeps)}`);
|
|
1161
1223
|
});
|
|
1162
1224
|
});
|
|
1163
1225
|
// ── value() integration ─────────────────────────────────────────
|
package/dist/index.cdk.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
export { type ConfigValue, config, DEFAULT_CONFIG_PARAMETER_PREFIX, DEFAULT_SECRET_PARAMETER_PREFIX, isConfig, isManagedValue, isSecret, type ManagedValue, type SecretValue, secret, type ValueKind, } from '@aws-blocks/hosting';
|
|
2
2
|
export { type ApiHandler, ApiNamespace, type BlocksContext } from './api.js';
|
|
3
|
-
export
|
|
3
|
+
export type { BlocksVpcOptions, ScopeOptions, SubnetRole, VpcContext, VpcRequirements } from './cdk/index.js';
|
|
4
|
+
export { BlocksBackend, type BlocksBackendProps, type BlocksDefaults, BlocksPresets, BlocksStack, type BlocksThrottling, BuildingBlockScope, blocksNodejsBundling, type CoreBlocksBackendProps, type CoreBlocksStackProps, DEFAULT_NODE_RUNTIME, ensureApiGatewayAccount, finalizeConfigRegistry, finalizeDashboards, finalizeTracing, getConfigLocation, getVpcContext, registerConfig, registerDashboardFinalizer, registerTracer, SandboxDisableDeletionProtection, Scope, SHARED_HANDLER_TIMEOUT_SECONDS, synthGuard, } from './cdk/index.js';
|
|
4
5
|
export { _resetConfigCache, getConfig, getConfigSync, loadConfigToProcessEnv, preloadConfig } from './common/config.js';
|
|
5
6
|
export { BlocksStackProps } from './common/index.js';
|
|
6
7
|
export { _resetSdkRegistry, getAllSdkIdentifiers, getSdkIdentifiers, registerSdkIdentifiers, } from './common/sdk-registry.js';
|
|
7
8
|
export { BLOCKS_AUTH_PREFIX, BLOCKS_RPC_PREFIX } from './constants.js';
|
|
8
|
-
export { ApiError, DEFAULT_API_ERROR_NAME, hasAuthError, isBlocksError } from './errors.js';
|
|
9
|
+
export { ApiError, blocksError, DEFAULT_API_ERROR_NAME, hasAuthError, isBlocksError } from './errors.js';
|
|
9
10
|
export { type BlocksStackApi, type ComputeConfig, type FrameworkType, Hosting, type HostingDomainConfig, type HostingProps, type HostingWafConfig, } from './hosting.js';
|
|
10
11
|
export { EventSourceMapping } from './lambda-handler.js';
|
|
11
12
|
export { __PIPELINE_STAGE_SCOPE__, type BranchConfig, DeployStage, type DeployStageProps, Pipeline, type PipelineProps, type PipelineSourceConfig, type PipelineStageConfig, type PipelineSynthConfig, } from './pipeline/index.js';
|
package/dist/index.cdk.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cdk.d.ts","sourceRoot":"","sources":["../src/index.cdk.ts"],"names":[],"mappings":"AAMA,OAAO,EACN,KAAK,WAAW,EAChB,MAAM,EACN,+BAA+B,EAC/B,+BAA+B,EAC/B,QAAQ,EACR,cAAc,EACd,QAAQ,EACR,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,MAAM,EACN,KAAK,SAAS,GACd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,KAAK,UAAU,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAC7E,OAAO,EACN,aAAa,EACb,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,aAAa,EACb,WAAW,EACX,oBAAoB,EACpB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,oBAAoB,EACpB,sBAAsB,EACtB,cAAc,EACd,gCAAgC,EAChC,KAAK,EACL,8BAA8B,EAC9B,UAAU,GACV,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,aAAa,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxH,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EACN,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,sBAAsB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,sBAAsB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.cdk.d.ts","sourceRoot":"","sources":["../src/index.cdk.ts"],"names":[],"mappings":"AAMA,OAAO,EACN,KAAK,WAAW,EAChB,MAAM,EACN,+BAA+B,EAC/B,+BAA+B,EAC/B,QAAQ,EACR,cAAc,EACd,QAAQ,EACR,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,MAAM,EACN,KAAK,SAAS,GACd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,KAAK,UAAU,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAC7E,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC9G,OAAO,EACN,aAAa,EACb,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,aAAa,EACb,WAAW,EACX,KAAK,gBAAgB,EACrB,kBAAkB,EAClB,oBAAoB,EACpB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EACtB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,0BAA0B,EAC1B,cAAc,EACd,gCAAgC,EAChC,KAAK,EACL,8BAA8B,EAC9B,UAAU,GACV,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,aAAa,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxH,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EACN,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,sBAAsB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,sBAAsB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACzG,OAAO,EACN,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,OAAO,EACP,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,gBAAgB,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EACN,wBAAwB,EACxB,KAAK,YAAY,EACjB,WAAW,EACX,KAAK,gBAAgB,EACrB,QAAQ,EACR,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,GACxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,KAAK,UAAU,EACf,QAAQ,EACR,cAAc,EACd,KAAK,eAAe,GACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACN,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,UAAU,EACV,KAAK,eAAe,EACpB,aAAa,EACb,mBAAmB,GACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACN,8BAA8B,EAC9B,8BAA8B,EAC9B,yBAAyB,EACzB,yBAAyB,GACzB,MAAM,oBAAoB,CAAC"}
|
package/dist/index.cdk.js
CHANGED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
// getConfig (backend config loader, above) owns that name here.
|
|
6
6
|
export { config, DEFAULT_CONFIG_PARAMETER_PREFIX, DEFAULT_SECRET_PARAMETER_PREFIX, isConfig, isManagedValue, isSecret, secret, } from '@aws-blocks/hosting';
|
|
7
7
|
export { ApiNamespace } from './api.js';
|
|
8
|
-
export { BlocksBackend, BlocksPresets, BlocksStack, blocksNodejsBundling, DEFAULT_NODE_RUNTIME, finalizeConfigRegistry, registerConfig, SandboxDisableDeletionProtection, Scope, SHARED_HANDLER_TIMEOUT_SECONDS, synthGuard, } from './cdk/index.js';
|
|
8
|
+
export { BlocksBackend, BlocksPresets, BlocksStack, BuildingBlockScope, blocksNodejsBundling, DEFAULT_NODE_RUNTIME, ensureApiGatewayAccount, finalizeConfigRegistry, finalizeDashboards, finalizeTracing, getConfigLocation, getVpcContext, registerConfig, registerDashboardFinalizer, registerTracer, SandboxDisableDeletionProtection, Scope, SHARED_HANDLER_TIMEOUT_SECONDS, synthGuard, } from './cdk/index.js';
|
|
9
9
|
export { _resetConfigCache, getConfig, getConfigSync, loadConfigToProcessEnv, preloadConfig } from './common/config.js';
|
|
10
10
|
export { _resetSdkRegistry, getAllSdkIdentifiers, getSdkIdentifiers, registerSdkIdentifiers, } from './common/sdk-registry.js';
|
|
11
11
|
export { BLOCKS_AUTH_PREFIX, BLOCKS_RPC_PREFIX } from './constants.js';
|
|
12
|
-
export { ApiError, DEFAULT_API_ERROR_NAME, hasAuthError, isBlocksError } from './errors.js';
|
|
12
|
+
export { ApiError, blocksError, DEFAULT_API_ERROR_NAME, hasAuthError, isBlocksError } from './errors.js';
|
|
13
13
|
export { Hosting, } from './hosting.js';
|
|
14
14
|
export { EventSourceMapping } from './lambda-handler.js';
|
|
15
15
|
export { __PIPELINE_STAGE_SCOPE__, DeployStage, Pipeline, } from './pipeline/index.js';
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export { _resetConfigCache, getConfig, getConfigSync, loadConfigToProcessEnv, pr
|
|
|
4
4
|
export { type BuildingBlockMeta, Scope, type ScopeOptions, type ScopeParent } from './common/index.js';
|
|
5
5
|
export { _resetSdkRegistry, getAllSdkIdentifiers, getSdkIdentifiers, registerSdkIdentifiers, } from './common/sdk-registry.js';
|
|
6
6
|
export { BLOCKS_AUTH_PREFIX, BLOCKS_RPC_PREFIX } from './constants.js';
|
|
7
|
-
export { ApiError, DEFAULT_API_ERROR_NAME, hasAuthError, isBlocksError } from './errors.js';
|
|
7
|
+
export { ApiError, blocksError, DEFAULT_API_ERROR_NAME, hasAuthError, isBlocksError } from './errors.js';
|
|
8
8
|
export { clearRouteRegistry, getRegisteredRoutes, type HttpMethod, lockRouteRegistry, matchRoute, RawRouteErrors, type RawRouteOptions, type RegisteredRoute, registerRoute, unlockRouteRegistry, } from './raw-route.js';
|
|
9
9
|
export { RawRoute } from './raw-route.mock.js';
|
|
10
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EACN,KAAK,WAAW,EAChB,MAAM,EACN,QAAQ,EACR,cAAc,EACd,QAAQ,EACR,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,MAAM,EACN,KAAK,SAAS,GACd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,KAAK,UAAU,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,aAAa,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxH,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACvG,OAAO,EACN,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,sBAAsB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,sBAAsB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EACN,KAAK,WAAW,EAChB,MAAM,EACN,QAAQ,EACR,cAAc,EACd,QAAQ,EACR,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,MAAM,EACN,KAAK,SAAS,GACd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,KAAK,UAAU,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,aAAa,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxH,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACvG,OAAO,EACN,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,sBAAsB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,sBAAsB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACzG,OAAO,EACN,kBAAkB,EAClB,mBAAmB,EACnB,KAAK,UAAU,EACf,iBAAiB,EACjB,UAAU,EACV,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,aAAa,EACb,mBAAmB,GACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,6 @@ export { _resetConfigCache, getConfig, getConfigSync, loadConfigToProcessEnv, pr
|
|
|
9
9
|
export { Scope } from './common/index.js';
|
|
10
10
|
export { _resetSdkRegistry, getAllSdkIdentifiers, getSdkIdentifiers, registerSdkIdentifiers, } from './common/sdk-registry.js';
|
|
11
11
|
export { BLOCKS_AUTH_PREFIX, BLOCKS_RPC_PREFIX } from './constants.js';
|
|
12
|
-
export { ApiError, DEFAULT_API_ERROR_NAME, hasAuthError, isBlocksError } from './errors.js';
|
|
12
|
+
export { ApiError, blocksError, DEFAULT_API_ERROR_NAME, hasAuthError, isBlocksError } from './errors.js';
|
|
13
13
|
export { clearRouteRegistry, getRegisteredRoutes, lockRouteRegistry, matchRoute, RawRouteErrors, registerRoute, unlockRouteRegistry, } from './raw-route.js';
|
|
14
14
|
export { RawRoute } from './raw-route.mock.js';
|
package/dist/lambda-handler.d.ts
CHANGED
|
@@ -128,4 +128,21 @@ export interface LambdaContext {
|
|
|
128
128
|
* @param backendFactory - Async function returning the backend module (typically `() => import('./index.js')`)
|
|
129
129
|
*/
|
|
130
130
|
export declare function createLambdaHandler(backendFactory: () => Promise<any>): (event: any, context?: LambdaContext) => Promise<any>;
|
|
131
|
+
/**
|
|
132
|
+
* Thrown by `initialize()` when the app has config coordinates
|
|
133
|
+
* (BLOCKS_CONFIG_BUCKET/KEY) but the S3 config load resolved empty because
|
|
134
|
+
* blocks-config.json wasn't readable yet — the transient window right after a
|
|
135
|
+
* deploy, before the BucketDeployment settles.
|
|
136
|
+
*
|
|
137
|
+
* It flows through the `createLambdaHandler()` init catch, which resets
|
|
138
|
+
* `initPromise` so the NEXT request re-runs `initialize()` and picks up the
|
|
139
|
+
* now-present config (config.ts does not cache a not-found result, so the retry
|
|
140
|
+
* re-fetches). A distinct type keeps the recovery path greppable and testable
|
|
141
|
+
* and separates it from real init failures, which surface with their own error.
|
|
142
|
+
*
|
|
143
|
+
* @internal Exported for testing only.
|
|
144
|
+
*/
|
|
145
|
+
export declare class TransientConfigError extends Error {
|
|
146
|
+
constructor();
|
|
147
|
+
}
|
|
131
148
|
//# sourceMappingURL=lambda-handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lambda-handler.d.ts","sourceRoot":"","sources":["../src/lambda-handler.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAerD,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAElE;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,2BAAkC,CAAC;AAG9D;;;GAGG;AACH,eAAO,MAAM,kBAAkB;;CAErB,CAAC;AAqCX;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAWlF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,CAwD7C;AAiBD;;;;;;;GAOG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAC;AAErE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,GAAG,GAAG,UAAU,CAWpD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAEzD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,CAIrE;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,wBAAwB,IAAI,MAAM,CAAC;CACpC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"lambda-handler.d.ts","sourceRoot":"","sources":["../src/lambda-handler.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAerD,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAElE;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,2BAAkC,CAAC;AAG9D;;;GAGG;AACH,eAAO,MAAM,kBAAkB;;CAErB,CAAC;AAqCX;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAWlF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,CAwD7C;AAiBD;;;;;;;GAOG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAC;AAErE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,GAAG,GAAG,UAAU,CAWpD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAEzD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,CAIrE;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,wBAAwB,IAAI,MAAM,CAAC;CACpC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,IA8CtD,OAAO,GAAG,EAAE,UAAU,aAAa,kBA4ElD;AASD;;;;;;;;;;;;;GAaG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;;CAK9C"}
|
package/dist/lambda-handler.js
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
5
5
|
import { ApiError } from './errors.js';
|
|
6
6
|
import { BLOCKS_RPC_PREFIX } from './constants.js';
|
|
7
|
-
import { matchRoute, lockRouteRegistry } from './raw-route.js';
|
|
7
|
+
import { matchRoute, lockRouteRegistry, getRegisteredRoutes, getLoadedCoreCopies } from './raw-route.js';
|
|
8
8
|
import { registerBuiltinRoutes } from './builtin-routes.js';
|
|
9
|
-
import { loadConfigToProcessEnv } from './common/config.js';
|
|
9
|
+
import { loadConfigToProcessEnv, isConfigResolved } from './common/config.js';
|
|
10
10
|
import { parseRpcRequest, successResponse, errorResponse, errorResponseFromCatch, methodNotFoundResponse, } from './rpc.js';
|
|
11
11
|
import { getCorsPatterns, isOriginAllowed, corsRejection, buildCorsHeaders, CORS_MAX_AGE } from './cors.js';
|
|
12
12
|
export { parseCorsPatterns, _resetCorsPatterns } from './cors.js';
|
|
@@ -257,6 +257,25 @@ export function createLambdaHandler(backendFactory) {
|
|
|
257
257
|
let initPromise = null;
|
|
258
258
|
async function initialize() {
|
|
259
259
|
await loadConfigToProcessEnv();
|
|
260
|
+
// If the app has config coordinates (BLOCKS_CONFIG_BUCKET/KEY set) but the
|
|
261
|
+
// load didn't actually resolve the config, we're in the transient post-deploy
|
|
262
|
+
// S3 window where blocks-config.json isn't readable yet. loadConfigFromS3()
|
|
263
|
+
// deliberately does NOT cache that empty result, so throw a typed transient
|
|
264
|
+
// error here — BEFORE importing the backend — so the createLambdaHandler()
|
|
265
|
+
// catch resets initPromise and the next request re-runs initialize(), which
|
|
266
|
+
// re-fetches from S3 and picks up the now-present config. Without this throw,
|
|
267
|
+
// initialize() would succeed with empty config, `handler` would be assigned,
|
|
268
|
+
// and the `if (!handler)` guard below would never fire again, poisoning the
|
|
269
|
+
// container for its whole life (it would import the backend against empty
|
|
270
|
+
// process.env and serve "not configured" 500s forever).
|
|
271
|
+
//
|
|
272
|
+
// A genuinely config-less app does NOT throw: the no-bucket local-dev path
|
|
273
|
+
// and a real empty `{}` config both cache their result, so isConfigResolved()
|
|
274
|
+
// is true and the retry never spins. Once the blob is readable the successful
|
|
275
|
+
// load caches, so there is no unbounded per-request S3 re-fetch either.
|
|
276
|
+
if (process.env.BLOCKS_CONFIG_BUCKET && process.env.BLOCKS_CONFIG_KEY && !isConfigResolved()) {
|
|
277
|
+
throw new TransientConfigError();
|
|
278
|
+
}
|
|
260
279
|
// Merge hosting-provided CORS origins into the main env var so the lazy
|
|
261
280
|
// getCorsPatterns() sees a combined value on first access.
|
|
262
281
|
// loadConfigToProcessEnv() won't override CORS_ALLOWED_ORIGINS if it's
|
|
@@ -276,8 +295,18 @@ export function createLambdaHandler(backendFactory) {
|
|
|
276
295
|
}
|
|
277
296
|
return async (event, context) => {
|
|
278
297
|
if (!handler) {
|
|
279
|
-
|
|
280
|
-
|
|
298
|
+
// Retry init on failure instead of caching the rejection. If initialize() throws (most often
|
|
299
|
+
// because loadConfigToProcessEnv() couldn't read blocks-config.json during the brief
|
|
300
|
+
// post-deploy window before it's readable), a memoized rejected promise would poison this
|
|
301
|
+
// container for its whole lifetime — every later request re-awaits the same rejection and 500s.
|
|
302
|
+
// Resetting initPromise lets the next invocation re-run initialize() (config.ts re-fetches,
|
|
303
|
+
// since it doesn't cache failures), so the handler self-heals once config is available.
|
|
304
|
+
if (!initPromise) {
|
|
305
|
+
initPromise = initialize().catch((err) => {
|
|
306
|
+
initPromise = null;
|
|
307
|
+
throw err;
|
|
308
|
+
});
|
|
309
|
+
}
|
|
281
310
|
await initPromise;
|
|
282
311
|
}
|
|
283
312
|
// Only apply the HTTP timeout guard to API Gateway requests; async event
|
|
@@ -344,6 +373,26 @@ class HandlerTimeoutError extends Error {
|
|
|
344
373
|
this.name = 'HandlerTimeoutError';
|
|
345
374
|
}
|
|
346
375
|
}
|
|
376
|
+
/**
|
|
377
|
+
* Thrown by `initialize()` when the app has config coordinates
|
|
378
|
+
* (BLOCKS_CONFIG_BUCKET/KEY) but the S3 config load resolved empty because
|
|
379
|
+
* blocks-config.json wasn't readable yet — the transient window right after a
|
|
380
|
+
* deploy, before the BucketDeployment settles.
|
|
381
|
+
*
|
|
382
|
+
* It flows through the `createLambdaHandler()` init catch, which resets
|
|
383
|
+
* `initPromise` so the NEXT request re-runs `initialize()` and picks up the
|
|
384
|
+
* now-present config (config.ts does not cache a not-found result, so the retry
|
|
385
|
+
* re-fetches). A distinct type keeps the recovery path greppable and testable
|
|
386
|
+
* and separates it from real init failures, which surface with their own error.
|
|
387
|
+
*
|
|
388
|
+
* @internal Exported for testing only.
|
|
389
|
+
*/
|
|
390
|
+
export class TransientConfigError extends Error {
|
|
391
|
+
constructor() {
|
|
392
|
+
super('[Blocks] Config not readable yet (transient post-deploy S3 window); will retry on next request');
|
|
393
|
+
this.name = 'TransientConfigError';
|
|
394
|
+
}
|
|
395
|
+
}
|
|
347
396
|
/**
|
|
348
397
|
* Extract the request path from a Lambda event, normalizing between
|
|
349
398
|
* API Gateway v1 (REST) and v2 (HTTP API) event shapes.
|
|
@@ -420,8 +469,15 @@ function createHandler(backend) {
|
|
|
420
469
|
if (matched) {
|
|
421
470
|
return handleRawRoute(event, matched.route, matched.params, corsHeaders, signal);
|
|
422
471
|
}
|
|
423
|
-
// No RawRoute matched and path is not the RPC endpoint — return 404
|
|
472
|
+
// No RawRoute matched and path is not the RPC endpoint — return 404.
|
|
473
|
+
// Log it: an unmatched route used to be entirely silent, which is what
|
|
474
|
+
// made a split route registry (duplicate @aws-blocks/core copies)
|
|
475
|
+
// undiagnosable from CloudWatch alone. The path is already in the API
|
|
476
|
+
// Gateway access logs, so this adds no new category of data.
|
|
424
477
|
if (!requestPath.startsWith(BLOCKS_RPC_PREFIX)) {
|
|
478
|
+
const copies = getLoadedCoreCopies();
|
|
479
|
+
const copiesNote = copies > 1 ? ` — ${copies} copies of @aws-blocks/core are loaded` : '';
|
|
480
|
+
console.error(`No RawRoute matched ${httpMethod} ${requestPath} (${getRegisteredRoutes().length} routes registered)${copiesNote}`);
|
|
425
481
|
return {
|
|
426
482
|
statusCode: 404,
|
|
427
483
|
headers: {
|