@friggframework/devtools 2.0.0-next.11 → 2.0.0-next.110
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/frigg-cli/README.md +1289 -0
- package/frigg-cli/__tests__/unit/commands/build.test.js +279 -0
- package/frigg-cli/__tests__/unit/commands/db-setup.test.js +649 -0
- package/frigg-cli/__tests__/unit/commands/deploy.test.js +320 -0
- package/frigg-cli/__tests__/unit/commands/doctor.test.js +309 -0
- package/frigg-cli/__tests__/unit/commands/generate-iam.test.js +97 -0
- package/frigg-cli/__tests__/unit/commands/install.test.js +400 -0
- package/frigg-cli/__tests__/unit/commands/ui.test.js +346 -0
- package/frigg-cli/__tests__/unit/dependencies.test.js +74 -0
- package/frigg-cli/__tests__/unit/utils/database-validator.test.js +397 -0
- package/frigg-cli/__tests__/unit/utils/error-messages.test.js +345 -0
- package/frigg-cli/__tests__/unit/version-detection.test.js +171 -0
- package/frigg-cli/__tests__/utils/mock-factory.js +270 -0
- package/frigg-cli/__tests__/utils/prisma-mock.js +194 -0
- package/frigg-cli/__tests__/utils/test-fixtures.js +463 -0
- package/frigg-cli/__tests__/utils/test-setup.js +287 -0
- package/frigg-cli/auth-command/CLAUDE.md +293 -0
- package/frigg-cli/auth-command/README.md +450 -0
- package/frigg-cli/auth-command/api-key-flow.js +153 -0
- package/frigg-cli/auth-command/auth-tester.js +344 -0
- package/frigg-cli/auth-command/credential-storage.js +182 -0
- package/frigg-cli/auth-command/index.js +256 -0
- package/frigg-cli/auth-command/json-schema-form.js +67 -0
- package/frigg-cli/auth-command/module-loader.js +172 -0
- package/frigg-cli/auth-command/oauth-callback-server.js +431 -0
- package/frigg-cli/auth-command/oauth-flow.js +195 -0
- package/frigg-cli/auth-command/utils/browser.js +30 -0
- package/frigg-cli/build-command/index.js +45 -12
- package/frigg-cli/db-setup-command/index.js +246 -0
- package/frigg-cli/deploy-command/SPEC-DEPLOY-DRY-RUN.md +981 -0
- package/frigg-cli/deploy-command/index.js +339 -23
- package/frigg-cli/doctor-command/index.js +335 -0
- package/frigg-cli/generate-command/__tests__/generate-command.test.js +301 -0
- package/frigg-cli/generate-command/azure-generator.js +43 -0
- package/frigg-cli/generate-command/gcp-generator.js +47 -0
- package/frigg-cli/generate-command/index.js +333 -0
- package/frigg-cli/generate-command/terraform-generator.js +555 -0
- package/frigg-cli/generate-iam-command.js +119 -0
- package/frigg-cli/index.js +189 -1
- package/frigg-cli/index.test.js +1 -4
- package/frigg-cli/init-command/backend-first-handler.js +756 -0
- package/frigg-cli/init-command/index.js +93 -0
- package/frigg-cli/init-command/template-handler.js +143 -0
- package/frigg-cli/install-command/index.js +1 -4
- package/frigg-cli/jest.config.js +124 -0
- package/frigg-cli/package.json +63 -0
- package/frigg-cli/repair-command/index.js +564 -0
- package/frigg-cli/ssm-command/index.js +308 -0
- package/frigg-cli/ssm-command/index.test.js +318 -0
- package/frigg-cli/start-command/index.js +118 -5
- package/frigg-cli/start-command/start-command.test.js +297 -0
- package/frigg-cli/test/init-command.test.js +180 -0
- package/frigg-cli/test/npm-registry.test.js +319 -0
- package/frigg-cli/ui-command/index.js +154 -0
- package/frigg-cli/utils/app-resolver.js +319 -0
- package/frigg-cli/utils/backend-path.js +16 -17
- package/frigg-cli/utils/database-validator.js +167 -0
- package/frigg-cli/utils/error-messages.js +329 -0
- package/frigg-cli/utils/npm-registry.js +167 -0
- package/frigg-cli/utils/process-manager.js +199 -0
- package/frigg-cli/utils/repo-detection.js +405 -0
- package/infrastructure/ARCHITECTURE.md +487 -0
- package/infrastructure/CLAUDE.md +481 -0
- package/infrastructure/HEALTH.md +468 -0
- package/infrastructure/README.md +540 -0
- package/infrastructure/__tests__/fixtures/mock-aws-resources.js +391 -0
- package/infrastructure/__tests__/helpers/test-utils.js +275 -0
- package/infrastructure/__tests__/postgres-config.test.js +914 -0
- package/infrastructure/__tests__/scoped-environment.test.js +126 -0
- package/infrastructure/__tests__/ssm-preload-node-options.test.js +79 -0
- package/infrastructure/__tests__/template-generation.test.js +687 -0
- package/infrastructure/create-frigg-infrastructure.js +129 -20
- package/infrastructure/docs/POSTGRES-CONFIGURATION.md +630 -0
- package/infrastructure/docs/PRE-DEPLOYMENT-HEALTH-CHECK-SPEC.md +1317 -0
- package/infrastructure/docs/WEBSOCKET-CONFIGURATION.md +105 -0
- package/infrastructure/docs/deployment-instructions.md +268 -0
- package/infrastructure/docs/generate-iam-command.md +278 -0
- package/infrastructure/docs/iam-policy-templates.md +193 -0
- package/infrastructure/domains/admin-scripts/admin-script-builder.js +567 -0
- package/infrastructure/domains/admin-scripts/admin-script-builder.test.js +1017 -0
- package/infrastructure/domains/admin-scripts/index.js +5 -0
- package/infrastructure/domains/database/aurora-builder.js +857 -0
- package/infrastructure/domains/database/aurora-builder.test.js +960 -0
- package/infrastructure/domains/database/aurora-discovery.js +87 -0
- package/infrastructure/domains/database/aurora-discovery.test.js +188 -0
- package/infrastructure/domains/database/aurora-resolver.js +210 -0
- package/infrastructure/domains/database/aurora-resolver.test.js +347 -0
- package/infrastructure/domains/database/migration-builder.js +757 -0
- package/infrastructure/domains/database/migration-builder.test.js +454 -0
- package/infrastructure/domains/database/migration-resolver.js +163 -0
- package/infrastructure/domains/database/migration-resolver.test.js +337 -0
- package/infrastructure/domains/health/application/ports/IPropertyReconciler.js +164 -0
- package/infrastructure/domains/health/application/ports/IResourceDetector.js +129 -0
- package/infrastructure/domains/health/application/ports/IResourceImporter.js +142 -0
- package/infrastructure/domains/health/application/ports/IStackRepository.js +131 -0
- package/infrastructure/domains/health/application/ports/index.js +26 -0
- package/infrastructure/domains/health/application/use-cases/__tests__/execute-resource-import-use-case.test.js +679 -0
- package/infrastructure/domains/health/application/use-cases/__tests__/mismatch-analyzer-method-name.test.js +167 -0
- package/infrastructure/domains/health/application/use-cases/__tests__/repair-via-import-use-case.test.js +1130 -0
- package/infrastructure/domains/health/application/use-cases/execute-resource-import-use-case.js +221 -0
- package/infrastructure/domains/health/application/use-cases/reconcile-properties-use-case.js +152 -0
- package/infrastructure/domains/health/application/use-cases/reconcile-properties-use-case.test.js +343 -0
- package/infrastructure/domains/health/application/use-cases/repair-via-import-use-case.js +535 -0
- package/infrastructure/domains/health/application/use-cases/repair-via-import-use-case.test.js +376 -0
- package/infrastructure/domains/health/application/use-cases/run-health-check-use-case.js +213 -0
- package/infrastructure/domains/health/application/use-cases/run-health-check-use-case.test.js +441 -0
- package/infrastructure/domains/health/docs/ACME-DEV-DRIFT-ANALYSIS.md +267 -0
- package/infrastructure/domains/health/docs/BUILD-VS-DEPLOYED-TEMPLATE-ANALYSIS.md +324 -0
- package/infrastructure/domains/health/docs/ORPHAN-DETECTION-ANALYSIS.md +386 -0
- package/infrastructure/domains/health/docs/SPEC-CLEANUP-COMMAND.md +1419 -0
- package/infrastructure/domains/health/docs/TDD-IMPLEMENTATION-SUMMARY.md +391 -0
- package/infrastructure/domains/health/docs/TEMPLATE-COMPARISON-IMPLEMENTATION.md +551 -0
- package/infrastructure/domains/health/domain/entities/issue.js +299 -0
- package/infrastructure/domains/health/domain/entities/issue.test.js +528 -0
- package/infrastructure/domains/health/domain/entities/property-mismatch.js +108 -0
- package/infrastructure/domains/health/domain/entities/property-mismatch.test.js +275 -0
- package/infrastructure/domains/health/domain/entities/resource.js +159 -0
- package/infrastructure/domains/health/domain/entities/resource.test.js +432 -0
- package/infrastructure/domains/health/domain/entities/stack-health-report.js +306 -0
- package/infrastructure/domains/health/domain/entities/stack-health-report.test.js +601 -0
- package/infrastructure/domains/health/domain/services/__tests__/health-score-percentage-based.test.js +380 -0
- package/infrastructure/domains/health/domain/services/__tests__/import-progress-monitor.test.js +971 -0
- package/infrastructure/domains/health/domain/services/__tests__/import-template-generator.test.js +1150 -0
- package/infrastructure/domains/health/domain/services/__tests__/logical-id-mapper.test.js +672 -0
- package/infrastructure/domains/health/domain/services/__tests__/template-parser.test.js +496 -0
- package/infrastructure/domains/health/domain/services/__tests__/update-progress-monitor.test.js +419 -0
- package/infrastructure/domains/health/domain/services/health-score-calculator.js +248 -0
- package/infrastructure/domains/health/domain/services/health-score-calculator.test.js +504 -0
- package/infrastructure/domains/health/domain/services/import-progress-monitor.js +195 -0
- package/infrastructure/domains/health/domain/services/import-template-generator.js +435 -0
- package/infrastructure/domains/health/domain/services/logical-id-mapper.js +345 -0
- package/infrastructure/domains/health/domain/services/mismatch-analyzer.js +234 -0
- package/infrastructure/domains/health/domain/services/mismatch-analyzer.test.js +431 -0
- package/infrastructure/domains/health/domain/services/property-mutability-config.js +382 -0
- package/infrastructure/domains/health/domain/services/template-parser.js +245 -0
- package/infrastructure/domains/health/domain/services/update-progress-monitor.js +192 -0
- package/infrastructure/domains/health/domain/value-objects/health-score.js +138 -0
- package/infrastructure/domains/health/domain/value-objects/health-score.test.js +267 -0
- package/infrastructure/domains/health/domain/value-objects/property-mutability.js +161 -0
- package/infrastructure/domains/health/domain/value-objects/property-mutability.test.js +198 -0
- package/infrastructure/domains/health/domain/value-objects/resource-state.js +167 -0
- package/infrastructure/domains/health/domain/value-objects/resource-state.test.js +196 -0
- package/infrastructure/domains/health/domain/value-objects/stack-identifier.js +192 -0
- package/infrastructure/domains/health/domain/value-objects/stack-identifier.test.js +262 -0
- package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-cfn-tagged.test.js +312 -0
- package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-multi-stack.test.js +367 -0
- package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-relationship-analysis.test.js +432 -0
- package/infrastructure/domains/health/infrastructure/adapters/aws-property-reconciler.js +784 -0
- package/infrastructure/domains/health/infrastructure/adapters/aws-property-reconciler.test.js +1133 -0
- package/infrastructure/domains/health/infrastructure/adapters/aws-resource-detector.js +565 -0
- package/infrastructure/domains/health/infrastructure/adapters/aws-resource-detector.test.js +554 -0
- package/infrastructure/domains/health/infrastructure/adapters/aws-resource-importer.js +318 -0
- package/infrastructure/domains/health/infrastructure/adapters/aws-resource-importer.test.js +398 -0
- package/infrastructure/domains/health/infrastructure/adapters/aws-stack-repository.js +777 -0
- package/infrastructure/domains/health/infrastructure/adapters/aws-stack-repository.test.js +580 -0
- package/infrastructure/domains/integration/integration-builder.js +656 -0
- package/infrastructure/domains/integration/integration-builder.test.js +1064 -0
- package/infrastructure/domains/integration/integration-resolver.js +170 -0
- package/infrastructure/domains/integration/integration-resolver.test.js +369 -0
- package/infrastructure/domains/integration/websocket-builder.js +69 -0
- package/infrastructure/domains/integration/websocket-builder.test.js +195 -0
- package/infrastructure/domains/networking/vpc-builder.js +2101 -0
- package/infrastructure/domains/networking/vpc-builder.test.js +2001 -0
- package/infrastructure/domains/networking/vpc-discovery.js +184 -0
- package/infrastructure/domains/networking/vpc-discovery.test.js +368 -0
- package/infrastructure/domains/networking/vpc-resolver.js +514 -0
- package/infrastructure/domains/networking/vpc-resolver.test.js +841 -0
- package/infrastructure/domains/parameters/offload-utils.js +190 -0
- package/infrastructure/domains/parameters/offload-utils.test.js +193 -0
- package/infrastructure/domains/parameters/ssm-builder.js +132 -0
- package/infrastructure/domains/parameters/ssm-builder.test.js +346 -0
- package/infrastructure/domains/parameters/ssm-discovery.js +84 -0
- package/infrastructure/domains/parameters/ssm-discovery.test.js +210 -0
- package/infrastructure/domains/scheduler/scheduler-builder.js +247 -0
- package/infrastructure/domains/scheduler/scheduler-builder.test.js +118 -0
- package/infrastructure/domains/security/iam-generator.js +851 -0
- package/infrastructure/domains/security/iam-generator.test.js +287 -0
- package/infrastructure/domains/security/kms-builder.js +415 -0
- package/infrastructure/domains/security/kms-builder.test.js +392 -0
- package/infrastructure/domains/security/kms-discovery.js +80 -0
- package/infrastructure/domains/security/kms-discovery.test.js +177 -0
- package/infrastructure/domains/security/kms-resolver.js +96 -0
- package/infrastructure/domains/security/kms-resolver.test.js +216 -0
- package/infrastructure/domains/security/templates/frigg-deployment-iam-stack.yaml +418 -0
- package/infrastructure/domains/security/templates/iam-policy-basic.json +218 -0
- package/infrastructure/domains/security/templates/iam-policy-full.json +293 -0
- package/infrastructure/domains/shared/base-builder.js +112 -0
- package/infrastructure/domains/shared/base-resolver.js +186 -0
- package/infrastructure/domains/shared/base-resolver.test.js +305 -0
- package/infrastructure/domains/shared/builder-orchestrator.js +226 -0
- package/infrastructure/domains/shared/builder-orchestrator.test.js +258 -0
- package/infrastructure/domains/shared/cloudformation-discovery-v2.js +334 -0
- package/infrastructure/domains/shared/cloudformation-discovery.js +681 -0
- package/infrastructure/domains/shared/cloudformation-discovery.test.js +1320 -0
- package/infrastructure/domains/shared/environment-builder.js +192 -0
- package/infrastructure/domains/shared/environment-builder.test.js +529 -0
- package/infrastructure/domains/shared/function-environments.js +97 -0
- package/infrastructure/domains/shared/function-environments.test.js +146 -0
- package/infrastructure/domains/shared/providers/aws-provider-adapter.js +579 -0
- package/infrastructure/domains/shared/providers/aws-provider-adapter.test.js +416 -0
- package/infrastructure/domains/shared/providers/azure-provider-adapter.stub.js +93 -0
- package/infrastructure/domains/shared/providers/cloud-provider-adapter.js +136 -0
- package/infrastructure/domains/shared/providers/gcp-provider-adapter.stub.js +82 -0
- package/infrastructure/domains/shared/providers/provider-factory.js +108 -0
- package/infrastructure/domains/shared/providers/provider-factory.test.js +170 -0
- package/infrastructure/domains/shared/resource-discovery.enhanced.test.js +306 -0
- package/infrastructure/domains/shared/resource-discovery.js +256 -0
- package/infrastructure/domains/shared/resource-discovery.test.js +757 -0
- package/infrastructure/domains/shared/types/app-definition.js +225 -0
- package/infrastructure/domains/shared/types/discovery-result.js +106 -0
- package/infrastructure/domains/shared/types/discovery-result.test.js +258 -0
- package/infrastructure/domains/shared/types/index.js +46 -0
- package/infrastructure/domains/shared/types/resource-ownership.js +108 -0
- package/infrastructure/domains/shared/types/resource-ownership.test.js +101 -0
- package/infrastructure/domains/shared/utilities/base-definition-factory.js +409 -0
- package/infrastructure/domains/shared/utilities/base-definition-factory.js.bak +338 -0
- package/infrastructure/domains/shared/utilities/base-definition-factory.test.js +319 -0
- package/infrastructure/domains/shared/utilities/handler-path-resolver.js +134 -0
- package/infrastructure/domains/shared/utilities/handler-path-resolver.test.js +268 -0
- package/infrastructure/domains/shared/utilities/nested-node-modules.js +53 -0
- package/infrastructure/domains/shared/utilities/nested-node-modules.test.js +61 -0
- package/infrastructure/domains/shared/utilities/prisma-layer-manager.js +159 -0
- package/infrastructure/domains/shared/utilities/prisma-layer-manager.test.js +444 -0
- package/infrastructure/domains/shared/validation/env-validator.js +78 -0
- package/infrastructure/domains/shared/validation/env-validator.test.js +173 -0
- package/infrastructure/domains/shared/validation/plugin-validator.js +187 -0
- package/infrastructure/domains/shared/validation/plugin-validator.test.js +323 -0
- package/infrastructure/esbuild.config.js +53 -0
- package/infrastructure/infrastructure-composer.js +168 -0
- package/infrastructure/infrastructure-composer.test.js +2042 -0
- package/infrastructure/integration.test.js +381 -0
- package/infrastructure/scripts/build-prisma-layer.js +701 -0
- package/infrastructure/scripts/build-prisma-layer.test.js +170 -0
- package/infrastructure/scripts/build-time-discovery.js +238 -0
- package/infrastructure/scripts/build-time-discovery.test.js +379 -0
- package/infrastructure/scripts/run-discovery.js +110 -0
- package/infrastructure/scripts/verify-prisma-layer.js +72 -0
- package/management-ui/README.md +203 -0
- package/package.json +48 -16
- package/test/index.js +2 -4
- package/test/mock-api.js +1 -3
- package/test/mock-integration.js +4 -14
- package/.eslintrc.json +0 -3
- package/CHANGELOG.md +0 -132
- package/infrastructure/serverless-template.js +0 -283
- package/infrastructure/webpack.config.js +0 -20
- package/test/auther-definition-tester.js +0 -125
|
@@ -0,0 +1,529 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for Environment Builder Service
|
|
3
|
+
*
|
|
4
|
+
* Tests environment variable extraction and building
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const {
|
|
8
|
+
getAppEnvironmentVars,
|
|
9
|
+
buildEnvironment,
|
|
10
|
+
} = require('./environment-builder');
|
|
11
|
+
|
|
12
|
+
describe('Environment Builder', () => {
|
|
13
|
+
describe('getAppEnvironmentVars()', () => {
|
|
14
|
+
it('should extract environment variables with value true', () => {
|
|
15
|
+
const appDefinition = {
|
|
16
|
+
environment: {
|
|
17
|
+
API_KEY: true,
|
|
18
|
+
DATABASE_URL: true,
|
|
19
|
+
CUSTOM_VAR: true,
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const result = getAppEnvironmentVars(appDefinition);
|
|
24
|
+
|
|
25
|
+
expect(result.API_KEY).toBe("${env:API_KEY, ''}");
|
|
26
|
+
expect(result.DATABASE_URL).toBe("${env:DATABASE_URL, ''}");
|
|
27
|
+
expect(result.CUSTOM_VAR).toBe("${env:CUSTOM_VAR, ''}");
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should ignore environment variables with value false', () => {
|
|
31
|
+
const appDefinition = {
|
|
32
|
+
environment: {
|
|
33
|
+
ENABLED_VAR: true,
|
|
34
|
+
DISABLED_VAR: false,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const result = getAppEnvironmentVars(appDefinition);
|
|
39
|
+
|
|
40
|
+
expect(result.ENABLED_VAR).toBeDefined();
|
|
41
|
+
expect(result.DISABLED_VAR).toBeUndefined();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("ignores non-boolean values other than the meaningful 'ssm' marker", () => {
|
|
45
|
+
const appDefinition = {
|
|
46
|
+
environment: {
|
|
47
|
+
VALID: true,
|
|
48
|
+
STRING_VALUE: 'some-value',
|
|
49
|
+
NUMBER_VALUE: 123,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const result = getAppEnvironmentVars(appDefinition);
|
|
54
|
+
|
|
55
|
+
expect(result.VALID).toBeDefined();
|
|
56
|
+
expect(result.STRING_VALUE).toBeUndefined();
|
|
57
|
+
expect(result.NUMBER_VALUE).toBeUndefined();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should skip reserved AWS Lambda variables', () => {
|
|
61
|
+
const appDefinition = {
|
|
62
|
+
environment: {
|
|
63
|
+
CUSTOM_VAR: true,
|
|
64
|
+
AWS_REGION: true,
|
|
65
|
+
AWS_ACCESS_KEY_ID: true,
|
|
66
|
+
AWS_SECRET_ACCESS_KEY: true,
|
|
67
|
+
_HANDLER: true,
|
|
68
|
+
AWS_LAMBDA_FUNCTION_NAME: true,
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const result = getAppEnvironmentVars(appDefinition);
|
|
73
|
+
|
|
74
|
+
expect(result.CUSTOM_VAR).toBeDefined();
|
|
75
|
+
expect(result.AWS_REGION).toBeUndefined();
|
|
76
|
+
expect(result.AWS_ACCESS_KEY_ID).toBeUndefined();
|
|
77
|
+
expect(result.AWS_SECRET_ACCESS_KEY).toBeUndefined();
|
|
78
|
+
expect(result._HANDLER).toBeUndefined();
|
|
79
|
+
expect(result.AWS_LAMBDA_FUNCTION_NAME).toBeUndefined();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('should return empty object if no environment defined', () => {
|
|
83
|
+
const appDefinition = {};
|
|
84
|
+
|
|
85
|
+
const result = getAppEnvironmentVars(appDefinition);
|
|
86
|
+
|
|
87
|
+
expect(result).toEqual({});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('should handle empty environment object', () => {
|
|
91
|
+
const appDefinition = {
|
|
92
|
+
environment: {},
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const result = getAppEnvironmentVars(appDefinition);
|
|
96
|
+
|
|
97
|
+
expect(result).toEqual({});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('should create serverless variable references', () => {
|
|
101
|
+
const appDefinition = {
|
|
102
|
+
environment: {
|
|
103
|
+
MY_VAR: true,
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const result = getAppEnvironmentVars(appDefinition);
|
|
108
|
+
|
|
109
|
+
// Should use serverless variable syntax with empty string fallback
|
|
110
|
+
expect(result.MY_VAR).toBe("${env:MY_VAR, ''}");
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
describe('telemetry env passthrough (ADR-011)', () => {
|
|
115
|
+
it('auto-adds OTLP env passthroughs when an OTLP-family exporter is configured', () => {
|
|
116
|
+
const result = getAppEnvironmentVars({
|
|
117
|
+
telemetry: { exporter: { type: 'otlp' } },
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
expect(result.OTEL_EXPORTER_OTLP_ENDPOINT).toBe(
|
|
121
|
+
"${env:OTEL_EXPORTER_OTLP_ENDPOINT, ''}"
|
|
122
|
+
);
|
|
123
|
+
expect(result.OTEL_EXPORTER_OTLP_HEADERS).toBe(
|
|
124
|
+
"${env:OTEL_EXPORTER_OTLP_HEADERS, ''}"
|
|
125
|
+
);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it.each(['honeycomb', 'datadog'])(
|
|
129
|
+
'adds OTLP passthroughs for the "%s" preset',
|
|
130
|
+
(type) => {
|
|
131
|
+
const result = getAppEnvironmentVars({
|
|
132
|
+
telemetry: { exporter: { type } },
|
|
133
|
+
});
|
|
134
|
+
expect(result.OTEL_EXPORTER_OTLP_ENDPOINT).toBeDefined();
|
|
135
|
+
}
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
it('adds no OTLP env vars for console/none exporters or absent telemetry', () => {
|
|
139
|
+
expect(
|
|
140
|
+
getAppEnvironmentVars({
|
|
141
|
+
telemetry: { exporter: { type: 'console' } },
|
|
142
|
+
}).OTEL_EXPORTER_OTLP_ENDPOINT
|
|
143
|
+
).toBeUndefined();
|
|
144
|
+
expect(
|
|
145
|
+
getAppEnvironmentVars({}).OTEL_EXPORTER_OTLP_ENDPOINT
|
|
146
|
+
).toBeUndefined();
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
describe("getAppEnvironmentVars() - 'ssm' offload", () => {
|
|
151
|
+
const originalSkipDiscovery = process.env.FRIGG_SKIP_AWS_DISCOVERY;
|
|
152
|
+
|
|
153
|
+
afterEach(() => {
|
|
154
|
+
if (originalSkipDiscovery === undefined) {
|
|
155
|
+
delete process.env.FRIGG_SKIP_AWS_DISCOVERY;
|
|
156
|
+
} else {
|
|
157
|
+
process.env.FRIGG_SKIP_AWS_DISCOVERY = originalSkipDiscovery;
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it("excludes 'ssm' keys when offload is active", () => {
|
|
162
|
+
delete process.env.FRIGG_SKIP_AWS_DISCOVERY;
|
|
163
|
+
const appDefinition = {
|
|
164
|
+
ssm: { enable: true },
|
|
165
|
+
environment: { FOO: 'ssm', BAR: true },
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const result = getAppEnvironmentVars(appDefinition);
|
|
169
|
+
|
|
170
|
+
expect(result.FOO).toBeUndefined();
|
|
171
|
+
expect(result.BAR).toBe("${env:BAR, ''}");
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it("falls back to env reference for 'ssm' keys when FRIGG_SKIP_AWS_DISCOVERY is set", () => {
|
|
175
|
+
process.env.FRIGG_SKIP_AWS_DISCOVERY = 'true';
|
|
176
|
+
const appDefinition = {
|
|
177
|
+
ssm: { enable: true },
|
|
178
|
+
environment: { FOO: 'ssm' },
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const result = getAppEnvironmentVars(appDefinition);
|
|
182
|
+
|
|
183
|
+
expect(result.FOO).toBe("${env:FOO, ''}");
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it("falls back to env reference for 'ssm' keys when ssm is disabled", () => {
|
|
187
|
+
delete process.env.FRIGG_SKIP_AWS_DISCOVERY;
|
|
188
|
+
const appDefinition = {
|
|
189
|
+
ssm: { enable: false },
|
|
190
|
+
environment: { FOO: 'ssm' },
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const result = getAppEnvironmentVars(appDefinition);
|
|
194
|
+
|
|
195
|
+
expect(result.FOO).toBe("${env:FOO, ''}");
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('falls back to env reference for a key declared only in ssm.parameters when FRIGG_SKIP_AWS_DISCOVERY is set', () => {
|
|
199
|
+
process.env.FRIGG_SKIP_AWS_DISCOVERY = 'true';
|
|
200
|
+
const appDefinition = {
|
|
201
|
+
ssm: {
|
|
202
|
+
enable: true,
|
|
203
|
+
parameters: {
|
|
204
|
+
HUBSPOT_CLIENT_SECRET: { type: 'SecureString' },
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
const result = getAppEnvironmentVars(appDefinition);
|
|
210
|
+
|
|
211
|
+
expect(result.HUBSPOT_CLIENT_SECRET).toBe(
|
|
212
|
+
"${env:HUBSPOT_CLIENT_SECRET, ''}"
|
|
213
|
+
);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('excludes a key declared only in ssm.parameters when offload is active', () => {
|
|
217
|
+
delete process.env.FRIGG_SKIP_AWS_DISCOVERY;
|
|
218
|
+
const appDefinition = {
|
|
219
|
+
ssm: {
|
|
220
|
+
enable: true,
|
|
221
|
+
parameters: {
|
|
222
|
+
HUBSPOT_CLIENT_SECRET: { type: 'SecureString' },
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
const result = getAppEnvironmentVars(appDefinition);
|
|
228
|
+
|
|
229
|
+
expect(result.HUBSPOT_CLIENT_SECRET).toBeUndefined();
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it("does not double-process a key present in both environment:'ssm' and ssm.parameters", () => {
|
|
233
|
+
delete process.env.FRIGG_SKIP_AWS_DISCOVERY;
|
|
234
|
+
const appDefinition = {
|
|
235
|
+
ssm: {
|
|
236
|
+
enable: true,
|
|
237
|
+
parameters: { FOO: { type: 'SecureString' } },
|
|
238
|
+
},
|
|
239
|
+
environment: { FOO: 'ssm' },
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
const result = getAppEnvironmentVars(appDefinition);
|
|
243
|
+
|
|
244
|
+
expect(result.FOO).toBeUndefined();
|
|
245
|
+
|
|
246
|
+
process.env.FRIGG_SKIP_AWS_DISCOVERY = 'true';
|
|
247
|
+
const fallbackResult = getAppEnvironmentVars(appDefinition);
|
|
248
|
+
expect(fallbackResult.FOO).toBe("${env:FOO, ''}");
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
describe('telemetry env passthrough + SSM offload interaction', () => {
|
|
253
|
+
const originalSkipDiscovery = process.env.FRIGG_SKIP_AWS_DISCOVERY;
|
|
254
|
+
|
|
255
|
+
afterEach(() => {
|
|
256
|
+
if (originalSkipDiscovery === undefined) {
|
|
257
|
+
delete process.env.FRIGG_SKIP_AWS_DISCOVERY;
|
|
258
|
+
} else {
|
|
259
|
+
process.env.FRIGG_SKIP_AWS_DISCOVERY = originalSkipDiscovery;
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it("does not bake an OTEL passthrough var that is marked 'ssm' when offload is active", () => {
|
|
264
|
+
delete process.env.FRIGG_SKIP_AWS_DISCOVERY;
|
|
265
|
+
const appDefinition = {
|
|
266
|
+
telemetry: { exporter: { type: 'datadog' } },
|
|
267
|
+
ssm: { enable: true },
|
|
268
|
+
environment: {
|
|
269
|
+
OTEL_EXPORTER_OTLP_ENDPOINT: 'ssm',
|
|
270
|
+
OTEL_EXPORTER_OTLP_HEADERS: 'ssm',
|
|
271
|
+
},
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
const result = getAppEnvironmentVars(appDefinition);
|
|
275
|
+
|
|
276
|
+
expect(result.OTEL_EXPORTER_OTLP_ENDPOINT).toBeUndefined();
|
|
277
|
+
expect(result.OTEL_EXPORTER_OTLP_HEADERS).toBeUndefined();
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
it("keeps the direct passthrough for an OTEL var not marked 'ssm' while offloading its sibling", () => {
|
|
281
|
+
delete process.env.FRIGG_SKIP_AWS_DISCOVERY;
|
|
282
|
+
const appDefinition = {
|
|
283
|
+
telemetry: { exporter: { type: 'otlp' } },
|
|
284
|
+
ssm: { enable: true },
|
|
285
|
+
environment: {
|
|
286
|
+
OTEL_EXPORTER_OTLP_ENDPOINT: 'ssm',
|
|
287
|
+
},
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
const result = getAppEnvironmentVars(appDefinition);
|
|
291
|
+
|
|
292
|
+
expect(result.OTEL_EXPORTER_OTLP_ENDPOINT).toBeUndefined();
|
|
293
|
+
expect(result.OTEL_EXPORTER_OTLP_HEADERS).toBe(
|
|
294
|
+
"${env:OTEL_EXPORTER_OTLP_HEADERS, ''}"
|
|
295
|
+
);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it("falls back to the env passthrough for an 'ssm'-marked OTEL var in local mode", () => {
|
|
299
|
+
process.env.FRIGG_SKIP_AWS_DISCOVERY = 'true';
|
|
300
|
+
const appDefinition = {
|
|
301
|
+
telemetry: { exporter: { type: 'datadog' } },
|
|
302
|
+
ssm: { enable: true },
|
|
303
|
+
environment: {
|
|
304
|
+
OTEL_EXPORTER_OTLP_ENDPOINT: 'ssm',
|
|
305
|
+
},
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
const result = getAppEnvironmentVars(appDefinition);
|
|
309
|
+
|
|
310
|
+
expect(result.OTEL_EXPORTER_OTLP_ENDPOINT).toBe(
|
|
311
|
+
"${env:OTEL_EXPORTER_OTLP_ENDPOINT, ''}"
|
|
312
|
+
);
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
it("leaves a 'true'-marked OTEL var as a direct passthrough even when offload is active for another key", () => {
|
|
316
|
+
delete process.env.FRIGG_SKIP_AWS_DISCOVERY;
|
|
317
|
+
const appDefinition = {
|
|
318
|
+
telemetry: { exporter: { type: 'datadog' } },
|
|
319
|
+
ssm: { enable: true },
|
|
320
|
+
environment: {
|
|
321
|
+
OTEL_EXPORTER_OTLP_ENDPOINT: true,
|
|
322
|
+
SOME_OFFLOADED_SECRET: 'ssm',
|
|
323
|
+
},
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
const result = getAppEnvironmentVars(appDefinition);
|
|
327
|
+
|
|
328
|
+
expect(result.OTEL_EXPORTER_OTLP_ENDPOINT).toBe(
|
|
329
|
+
"${env:OTEL_EXPORTER_OTLP_ENDPOINT, ''}"
|
|
330
|
+
);
|
|
331
|
+
expect(result.SOME_OFFLOADED_SECRET).toBeUndefined();
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
it('does not bake an OTEL passthrough var offloaded only via ssm.parameters', () => {
|
|
335
|
+
delete process.env.FRIGG_SKIP_AWS_DISCOVERY;
|
|
336
|
+
const appDefinition = {
|
|
337
|
+
telemetry: { exporter: { type: 'datadog' } },
|
|
338
|
+
ssm: {
|
|
339
|
+
enable: true,
|
|
340
|
+
parameters: {
|
|
341
|
+
OTEL_EXPORTER_OTLP_ENDPOINT: { type: 'SecureString' },
|
|
342
|
+
},
|
|
343
|
+
},
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
const result = getAppEnvironmentVars(appDefinition);
|
|
347
|
+
|
|
348
|
+
expect(result.OTEL_EXPORTER_OTLP_ENDPOINT).toBeUndefined();
|
|
349
|
+
});
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
describe('buildEnvironment()', () => {
|
|
353
|
+
it('should combine app vars with standard Frigg variables', () => {
|
|
354
|
+
const appEnvironmentVars = {
|
|
355
|
+
API_KEY: "${env:API_KEY, ''}",
|
|
356
|
+
};
|
|
357
|
+
const discoveredResources = {};
|
|
358
|
+
|
|
359
|
+
const result = buildEnvironment(
|
|
360
|
+
appEnvironmentVars,
|
|
361
|
+
discoveredResources
|
|
362
|
+
);
|
|
363
|
+
|
|
364
|
+
expect(result.API_KEY).toBe("${env:API_KEY, ''}");
|
|
365
|
+
expect(result.STAGE).toBe('${self:provider.stage}');
|
|
366
|
+
expect(result.FRIGG_STACK).toBe('${self:service}');
|
|
367
|
+
expect(result.FRIGG_STAGE).toBe('${self:provider.stage}');
|
|
368
|
+
expect(result.FRIGG_REGION).toBe('${self:provider.region}');
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
it('should add KMS key ARN if discovered', () => {
|
|
372
|
+
const appEnvironmentVars = {};
|
|
373
|
+
const discoveredResources = {
|
|
374
|
+
kmsKeyId: 'arn:aws:kms:us-east-1:123456:key/abc-123',
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
const result = buildEnvironment(
|
|
378
|
+
appEnvironmentVars,
|
|
379
|
+
discoveredResources
|
|
380
|
+
);
|
|
381
|
+
|
|
382
|
+
expect(result.KMS_KEY_ARN).toBe(
|
|
383
|
+
'arn:aws:kms:us-east-1:123456:key/abc-123'
|
|
384
|
+
);
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
it('should prefer kmsKeyId over kmsKeyArn if both present', () => {
|
|
388
|
+
const appEnvironmentVars = {};
|
|
389
|
+
const discoveredResources = {
|
|
390
|
+
kmsKeyId: 'arn:aws:kms:us-east-1:123456:key/primary',
|
|
391
|
+
kmsKeyArn: 'arn:aws:kms:us-east-1:123456:key/secondary',
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
const result = buildEnvironment(
|
|
395
|
+
appEnvironmentVars,
|
|
396
|
+
discoveredResources
|
|
397
|
+
);
|
|
398
|
+
|
|
399
|
+
// Implementation uses if/else-if, so kmsKeyId takes priority
|
|
400
|
+
expect(result.KMS_KEY_ARN).toBe(
|
|
401
|
+
'arn:aws:kms:us-east-1:123456:key/primary'
|
|
402
|
+
);
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
it('should add database connection info if discovered', () => {
|
|
406
|
+
const appEnvironmentVars = {};
|
|
407
|
+
const discoveredResources = {
|
|
408
|
+
auroraClusterEndpoint:
|
|
409
|
+
'cluster.abc.us-east-1.rds.amazonaws.com',
|
|
410
|
+
auroraPort: 5432,
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
const result = buildEnvironment(
|
|
414
|
+
appEnvironmentVars,
|
|
415
|
+
discoveredResources
|
|
416
|
+
);
|
|
417
|
+
|
|
418
|
+
expect(result.DATABASE_HOST).toBe(
|
|
419
|
+
'cluster.abc.us-east-1.rds.amazonaws.com'
|
|
420
|
+
);
|
|
421
|
+
expect(result.DATABASE_PORT).toBe('5432');
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
it('should default database port to 5432 if not specified', () => {
|
|
425
|
+
const appEnvironmentVars = {};
|
|
426
|
+
const discoveredResources = {
|
|
427
|
+
auroraClusterEndpoint: 'cluster.example.com',
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
const result = buildEnvironment(
|
|
431
|
+
appEnvironmentVars,
|
|
432
|
+
discoveredResources
|
|
433
|
+
);
|
|
434
|
+
|
|
435
|
+
expect(result.DATABASE_HOST).toBe('cluster.example.com');
|
|
436
|
+
expect(result.DATABASE_PORT).toBe('5432');
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
it('should add database secret ARN if discovered', () => {
|
|
440
|
+
const appEnvironmentVars = {};
|
|
441
|
+
const discoveredResources = {
|
|
442
|
+
databaseSecretArn:
|
|
443
|
+
'arn:aws:secretsmanager:us-east-1:123456:secret:db-secret',
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
const result = buildEnvironment(
|
|
447
|
+
appEnvironmentVars,
|
|
448
|
+
discoveredResources
|
|
449
|
+
);
|
|
450
|
+
|
|
451
|
+
expect(result.DATABASE_SECRET_ARN).toBe(
|
|
452
|
+
'arn:aws:secretsmanager:us-east-1:123456:secret:db-secret'
|
|
453
|
+
);
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
it('should combine all discovered resources', () => {
|
|
457
|
+
const appEnvironmentVars = {
|
|
458
|
+
CUSTOM_VAR: "${env:CUSTOM_VAR, ''}",
|
|
459
|
+
};
|
|
460
|
+
const discoveredResources = {
|
|
461
|
+
kmsKeyArn: 'arn:aws:kms:us-east-1:123456:key/abc',
|
|
462
|
+
auroraClusterEndpoint: 'db.example.com',
|
|
463
|
+
auroraPort: 3306,
|
|
464
|
+
databaseSecretArn:
|
|
465
|
+
'arn:aws:secretsmanager:us-east-1:123456:secret:db',
|
|
466
|
+
};
|
|
467
|
+
|
|
468
|
+
const result = buildEnvironment(
|
|
469
|
+
appEnvironmentVars,
|
|
470
|
+
discoveredResources
|
|
471
|
+
);
|
|
472
|
+
|
|
473
|
+
expect(result.CUSTOM_VAR).toBe("${env:CUSTOM_VAR, ''}");
|
|
474
|
+
expect(result.FRIGG_STACK).toBe('${self:service}');
|
|
475
|
+
expect(result.FRIGG_STAGE).toBe('${self:provider.stage}');
|
|
476
|
+
expect(result.FRIGG_REGION).toBe('${self:provider.region}');
|
|
477
|
+
expect(result.KMS_KEY_ARN).toBe(
|
|
478
|
+
'arn:aws:kms:us-east-1:123456:key/abc'
|
|
479
|
+
);
|
|
480
|
+
expect(result.DATABASE_HOST).toBe('db.example.com');
|
|
481
|
+
expect(result.DATABASE_PORT).toBe('3306');
|
|
482
|
+
expect(result.DATABASE_SECRET_ARN).toBe(
|
|
483
|
+
'arn:aws:secretsmanager:us-east-1:123456:secret:db'
|
|
484
|
+
);
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
it('should handle empty discoveredResources', () => {
|
|
488
|
+
const appEnvironmentVars = {
|
|
489
|
+
API_KEY: "${env:API_KEY, ''}",
|
|
490
|
+
};
|
|
491
|
+
const discoveredResources = {};
|
|
492
|
+
|
|
493
|
+
const result = buildEnvironment(
|
|
494
|
+
appEnvironmentVars,
|
|
495
|
+
discoveredResources
|
|
496
|
+
);
|
|
497
|
+
|
|
498
|
+
expect(result.API_KEY).toBe("${env:API_KEY, ''}");
|
|
499
|
+
expect(result.FRIGG_STACK).toBe('${self:service}');
|
|
500
|
+
expect(result.KMS_KEY_ARN).toBeUndefined();
|
|
501
|
+
expect(result.DATABASE_HOST).toBeUndefined();
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
it('should handle empty discoveredResources gracefully', () => {
|
|
505
|
+
const appEnvironmentVars = {};
|
|
506
|
+
|
|
507
|
+
const result = buildEnvironment(appEnvironmentVars, {});
|
|
508
|
+
|
|
509
|
+
expect(result.FRIGG_STACK).toBe('${self:service}');
|
|
510
|
+
expect(result.KMS_KEY_ARN).toBeUndefined();
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
it('should convert database port to string', () => {
|
|
514
|
+
const appEnvironmentVars = {};
|
|
515
|
+
const discoveredResources = {
|
|
516
|
+
auroraClusterEndpoint: 'db.example.com',
|
|
517
|
+
auroraPort: 3306, // Number
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
const result = buildEnvironment(
|
|
521
|
+
appEnvironmentVars,
|
|
522
|
+
discoveredResources
|
|
523
|
+
);
|
|
524
|
+
|
|
525
|
+
expect(result.DATABASE_PORT).toBe('3306'); // String
|
|
526
|
+
expect(typeof result.DATABASE_PORT).toBe('string');
|
|
527
|
+
});
|
|
528
|
+
});
|
|
529
|
+
});
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-function environment scoping (ADR-027)
|
|
3
|
+
*
|
|
4
|
+
* Builders emit `result.functionEnvironments` — a map of function name to
|
|
5
|
+
* env vars — instead of broadcasting framework vars app-wide through
|
|
6
|
+
* `result.environment`. The composer applies the merged map onto the final
|
|
7
|
+
* function definitions after every function (base + builder) exists.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Whether builders should scope framework env vars per function. Skipped in
|
|
12
|
+
* local mode: the serverless-plugin injects LocalStack queue URLs at
|
|
13
|
+
* provider level only, and function-level values would shadow them.
|
|
14
|
+
*
|
|
15
|
+
* @param {Object} appDefinition
|
|
16
|
+
* @returns {boolean}
|
|
17
|
+
*/
|
|
18
|
+
function isScopedEnvironmentActive(appDefinition = {}) {
|
|
19
|
+
if (process.env.FRIGG_SKIP_AWS_DISCOVERY === 'true') return false;
|
|
20
|
+
return appDefinition.lambda?.scopedEnvironment === true;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Apply a merged functionEnvironments map onto the composed functions.
|
|
25
|
+
* A key a builder already set directly on a function wins (e.g. the
|
|
26
|
+
* admin-script router's own SCHEDULER_ROLE_ARN must not be clobbered by
|
|
27
|
+
* the integration-scheduler value). An unknown function name is a hard
|
|
28
|
+
* error — silently dropping a var would surface as a runtime failure.
|
|
29
|
+
*
|
|
30
|
+
* @param {Object} functions - definition.functions (mutated)
|
|
31
|
+
* @param {Object} functionEnvironments - { fnName: { KEY: value } }
|
|
32
|
+
*/
|
|
33
|
+
function applyFunctionEnvironments(functions, functionEnvironments = {}) {
|
|
34
|
+
for (const [fnName, env] of Object.entries(functionEnvironments)) {
|
|
35
|
+
const fn = functions[fnName];
|
|
36
|
+
if (!fn) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
`functionEnvironments targets unknown function '${fnName}' (known: ${Object.keys(
|
|
39
|
+
functions
|
|
40
|
+
).join(', ')})`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
fn.environment = { ...env, ...(fn.environment || {}) };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Function names the integration builder creates for one integration.
|
|
49
|
+
* Wire contract: must stay in sync with
|
|
50
|
+
* IntegrationBuilder.createFunctionDefinitions — a drift here surfaces as a
|
|
51
|
+
* hard unknown-function error at compose time, not a silent var drop.
|
|
52
|
+
*
|
|
53
|
+
* @param {Object} integration - entry from appDefinition.integrations
|
|
54
|
+
* @returns {string[]}
|
|
55
|
+
*/
|
|
56
|
+
function getIntegrationFunctionNames(integration) {
|
|
57
|
+
const name = integration.Definition.name;
|
|
58
|
+
const names = [name, `${name}QueueWorker`];
|
|
59
|
+
|
|
60
|
+
const webhooks = integration.Definition.webhooks;
|
|
61
|
+
if (webhooks === true || webhooks?.enabled === true) {
|
|
62
|
+
names.splice(1, 0, `${name}Webhook`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
for (const [bindingKey, binding] of Object.entries(
|
|
66
|
+
integration.Definition.extensions || {}
|
|
67
|
+
)) {
|
|
68
|
+
const routes = binding?.extension?.routes || [];
|
|
69
|
+
if (routes.length === 0) continue;
|
|
70
|
+
names.push(`${name}__${String(bindingKey).replace(/[^A-Za-z0-9]/g, '')}`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return names;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Admin-script functions, when the feature is on (mirrors
|
|
78
|
+
* AdminScriptBuilder.shouldExecute). Both can instantiate arbitrary
|
|
79
|
+
* integrations, so they belong in every integration's queue-URL consumer
|
|
80
|
+
* set.
|
|
81
|
+
*
|
|
82
|
+
* @param {Object} appDefinition
|
|
83
|
+
* @returns {string[]}
|
|
84
|
+
*/
|
|
85
|
+
function getAdminFunctionNames(appDefinition = {}) {
|
|
86
|
+
return Array.isArray(appDefinition.adminScripts) &&
|
|
87
|
+
appDefinition.adminScripts.length > 0
|
|
88
|
+
? ['adminScriptRouter', 'adminScriptExecutor']
|
|
89
|
+
: [];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
module.exports = {
|
|
93
|
+
isScopedEnvironmentActive,
|
|
94
|
+
applyFunctionEnvironments,
|
|
95
|
+
getIntegrationFunctionNames,
|
|
96
|
+
getAdminFunctionNames,
|
|
97
|
+
};
|