@friggframework/devtools 2.0.0--canary.622.bcbe848.0 → 2.0.0--canary.623.ee3bde8.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.
|
@@ -1,42 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Environment Builder Service
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* Domain Service - Hexagonal Architecture
|
|
5
|
-
*
|
|
5
|
+
*
|
|
6
6
|
* Builds Lambda environment variable configuration from:
|
|
7
7
|
* 1. AppDefinition environment flags
|
|
8
8
|
* 2. Discovered AWS resources (VPC IDs, KMS keys, etc.)
|
|
9
9
|
* 3. Generated resource references
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
// OTLP-family exporters read their endpoint/headers from these standard env
|
|
13
|
-
// vars (ADR-011). When such an exporter is configured we auto-register them as
|
|
14
|
-
// Serverless passthroughs so the deployed Lambda inherits them from the deploy
|
|
15
|
-
// environment — no need for the adopter to also list them under `environment`.
|
|
16
|
-
//
|
|
17
|
-
// NOTE (VPC egress): a Lambda in a private subnet needs a NAT gateway or a VPC
|
|
18
|
-
// endpoint to reach an external OTLP backend (Honeycomb/Datadog). Without egress
|
|
19
|
-
// the exporter fails silently within its flush timeout — see the deploy docs.
|
|
20
|
-
const OTLP_EXPORTER_TYPES = new Set(['otlp', 'honeycomb', 'datadog']);
|
|
21
|
-
const OTEL_PASSTHROUGH_VARS = [
|
|
22
|
-
'OTEL_EXPORTER_OTLP_ENDPOINT',
|
|
23
|
-
'OTEL_EXPORTER_OTLP_HEADERS',
|
|
24
|
-
];
|
|
25
|
-
|
|
26
|
-
function addTelemetryEnvPassthrough(appDefinition, envVars) {
|
|
27
|
-
const exporterType = appDefinition?.telemetry?.exporter?.type;
|
|
28
|
-
if (!OTLP_EXPORTER_TYPES.has(exporterType)) return;
|
|
29
|
-
for (const key of OTEL_PASSTHROUGH_VARS) {
|
|
30
|
-
envVars[key] = `\${env:${key}, ''}`;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
12
|
/**
|
|
35
13
|
* Get environment variables from AppDefinition
|
|
36
|
-
*
|
|
14
|
+
*
|
|
37
15
|
* Extracts environment variable definitions where value is true,
|
|
38
16
|
* and creates Serverless variable references.
|
|
39
|
-
*
|
|
17
|
+
*
|
|
40
18
|
* @param {Object} appDefinition - Application definition
|
|
41
19
|
* @returns {Object} Environment variable mappings
|
|
42
20
|
*/
|
|
@@ -60,8 +38,6 @@ function getAppEnvironmentVars(appDefinition) {
|
|
|
60
38
|
'AWS_SESSION_TOKEN',
|
|
61
39
|
]);
|
|
62
40
|
|
|
63
|
-
addTelemetryEnvPassthrough(appDefinition, envVars);
|
|
64
|
-
|
|
65
41
|
if (!appDefinition.environment) {
|
|
66
42
|
return envVars;
|
|
67
43
|
}
|
|
@@ -89,8 +65,7 @@ function getAppEnvironmentVars(appDefinition) {
|
|
|
89
65
|
}
|
|
90
66
|
if (skippedKeys.length > 0) {
|
|
91
67
|
console.log(
|
|
92
|
-
` ⚠️ Skipped ${
|
|
93
|
-
skippedKeys.length
|
|
68
|
+
` ⚠️ Skipped ${skippedKeys.length
|
|
94
69
|
} reserved AWS Lambda variables: ${skippedKeys.join(', ')}`
|
|
95
70
|
);
|
|
96
71
|
}
|
|
@@ -100,9 +75,9 @@ function getAppEnvironmentVars(appDefinition) {
|
|
|
100
75
|
|
|
101
76
|
/**
|
|
102
77
|
* Build complete environment configuration for Lambda functions
|
|
103
|
-
*
|
|
78
|
+
*
|
|
104
79
|
* Combines app environment vars with discovered AWS resource references
|
|
105
|
-
*
|
|
80
|
+
*
|
|
106
81
|
* @param {Object} appEnvironmentVars - Environment vars from AppDefinition
|
|
107
82
|
* @param {Object} discoveredResources - Discovered AWS resources
|
|
108
83
|
* @returns {Object} Complete environment configuration
|
|
@@ -110,7 +85,7 @@ function getAppEnvironmentVars(appDefinition) {
|
|
|
110
85
|
function buildEnvironment(appEnvironmentVars, discoveredResources) {
|
|
111
86
|
const environment = {
|
|
112
87
|
...appEnvironmentVars,
|
|
113
|
-
STAGE: '${self:provider.stage}',
|
|
88
|
+
STAGE: '${self:provider.stage}', // Used by encryption bypass logic
|
|
114
89
|
FRIGG_STACK: '${self:service}',
|
|
115
90
|
FRIGG_STAGE: '${self:provider.stage}',
|
|
116
91
|
FRIGG_REGION: '${self:provider.region}',
|
|
@@ -126,9 +101,7 @@ function buildEnvironment(appEnvironmentVars, discoveredResources) {
|
|
|
126
101
|
// Add database connection info if discovered
|
|
127
102
|
if (discoveredResources.auroraClusterEndpoint) {
|
|
128
103
|
environment.DATABASE_HOST = discoveredResources.auroraClusterEndpoint;
|
|
129
|
-
environment.DATABASE_PORT = String(
|
|
130
|
-
discoveredResources.auroraPort || 5432
|
|
131
|
-
);
|
|
104
|
+
environment.DATABASE_PORT = String(discoveredResources.auroraPort || 5432);
|
|
132
105
|
}
|
|
133
106
|
|
|
134
107
|
// Add secrets manager secret ARN if discovered
|
|
@@ -143,3 +116,4 @@ module.exports = {
|
|
|
143
116
|
getAppEnvironmentVars,
|
|
144
117
|
buildEnvironment,
|
|
145
118
|
};
|
|
119
|
+
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tests for Environment Builder Service
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* Tests environment variable extraction and building
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
const {
|
|
8
|
-
getAppEnvironmentVars,
|
|
9
|
-
buildEnvironment,
|
|
10
|
-
} = require('./environment-builder');
|
|
7
|
+
const { getAppEnvironmentVars, buildEnvironment } = require('./environment-builder');
|
|
11
8
|
|
|
12
9
|
describe('Environment Builder', () => {
|
|
13
10
|
describe('getAppEnvironmentVars()', () => {
|
|
@@ -111,42 +108,6 @@ describe('Environment Builder', () => {
|
|
|
111
108
|
});
|
|
112
109
|
});
|
|
113
110
|
|
|
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
111
|
describe('buildEnvironment()', () => {
|
|
151
112
|
it('should combine app vars with standard Frigg variables', () => {
|
|
152
113
|
const appEnvironmentVars = {
|
|
@@ -154,10 +115,7 @@ describe('Environment Builder', () => {
|
|
|
154
115
|
};
|
|
155
116
|
const discoveredResources = {};
|
|
156
117
|
|
|
157
|
-
const result = buildEnvironment(
|
|
158
|
-
appEnvironmentVars,
|
|
159
|
-
discoveredResources
|
|
160
|
-
);
|
|
118
|
+
const result = buildEnvironment(appEnvironmentVars, discoveredResources);
|
|
161
119
|
|
|
162
120
|
expect(result.API_KEY).toBe("${env:API_KEY, ''}");
|
|
163
121
|
expect(result.STAGE).toBe('${self:provider.stage}');
|
|
@@ -172,14 +130,9 @@ describe('Environment Builder', () => {
|
|
|
172
130
|
kmsKeyId: 'arn:aws:kms:us-east-1:123456:key/abc-123',
|
|
173
131
|
};
|
|
174
132
|
|
|
175
|
-
const result = buildEnvironment(
|
|
176
|
-
appEnvironmentVars,
|
|
177
|
-
discoveredResources
|
|
178
|
-
);
|
|
133
|
+
const result = buildEnvironment(appEnvironmentVars, discoveredResources);
|
|
179
134
|
|
|
180
|
-
expect(result.KMS_KEY_ARN).toBe(
|
|
181
|
-
'arn:aws:kms:us-east-1:123456:key/abc-123'
|
|
182
|
-
);
|
|
135
|
+
expect(result.KMS_KEY_ARN).toBe('arn:aws:kms:us-east-1:123456:key/abc-123');
|
|
183
136
|
});
|
|
184
137
|
|
|
185
138
|
it('should prefer kmsKeyId over kmsKeyArn if both present', () => {
|
|
@@ -189,33 +142,22 @@ describe('Environment Builder', () => {
|
|
|
189
142
|
kmsKeyArn: 'arn:aws:kms:us-east-1:123456:key/secondary',
|
|
190
143
|
};
|
|
191
144
|
|
|
192
|
-
const result = buildEnvironment(
|
|
193
|
-
appEnvironmentVars,
|
|
194
|
-
discoveredResources
|
|
195
|
-
);
|
|
145
|
+
const result = buildEnvironment(appEnvironmentVars, discoveredResources);
|
|
196
146
|
|
|
197
147
|
// Implementation uses if/else-if, so kmsKeyId takes priority
|
|
198
|
-
expect(result.KMS_KEY_ARN).toBe(
|
|
199
|
-
'arn:aws:kms:us-east-1:123456:key/primary'
|
|
200
|
-
);
|
|
148
|
+
expect(result.KMS_KEY_ARN).toBe('arn:aws:kms:us-east-1:123456:key/primary');
|
|
201
149
|
});
|
|
202
150
|
|
|
203
151
|
it('should add database connection info if discovered', () => {
|
|
204
152
|
const appEnvironmentVars = {};
|
|
205
153
|
const discoveredResources = {
|
|
206
|
-
auroraClusterEndpoint:
|
|
207
|
-
'cluster.abc.us-east-1.rds.amazonaws.com',
|
|
154
|
+
auroraClusterEndpoint: 'cluster.abc.us-east-1.rds.amazonaws.com',
|
|
208
155
|
auroraPort: 5432,
|
|
209
156
|
};
|
|
210
157
|
|
|
211
|
-
const result = buildEnvironment(
|
|
212
|
-
appEnvironmentVars,
|
|
213
|
-
discoveredResources
|
|
214
|
-
);
|
|
158
|
+
const result = buildEnvironment(appEnvironmentVars, discoveredResources);
|
|
215
159
|
|
|
216
|
-
expect(result.DATABASE_HOST).toBe(
|
|
217
|
-
'cluster.abc.us-east-1.rds.amazonaws.com'
|
|
218
|
-
);
|
|
160
|
+
expect(result.DATABASE_HOST).toBe('cluster.abc.us-east-1.rds.amazonaws.com');
|
|
219
161
|
expect(result.DATABASE_PORT).toBe('5432');
|
|
220
162
|
});
|
|
221
163
|
|
|
@@ -225,10 +167,7 @@ describe('Environment Builder', () => {
|
|
|
225
167
|
auroraClusterEndpoint: 'cluster.example.com',
|
|
226
168
|
};
|
|
227
169
|
|
|
228
|
-
const result = buildEnvironment(
|
|
229
|
-
appEnvironmentVars,
|
|
230
|
-
discoveredResources
|
|
231
|
-
);
|
|
170
|
+
const result = buildEnvironment(appEnvironmentVars, discoveredResources);
|
|
232
171
|
|
|
233
172
|
expect(result.DATABASE_HOST).toBe('cluster.example.com');
|
|
234
173
|
expect(result.DATABASE_PORT).toBe('5432');
|
|
@@ -237,18 +176,12 @@ describe('Environment Builder', () => {
|
|
|
237
176
|
it('should add database secret ARN if discovered', () => {
|
|
238
177
|
const appEnvironmentVars = {};
|
|
239
178
|
const discoveredResources = {
|
|
240
|
-
databaseSecretArn:
|
|
241
|
-
'arn:aws:secretsmanager:us-east-1:123456:secret:db-secret',
|
|
179
|
+
databaseSecretArn: 'arn:aws:secretsmanager:us-east-1:123456:secret:db-secret',
|
|
242
180
|
};
|
|
243
181
|
|
|
244
|
-
const result = buildEnvironment(
|
|
245
|
-
appEnvironmentVars,
|
|
246
|
-
discoveredResources
|
|
247
|
-
);
|
|
182
|
+
const result = buildEnvironment(appEnvironmentVars, discoveredResources);
|
|
248
183
|
|
|
249
|
-
expect(result.DATABASE_SECRET_ARN).toBe(
|
|
250
|
-
'arn:aws:secretsmanager:us-east-1:123456:secret:db-secret'
|
|
251
|
-
);
|
|
184
|
+
expect(result.DATABASE_SECRET_ARN).toBe('arn:aws:secretsmanager:us-east-1:123456:secret:db-secret');
|
|
252
185
|
});
|
|
253
186
|
|
|
254
187
|
it('should combine all discovered resources', () => {
|
|
@@ -259,27 +192,19 @@ describe('Environment Builder', () => {
|
|
|
259
192
|
kmsKeyArn: 'arn:aws:kms:us-east-1:123456:key/abc',
|
|
260
193
|
auroraClusterEndpoint: 'db.example.com',
|
|
261
194
|
auroraPort: 3306,
|
|
262
|
-
databaseSecretArn:
|
|
263
|
-
'arn:aws:secretsmanager:us-east-1:123456:secret:db',
|
|
195
|
+
databaseSecretArn: 'arn:aws:secretsmanager:us-east-1:123456:secret:db',
|
|
264
196
|
};
|
|
265
197
|
|
|
266
|
-
const result = buildEnvironment(
|
|
267
|
-
appEnvironmentVars,
|
|
268
|
-
discoveredResources
|
|
269
|
-
);
|
|
198
|
+
const result = buildEnvironment(appEnvironmentVars, discoveredResources);
|
|
270
199
|
|
|
271
200
|
expect(result.CUSTOM_VAR).toBe("${env:CUSTOM_VAR, ''}");
|
|
272
201
|
expect(result.FRIGG_STACK).toBe('${self:service}');
|
|
273
202
|
expect(result.FRIGG_STAGE).toBe('${self:provider.stage}');
|
|
274
203
|
expect(result.FRIGG_REGION).toBe('${self:provider.region}');
|
|
275
|
-
expect(result.KMS_KEY_ARN).toBe(
|
|
276
|
-
'arn:aws:kms:us-east-1:123456:key/abc'
|
|
277
|
-
);
|
|
204
|
+
expect(result.KMS_KEY_ARN).toBe('arn:aws:kms:us-east-1:123456:key/abc');
|
|
278
205
|
expect(result.DATABASE_HOST).toBe('db.example.com');
|
|
279
206
|
expect(result.DATABASE_PORT).toBe('3306');
|
|
280
|
-
expect(result.DATABASE_SECRET_ARN).toBe(
|
|
281
|
-
'arn:aws:secretsmanager:us-east-1:123456:secret:db'
|
|
282
|
-
);
|
|
207
|
+
expect(result.DATABASE_SECRET_ARN).toBe('arn:aws:secretsmanager:us-east-1:123456:secret:db');
|
|
283
208
|
});
|
|
284
209
|
|
|
285
210
|
it('should handle empty discoveredResources', () => {
|
|
@@ -288,10 +213,7 @@ describe('Environment Builder', () => {
|
|
|
288
213
|
};
|
|
289
214
|
const discoveredResources = {};
|
|
290
215
|
|
|
291
|
-
const result = buildEnvironment(
|
|
292
|
-
appEnvironmentVars,
|
|
293
|
-
discoveredResources
|
|
294
|
-
);
|
|
216
|
+
const result = buildEnvironment(appEnvironmentVars, discoveredResources);
|
|
295
217
|
|
|
296
218
|
expect(result.API_KEY).toBe("${env:API_KEY, ''}");
|
|
297
219
|
expect(result.FRIGG_STACK).toBe('${self:service}');
|
|
@@ -315,13 +237,11 @@ describe('Environment Builder', () => {
|
|
|
315
237
|
auroraPort: 3306, // Number
|
|
316
238
|
};
|
|
317
239
|
|
|
318
|
-
const result = buildEnvironment(
|
|
319
|
-
appEnvironmentVars,
|
|
320
|
-
discoveredResources
|
|
321
|
-
);
|
|
240
|
+
const result = buildEnvironment(appEnvironmentVars, discoveredResources);
|
|
322
241
|
|
|
323
242
|
expect(result.DATABASE_PORT).toBe('3306'); // String
|
|
324
243
|
expect(typeof result.DATABASE_PORT).toBe('string');
|
|
325
244
|
});
|
|
326
245
|
});
|
|
327
246
|
});
|
|
247
|
+
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@friggframework/devtools",
|
|
3
3
|
"prettier": "@friggframework/prettier-config",
|
|
4
|
-
"version": "2.0.0--canary.
|
|
4
|
+
"version": "2.0.0--canary.623.ee3bde8.0",
|
|
5
5
|
"bin": {
|
|
6
6
|
"frigg": "./frigg-cli/index.js"
|
|
7
7
|
},
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"@babel/eslint-parser": "^7.18.9",
|
|
26
26
|
"@babel/parser": "^7.25.3",
|
|
27
27
|
"@babel/traverse": "^7.25.3",
|
|
28
|
-
"@friggframework/core": "2.0.0--canary.
|
|
29
|
-
"@friggframework/schemas": "2.0.0--canary.
|
|
30
|
-
"@friggframework/test": "2.0.0--canary.
|
|
28
|
+
"@friggframework/core": "2.0.0--canary.623.ee3bde8.0",
|
|
29
|
+
"@friggframework/schemas": "2.0.0--canary.623.ee3bde8.0",
|
|
30
|
+
"@friggframework/test": "2.0.0--canary.623.ee3bde8.0",
|
|
31
31
|
"@hapi/boom": "^10.0.1",
|
|
32
32
|
"@inquirer/prompts": "^5.3.8",
|
|
33
33
|
"axios": "^1.18.0",
|
|
@@ -55,8 +55,8 @@
|
|
|
55
55
|
"validate-npm-package-name": "^5.0.0"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@friggframework/eslint-config": "2.0.0--canary.
|
|
59
|
-
"@friggframework/prettier-config": "2.0.0--canary.
|
|
58
|
+
"@friggframework/eslint-config": "2.0.0--canary.623.ee3bde8.0",
|
|
59
|
+
"@friggframework/prettier-config": "2.0.0--canary.623.ee3bde8.0",
|
|
60
60
|
"aws-sdk-client-mock": "^4.1.0",
|
|
61
61
|
"aws-sdk-client-mock-jest": "^4.1.0",
|
|
62
62
|
"jest": "^30.1.3",
|
|
@@ -88,5 +88,5 @@
|
|
|
88
88
|
"publishConfig": {
|
|
89
89
|
"access": "public"
|
|
90
90
|
},
|
|
91
|
-
"gitHead": "
|
|
91
|
+
"gitHead": "ee3bde8d1adc7e90a424a26429ce4b4d612ff52f"
|
|
92
92
|
}
|