@aws-blocks/core 0.1.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/LICENSE +174 -0
- package/dist/api.d.ts +147 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +10 -0
- package/dist/api.test.d.ts +2 -0
- package/dist/api.test.d.ts.map +1 -0
- package/dist/api.test.js +19 -0
- package/dist/bb-utils.d.ts +11 -0
- package/dist/bb-utils.d.ts.map +1 -0
- package/dist/bb-utils.js +12 -0
- package/dist/builtin-routes.d.ts +6 -0
- package/dist/builtin-routes.d.ts.map +1 -0
- package/dist/builtin-routes.js +57 -0
- package/dist/cdk/__fixtures__/factory-backend.d.ts +3 -0
- package/dist/cdk/__fixtures__/factory-backend.d.ts.map +1 -0
- package/dist/cdk/__fixtures__/factory-backend.js +6 -0
- package/dist/cdk/__fixtures__/fullid-construct-backend.d.ts +2 -0
- package/dist/cdk/__fixtures__/fullid-construct-backend.d.ts.map +1 -0
- package/dist/cdk/__fixtures__/fullid-construct-backend.js +37 -0
- package/dist/cdk/__fixtures__/handler.d.ts +5 -0
- package/dist/cdk/__fixtures__/handler.d.ts.map +1 -0
- package/dist/cdk/__fixtures__/handler.js +3 -0
- package/dist/cdk/__fixtures__/side-effect-backend.d.ts +2 -0
- package/dist/cdk/__fixtures__/side-effect-backend.d.ts.map +1 -0
- package/dist/cdk/__fixtures__/side-effect-backend.js +5 -0
- package/dist/cdk/blocks-backend.d.ts +68 -0
- package/dist/cdk/blocks-backend.d.ts.map +1 -0
- package/dist/cdk/blocks-backend.js +214 -0
- package/dist/cdk/blocks-backend.test.d.ts +2 -0
- package/dist/cdk/blocks-backend.test.d.ts.map +1 -0
- package/dist/cdk/blocks-backend.test.js +151 -0
- package/dist/cdk/blocks-stack.test.d.ts +2 -0
- package/dist/cdk/blocks-stack.test.d.ts.map +1 -0
- package/dist/cdk/blocks-stack.test.js +78 -0
- package/dist/cdk/config-registry.d.ts +26 -0
- package/dist/cdk/config-registry.d.ts.map +1 -0
- package/dist/cdk/config-registry.js +80 -0
- package/dist/cdk/index.d.ts +35 -0
- package/dist/cdk/index.d.ts.map +1 -0
- package/dist/cdk/index.js +90 -0
- package/dist/cdk/mixins.d.ts +28 -0
- package/dist/cdk/mixins.d.ts.map +1 -0
- package/dist/cdk/mixins.js +37 -0
- package/dist/cdk/mixins.test.d.ts +2 -0
- package/dist/cdk/mixins.test.d.ts.map +1 -0
- package/dist/cdk/mixins.test.js +108 -0
- package/dist/cdk/node-version.d.ts +14 -0
- package/dist/cdk/node-version.d.ts.map +1 -0
- package/dist/cdk/node-version.js +15 -0
- package/dist/cdk/stack-metadata.d.ts +12 -0
- package/dist/cdk/stack-metadata.d.ts.map +1 -0
- package/dist/cdk/stack-metadata.js +22 -0
- package/dist/cdk/stack-metadata.test.d.ts +2 -0
- package/dist/cdk/stack-metadata.test.d.ts.map +1 -0
- package/dist/cdk/stack-metadata.test.js +56 -0
- package/dist/cdk/synth-guard.d.ts +14 -0
- package/dist/cdk/synth-guard.d.ts.map +1 -0
- package/dist/cdk/synth-guard.js +20 -0
- package/dist/cdk/synth-guard.test.d.ts +2 -0
- package/dist/cdk/synth-guard.test.d.ts.map +1 -0
- package/dist/cdk/synth-guard.test.js +15 -0
- package/dist/client/index.d.ts +97 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +238 -0
- package/dist/client/index.test.d.ts +2 -0
- package/dist/client/index.test.d.ts.map +1 -0
- package/dist/client/index.test.js +113 -0
- package/dist/common/config.d.ts +45 -0
- package/dist/common/config.d.ts.map +1 -0
- package/dist/common/config.js +154 -0
- package/dist/common/config.test.d.ts +2 -0
- package/dist/common/config.test.d.ts.map +1 -0
- package/dist/common/config.test.js +173 -0
- package/dist/common/constants.d.ts +11 -0
- package/dist/common/constants.d.ts.map +1 -0
- package/dist/common/constants.js +12 -0
- package/dist/common/crypto.d.ts +6 -0
- package/dist/common/crypto.d.ts.map +1 -0
- package/dist/common/crypto.js +14 -0
- package/dist/common/index.d.ts +220 -0
- package/dist/common/index.d.ts.map +1 -0
- package/dist/common/index.js +180 -0
- package/dist/common/index.test.d.ts +2 -0
- package/dist/common/index.test.d.ts.map +1 -0
- package/dist/common/index.test.js +195 -0
- package/dist/common/mock-data.d.ts +40 -0
- package/dist/common/mock-data.d.ts.map +1 -0
- package/dist/common/mock-data.js +39 -0
- package/dist/common/official-bb-names.generated.d.ts +7 -0
- package/dist/common/official-bb-names.generated.d.ts.map +1 -0
- package/dist/common/official-bb-names.generated.js +28 -0
- package/dist/common/sdk-registry.d.ts +136 -0
- package/dist/common/sdk-registry.d.ts.map +1 -0
- package/dist/common/sdk-registry.js +125 -0
- package/dist/constants.d.ts +27 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +28 -0
- package/dist/cors.d.ts +39 -0
- package/dist/cors.d.ts.map +1 -0
- package/dist/cors.js +85 -0
- package/dist/cors.test.d.ts +2 -0
- package/dist/cors.test.d.ts.map +1 -0
- package/dist/cors.test.js +241 -0
- package/dist/db-naming.d.ts +21 -0
- package/dist/db-naming.d.ts.map +1 -0
- package/dist/db-naming.js +38 -0
- package/dist/db-naming.test.d.ts +2 -0
- package/dist/db-naming.test.d.ts.map +1 -0
- package/dist/db-naming.test.js +29 -0
- package/dist/errors.d.ts +67 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +69 -0
- package/dist/hosting.d.ts +258 -0
- package/dist/hosting.d.ts.map +1 -0
- package/dist/hosting.js +340 -0
- package/dist/hosting.test.d.ts +2 -0
- package/dist/hosting.test.d.ts.map +1 -0
- package/dist/hosting.test.js +1077 -0
- package/dist/index.cdk.d.ts +13 -0
- package/dist/index.cdk.d.ts.map +1 -0
- package/dist/index.cdk.js +13 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/lambda-handler.d.ts +131 -0
- package/dist/lambda-handler.d.ts.map +1 -0
- package/dist/lambda-handler.js +610 -0
- package/dist/lambda-handler.test.d.ts +2 -0
- package/dist/lambda-handler.test.d.ts.map +1 -0
- package/dist/lambda-handler.test.js +835 -0
- package/dist/pipeline/index.d.ts +4 -0
- package/dist/pipeline/index.d.ts.map +1 -0
- package/dist/pipeline/index.js +3 -0
- package/dist/pipeline/pipeline-construct.d.ts +130 -0
- package/dist/pipeline/pipeline-construct.d.ts.map +1 -0
- package/dist/pipeline/pipeline-construct.js +484 -0
- package/dist/pipeline/pipeline.test.d.ts +2 -0
- package/dist/pipeline/pipeline.test.d.ts.map +1 -0
- package/dist/pipeline/pipeline.test.js +1231 -0
- package/dist/pipeline/types.d.ts +351 -0
- package/dist/pipeline/types.d.ts.map +1 -0
- package/dist/pipeline/types.js +3 -0
- package/dist/raw-route.cdk.d.ts +47 -0
- package/dist/raw-route.cdk.d.ts.map +1 -0
- package/dist/raw-route.cdk.js +51 -0
- package/dist/raw-route.d.ts +119 -0
- package/dist/raw-route.d.ts.map +1 -0
- package/dist/raw-route.js +239 -0
- package/dist/raw-route.mock.d.ts +47 -0
- package/dist/raw-route.mock.d.ts.map +1 -0
- package/dist/raw-route.mock.js +51 -0
- package/dist/raw-route.test.d.ts +2 -0
- package/dist/raw-route.test.d.ts.map +1 -0
- package/dist/raw-route.test.js +597 -0
- package/dist/redact.d.ts +51 -0
- package/dist/redact.d.ts.map +1 -0
- package/dist/redact.js +134 -0
- package/dist/redact.test.d.ts +2 -0
- package/dist/redact.test.d.ts.map +1 -0
- package/dist/redact.test.js +199 -0
- package/dist/rpc.d.ts +54 -0
- package/dist/rpc.d.ts.map +1 -0
- package/dist/rpc.js +127 -0
- package/dist/rpc.test.d.ts +2 -0
- package/dist/rpc.test.d.ts.map +1 -0
- package/dist/rpc.test.js +60 -0
- package/dist/scripts/cdk-telemetry-env.d.ts +13 -0
- package/dist/scripts/cdk-telemetry-env.d.ts.map +1 -0
- package/dist/scripts/cdk-telemetry-env.js +21 -0
- package/dist/scripts/cdk-telemetry-env.test.d.ts +2 -0
- package/dist/scripts/cdk-telemetry-env.test.d.ts.map +1 -0
- package/dist/scripts/cdk-telemetry-env.test.js +56 -0
- package/dist/scripts/cleanup.d.ts +3 -0
- package/dist/scripts/cleanup.d.ts.map +1 -0
- package/dist/scripts/cleanup.js +35 -0
- package/dist/scripts/console.d.ts +6 -0
- package/dist/scripts/console.d.ts.map +1 -0
- package/dist/scripts/console.js +25 -0
- package/dist/scripts/deploy.d.ts +6 -0
- package/dist/scripts/deploy.d.ts.map +1 -0
- package/dist/scripts/deploy.js +82 -0
- package/dist/scripts/destroy.d.ts +6 -0
- package/dist/scripts/destroy.d.ts.map +1 -0
- package/dist/scripts/destroy.js +30 -0
- package/dist/scripts/dev-server-cors.test.d.ts +2 -0
- package/dist/scripts/dev-server-cors.test.d.ts.map +1 -0
- package/dist/scripts/dev-server-cors.test.js +23 -0
- package/dist/scripts/dev-server-telemetry.test.d.ts +2 -0
- package/dist/scripts/dev-server-telemetry.test.d.ts.map +1 -0
- package/dist/scripts/dev-server-telemetry.test.js +113 -0
- package/dist/scripts/dev-server.d.ts +21 -0
- package/dist/scripts/dev-server.d.ts.map +1 -0
- package/dist/scripts/dev-server.js +456 -0
- package/dist/scripts/ensure-secrets.d.ts +31 -0
- package/dist/scripts/ensure-secrets.d.ts.map +1 -0
- package/dist/scripts/ensure-secrets.js +100 -0
- package/dist/scripts/ensure-secrets.test.d.ts +2 -0
- package/dist/scripts/ensure-secrets.test.d.ts.map +1 -0
- package/dist/scripts/ensure-secrets.test.js +44 -0
- package/dist/scripts/external-migrations-step.d.ts +62 -0
- package/dist/scripts/external-migrations-step.d.ts.map +1 -0
- package/dist/scripts/external-migrations-step.js +243 -0
- package/dist/scripts/external-migrations-step.test.d.ts +2 -0
- package/dist/scripts/external-migrations-step.test.d.ts.map +1 -0
- package/dist/scripts/external-migrations-step.test.js +47 -0
- package/dist/scripts/extract-ts-types.d.ts +65 -0
- package/dist/scripts/extract-ts-types.d.ts.map +1 -0
- package/dist/scripts/extract-ts-types.js +664 -0
- package/dist/scripts/extract-ts-types.test.d.ts +2 -0
- package/dist/scripts/extract-ts-types.test.d.ts.map +1 -0
- package/dist/scripts/extract-ts-types.test.js +497 -0
- package/dist/scripts/generate-client-worker.d.ts +2 -0
- package/dist/scripts/generate-client-worker.d.ts.map +1 -0
- package/dist/scripts/generate-client-worker.js +13 -0
- package/dist/scripts/generate-client.d.ts +14 -0
- package/dist/scripts/generate-client.d.ts.map +1 -0
- package/dist/scripts/generate-client.js +73 -0
- package/dist/scripts/generate-client.test.d.ts +2 -0
- package/dist/scripts/generate-client.test.d.ts.map +1 -0
- package/dist/scripts/generate-client.test.js +48 -0
- package/dist/scripts/generate-spec-cli.d.ts +3 -0
- package/dist/scripts/generate-spec-cli.d.ts.map +1 -0
- package/dist/scripts/generate-spec-cli.js +77 -0
- package/dist/scripts/generate-spec-cli.test.d.ts +14 -0
- package/dist/scripts/generate-spec-cli.test.d.ts.map +1 -0
- package/dist/scripts/generate-spec-cli.test.js +90 -0
- package/dist/scripts/generate-spec.d.ts +61 -0
- package/dist/scripts/generate-spec.d.ts.map +1 -0
- package/dist/scripts/generate-spec.js +746 -0
- package/dist/scripts/generate-spec.test.d.ts +12 -0
- package/dist/scripts/generate-spec.test.d.ts.map +1 -0
- package/dist/scripts/generate-spec.test.js +88 -0
- package/dist/scripts/index.d.ts +12 -0
- package/dist/scripts/index.d.ts.map +1 -0
- package/dist/scripts/index.js +13 -0
- package/dist/scripts/sandbox.d.ts +11 -0
- package/dist/scripts/sandbox.d.ts.map +1 -0
- package/dist/scripts/sandbox.js +200 -0
- package/dist/scripts/telemetry-cli.d.ts +3 -0
- package/dist/scripts/telemetry-cli.d.ts.map +1 -0
- package/dist/scripts/telemetry-cli.js +8 -0
- package/dist/scripts/telemetry.d.ts +17 -0
- package/dist/scripts/telemetry.d.ts.map +1 -0
- package/dist/scripts/telemetry.js +150 -0
- package/dist/scripts/telemetry.test.d.ts +2 -0
- package/dist/scripts/telemetry.test.d.ts.map +1 -0
- package/dist/scripts/telemetry.test.js +203 -0
- package/dist/scripts/validate-spec.d.ts +22 -0
- package/dist/scripts/validate-spec.d.ts.map +1 -0
- package/dist/scripts/validate-spec.js +159 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +3 -0
- package/dist/server/withAuth.d.ts +142 -0
- package/dist/server/withAuth.d.ts.map +1 -0
- package/dist/server/withAuth.js +261 -0
- package/dist/server/withAuth.test.d.ts +2 -0
- package/dist/server/withAuth.test.d.ts.map +1 -0
- package/dist/server/withAuth.test.js +278 -0
- package/dist/telemetry/client.d.ts +59 -0
- package/dist/telemetry/client.d.ts.map +1 -0
- package/dist/telemetry/client.js +215 -0
- package/dist/telemetry/config-writer.d.ts +16 -0
- package/dist/telemetry/config-writer.d.ts.map +1 -0
- package/dist/telemetry/config-writer.js +36 -0
- package/dist/telemetry/consent-commands.test.d.ts +2 -0
- package/dist/telemetry/consent-commands.test.d.ts.map +1 -0
- package/dist/telemetry/consent-commands.test.js +161 -0
- package/dist/telemetry/consent.d.ts +60 -0
- package/dist/telemetry/consent.d.ts.map +1 -0
- package/dist/telemetry/consent.js +122 -0
- package/dist/telemetry/environment.d.ts +33 -0
- package/dist/telemetry/environment.d.ts.map +1 -0
- package/dist/telemetry/environment.js +87 -0
- package/dist/telemetry/identifiers.d.ts +20 -0
- package/dist/telemetry/identifiers.d.ts.map +1 -0
- package/dist/telemetry/identifiers.js +86 -0
- package/dist/telemetry/index.d.ts +6 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +4 -0
- package/dist/telemetry/telemetry.test.d.ts +2 -0
- package/dist/telemetry/telemetry.test.d.ts.map +1 -0
- package/dist/telemetry/telemetry.test.js +1131 -0
- package/dist/telemetry/trackCommand.d.ts +32 -0
- package/dist/telemetry/trackCommand.d.ts.map +1 -0
- package/dist/telemetry/trackCommand.js +102 -0
- package/dist/telemetry/types.d.ts +92 -0
- package/dist/telemetry/types.d.ts.map +1 -0
- package/dist/telemetry/types.js +1 -0
- package/dist/types.d.ts +24 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +2 -0
- package/package.json +83 -0
- package/src/api.test.ts +25 -0
- package/src/api.ts +163 -0
- package/src/bb-utils.ts +13 -0
- package/src/builtin-routes.ts +62 -0
- package/src/cdk/__fixtures__/factory-backend.ts +8 -0
- package/src/cdk/__fixtures__/fullid-construct-backend.ts +42 -0
- package/src/cdk/__fixtures__/handler.ts +4 -0
- package/src/cdk/__fixtures__/side-effect-backend.ts +7 -0
- package/src/cdk/blocks-backend.test.ts +207 -0
- package/src/cdk/blocks-backend.ts +249 -0
- package/src/cdk/blocks-stack.test.ts +106 -0
- package/src/cdk/config-registry.ts +106 -0
- package/src/cdk/index.ts +115 -0
- package/src/cdk/mixins.test.ts +129 -0
- package/src/cdk/mixins.ts +41 -0
- package/src/cdk/node-version.ts +17 -0
- package/src/cdk/stack-metadata.test.ts +71 -0
- package/src/cdk/stack-metadata.ts +29 -0
- package/src/cdk/synth-guard.test.ts +21 -0
- package/src/cdk/synth-guard.ts +23 -0
- package/src/client/index.test.ts +118 -0
- package/src/client/index.ts +320 -0
- package/src/common/config.test.ts +236 -0
- package/src/common/config.ts +169 -0
- package/src/common/constants.ts +15 -0
- package/src/common/crypto.ts +15 -0
- package/src/common/index.test.ts +242 -0
- package/src/common/index.ts +335 -0
- package/src/common/mock-data.ts +52 -0
- package/src/common/official-bb-names.generated.ts +29 -0
- package/src/common/sdk-registry.ts +150 -0
- package/src/constants.ts +31 -0
- package/src/cors.test.ts +279 -0
- package/src/cors.ts +91 -0
- package/src/db-naming.test.ts +48 -0
- package/src/db-naming.ts +41 -0
- package/src/errors.ts +72 -0
- package/src/hosting.test.ts +1431 -0
- package/src/hosting.ts +626 -0
- package/src/index.cdk.ts +45 -0
- package/src/index.ts +22 -0
- package/src/lambda-handler.test.ts +1005 -0
- package/src/lambda-handler.ts +706 -0
- package/src/pipeline/index.ts +12 -0
- package/src/pipeline/pipeline-construct.ts +662 -0
- package/src/pipeline/pipeline.test.ts +1565 -0
- package/src/pipeline/types.ts +384 -0
- package/src/raw-route.cdk.ts +56 -0
- package/src/raw-route.mock.ts +56 -0
- package/src/raw-route.test.ts +819 -0
- package/src/raw-route.ts +316 -0
- package/src/redact.test.ts +222 -0
- package/src/redact.ts +143 -0
- package/src/rpc.test.ts +73 -0
- package/src/rpc.ts +174 -0
- package/src/scripts/cdk-telemetry-env.test.ts +75 -0
- package/src/scripts/cdk-telemetry-env.ts +23 -0
- package/src/scripts/cleanup.ts +39 -0
- package/src/scripts/console.ts +34 -0
- package/src/scripts/deploy.ts +106 -0
- package/src/scripts/destroy.ts +42 -0
- package/src/scripts/dev-server-cors.test.ts +28 -0
- package/src/scripts/dev-server-telemetry.test.ts +127 -0
- package/src/scripts/dev-server.ts +515 -0
- package/src/scripts/ensure-secrets.test.ts +50 -0
- package/src/scripts/ensure-secrets.ts +113 -0
- package/src/scripts/external-migrations-step.test.ts +64 -0
- package/src/scripts/external-migrations-step.ts +269 -0
- package/src/scripts/extract-ts-types.test.ts +516 -0
- package/src/scripts/extract-ts-types.ts +773 -0
- package/src/scripts/generate-client-worker.ts +15 -0
- package/src/scripts/generate-client.test.ts +69 -0
- package/src/scripts/generate-client.ts +86 -0
- package/src/scripts/generate-spec-cli.test.ts +106 -0
- package/src/scripts/generate-spec-cli.ts +92 -0
- package/src/scripts/generate-spec.test.ts +99 -0
- package/src/scripts/generate-spec.ts +833 -0
- package/src/scripts/index.ts +21 -0
- package/src/scripts/sandbox.ts +230 -0
- package/src/scripts/telemetry-cli.ts +10 -0
- package/src/scripts/telemetry.test.ts +239 -0
- package/src/scripts/telemetry.ts +173 -0
- package/src/scripts/validate-spec.ts +199 -0
- package/src/server/index.ts +5 -0
- package/src/server/withAuth.test.ts +348 -0
- package/src/server/withAuth.ts +323 -0
- package/src/telemetry/client.ts +226 -0
- package/src/telemetry/config-writer.ts +52 -0
- package/src/telemetry/consent-commands.test.ts +196 -0
- package/src/telemetry/consent.ts +154 -0
- package/src/telemetry/environment.ts +100 -0
- package/src/telemetry/identifiers.ts +94 -0
- package/src/telemetry/index.ts +11 -0
- package/src/telemetry/telemetry.test.ts +1343 -0
- package/src/telemetry/trackCommand.ts +110 -0
- package/src/telemetry/types.ts +92 -0
- package/src/types.ts +33 -0
- package/src/version.ts +2 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { describe, it, beforeEach, afterEach } from 'node:test';
|
|
4
|
+
import assert from 'node:assert';
|
|
5
|
+
import { getConfig, getConfigSync, loadConfigToProcessEnv, preloadConfig, _resetConfigCache, _setS3Fetcher } from './config.js';
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
_resetConfigCache();
|
|
8
|
+
delete process.env.BLOCKS_CONFIG_BUCKET;
|
|
9
|
+
delete process.env.BLOCKS_CONFIG_KEY;
|
|
10
|
+
});
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
_resetConfigCache();
|
|
13
|
+
delete process.env.BLOCKS_CONFIG_BUCKET;
|
|
14
|
+
delete process.env.BLOCKS_CONFIG_KEY;
|
|
15
|
+
});
|
|
16
|
+
describe('config — no S3 env vars (local dev)', () => {
|
|
17
|
+
it('getConfig returns empty string when key not in env', async () => {
|
|
18
|
+
const result = await getConfig('SOME_KEY');
|
|
19
|
+
assert.strictEqual(result, '');
|
|
20
|
+
});
|
|
21
|
+
it('getConfig returns env var value when set', async () => {
|
|
22
|
+
process.env.MY_KEY = 'my-value';
|
|
23
|
+
const result = await getConfig('MY_KEY');
|
|
24
|
+
assert.strictEqual(result, 'my-value');
|
|
25
|
+
delete process.env.MY_KEY;
|
|
26
|
+
});
|
|
27
|
+
it('loadConfigToProcessEnv does not throw when no S3 vars', async () => {
|
|
28
|
+
await assert.doesNotReject(() => loadConfigToProcessEnv());
|
|
29
|
+
});
|
|
30
|
+
it('preloadConfig does not throw when no S3 vars', async () => {
|
|
31
|
+
await assert.doesNotReject(() => preloadConfig());
|
|
32
|
+
});
|
|
33
|
+
it('getConfigSync returns env var value', () => {
|
|
34
|
+
process.env.SYNC_KEY = 'sync-value';
|
|
35
|
+
const result = getConfigSync('SYNC_KEY');
|
|
36
|
+
assert.strictEqual(result, 'sync-value');
|
|
37
|
+
delete process.env.SYNC_KEY;
|
|
38
|
+
});
|
|
39
|
+
it('getConfigSync returns empty string for unknown key', () => {
|
|
40
|
+
const result = getConfigSync('UNKNOWN');
|
|
41
|
+
assert.strictEqual(result, '');
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
describe('config — S3 load success', () => {
|
|
45
|
+
it('loads config from S3 and caches it', async () => {
|
|
46
|
+
process.env.BLOCKS_CONFIG_BUCKET = 'test-bucket';
|
|
47
|
+
process.env.BLOCKS_CONFIG_KEY = 'blocks-config.json';
|
|
48
|
+
let callCount = 0;
|
|
49
|
+
_setS3Fetcher(async () => {
|
|
50
|
+
callCount++;
|
|
51
|
+
return JSON.stringify({ DB_URL: 'postgres://localhost', QUEUE_ARN: 'arn:aws:sqs:us-east-1:123:queue' });
|
|
52
|
+
});
|
|
53
|
+
const result = await getConfig('DB_URL');
|
|
54
|
+
assert.strictEqual(result, 'postgres://localhost');
|
|
55
|
+
const result2 = await getConfig('QUEUE_ARN');
|
|
56
|
+
assert.strictEqual(result2, 'arn:aws:sqs:us-east-1:123:queue');
|
|
57
|
+
assert.strictEqual(callCount, 1, 'S3 should only be called once (cached)');
|
|
58
|
+
});
|
|
59
|
+
it('loadConfigToProcessEnv injects values into process.env', async () => {
|
|
60
|
+
process.env.BLOCKS_CONFIG_BUCKET = 'test-bucket';
|
|
61
|
+
process.env.BLOCKS_CONFIG_KEY = 'blocks-config.json';
|
|
62
|
+
_setS3Fetcher(async () => JSON.stringify({ INJECTED_KEY: 'injected-value' }));
|
|
63
|
+
await loadConfigToProcessEnv();
|
|
64
|
+
assert.strictEqual(process.env.INJECTED_KEY, 'injected-value');
|
|
65
|
+
delete process.env.INJECTED_KEY;
|
|
66
|
+
});
|
|
67
|
+
it('loadConfigToProcessEnv does not override existing env vars', async () => {
|
|
68
|
+
process.env.BLOCKS_CONFIG_BUCKET = 'test-bucket';
|
|
69
|
+
process.env.BLOCKS_CONFIG_KEY = 'blocks-config.json';
|
|
70
|
+
process.env.EXISTING_KEY = 'original';
|
|
71
|
+
_setS3Fetcher(async () => JSON.stringify({ EXISTING_KEY: 'from-s3' }));
|
|
72
|
+
await loadConfigToProcessEnv();
|
|
73
|
+
assert.strictEqual(process.env.EXISTING_KEY, 'original');
|
|
74
|
+
delete process.env.EXISTING_KEY;
|
|
75
|
+
});
|
|
76
|
+
it('getConfigSync returns cached value after load', async () => {
|
|
77
|
+
process.env.BLOCKS_CONFIG_BUCKET = 'test-bucket';
|
|
78
|
+
process.env.BLOCKS_CONFIG_KEY = 'blocks-config.json';
|
|
79
|
+
_setS3Fetcher(async () => JSON.stringify({ CACHED_KEY: 'cached-value' }));
|
|
80
|
+
await preloadConfig();
|
|
81
|
+
const result = getConfigSync('CACHED_KEY');
|
|
82
|
+
assert.strictEqual(result, 'cached-value');
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
describe('config — S3 errors', () => {
|
|
86
|
+
it('gracefully handles NoSuchKey (file not yet written)', async () => {
|
|
87
|
+
process.env.BLOCKS_CONFIG_BUCKET = 'test-bucket';
|
|
88
|
+
process.env.BLOCKS_CONFIG_KEY = 'blocks-config.json';
|
|
89
|
+
const noSuchKeyError = new Error('The specified key does not exist.');
|
|
90
|
+
noSuchKeyError.name = 'NoSuchKey';
|
|
91
|
+
_setS3Fetcher(async () => { throw noSuchKeyError; });
|
|
92
|
+
const result = await getConfig('ANY_KEY');
|
|
93
|
+
assert.strictEqual(result, '', 'Should return empty string (empty config) on NoSuchKey');
|
|
94
|
+
});
|
|
95
|
+
it('gracefully handles S3 404 status code', async () => {
|
|
96
|
+
process.env.BLOCKS_CONFIG_BUCKET = 'test-bucket';
|
|
97
|
+
process.env.BLOCKS_CONFIG_KEY = 'blocks-config.json';
|
|
98
|
+
const notFoundError = new Error('Not Found');
|
|
99
|
+
notFoundError.$metadata = { httpStatusCode: 404 };
|
|
100
|
+
_setS3Fetcher(async () => { throw notFoundError; });
|
|
101
|
+
const result = await getConfig('ANY_KEY');
|
|
102
|
+
assert.strictEqual(result, '', 'Should return empty string (empty config) on 404');
|
|
103
|
+
});
|
|
104
|
+
it('throws with clear message on S3 network error', async () => {
|
|
105
|
+
process.env.BLOCKS_CONFIG_BUCKET = 'test-bucket';
|
|
106
|
+
process.env.BLOCKS_CONFIG_KEY = 'blocks-config.json';
|
|
107
|
+
_setS3Fetcher(async () => { throw new Error('Network timeout'); });
|
|
108
|
+
await assert.rejects(() => getConfig('ANY_KEY'), (err) => {
|
|
109
|
+
assert.ok(err.message.includes('[Blocks] Failed to load config from S3'));
|
|
110
|
+
assert.ok(err.message.includes('test-bucket/blocks-config.json'));
|
|
111
|
+
assert.ok(err.message.includes('Network timeout'));
|
|
112
|
+
return true;
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
it('throws on empty config file', async () => {
|
|
116
|
+
process.env.BLOCKS_CONFIG_BUCKET = 'test-bucket';
|
|
117
|
+
process.env.BLOCKS_CONFIG_KEY = 'blocks-config.json';
|
|
118
|
+
_setS3Fetcher(async () => { throw new Error('Empty config file'); });
|
|
119
|
+
await assert.rejects(() => getConfig('ANY_KEY'), (err) => {
|
|
120
|
+
assert.ok(err.message.includes('[Blocks] Failed to load config from S3'));
|
|
121
|
+
assert.ok(err.message.includes('Empty config file'));
|
|
122
|
+
return true;
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
it('throws on malformed JSON', async () => {
|
|
126
|
+
process.env.BLOCKS_CONFIG_BUCKET = 'test-bucket';
|
|
127
|
+
process.env.BLOCKS_CONFIG_KEY = 'blocks-config.json';
|
|
128
|
+
_setS3Fetcher(async () => 'not valid json {{{');
|
|
129
|
+
await assert.rejects(() => getConfig('ANY_KEY'), (err) => {
|
|
130
|
+
assert.ok(err.message.includes('[Blocks] Failed to load config from S3'));
|
|
131
|
+
return true;
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
it('throws when config is an array instead of object', async () => {
|
|
135
|
+
process.env.BLOCKS_CONFIG_BUCKET = 'test-bucket';
|
|
136
|
+
process.env.BLOCKS_CONFIG_KEY = 'blocks-config.json';
|
|
137
|
+
_setS3Fetcher(async () => '["not", "an", "object"]');
|
|
138
|
+
await assert.rejects(() => getConfig('ANY_KEY'), (err) => {
|
|
139
|
+
assert.ok(err.message.includes('[Blocks] Config file must be a JSON object'));
|
|
140
|
+
return true;
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
it('throws when config is null', async () => {
|
|
144
|
+
process.env.BLOCKS_CONFIG_BUCKET = 'test-bucket';
|
|
145
|
+
process.env.BLOCKS_CONFIG_KEY = 'blocks-config.json';
|
|
146
|
+
_setS3Fetcher(async () => 'null');
|
|
147
|
+
await assert.rejects(() => getConfig('ANY_KEY'), (err) => {
|
|
148
|
+
assert.ok(err.message.includes('[Blocks] Config file must be a JSON object'));
|
|
149
|
+
return true;
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
describe('config — concurrent access', () => {
|
|
154
|
+
it('deduplicates concurrent calls to the same S3 fetch', async () => {
|
|
155
|
+
process.env.BLOCKS_CONFIG_BUCKET = 'test-bucket';
|
|
156
|
+
process.env.BLOCKS_CONFIG_KEY = 'blocks-config.json';
|
|
157
|
+
let callCount = 0;
|
|
158
|
+
_setS3Fetcher(async () => {
|
|
159
|
+
callCount++;
|
|
160
|
+
await new Promise(r => setTimeout(r, 50));
|
|
161
|
+
return JSON.stringify({ KEY_A: 'value-a' });
|
|
162
|
+
});
|
|
163
|
+
const [r1, r2, r3] = await Promise.all([
|
|
164
|
+
getConfig('KEY_A'),
|
|
165
|
+
getConfig('KEY_A'),
|
|
166
|
+
getConfig('KEY_A'),
|
|
167
|
+
]);
|
|
168
|
+
assert.strictEqual(r1, 'value-a');
|
|
169
|
+
assert.strictEqual(r2, 'value-a');
|
|
170
|
+
assert.strictEqual(r3, 'value-a');
|
|
171
|
+
assert.strictEqual(callCount, 1, 'S3 should only be called once even with concurrent access');
|
|
172
|
+
});
|
|
173
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared constants used across the Blocks framework.
|
|
3
|
+
*
|
|
4
|
+
* Centralizes magic strings so directory names and conventions
|
|
5
|
+
* can be updated in one place.
|
|
6
|
+
*/
|
|
7
|
+
/** Directory where sandbox/deploy config is written (relative to project root). */
|
|
8
|
+
export declare const BLOCKS_SANDBOX_DIR = ".blocks-sandbox";
|
|
9
|
+
/** Default backend entry point directory name. */
|
|
10
|
+
export declare const BLOCKS_BACKEND_DIR = "aws-blocks";
|
|
11
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/common/constants.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AAEH,mFAAmF;AACnF,eAAO,MAAM,kBAAkB,oBAAoB,CAAC;AAEpD,kDAAkD;AAClD,eAAO,MAAM,kBAAkB,eAAe,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Shared constants used across the Blocks framework.
|
|
5
|
+
*
|
|
6
|
+
* Centralizes magic strings so directory names and conventions
|
|
7
|
+
* can be updated in one place.
|
|
8
|
+
*/
|
|
9
|
+
/** Directory where sandbox/deploy config is written (relative to project root). */
|
|
10
|
+
export const BLOCKS_SANDBOX_DIR = '.blocks-sandbox';
|
|
11
|
+
/** Default backend entry point directory name. */
|
|
12
|
+
export const BLOCKS_BACKEND_DIR = 'aws-blocks';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compares two strings in constant time to prevent timing side-channel attacks.
|
|
3
|
+
* Use this for HMAC signature validation — never use === or !== for crypto comparisons.
|
|
4
|
+
*/
|
|
5
|
+
export declare function constantTimeEquals(a: string, b: string): boolean;
|
|
6
|
+
//# sourceMappingURL=crypto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/common/crypto.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAKhE"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { timingSafeEqual } from 'node:crypto';
|
|
4
|
+
/**
|
|
5
|
+
* Compares two strings in constant time to prevent timing side-channel attacks.
|
|
6
|
+
* Use this for HMAC signature validation — never use === or !== for crypto comparisons.
|
|
7
|
+
*/
|
|
8
|
+
export function constantTimeEquals(a, b) {
|
|
9
|
+
const ab = Buffer.from(a, 'utf8');
|
|
10
|
+
const bb = Buffer.from(b, 'utf8');
|
|
11
|
+
if (ab.length !== bb.length)
|
|
12
|
+
return false;
|
|
13
|
+
return timingSafeEqual(ab, bb);
|
|
14
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import type { StackProps } from 'aws-cdk-lib';
|
|
2
|
+
import type { Construct } from 'constructs';
|
|
3
|
+
export { OFFICIAL_BB_NAMES } from './official-bb-names.generated.js';
|
|
4
|
+
export interface ScopeOptions {
|
|
5
|
+
parent?: ScopeParent;
|
|
6
|
+
bbName?: string;
|
|
7
|
+
bbVersion?: string;
|
|
8
|
+
}
|
|
9
|
+
export type ScopeParent = Scope | {
|
|
10
|
+
id: string;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Scope defines a logical boundary for your backend resources.
|
|
14
|
+
*
|
|
15
|
+
* Building Blocks are instantiated within a scope. The scope provides namespacing and resource organization.
|
|
16
|
+
*
|
|
17
|
+
* ## Usage
|
|
18
|
+
*
|
|
19
|
+
* Create a scope at the top of your backend file:
|
|
20
|
+
*
|
|
21
|
+
* ```typescript
|
|
22
|
+
* import { Scope } from '@aws-blocks/core';
|
|
23
|
+
*
|
|
24
|
+
* const scope = new Scope('my-app');
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* Then instantiate Building Blocks within that scope:
|
|
28
|
+
*
|
|
29
|
+
* ```typescript
|
|
30
|
+
* import { KVStore } from '@aws-blocks/bb-kv-store';
|
|
31
|
+
*
|
|
32
|
+
* const store = new KVStore(scope, 'user-prefs', {});
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* ## Available Building Blocks
|
|
36
|
+
*
|
|
37
|
+
* **IMPORTANT: Always use Blocks Building Blocks instead of creating your own storage, data structures, or AWS SDK calls.**
|
|
38
|
+
*
|
|
39
|
+
* Building Blocks provide:
|
|
40
|
+
* - **Local mocking** - Run in-process during development (`npm run dev`) with no AWS resources
|
|
41
|
+
* - **Production deployment** - Automatically provision and configure AWS resources (`npm run sandbox` or `npm run deploy`)
|
|
42
|
+
* - **Same code, both environments** - Your application logic works identically in local and production
|
|
43
|
+
*
|
|
44
|
+
* Each Building Block has comprehensive docstrings with use-cases, scaling characteristics, performance metrics, and best practices. Import and explore:
|
|
45
|
+
*
|
|
46
|
+
* - **`ApiNamespace`** from `@aws-blocks/core` - Define type-safe APIs with automatic frontend/backend integration
|
|
47
|
+
* - **`KVStore`** from `@aws-blocks/bb-kv-store` - Simple key-value storage (DynamoDB)
|
|
48
|
+
* - **`DistributedTable`** from `@aws-blocks/bb-distributed-table` - Type-safe tables with Zod schemas, indexes, and queries (DynamoDB)
|
|
49
|
+
* - **`AuthBasic`** from `@aws-blocks/bb-auth-basic` - Username/password authentication with JWT tokens and built-in UI components
|
|
50
|
+
* - **`Database`** from `@aws-blocks/bb-data` - SQL database with Kysely query builder (Aurora Serverless)
|
|
51
|
+
*
|
|
52
|
+
* Read each Building Block's class and method docstrings for detailed documentation.
|
|
53
|
+
*
|
|
54
|
+
* ## Choosing the Right Building Block
|
|
55
|
+
*
|
|
56
|
+
* **For authentication:**
|
|
57
|
+
* - Use `AuthBasic` for username/password auth (includes built-in UI component)
|
|
58
|
+
* - Provides JWT tokens, password hashing, and session management
|
|
59
|
+
*
|
|
60
|
+
* **For data storage, choose based on your access patterns:**
|
|
61
|
+
*
|
|
62
|
+
* - **`KVStore`** - Simple key-value lookups (user preferences, feature flags, session data)
|
|
63
|
+
* - Get/set by key only
|
|
64
|
+
* - No queries or indexes
|
|
65
|
+
* - Simplest option
|
|
66
|
+
*
|
|
67
|
+
* - **`DistributedTable`** - Structured data with queries and indexes
|
|
68
|
+
* - Query by partition key with optional filtering
|
|
69
|
+
* - Secondary indexes for alternate access patterns
|
|
70
|
+
* - Supports filtering, sorting, pagination
|
|
71
|
+
* - Use Zod schemas for type safety
|
|
72
|
+
* - **Zero cost to start, highly scalable**
|
|
73
|
+
* - **Default choice for most application data**
|
|
74
|
+
*
|
|
75
|
+
* - **`Database`** - SQL database with full relational features
|
|
76
|
+
* - Use when you need: complex multi-table JOINs, SQL transactions across tables, foreign key constraints
|
|
77
|
+
* - Avoid when: DynamoDB limitations are acceptable (no ad-hoc queries, eventual consistency on indexes, 400KB item limit)
|
|
78
|
+
* - Requires migrations folder with .sql files
|
|
79
|
+
* - Local dev requires manual schema setup (see Database README)
|
|
80
|
+
* - Higher baseline cost than DistributedTable
|
|
81
|
+
*
|
|
82
|
+
* **Rule of thumb:** Use DistributedTable unless you specifically need SQL JOINs or transactions.
|
|
83
|
+
*
|
|
84
|
+
* ## Data Modeling
|
|
85
|
+
*
|
|
86
|
+
* - **For DistributedTable**: Use Zod schemas for runtime validation and type inference. Install: `npm install zod`
|
|
87
|
+
* - For flexible key-value fields: `z.record(z.string(), z.any())`
|
|
88
|
+
* - **For Database**: Define TypeScript interfaces and create migrations folder with .sql files
|
|
89
|
+
* - **For KVStore**: Store strings only (serialize objects as JSON)
|
|
90
|
+
*
|
|
91
|
+
* ## Local Development
|
|
92
|
+
*
|
|
93
|
+
* In local dev mode (`npm run dev`), Building Blocks run in-process with mock implementations.
|
|
94
|
+
* No AWS resources are created. State is ephemeral.
|
|
95
|
+
*
|
|
96
|
+
* ## Deployed to AWS
|
|
97
|
+
*
|
|
98
|
+
* When deployed (`npm run sandbox` or `npm run deploy`), Blocks provisions real AWS resources:
|
|
99
|
+
* - Lambda functions for your APIs
|
|
100
|
+
* - DynamoDB tables for KVStore and DistributedTable
|
|
101
|
+
* - Aurora Serverless for Database
|
|
102
|
+
* - S3 buckets for file storage
|
|
103
|
+
* - IAM roles and policies
|
|
104
|
+
*
|
|
105
|
+
* Infrastructure is **inferred from your code**. You write application logic; Blocks determines
|
|
106
|
+
* what AWS resources are needed and provisions them automatically.
|
|
107
|
+
*
|
|
108
|
+
* ## Best Practices
|
|
109
|
+
*
|
|
110
|
+
* - Use one scope per application or major feature boundary
|
|
111
|
+
* - Give scopes descriptive IDs (e.g., 'user-service', 'orders')
|
|
112
|
+
* - Nest scopes for complex applications using the `parent` option
|
|
113
|
+
* - Always use Building Blocks for storage - never create your own in-memory Maps or custom storage
|
|
114
|
+
*/
|
|
115
|
+
/**
|
|
116
|
+
* Metadata identifying a Building Block for user-agent attribution.
|
|
117
|
+
* BBs that want to participate in user-agent chains must set these on their class.
|
|
118
|
+
*/
|
|
119
|
+
export interface BuildingBlockMeta {
|
|
120
|
+
/** Short BB name used in user-agent strings, e.g. "KVStore", "AuthCognito" */
|
|
121
|
+
readonly bbName: string;
|
|
122
|
+
/** Package version from the BB's own package.json (build-time generated) */
|
|
123
|
+
readonly bbVersion: string;
|
|
124
|
+
}
|
|
125
|
+
export declare class Scope {
|
|
126
|
+
readonly id: string;
|
|
127
|
+
readonly parent: ScopeParent;
|
|
128
|
+
/** Short BB name used in user-agent strings. Set by subclass BBs. */
|
|
129
|
+
readonly bbName?: string;
|
|
130
|
+
/** Package version from the BB's own package.json. Set by subclass BBs. */
|
|
131
|
+
readonly bbVersion?: string;
|
|
132
|
+
/** Static registry — collects BB names as they're instantiated */
|
|
133
|
+
private static _bbRegistry;
|
|
134
|
+
constructor(id: string, options?: ScopeOptions);
|
|
135
|
+
/**
|
|
136
|
+
* Get registered BBs filtered for telemetry privacy.
|
|
137
|
+
*
|
|
138
|
+
* Only official BB names (in OFFICIAL_BB_NAMES) are returned in `blocks`.
|
|
139
|
+
* Custom BBs are counted in `customBlocksCount` but their names are never exposed.
|
|
140
|
+
*
|
|
141
|
+
* @returns Official blocks, total instance count, and total number of custom BB instances.
|
|
142
|
+
* @internal
|
|
143
|
+
*/
|
|
144
|
+
static getRegisteredBlocks(): {
|
|
145
|
+
blocks: Array<{
|
|
146
|
+
name: string;
|
|
147
|
+
version: string;
|
|
148
|
+
}>;
|
|
149
|
+
totalCount: number;
|
|
150
|
+
customBlocksCount: number;
|
|
151
|
+
};
|
|
152
|
+
/** Reset registry (useful for testing). */
|
|
153
|
+
static _resetRegistry(): void;
|
|
154
|
+
get fullId(): string;
|
|
155
|
+
/**
|
|
156
|
+
* Register a Lambda event handler for non-HTTP events (e.g., SQS, WebSocket).
|
|
157
|
+
* The handler receives the raw Lambda event record and processes it.
|
|
158
|
+
* Used by Building Blocks that consume event sources (e.g., AsyncJob → SQS,
|
|
159
|
+
* Realtime → API Gateway WebSocket).
|
|
160
|
+
*
|
|
161
|
+
* @param eventSource - Event source prefix (e.g., 'blocks.asyncjob', 'blocks.websocket').
|
|
162
|
+
* @param identifier - Building Block's fullId (scope-qualified ID, e.g., 'myapp-rt').
|
|
163
|
+
* Combined with eventSource to form the registry key '{eventSource}:{identifier}'.
|
|
164
|
+
* @param handler - Async function that processes the raw Lambda event.
|
|
165
|
+
*/
|
|
166
|
+
registerLambdaEventHandler(eventSource: string, identifier: string, handler: (record: any) => Promise<void>): void;
|
|
167
|
+
/**
|
|
168
|
+
* Register a client middleware package to be imported in the generated browser client.
|
|
169
|
+
* Used by Building Blocks that need browser-side protocol support (e.g., Realtime WebSocket).
|
|
170
|
+
* Only has effect during codegen — pushes to a global collector if one is active.
|
|
171
|
+
*/
|
|
172
|
+
registerClientMiddleware(packageSpecifier: string): void;
|
|
173
|
+
/**
|
|
174
|
+
* Register a dev server attachment package to be attached to the local HTTP server.
|
|
175
|
+
* Used by Building Blocks that need special local dev protocols (e.g., WebSocket server).
|
|
176
|
+
* Only has effect during dev server startup — pushes to a global collector if one is active.
|
|
177
|
+
*
|
|
178
|
+
* Dev attachments use an **explicit registration** pattern: the dev server imports
|
|
179
|
+
* the module and calls its exported `attach(server)` function, passing the HTTP
|
|
180
|
+
* server instance. This differs intentionally from client middleware, which uses
|
|
181
|
+
* self-registering side-effect imports — dev attachments need the server instance
|
|
182
|
+
* at registration time, which isn't available during a bare import.
|
|
183
|
+
*/
|
|
184
|
+
registerDevAttachment(packageSpecifier: string): void;
|
|
185
|
+
/**
|
|
186
|
+
* Build the customUserAgent chain by walking the scope tree.
|
|
187
|
+
*
|
|
188
|
+
* Produces an array of `[key, value]` pairs suitable for passing directly
|
|
189
|
+
* to any AWS SDK v3 client's `customUserAgent` configuration option.
|
|
190
|
+
*
|
|
191
|
+
* The chain encodes the nesting hierarchy:
|
|
192
|
+
* - `['aws-blocks', coreVersion]` — always first
|
|
193
|
+
* - `['bb', 'ParentBB/parentVersion']` — if this BB is nested inside another BB
|
|
194
|
+
* - `['bb', 'SelfBB/selfVersion']` — the current BB
|
|
195
|
+
*
|
|
196
|
+
* @param coreVersion - The version of @aws-blocks/core
|
|
197
|
+
* @returns Array of [key, value] pairs for customUserAgent
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* ```typescript
|
|
201
|
+
* const client = new DynamoDBClient({
|
|
202
|
+
* customUserAgent: this.buildUserAgentChain(),
|
|
203
|
+
* });
|
|
204
|
+
* ```
|
|
205
|
+
*/
|
|
206
|
+
protected buildUserAgentChain(): [string, string][];
|
|
207
|
+
}
|
|
208
|
+
export declare function computeScopeFullId(scope: {
|
|
209
|
+
id: string;
|
|
210
|
+
parent?: any;
|
|
211
|
+
}): string;
|
|
212
|
+
export interface BlocksStackProps extends StackProps {
|
|
213
|
+
backendHandlerPath: string;
|
|
214
|
+
backendCDKPath: string;
|
|
215
|
+
}
|
|
216
|
+
export declare class BlocksStack {
|
|
217
|
+
readonly id: string;
|
|
218
|
+
constructor(scope: Construct, id: string, props: BlocksStackProps);
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +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;AAG5C,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;CACxB;AAED,qBAAa,WAAW;IACvB,SAAgB,EAAE,EAAE,MAAM,CAAC;gBACf,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB;CAGjE"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { CORE_VERSION } from '../version.js';
|
|
4
|
+
import { OFFICIAL_BB_NAMES } from './official-bb-names.generated.js';
|
|
5
|
+
export { OFFICIAL_BB_NAMES } from './official-bb-names.generated.js';
|
|
6
|
+
export class Scope {
|
|
7
|
+
id;
|
|
8
|
+
parent;
|
|
9
|
+
/** Short BB name used in user-agent strings. Set by subclass BBs. */
|
|
10
|
+
bbName;
|
|
11
|
+
/** Package version from the BB's own package.json. Set by subclass BBs. */
|
|
12
|
+
bbVersion;
|
|
13
|
+
/** Static registry — collects BB names as they're instantiated */
|
|
14
|
+
static _bbRegistry = new Map();
|
|
15
|
+
constructor(id, options) {
|
|
16
|
+
this.id = id;
|
|
17
|
+
this.parent = options?.parent || globalThis.CURRENT_BLOCKS_STACK || {
|
|
18
|
+
id: typeof process !== 'undefined' ? process.env?.BLOCKS_STACK_NAME : undefined
|
|
19
|
+
};
|
|
20
|
+
if (options?.bbName) {
|
|
21
|
+
this.bbName = options.bbName;
|
|
22
|
+
this.bbVersion = options.bbVersion;
|
|
23
|
+
const existing = Scope._bbRegistry.get(options.bbName);
|
|
24
|
+
Scope._bbRegistry.set(options.bbName, {
|
|
25
|
+
version: options.bbVersion || 'unknown',
|
|
26
|
+
count: (existing?.count || 0) + 1,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Get registered BBs filtered for telemetry privacy.
|
|
32
|
+
*
|
|
33
|
+
* Only official BB names (in OFFICIAL_BB_NAMES) are returned in `blocks`.
|
|
34
|
+
* Custom BBs are counted in `customBlocksCount` but their names are never exposed.
|
|
35
|
+
*
|
|
36
|
+
* @returns Official blocks, total instance count, and total number of custom BB instances.
|
|
37
|
+
* @internal
|
|
38
|
+
*/
|
|
39
|
+
static getRegisteredBlocks() {
|
|
40
|
+
const blocks = [];
|
|
41
|
+
let totalCount = 0;
|
|
42
|
+
let customBlocksCount = 0;
|
|
43
|
+
for (const [name, { version, count }] of Scope._bbRegistry.entries()) {
|
|
44
|
+
totalCount += count;
|
|
45
|
+
if (OFFICIAL_BB_NAMES.has(name)) {
|
|
46
|
+
blocks.push({ name, version });
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
customBlocksCount += count;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return { blocks, totalCount, customBlocksCount };
|
|
53
|
+
}
|
|
54
|
+
/** Reset registry (useful for testing). */
|
|
55
|
+
static _resetRegistry() {
|
|
56
|
+
Scope._bbRegistry.clear();
|
|
57
|
+
}
|
|
58
|
+
get fullId() {
|
|
59
|
+
return computeScopeFullId(this);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Register a Lambda event handler for non-HTTP events (e.g., SQS, WebSocket).
|
|
63
|
+
* The handler receives the raw Lambda event record and processes it.
|
|
64
|
+
* Used by Building Blocks that consume event sources (e.g., AsyncJob → SQS,
|
|
65
|
+
* Realtime → API Gateway WebSocket).
|
|
66
|
+
*
|
|
67
|
+
* @param eventSource - Event source prefix (e.g., 'blocks.asyncjob', 'blocks.websocket').
|
|
68
|
+
* @param identifier - Building Block's fullId (scope-qualified ID, e.g., 'myapp-rt').
|
|
69
|
+
* Combined with eventSource to form the registry key '{eventSource}:{identifier}'.
|
|
70
|
+
* @param handler - Async function that processes the raw Lambda event.
|
|
71
|
+
*/
|
|
72
|
+
registerLambdaEventHandler(eventSource, identifier, handler) {
|
|
73
|
+
if (!globalThis.__BLOCKS_LAMBDA_EVENT_HANDLERS__) {
|
|
74
|
+
globalThis.__BLOCKS_LAMBDA_EVENT_HANDLERS__ = new Map();
|
|
75
|
+
}
|
|
76
|
+
globalThis.__BLOCKS_LAMBDA_EVENT_HANDLERS__.set(`${eventSource}:${identifier}`, handler);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Register a client middleware package to be imported in the generated browser client.
|
|
80
|
+
* Used by Building Blocks that need browser-side protocol support (e.g., Realtime WebSocket).
|
|
81
|
+
* Only has effect during codegen — pushes to a global collector if one is active.
|
|
82
|
+
*/
|
|
83
|
+
registerClientMiddleware(packageSpecifier) {
|
|
84
|
+
globalThis.__BLOCKS_CLIENT_MIDDLEWARE__?.push(packageSpecifier);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Register a dev server attachment package to be attached to the local HTTP server.
|
|
88
|
+
* Used by Building Blocks that need special local dev protocols (e.g., WebSocket server).
|
|
89
|
+
* Only has effect during dev server startup — pushes to a global collector if one is active.
|
|
90
|
+
*
|
|
91
|
+
* Dev attachments use an **explicit registration** pattern: the dev server imports
|
|
92
|
+
* the module and calls its exported `attach(server)` function, passing the HTTP
|
|
93
|
+
* server instance. This differs intentionally from client middleware, which uses
|
|
94
|
+
* self-registering side-effect imports — dev attachments need the server instance
|
|
95
|
+
* at registration time, which isn't available during a bare import.
|
|
96
|
+
*/
|
|
97
|
+
registerDevAttachment(packageSpecifier) {
|
|
98
|
+
globalThis.__BLOCKS_DEV_ATTACHMENTS__?.push(packageSpecifier);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Build the customUserAgent chain by walking the scope tree.
|
|
102
|
+
*
|
|
103
|
+
* Produces an array of `[key, value]` pairs suitable for passing directly
|
|
104
|
+
* to any AWS SDK v3 client's `customUserAgent` configuration option.
|
|
105
|
+
*
|
|
106
|
+
* The chain encodes the nesting hierarchy:
|
|
107
|
+
* - `['aws-blocks', coreVersion]` — always first
|
|
108
|
+
* - `['bb', 'ParentBB/parentVersion']` — if this BB is nested inside another BB
|
|
109
|
+
* - `['bb', 'SelfBB/selfVersion']` — the current BB
|
|
110
|
+
*
|
|
111
|
+
* @param coreVersion - The version of @aws-blocks/core
|
|
112
|
+
* @returns Array of [key, value] pairs for customUserAgent
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```typescript
|
|
116
|
+
* const client = new DynamoDBClient({
|
|
117
|
+
* customUserAgent: this.buildUserAgentChain(),
|
|
118
|
+
* });
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
buildUserAgentChain() {
|
|
122
|
+
const chain = [['aws-blocks', CORE_VERSION]];
|
|
123
|
+
const parents = collectBBParents(this.parent);
|
|
124
|
+
for (const parent of parents) {
|
|
125
|
+
chain.push(['bb', `${parent.bbName}/${parent.bbVersion}`]);
|
|
126
|
+
}
|
|
127
|
+
if (this.bbName && this.bbVersion && OFFICIAL_BB_NAMES.has(this.bbName)) {
|
|
128
|
+
chain.push(['bb', `${this.bbName}/${this.bbVersion}`]);
|
|
129
|
+
}
|
|
130
|
+
return chain;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Walk up the scope tree collecting any parent that has BuildingBlockMeta.
|
|
135
|
+
* Returns them in root-to-leaf order (outermost parent first).
|
|
136
|
+
*/
|
|
137
|
+
function collectBBParents(parent) {
|
|
138
|
+
const result = [];
|
|
139
|
+
let current = parent;
|
|
140
|
+
while (current) {
|
|
141
|
+
if (isOfficialBuildingBlock(current)) {
|
|
142
|
+
result.unshift(current);
|
|
143
|
+
}
|
|
144
|
+
current = 'parent' in current ? current.parent : undefined;
|
|
145
|
+
}
|
|
146
|
+
return result;
|
|
147
|
+
}
|
|
148
|
+
function isBuildingBlock(obj) {
|
|
149
|
+
return (obj !== null &&
|
|
150
|
+
typeof obj === 'object' &&
|
|
151
|
+
'bbName' in obj &&
|
|
152
|
+
'bbVersion' in obj &&
|
|
153
|
+
typeof obj.bbName === 'string' &&
|
|
154
|
+
typeof obj.bbVersion === 'string');
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Returns true if the object is a Building Block with an official AWS name.
|
|
158
|
+
* Custom BBs (with names not in the allowlist) return false, ensuring
|
|
159
|
+
* customer-chosen names never appear in user-agent telemetry.
|
|
160
|
+
*/
|
|
161
|
+
function isOfficialBuildingBlock(obj) {
|
|
162
|
+
return isBuildingBlock(obj) && OFFICIAL_BB_NAMES.has(obj.bbName);
|
|
163
|
+
}
|
|
164
|
+
export function computeScopeFullId(scope) {
|
|
165
|
+
if (scope.parent) {
|
|
166
|
+
if ('fullId' in scope.parent && scope.parent.fullId) {
|
|
167
|
+
return `${scope.parent.fullId}-${scope.id}`;
|
|
168
|
+
}
|
|
169
|
+
if ('id' in scope.parent && scope.parent.id) {
|
|
170
|
+
return `${scope.parent.id}-${scope.id}`;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return scope.id;
|
|
174
|
+
}
|
|
175
|
+
export class BlocksStack {
|
|
176
|
+
id;
|
|
177
|
+
constructor(scope, id, props) {
|
|
178
|
+
this.id = id;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../src/common/index.test.ts"],"names":[],"mappings":""}
|