@aws-blocks/core 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/README.md +13 -0
  2. package/dist/api.d.ts.map +1 -1
  3. package/dist/api.js +32 -0
  4. package/dist/api.test.js +22 -0
  5. package/dist/bb-utils.d.ts +1 -0
  6. package/dist/bb-utils.d.ts.map +1 -1
  7. package/dist/bb-utils.js +3 -0
  8. package/dist/cdk/apigateway-account.d.ts +33 -0
  9. package/dist/cdk/apigateway-account.d.ts.map +1 -0
  10. package/dist/cdk/apigateway-account.js +60 -0
  11. package/dist/cdk/blocks-backend.d.ts +43 -9
  12. package/dist/cdk/blocks-backend.d.ts.map +1 -1
  13. package/dist/cdk/blocks-backend.js +69 -73
  14. package/dist/cdk/blocks-backend.test.js +78 -69
  15. package/dist/cdk/blocks-defaults.d.ts +92 -2
  16. package/dist/cdk/blocks-defaults.d.ts.map +1 -1
  17. package/dist/cdk/blocks-defaults.js +22 -2
  18. package/dist/cdk/blocks-defaults.test.js +21 -2
  19. package/dist/cdk/blocks-stack.test.js +94 -37
  20. package/dist/cdk/compute/compute-registry.d.ts +19 -0
  21. package/dist/cdk/compute/compute-registry.d.ts.map +1 -0
  22. package/dist/cdk/compute/compute-registry.js +38 -0
  23. package/dist/cdk/compute/compute.d.ts +2 -0
  24. package/dist/cdk/compute/compute.d.ts.map +1 -1
  25. package/dist/cdk/compute/compute.js +8 -0
  26. package/dist/cdk/compute/default-compute-factory.d.ts +34 -0
  27. package/dist/cdk/compute/default-compute-factory.d.ts.map +1 -0
  28. package/dist/cdk/compute/default-compute-factory.js +3 -0
  29. package/dist/cdk/config-registry.d.ts +34 -4
  30. package/dist/cdk/config-registry.d.ts.map +1 -1
  31. package/dist/cdk/config-registry.js +83 -25
  32. package/dist/cdk/config-registry.test.d.ts +2 -0
  33. package/dist/cdk/config-registry.test.d.ts.map +1 -0
  34. package/dist/cdk/config-registry.test.js +115 -0
  35. package/dist/cdk/index.d.ts +76 -7
  36. package/dist/cdk/index.d.ts.map +1 -1
  37. package/dist/cdk/index.js +99 -9
  38. package/dist/cdk/internal.d.ts +1 -0
  39. package/dist/cdk/internal.d.ts.map +1 -1
  40. package/dist/client/index.d.ts +1 -1
  41. package/dist/client/index.d.ts.map +1 -1
  42. package/dist/client/index.js +1 -1
  43. package/dist/common/config.d.ts +34 -0
  44. package/dist/common/config.d.ts.map +1 -1
  45. package/dist/common/config.js +45 -3
  46. package/dist/common/config.test.js +19 -0
  47. package/dist/common/index.d.ts +8 -0
  48. package/dist/common/index.d.ts.map +1 -1
  49. package/dist/errors.d.ts +16 -0
  50. package/dist/errors.d.ts.map +1 -1
  51. package/dist/errors.js +20 -0
  52. package/dist/hosting-secrets.d.ts +48 -0
  53. package/dist/hosting-secrets.d.ts.map +1 -0
  54. package/dist/hosting-secrets.js +57 -0
  55. package/dist/hosting-secrets.test.d.ts +2 -0
  56. package/dist/hosting-secrets.test.d.ts.map +1 -0
  57. package/dist/hosting-secrets.test.js +81 -0
  58. package/dist/hosting.d.ts +97 -6
  59. package/dist/hosting.d.ts.map +1 -1
  60. package/dist/hosting.js +91 -23
  61. package/dist/hosting.test.js +182 -10
  62. package/dist/index.cdk.d.ts +13 -12
  63. package/dist/index.cdk.d.ts.map +1 -1
  64. package/dist/index.cdk.js +13 -9
  65. package/dist/index.d.ts +8 -7
  66. package/dist/index.d.ts.map +1 -1
  67. package/dist/index.js +9 -5
  68. package/dist/lambda-handler.d.ts +17 -0
  69. package/dist/lambda-handler.d.ts.map +1 -1
  70. package/dist/lambda-handler.js +52 -3
  71. package/dist/lambda-handler.test.js +196 -1
  72. package/dist/pipeline/index.d.ts +24 -2
  73. package/dist/pipeline/index.d.ts.map +1 -1
  74. package/dist/pipeline/index.js +41 -1
  75. package/dist/pipeline.test.d.ts +2 -0
  76. package/dist/pipeline.test.d.ts.map +1 -0
  77. package/dist/pipeline.test.js +47 -0
  78. package/dist/rpc.d.ts +21 -0
  79. package/dist/rpc.d.ts.map +1 -1
  80. package/dist/rpc.js +34 -0
  81. package/dist/rpc.test.js +38 -1
  82. package/dist/scripts/config.d.ts +15 -0
  83. package/dist/scripts/config.d.ts.map +1 -0
  84. package/dist/scripts/config.js +29 -0
  85. package/dist/scripts/deploy.d.ts.map +1 -1
  86. package/dist/scripts/deploy.js +4 -0
  87. package/dist/scripts/dev-server.d.ts +8 -0
  88. package/dist/scripts/dev-server.d.ts.map +1 -1
  89. package/dist/scripts/dev-server.js +31 -0
  90. package/dist/scripts/generate-client.d.ts.map +1 -1
  91. package/dist/scripts/generate-client.js +9 -4
  92. package/dist/scripts/generate-client.test.js +19 -4
  93. package/dist/scripts/index.d.ts +13 -10
  94. package/dist/scripts/index.d.ts.map +1 -1
  95. package/dist/scripts/index.js +11 -8
  96. package/dist/scripts/preflight-credentials.d.ts +30 -0
  97. package/dist/scripts/preflight-credentials.d.ts.map +1 -0
  98. package/dist/scripts/preflight-credentials.js +108 -0
  99. package/dist/scripts/preflight-credentials.test.d.ts +2 -0
  100. package/dist/scripts/preflight-credentials.test.d.ts.map +1 -0
  101. package/dist/scripts/preflight-credentials.test.js +77 -0
  102. package/dist/scripts/sandbox-args.test.d.ts +2 -0
  103. package/dist/scripts/sandbox-args.test.d.ts.map +1 -0
  104. package/dist/scripts/sandbox-args.test.js +77 -0
  105. package/dist/scripts/sandbox-empty-buckets.test.d.ts +2 -0
  106. package/dist/scripts/sandbox-empty-buckets.test.d.ts.map +1 -0
  107. package/dist/scripts/sandbox-empty-buckets.test.js +171 -0
  108. package/dist/scripts/sandbox.d.ts +106 -0
  109. package/dist/scripts/sandbox.d.ts.map +1 -1
  110. package/dist/scripts/sandbox.js +255 -40
  111. package/dist/scripts/secret.d.ts +15 -0
  112. package/dist/scripts/secret.d.ts.map +1 -0
  113. package/dist/scripts/secret.js +29 -0
  114. package/dist/scripts/secret.test.d.ts +2 -0
  115. package/dist/scripts/secret.test.d.ts.map +1 -0
  116. package/dist/scripts/secret.test.js +28 -0
  117. package/dist/scripts/typegen.d.ts +15 -0
  118. package/dist/scripts/typegen.d.ts.map +1 -0
  119. package/dist/scripts/typegen.js +16 -0
  120. package/dist/secret-naming.d.ts +58 -0
  121. package/dist/secret-naming.d.ts.map +1 -0
  122. package/dist/secret-naming.js +67 -0
  123. package/dist/secret-naming.test.d.ts +2 -0
  124. package/dist/secret-naming.test.d.ts.map +1 -0
  125. package/dist/secret-naming.test.js +40 -0
  126. package/dist/version.d.ts +1 -1
  127. package/dist/version.js +1 -1
  128. package/package.json +4 -1
  129. package/src/api.test.ts +25 -0
  130. package/src/api.ts +39 -0
  131. package/src/bb-utils.ts +3 -0
  132. package/src/cdk/apigateway-account.ts +66 -0
  133. package/src/cdk/blocks-backend.test.ts +291 -272
  134. package/src/cdk/blocks-backend.ts +88 -83
  135. package/src/cdk/blocks-defaults.test.ts +25 -2
  136. package/src/cdk/blocks-defaults.ts +94 -2
  137. package/src/cdk/blocks-stack.test.ts +186 -118
  138. package/src/cdk/compute/compute-registry.ts +45 -0
  139. package/src/cdk/compute/compute.ts +10 -0
  140. package/src/cdk/compute/default-compute-factory.ts +38 -0
  141. package/src/cdk/config-registry.test.ts +135 -0
  142. package/src/cdk/config-registry.ts +92 -34
  143. package/src/cdk/index.ts +129 -10
  144. package/src/cdk/internal.ts +1 -0
  145. package/src/client/index.ts +1 -1
  146. package/src/common/config.test.ts +21 -0
  147. package/src/common/config.ts +47 -3
  148. package/src/common/index.ts +8 -0
  149. package/src/errors.ts +21 -0
  150. package/src/hosting-secrets.test.ts +106 -0
  151. package/src/hosting-secrets.ts +106 -0
  152. package/src/hosting.test.ts +272 -63
  153. package/src/hosting.ts +200 -68
  154. package/src/index.cdk.ts +80 -38
  155. package/src/index.ts +35 -16
  156. package/src/lambda-handler.test.ts +215 -1
  157. package/src/lambda-handler.ts +54 -2
  158. package/src/pipeline/index.ts +64 -11
  159. package/src/pipeline.test.ts +55 -0
  160. package/src/rpc.test.ts +44 -1
  161. package/src/rpc.ts +41 -0
  162. package/src/scripts/config.ts +35 -0
  163. package/src/scripts/deploy.ts +5 -0
  164. package/src/scripts/dev-server.ts +40 -0
  165. package/src/scripts/generate-client.test.ts +43 -8
  166. package/src/scripts/generate-client.ts +70 -65
  167. package/src/scripts/index.ts +20 -17
  168. package/src/scripts/preflight-credentials.test.ts +110 -0
  169. package/src/scripts/preflight-credentials.ts +131 -0
  170. package/src/scripts/sandbox-args.test.ts +92 -0
  171. package/src/scripts/sandbox-empty-buckets.test.ts +191 -0
  172. package/src/scripts/sandbox.ts +287 -39
  173. package/src/scripts/secret.test.ts +35 -0
  174. package/src/scripts/secret.ts +35 -0
  175. package/src/scripts/typegen.ts +18 -0
  176. package/src/secret-naming.test.ts +59 -0
  177. package/src/secret-naming.ts +99 -0
  178. package/src/version.ts +1 -1
@@ -1,13 +1,15 @@
1
1
  // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
2
  // SPDX-License-Identifier: Apache-2.0
3
- import { describe, it, beforeEach, afterEach } from 'node:test';
4
3
  import assert from 'node:assert';
5
4
  import * as fs from 'node:fs';
6
- import * as path from 'node:path';
7
5
  import * as os from 'node:os';
6
+ import * as path from 'node:path';
7
+ import { afterEach, beforeEach, describe, it } from 'node:test';
8
+ import { config, secret } from '@aws-blocks/hosting';
9
+ import { _setSynthExistsChecker } from '@aws-blocks/hosting/constructs';
8
10
  import * as cdk from 'aws-cdk-lib';
9
11
  import { App, Duration, Stack } from 'aws-cdk-lib';
10
- import { Template, Match } from 'aws-cdk-lib/assertions';
12
+ import { Match, Template } from 'aws-cdk-lib/assertions';
11
13
  import { BLOCKS_RPC_PREFIX } from './constants.js';
12
14
  import { Hosting } from './hosting.js';
13
15
  import { clearRouteRegistry, registerRoute } from './raw-route.js';
@@ -84,6 +86,31 @@ describe('Hosting', () => {
84
86
  fs.rmSync(tmpDir, { recursive: true, force: true });
85
87
  clearRouteRegistry();
86
88
  });
89
+ // ── Deploy-time existence check (key change 4) ───────────────
90
+ describe('environment marker existence check (Hosting.create)', () => {
91
+ it('rejects at deploy when a declared environment secret has no value', async () => {
92
+ createSpaBuildOutput(tmpDir);
93
+ const app = new App();
94
+ const stack = new Stack(app, 'MissingEnvSecretStack');
95
+ // Stub the synth existence probe to report "not set" — rejects before any
96
+ // CDK construction, so this needs no assets and no AWS.
97
+ _setSynthExistsChecker(async () => {
98
+ const e = new Error('missing');
99
+ e.name = 'ResourceNotFoundException';
100
+ throw e;
101
+ });
102
+ try {
103
+ await assert.rejects(Hosting.create(stack, 'Hosting', {
104
+ root: tmpDir,
105
+ api: MOCK_API,
106
+ environment: { MISSING_SECRET: secret('MISSING_SECRET') },
107
+ }), /MISSING_SECRET.*not set/s);
108
+ }
109
+ finally {
110
+ _setSynthExistsChecker(null);
111
+ }
112
+ });
113
+ });
87
114
  // ── SPA tests ────────────────────────────────────────────────
88
115
  describe('SPA mode', () => {
89
116
  it('creates S3 bucket and CloudFront distribution', () => {
@@ -345,6 +372,30 @@ describe('Hosting', () => {
345
372
  }
346
373
  assert.ok(foundRetain, 'At least one bucket should have Retain deletion policy');
347
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
+ });
348
399
  });
349
400
  // ── API integration tests ────────────────────────────────────
350
401
  describe('API integration', () => {
@@ -1092,8 +1143,7 @@ describe('Hosting', () => {
1092
1143
  ...(basePath !== undefined ? { basePath } : {}),
1093
1144
  });
1094
1145
  const tpl = Template.fromStack(stack).toJSON();
1095
- const kvKeys = Object.entries(tpl.Resources).find(([id, r]) => r.Type === 'AWS::CloudFormation::CustomResource' &&
1096
- /RouteStoreKeys/.test(id));
1146
+ const kvKeys = Object.entries(tpl.Resources).find(([id, r]) => r.Type === 'AWS::CloudFormation::CustomResource' && /RouteStoreKeys/.test(id));
1097
1147
  assert.ok(kvKeys, 'expected a RouteStoreKeys custom resource');
1098
1148
  const entries = JSON.parse(kvKeys[1].Properties.Entries);
1099
1149
  const meta = JSON.parse(entries.meta);
@@ -1134,6 +1184,131 @@ describe('Hosting', () => {
1134
1184
  `found DependsOn=${JSON.stringify(dependsOn)}`);
1135
1185
  });
1136
1186
  });
1187
+ // ── value() integration ─────────────────────────────────────────
1188
+ //
1189
+ // Runtime values: the store LOCATOR (never the value) is injected as a Lambda
1190
+ // env var, and the role is granted read + kms:Decrypt. The store is derived from
1191
+ // the marker's type — secret → Secrets Manager, config → SSM Parameter Store.
1192
+ // Domain markers resolve at synth time via Hosting.create().
1193
+ describe('secret() / config() integration', () => {
1194
+ it('secret() → Secrets Manager: injects the locator (not the value) + grants read+decrypt', () => {
1195
+ createNextjsBuildOutput(tmpDir);
1196
+ const app = new App();
1197
+ const stack = new Stack(app, 'SecretEnvStack');
1198
+ new Hosting(stack, 'Hosting', {
1199
+ root: tmpDir,
1200
+ customAdapter: createNextjsFixtureAdapter(tmpDir),
1201
+ api: MOCK_API,
1202
+ environment: { STRIPE_KEY: secret('STRIPE_KEY') },
1203
+ });
1204
+ const template = Template.fromStack(stack);
1205
+ // secret → Secrets Manager: slash-free locator under the Blocks /blocks/secrets namespace.
1206
+ template.hasResourceProperties('AWS::Lambda::Function', {
1207
+ Environment: {
1208
+ Variables: Match.objectLike({ HOSTING_SECRET_PARAM_STRIPE_KEY: 'blocks/secrets/STRIPE_KEY' }),
1209
+ },
1210
+ });
1211
+ // The plaintext value must NOT appear anywhere in the template.
1212
+ const json = JSON.stringify(template.toJSON());
1213
+ assert.ok(!json.includes('STRIPE_KEY_VALUE'), 'no value should be in the template');
1214
+ // The role has secretsmanager:GetSecretValue scoped to the secret + kms:Decrypt.
1215
+ template.hasResourceProperties('AWS::IAM::Policy', {
1216
+ PolicyDocument: {
1217
+ Statement: Match.arrayWith([
1218
+ Match.objectLike({ Action: 'secretsmanager:GetSecretValue' }),
1219
+ Match.objectLike({
1220
+ Action: 'kms:Decrypt',
1221
+ Condition: { StringEquals: Match.objectLike({ 'kms:ViaService': Match.anyValue() }) },
1222
+ }),
1223
+ ]),
1224
+ },
1225
+ });
1226
+ });
1227
+ it('threads secretStore { prefix, stage, cacheTtlSeconds } from core HostingProps to the wiring (B3)', () => {
1228
+ createNextjsBuildOutput(tmpDir);
1229
+ const app = new App();
1230
+ const stack = new Stack(app, 'SecretStoreOverrideStack');
1231
+ new Hosting(stack, 'Hosting', {
1232
+ root: tmpDir,
1233
+ customAdapter: createNextjsFixtureAdapter(tmpDir),
1234
+ api: MOCK_API,
1235
+ environment: { STRIPE_KEY: secret('STRIPE_KEY') },
1236
+ // Custom prefix + stage + warm-cache TTL must all reach the leaf wiring.
1237
+ secretStore: { prefix: '/myapp/secrets', stage: 'prod', cacheTtlSeconds: 30 },
1238
+ });
1239
+ const template = Template.fromStack(stack);
1240
+ template.hasResourceProperties('AWS::Lambda::Function', {
1241
+ Environment: {
1242
+ Variables: Match.objectLike({
1243
+ // custom prefix + stage (Secrets Manager → slash-free)
1244
+ HOSTING_SECRET_PARAM_STRIPE_KEY: 'myapp/secrets/prod/STRIPE_KEY',
1245
+ // shared fallback (no stage)
1246
+ HOSTING_SECRET_PARAM_STRIPE_KEY_FALLBACK: 'myapp/secrets/STRIPE_KEY',
1247
+ // warm-cache TTL for rotation without a cold start
1248
+ HOSTING_SECRET_CACHE_TTL: '30',
1249
+ }),
1250
+ },
1251
+ });
1252
+ });
1253
+ it('config() → SSM: HOSTING_CONFIG_PARAM_* (leading-slash) + ssm:GetParameter', () => {
1254
+ createNextjsBuildOutput(tmpDir);
1255
+ const app = new App();
1256
+ const stack = new Stack(app, 'ConfigEnvStack');
1257
+ new Hosting(stack, 'Hosting', {
1258
+ root: tmpDir,
1259
+ customAdapter: createNextjsFixtureAdapter(tmpDir),
1260
+ api: MOCK_API,
1261
+ environment: { FEATURE_FLAGS: config('FEATURE_FLAGS') },
1262
+ });
1263
+ const template = Template.fromStack(stack);
1264
+ template.hasResourceProperties('AWS::Lambda::Function', {
1265
+ Environment: {
1266
+ Variables: Match.objectLike({ HOSTING_CONFIG_PARAM_FEATURE_FLAGS: '/blocks/config/FEATURE_FLAGS' }),
1267
+ },
1268
+ });
1269
+ template.hasResourceProperties('AWS::IAM::Policy', {
1270
+ PolicyDocument: { Statement: Match.arrayWith([Match.objectLike({ Action: 'ssm:GetParameter' })]) },
1271
+ });
1272
+ });
1273
+ it('does not inject a plaintext env var for a runtime value', () => {
1274
+ createNextjsBuildOutput(tmpDir);
1275
+ const app = new App();
1276
+ const stack = new Stack(app, 'SecretNoPlaintextStack');
1277
+ new Hosting(stack, 'Hosting', {
1278
+ root: tmpDir,
1279
+ customAdapter: createNextjsFixtureAdapter(tmpDir),
1280
+ api: MOCK_API,
1281
+ environment: { FLAG: 'on', STRIPE_KEY: secret('STRIPE_KEY') },
1282
+ });
1283
+ const template = Template.fromStack(stack);
1284
+ const fns = template.findResources('AWS::Lambda::Function');
1285
+ for (const fn of Object.values(fns)) {
1286
+ const vars = (fn.Properties?.Environment?.Variables ?? {});
1287
+ assert.strictEqual(vars.STRIPE_KEY, undefined, 'value key must not be a plaintext env var');
1288
+ }
1289
+ });
1290
+ it('rejects a runtime value whose key mismatches the env var name', () => {
1291
+ createNextjsBuildOutput(tmpDir);
1292
+ const app = new App();
1293
+ const stack = new Stack(app, 'SecretMismatchStack');
1294
+ assert.throws(() => new Hosting(stack, 'Hosting', {
1295
+ root: tmpDir,
1296
+ customAdapter: createNextjsFixtureAdapter(tmpDir),
1297
+ api: MOCK_API,
1298
+ environment: { STRIPE_KEY: secret('OTHER') },
1299
+ }), /must match the environment variable name/);
1300
+ });
1301
+ it('throws if a domain marker is used with the sync constructor', () => {
1302
+ createSpaBuildOutput(tmpDir);
1303
+ const app = new App();
1304
+ const stack = new Stack(app, 'SecretDomainSyncStack');
1305
+ assert.throws(() => new Hosting(stack, 'Hosting', {
1306
+ root: tmpDir,
1307
+ api: MOCK_API,
1308
+ domain: { domainName: config('DOMAIN_PROD') },
1309
+ }), /requires async resolution/);
1310
+ });
1311
+ });
1137
1312
  describe('config.json stale-placeholder guard (#173)', () => {
1138
1313
  // Helper: pull every BucketDeployment custom resource's Properties.
1139
1314
  const bucketDeployments = (stack) => {
@@ -1169,8 +1344,7 @@ describe('Hosting', () => {
1169
1344
  directive.includes('s-maxage=31536000') &&
1170
1345
  !excludes(p).includes('.blocks-sandbox/config.json'));
1171
1346
  });
1172
- assert.strictEqual(leaks.length, 0, 'no mutable-tier deployment may apply s-maxage=31536000 to ' +
1173
- '.blocks-sandbox/config.json');
1347
+ assert.strictEqual(leaks.length, 0, 'no mutable-tier deployment may apply s-maxage=31536000 to ' + '.blocks-sandbox/config.json');
1174
1348
  });
1175
1349
  it('registers the placeholder as a no-cache path even for a static-only site (no api)', () => {
1176
1350
  // The placeholder is always written (step 5), so its no-cache
@@ -1201,9 +1375,7 @@ describe('Hosting', () => {
1201
1375
  // Assert via Template + Match so a CDK property rename fails loudly here
1202
1376
  // rather than silently skipping a structural-heuristic lookup.
1203
1377
  Template.fromStack(stack).hasResourceProperties('Custom::CDKBucketDeployment', Match.objectLike({
1204
- DistributionPaths: Match.arrayWith([
1205
- Match.stringLikeRegexp('^/builds/.+/\\.blocks-sandbox/\\*$'),
1206
- ]),
1378
+ DistributionPaths: Match.arrayWith([Match.stringLikeRegexp('^/builds/.+/\\.blocks-sandbox/\\*$')]),
1207
1379
  }));
1208
1380
  });
1209
1381
  });
@@ -1,14 +1,15 @@
1
- export { ApiNamespace, type BlocksContext, type ApiHandler } from './api.js';
2
- export { BLOCKS_RPC_PREFIX, BLOCKS_AUTH_PREFIX } from './constants.js';
3
- export { ApiError, isBlocksError, hasAuthError, DEFAULT_API_ERROR_NAME } from './errors.js';
4
- export { EventSourceMapping } from './lambda-handler.js';
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
+ export { type ApiHandler, ApiNamespace, type BlocksContext } from './api.js';
3
+ export { BlocksBackend, type BlocksBackendProps, type BlocksDefaults, BlocksPresets, BlocksStack, type BlocksThrottling, blocksNodejsBundling, type CoreBlocksBackendProps, type CoreBlocksStackProps, DEFAULT_NODE_RUNTIME, ensureApiGatewayAccount, finalizeConfigRegistry, getConfigLocation, registerConfig, SandboxDisableDeletionProtection, Scope, SHARED_HANDLER_TIMEOUT_SECONDS, synthGuard, } from './cdk/index.js';
4
+ export { _resetConfigCache, getConfig, getConfigSync, loadConfigToProcessEnv, preloadConfig } from './common/config.js';
5
5
  export { BlocksStackProps } from './common/index.js';
6
- export { registerSdkIdentifiers, getSdkIdentifiers, getAllSdkIdentifiers, _resetSdkRegistry } from './common/sdk-registry.js';
7
- export { getConfig, getConfigSync, preloadConfig, loadConfigToProcessEnv, _resetConfigCache } from './common/config.js';
8
- export { BlocksStack, Scope, SandboxDisableDeletionProtection, BlocksBackend, registerConfig, finalizeConfigRegistry, synthGuard, DEFAULT_NODE_RUNTIME, blocksNodejsBundling, type BlocksBackendProps } from './cdk/index.js';
9
- export { type BlocksDefaults, BlocksPresets, } from './cdk/index.js';
10
- export { Hosting, type HostingProps, type BlocksStackApi, type FrameworkType, type ComputeConfig, type HostingDomainConfig, type HostingWafConfig, } from './hosting.js';
11
- export { RawRoute, RawRouteErrors, type RawRouteOptions, type HttpMethod, } from './raw-route.cdk.js';
12
- export { registerRoute, matchRoute, getRegisteredRoutes, clearRouteRegistry, lockRouteRegistry, unlockRouteRegistry, type RegisteredRoute, } from './raw-route.js';
13
- export { Pipeline, DeployStage, __PIPELINE_STAGE_SCOPE__, type DeployStageProps, type BranchConfig, type PipelineProps, type PipelineSourceConfig, type PipelineSynthConfig, type PipelineStageConfig, } from './pipeline/index.js';
6
+ export { _resetSdkRegistry, getAllSdkIdentifiers, getSdkIdentifiers, registerSdkIdentifiers, } from './common/sdk-registry.js';
7
+ export { BLOCKS_AUTH_PREFIX, BLOCKS_RPC_PREFIX } from './constants.js';
8
+ export { ApiError, blocksError, DEFAULT_API_ERROR_NAME, hasAuthError, isBlocksError } from './errors.js';
9
+ export { type BlocksStackApi, type ComputeConfig, type FrameworkType, Hosting, type HostingDomainConfig, type HostingProps, type HostingWafConfig, } from './hosting.js';
10
+ export { EventSourceMapping } from './lambda-handler.js';
11
+ export { __PIPELINE_STAGE_SCOPE__, type BranchConfig, DeployStage, type DeployStageProps, Pipeline, type PipelineProps, type PipelineSourceConfig, type PipelineStageConfig, type PipelineSynthConfig, } from './pipeline/index.js';
12
+ export { type HttpMethod, RawRoute, RawRouteErrors, type RawRouteOptions, } from './raw-route.cdk.js';
13
+ export { clearRouteRegistry, getRegisteredRoutes, lockRouteRegistry, matchRoute, type RegisteredRoute, registerRoute, unlockRouteRegistry, } from './raw-route.js';
14
+ export { BLOCKS_CONFIG_PARAMETER_PREFIX, BLOCKS_SECRET_PARAMETER_PREFIX, blocksConfigParameterName, blocksSecretParameterName, } from './secret-naming.js';
14
15
  //# sourceMappingURL=index.cdk.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cdk.d.ts","sourceRoot":"","sources":["../src/index.cdk.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAC5F,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC9H,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,aAAa,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACxH,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,gCAAgC,EAAE,aAAa,EAAE,cAAc,EAAE,sBAAsB,EAAE,UAAU,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,KAAK,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAC9N,OAAO,EACL,KAAK,cAAc,EACnB,aAAa,GACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,OAAO,EACP,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,GACtB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,QAAQ,EACR,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,UAAU,GAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,aAAa,EACb,UAAU,EACV,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,KAAK,eAAe,GACrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,QAAQ,EACR,WAAW,EACX,wBAAwB,EACxB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,GACzB,MAAM,qBAAqB,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,OAAO,EACN,aAAa,EACb,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,aAAa,EACb,WAAW,EACX,KAAK,gBAAgB,EACrB,oBAAoB,EACpB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EACtB,iBAAiB,EACjB,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
@@ -1,14 +1,18 @@
1
1
  // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
2
  // SPDX-License-Identifier: Apache-2.0
3
+ // Declare functions for infra (secret/config). The runtime getters
4
+ // (getSecret/getConfig) are imported from '@aws-blocks/hosting' — core's own
5
+ // getConfig (backend config loader, above) owns that name here.
6
+ export { config, DEFAULT_CONFIG_PARAMETER_PREFIX, DEFAULT_SECRET_PARAMETER_PREFIX, isConfig, isManagedValue, isSecret, secret, } from '@aws-blocks/hosting';
3
7
  export { ApiNamespace } from './api.js';
4
- export { BLOCKS_RPC_PREFIX, BLOCKS_AUTH_PREFIX } from './constants.js';
5
- export { ApiError, isBlocksError, hasAuthError, DEFAULT_API_ERROR_NAME } from './errors.js';
6
- export { EventSourceMapping } from './lambda-handler.js';
7
- export { registerSdkIdentifiers, getSdkIdentifiers, getAllSdkIdentifiers, _resetSdkRegistry } from './common/sdk-registry.js';
8
- export { getConfig, getConfigSync, preloadConfig, loadConfigToProcessEnv, _resetConfigCache } from './common/config.js';
9
- export { BlocksStack, Scope, SandboxDisableDeletionProtection, BlocksBackend, registerConfig, finalizeConfigRegistry, synthGuard, DEFAULT_NODE_RUNTIME, blocksNodejsBundling } from './cdk/index.js';
10
- export { BlocksPresets, } from './cdk/index.js';
8
+ export { BlocksBackend, BlocksPresets, BlocksStack, blocksNodejsBundling, DEFAULT_NODE_RUNTIME, ensureApiGatewayAccount, finalizeConfigRegistry, getConfigLocation, registerConfig, SandboxDisableDeletionProtection, Scope, SHARED_HANDLER_TIMEOUT_SECONDS, synthGuard, } from './cdk/index.js';
9
+ export { _resetConfigCache, getConfig, getConfigSync, loadConfigToProcessEnv, preloadConfig } from './common/config.js';
10
+ export { _resetSdkRegistry, getAllSdkIdentifiers, getSdkIdentifiers, registerSdkIdentifiers, } from './common/sdk-registry.js';
11
+ export { BLOCKS_AUTH_PREFIX, BLOCKS_RPC_PREFIX } from './constants.js';
12
+ export { ApiError, blocksError, DEFAULT_API_ERROR_NAME, hasAuthError, isBlocksError } from './errors.js';
11
13
  export { Hosting, } from './hosting.js';
14
+ export { EventSourceMapping } from './lambda-handler.js';
15
+ export { __PIPELINE_STAGE_SCOPE__, DeployStage, Pipeline, } from './pipeline/index.js';
12
16
  export { RawRoute, RawRouteErrors, } from './raw-route.cdk.js';
13
- export { registerRoute, matchRoute, getRegisteredRoutes, clearRouteRegistry, lockRouteRegistry, unlockRouteRegistry, } from './raw-route.js';
14
- export { Pipeline, DeployStage, __PIPELINE_STAGE_SCOPE__, } from './pipeline/index.js';
17
+ export { clearRouteRegistry, getRegisteredRoutes, lockRouteRegistry, matchRoute, registerRoute, unlockRouteRegistry, } from './raw-route.js';
18
+ export { BLOCKS_CONFIG_PARAMETER_PREFIX, BLOCKS_SECRET_PARAMETER_PREFIX, blocksConfigParameterName, blocksSecretParameterName, } from './secret-naming.js';
package/dist/index.d.ts CHANGED
@@ -1,9 +1,10 @@
1
- export { ApiNamespace, type BlocksContext, type ApiHandler } from './api.js';
2
- export { BLOCKS_RPC_PREFIX, BLOCKS_AUTH_PREFIX } from './constants.js';
3
- export { ApiError, isBlocksError, hasAuthError, DEFAULT_API_ERROR_NAME } from './errors.js';
4
- export { Scope, type ScopeOptions, type ScopeParent, type BuildingBlockMeta } from './common/index.js';
5
- export { registerSdkIdentifiers, getSdkIdentifiers, getAllSdkIdentifiers, _resetSdkRegistry } from './common/sdk-registry.js';
6
- export { getConfig, getConfigSync, preloadConfig, loadConfigToProcessEnv, _resetConfigCache } from './common/config.js';
7
- export { registerRoute, matchRoute, getRegisteredRoutes, clearRouteRegistry, lockRouteRegistry, unlockRouteRegistry, RawRouteErrors, type RawRouteOptions, type HttpMethod, type RegisteredRoute, } from './raw-route.js';
1
+ export { type ConfigValue, config, isConfig, isManagedValue, isSecret, type ManagedValue, type SecretValue, secret, type ValueKind, } from '@aws-blocks/hosting';
2
+ export { type ApiHandler, ApiNamespace, type BlocksContext } from './api.js';
3
+ export { _resetConfigCache, getConfig, getConfigSync, loadConfigToProcessEnv, preloadConfig } from './common/config.js';
4
+ export { type BuildingBlockMeta, Scope, type ScopeOptions, type ScopeParent } from './common/index.js';
5
+ export { _resetSdkRegistry, getAllSdkIdentifiers, getSdkIdentifiers, registerSdkIdentifiers, } from './common/sdk-registry.js';
6
+ export { BLOCKS_AUTH_PREFIX, BLOCKS_RPC_PREFIX } from './constants.js';
7
+ export { ApiError, blocksError, DEFAULT_API_ERROR_NAME, hasAuthError, isBlocksError } from './errors.js';
8
+ export { clearRouteRegistry, getRegisteredRoutes, type HttpMethod, lockRouteRegistry, matchRoute, RawRouteErrors, type RawRouteOptions, type RegisteredRoute, registerRoute, unlockRouteRegistry, } from './raw-route.js';
8
9
  export { RawRoute } from './raw-route.mock.js';
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAC5F,OAAO,EAAE,KAAK,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACvG,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC9H,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,aAAa,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACxH,OAAO,EACL,aAAa,EACb,UAAU,EACV,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,UAAU,EACf,KAAK,eAAe,GACrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,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
@@ -1,10 +1,14 @@
1
1
  // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
2
  // SPDX-License-Identifier: Apache-2.0
3
+ // secret()/config() declare markers (CDK-free subpath). The runtime getters
4
+ // getSecret()/getConfig() are imported from '@aws-blocks/hosting' directly —
5
+ // core already exports a backend `getConfig` (config loader) under this name.
6
+ export { config, isConfig, isManagedValue, isSecret, secret, } from '@aws-blocks/hosting';
3
7
  export { ApiNamespace } from './api.js';
4
- export { BLOCKS_RPC_PREFIX, BLOCKS_AUTH_PREFIX } from './constants.js';
5
- export { ApiError, isBlocksError, hasAuthError, DEFAULT_API_ERROR_NAME } from './errors.js';
8
+ export { _resetConfigCache, getConfig, getConfigSync, loadConfigToProcessEnv, preloadConfig } from './common/config.js';
6
9
  export { Scope } from './common/index.js';
7
- export { registerSdkIdentifiers, getSdkIdentifiers, getAllSdkIdentifiers, _resetSdkRegistry } from './common/sdk-registry.js';
8
- export { getConfig, getConfigSync, preloadConfig, loadConfigToProcessEnv, _resetConfigCache } from './common/config.js';
9
- export { registerRoute, matchRoute, getRegisteredRoutes, clearRouteRegistry, lockRouteRegistry, unlockRouteRegistry, RawRouteErrors, } from './raw-route.js';
10
+ export { _resetSdkRegistry, getAllSdkIdentifiers, getSdkIdentifiers, registerSdkIdentifiers, } from './common/sdk-registry.js';
11
+ export { BLOCKS_AUTH_PREFIX, BLOCKS_RPC_PREFIX } from './constants.js';
12
+ export { ApiError, blocksError, DEFAULT_API_ERROR_NAME, hasAuthError, isBlocksError } from './errors.js';
13
+ export { clearRouteRegistry, getRegisteredRoutes, lockRouteRegistry, matchRoute, RawRouteErrors, registerRoute, unlockRouteRegistry, } from './raw-route.js';
10
14
  export { RawRoute } from './raw-route.mock.js';
@@ -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,IA0BtD,OAAO,GAAG,EAAE,UAAU,aAAa,kBAiElD"}
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"}
@@ -6,7 +6,7 @@ import { ApiError } from './errors.js';
6
6
  import { BLOCKS_RPC_PREFIX } from './constants.js';
7
7
  import { matchRoute, lockRouteRegistry } 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
- if (!initPromise)
280
- initPromise = initialize();
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.