@friggframework/devtools 2.0.0--canary.625.6bef7de.0 → 2.0.0--canary.622.8425dec.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,15 +1,40 @@
|
|
|
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
|
-
const {
|
|
12
|
+
const {
|
|
13
|
+
isSsmOffloadActive,
|
|
14
|
+
getOffloadedKeys,
|
|
15
|
+
} = require('../parameters/offload-utils');
|
|
16
|
+
|
|
17
|
+
// OTLP-family exporters read their endpoint/headers from these standard env
|
|
18
|
+
// vars (ADR-011). When such an exporter is configured we auto-register them as
|
|
19
|
+
// Serverless passthroughs so the deployed Lambda inherits them from the deploy
|
|
20
|
+
// environment — no need for the adopter to also list them under `environment`.
|
|
21
|
+
//
|
|
22
|
+
// NOTE (VPC egress): a Lambda in a private subnet needs a NAT gateway or a VPC
|
|
23
|
+
// endpoint to reach an external OTLP backend (Honeycomb/Datadog). Without egress
|
|
24
|
+
// the exporter fails silently within its flush timeout — see the deploy docs.
|
|
25
|
+
const OTLP_EXPORTER_TYPES = new Set(['otlp', 'honeycomb', 'datadog']);
|
|
26
|
+
const OTEL_PASSTHROUGH_VARS = [
|
|
27
|
+
'OTEL_EXPORTER_OTLP_ENDPOINT',
|
|
28
|
+
'OTEL_EXPORTER_OTLP_HEADERS',
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
function addTelemetryEnvPassthrough(appDefinition, envVars) {
|
|
32
|
+
const exporterType = appDefinition?.telemetry?.exporter?.type;
|
|
33
|
+
if (!OTLP_EXPORTER_TYPES.has(exporterType)) return;
|
|
34
|
+
for (const key of OTEL_PASSTHROUGH_VARS) {
|
|
35
|
+
envVars[key] = `\${env:${key}, ''}`;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
13
38
|
|
|
14
39
|
/**
|
|
15
40
|
* Get environment variables from AppDefinition
|
|
@@ -45,6 +70,8 @@ function getAppEnvironmentVars(appDefinition) {
|
|
|
45
70
|
'AWS_SESSION_TOKEN',
|
|
46
71
|
]);
|
|
47
72
|
|
|
73
|
+
addTelemetryEnvPassthrough(appDefinition, envVars);
|
|
74
|
+
|
|
48
75
|
const environment = appDefinition.environment || {};
|
|
49
76
|
|
|
50
77
|
console.log('📋 Loading environment variables from appDefinition...');
|
|
@@ -94,15 +121,16 @@ function getAppEnvironmentVars(appDefinition) {
|
|
|
94
121
|
}
|
|
95
122
|
if (skippedKeys.length > 0) {
|
|
96
123
|
console.log(
|
|
97
|
-
` ⚠️ Skipped ${
|
|
124
|
+
` ⚠️ Skipped ${
|
|
125
|
+
skippedKeys.length
|
|
98
126
|
} reserved AWS Lambda variables: ${skippedKeys.join(', ')}`
|
|
99
127
|
);
|
|
100
128
|
}
|
|
101
129
|
if (offloadedKeys.length > 0) {
|
|
102
130
|
console.log(
|
|
103
|
-
` 🔒 Offloaded ${
|
|
104
|
-
|
|
105
|
-
)}`
|
|
131
|
+
` 🔒 Offloaded ${
|
|
132
|
+
offloadedKeys.length
|
|
133
|
+
} variables to SSM: ${offloadedKeys.join(', ')}`
|
|
106
134
|
);
|
|
107
135
|
}
|
|
108
136
|
|
|
@@ -111,9 +139,9 @@ function getAppEnvironmentVars(appDefinition) {
|
|
|
111
139
|
|
|
112
140
|
/**
|
|
113
141
|
* Build complete environment configuration for Lambda functions
|
|
114
|
-
*
|
|
142
|
+
*
|
|
115
143
|
* Combines app environment vars with discovered AWS resource references
|
|
116
|
-
*
|
|
144
|
+
*
|
|
117
145
|
* @param {Object} appEnvironmentVars - Environment vars from AppDefinition
|
|
118
146
|
* @param {Object} discoveredResources - Discovered AWS resources
|
|
119
147
|
* @returns {Object} Complete environment configuration
|
|
@@ -121,7 +149,7 @@ function getAppEnvironmentVars(appDefinition) {
|
|
|
121
149
|
function buildEnvironment(appEnvironmentVars, discoveredResources) {
|
|
122
150
|
const environment = {
|
|
123
151
|
...appEnvironmentVars,
|
|
124
|
-
STAGE: '${self:provider.stage}',
|
|
152
|
+
STAGE: '${self:provider.stage}', // Used by encryption bypass logic
|
|
125
153
|
FRIGG_STACK: '${self:service}',
|
|
126
154
|
FRIGG_STAGE: '${self:provider.stage}',
|
|
127
155
|
FRIGG_REGION: '${self:provider.region}',
|
|
@@ -137,7 +165,9 @@ function buildEnvironment(appEnvironmentVars, discoveredResources) {
|
|
|
137
165
|
// Add database connection info if discovered
|
|
138
166
|
if (discoveredResources.auroraClusterEndpoint) {
|
|
139
167
|
environment.DATABASE_HOST = discoveredResources.auroraClusterEndpoint;
|
|
140
|
-
environment.DATABASE_PORT = String(
|
|
168
|
+
environment.DATABASE_PORT = String(
|
|
169
|
+
discoveredResources.auroraPort || 5432
|
|
170
|
+
);
|
|
141
171
|
}
|
|
142
172
|
|
|
143
173
|
// Add secrets manager secret ARN if discovered
|
|
@@ -152,4 +182,3 @@ module.exports = {
|
|
|
152
182
|
getAppEnvironmentVars,
|
|
153
183
|
buildEnvironment,
|
|
154
184
|
};
|
|
155
|
-
|
|
@@ -1,10 +1,13 @@
|
|
|
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 {
|
|
7
|
+
const {
|
|
8
|
+
getAppEnvironmentVars,
|
|
9
|
+
buildEnvironment,
|
|
10
|
+
} = require('./environment-builder');
|
|
8
11
|
|
|
9
12
|
describe('Environment Builder', () => {
|
|
10
13
|
describe('getAppEnvironmentVars()', () => {
|
|
@@ -108,6 +111,42 @@ describe('Environment Builder', () => {
|
|
|
108
111
|
});
|
|
109
112
|
});
|
|
110
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
|
+
|
|
111
150
|
describe("getAppEnvironmentVars() - 'ssm' offload", () => {
|
|
112
151
|
const originalSkipDiscovery = process.env.FRIGG_SKIP_AWS_DISCOVERY;
|
|
113
152
|
|
|
@@ -161,13 +200,17 @@ describe('Environment Builder', () => {
|
|
|
161
200
|
const appDefinition = {
|
|
162
201
|
ssm: {
|
|
163
202
|
enable: true,
|
|
164
|
-
parameters: {
|
|
203
|
+
parameters: {
|
|
204
|
+
HUBSPOT_CLIENT_SECRET: { type: 'SecureString' },
|
|
205
|
+
},
|
|
165
206
|
},
|
|
166
207
|
};
|
|
167
208
|
|
|
168
209
|
const result = getAppEnvironmentVars(appDefinition);
|
|
169
210
|
|
|
170
|
-
expect(result.HUBSPOT_CLIENT_SECRET).toBe(
|
|
211
|
+
expect(result.HUBSPOT_CLIENT_SECRET).toBe(
|
|
212
|
+
"${env:HUBSPOT_CLIENT_SECRET, ''}"
|
|
213
|
+
);
|
|
171
214
|
});
|
|
172
215
|
|
|
173
216
|
it('excludes a key declared only in ssm.parameters when offload is active', () => {
|
|
@@ -175,7 +218,9 @@ describe('Environment Builder', () => {
|
|
|
175
218
|
const appDefinition = {
|
|
176
219
|
ssm: {
|
|
177
220
|
enable: true,
|
|
178
|
-
parameters: {
|
|
221
|
+
parameters: {
|
|
222
|
+
HUBSPOT_CLIENT_SECRET: { type: 'SecureString' },
|
|
223
|
+
},
|
|
179
224
|
},
|
|
180
225
|
};
|
|
181
226
|
|
|
@@ -211,7 +256,10 @@ describe('Environment Builder', () => {
|
|
|
211
256
|
};
|
|
212
257
|
const discoveredResources = {};
|
|
213
258
|
|
|
214
|
-
const result = buildEnvironment(
|
|
259
|
+
const result = buildEnvironment(
|
|
260
|
+
appEnvironmentVars,
|
|
261
|
+
discoveredResources
|
|
262
|
+
);
|
|
215
263
|
|
|
216
264
|
expect(result.API_KEY).toBe("${env:API_KEY, ''}");
|
|
217
265
|
expect(result.STAGE).toBe('${self:provider.stage}');
|
|
@@ -226,9 +274,14 @@ describe('Environment Builder', () => {
|
|
|
226
274
|
kmsKeyId: 'arn:aws:kms:us-east-1:123456:key/abc-123',
|
|
227
275
|
};
|
|
228
276
|
|
|
229
|
-
const result = buildEnvironment(
|
|
277
|
+
const result = buildEnvironment(
|
|
278
|
+
appEnvironmentVars,
|
|
279
|
+
discoveredResources
|
|
280
|
+
);
|
|
230
281
|
|
|
231
|
-
expect(result.KMS_KEY_ARN).toBe(
|
|
282
|
+
expect(result.KMS_KEY_ARN).toBe(
|
|
283
|
+
'arn:aws:kms:us-east-1:123456:key/abc-123'
|
|
284
|
+
);
|
|
232
285
|
});
|
|
233
286
|
|
|
234
287
|
it('should prefer kmsKeyId over kmsKeyArn if both present', () => {
|
|
@@ -238,22 +291,33 @@ describe('Environment Builder', () => {
|
|
|
238
291
|
kmsKeyArn: 'arn:aws:kms:us-east-1:123456:key/secondary',
|
|
239
292
|
};
|
|
240
293
|
|
|
241
|
-
const result = buildEnvironment(
|
|
294
|
+
const result = buildEnvironment(
|
|
295
|
+
appEnvironmentVars,
|
|
296
|
+
discoveredResources
|
|
297
|
+
);
|
|
242
298
|
|
|
243
299
|
// Implementation uses if/else-if, so kmsKeyId takes priority
|
|
244
|
-
expect(result.KMS_KEY_ARN).toBe(
|
|
300
|
+
expect(result.KMS_KEY_ARN).toBe(
|
|
301
|
+
'arn:aws:kms:us-east-1:123456:key/primary'
|
|
302
|
+
);
|
|
245
303
|
});
|
|
246
304
|
|
|
247
305
|
it('should add database connection info if discovered', () => {
|
|
248
306
|
const appEnvironmentVars = {};
|
|
249
307
|
const discoveredResources = {
|
|
250
|
-
auroraClusterEndpoint:
|
|
308
|
+
auroraClusterEndpoint:
|
|
309
|
+
'cluster.abc.us-east-1.rds.amazonaws.com',
|
|
251
310
|
auroraPort: 5432,
|
|
252
311
|
};
|
|
253
312
|
|
|
254
|
-
const result = buildEnvironment(
|
|
313
|
+
const result = buildEnvironment(
|
|
314
|
+
appEnvironmentVars,
|
|
315
|
+
discoveredResources
|
|
316
|
+
);
|
|
255
317
|
|
|
256
|
-
expect(result.DATABASE_HOST).toBe(
|
|
318
|
+
expect(result.DATABASE_HOST).toBe(
|
|
319
|
+
'cluster.abc.us-east-1.rds.amazonaws.com'
|
|
320
|
+
);
|
|
257
321
|
expect(result.DATABASE_PORT).toBe('5432');
|
|
258
322
|
});
|
|
259
323
|
|
|
@@ -263,7 +327,10 @@ describe('Environment Builder', () => {
|
|
|
263
327
|
auroraClusterEndpoint: 'cluster.example.com',
|
|
264
328
|
};
|
|
265
329
|
|
|
266
|
-
const result = buildEnvironment(
|
|
330
|
+
const result = buildEnvironment(
|
|
331
|
+
appEnvironmentVars,
|
|
332
|
+
discoveredResources
|
|
333
|
+
);
|
|
267
334
|
|
|
268
335
|
expect(result.DATABASE_HOST).toBe('cluster.example.com');
|
|
269
336
|
expect(result.DATABASE_PORT).toBe('5432');
|
|
@@ -272,12 +339,18 @@ describe('Environment Builder', () => {
|
|
|
272
339
|
it('should add database secret ARN if discovered', () => {
|
|
273
340
|
const appEnvironmentVars = {};
|
|
274
341
|
const discoveredResources = {
|
|
275
|
-
databaseSecretArn:
|
|
342
|
+
databaseSecretArn:
|
|
343
|
+
'arn:aws:secretsmanager:us-east-1:123456:secret:db-secret',
|
|
276
344
|
};
|
|
277
345
|
|
|
278
|
-
const result = buildEnvironment(
|
|
346
|
+
const result = buildEnvironment(
|
|
347
|
+
appEnvironmentVars,
|
|
348
|
+
discoveredResources
|
|
349
|
+
);
|
|
279
350
|
|
|
280
|
-
expect(result.DATABASE_SECRET_ARN).toBe(
|
|
351
|
+
expect(result.DATABASE_SECRET_ARN).toBe(
|
|
352
|
+
'arn:aws:secretsmanager:us-east-1:123456:secret:db-secret'
|
|
353
|
+
);
|
|
281
354
|
});
|
|
282
355
|
|
|
283
356
|
it('should combine all discovered resources', () => {
|
|
@@ -288,19 +361,27 @@ describe('Environment Builder', () => {
|
|
|
288
361
|
kmsKeyArn: 'arn:aws:kms:us-east-1:123456:key/abc',
|
|
289
362
|
auroraClusterEndpoint: 'db.example.com',
|
|
290
363
|
auroraPort: 3306,
|
|
291
|
-
databaseSecretArn:
|
|
364
|
+
databaseSecretArn:
|
|
365
|
+
'arn:aws:secretsmanager:us-east-1:123456:secret:db',
|
|
292
366
|
};
|
|
293
367
|
|
|
294
|
-
const result = buildEnvironment(
|
|
368
|
+
const result = buildEnvironment(
|
|
369
|
+
appEnvironmentVars,
|
|
370
|
+
discoveredResources
|
|
371
|
+
);
|
|
295
372
|
|
|
296
373
|
expect(result.CUSTOM_VAR).toBe("${env:CUSTOM_VAR, ''}");
|
|
297
374
|
expect(result.FRIGG_STACK).toBe('${self:service}');
|
|
298
375
|
expect(result.FRIGG_STAGE).toBe('${self:provider.stage}');
|
|
299
376
|
expect(result.FRIGG_REGION).toBe('${self:provider.region}');
|
|
300
|
-
expect(result.KMS_KEY_ARN).toBe(
|
|
377
|
+
expect(result.KMS_KEY_ARN).toBe(
|
|
378
|
+
'arn:aws:kms:us-east-1:123456:key/abc'
|
|
379
|
+
);
|
|
301
380
|
expect(result.DATABASE_HOST).toBe('db.example.com');
|
|
302
381
|
expect(result.DATABASE_PORT).toBe('3306');
|
|
303
|
-
expect(result.DATABASE_SECRET_ARN).toBe(
|
|
382
|
+
expect(result.DATABASE_SECRET_ARN).toBe(
|
|
383
|
+
'arn:aws:secretsmanager:us-east-1:123456:secret:db'
|
|
384
|
+
);
|
|
304
385
|
});
|
|
305
386
|
|
|
306
387
|
it('should handle empty discoveredResources', () => {
|
|
@@ -309,7 +390,10 @@ describe('Environment Builder', () => {
|
|
|
309
390
|
};
|
|
310
391
|
const discoveredResources = {};
|
|
311
392
|
|
|
312
|
-
const result = buildEnvironment(
|
|
393
|
+
const result = buildEnvironment(
|
|
394
|
+
appEnvironmentVars,
|
|
395
|
+
discoveredResources
|
|
396
|
+
);
|
|
313
397
|
|
|
314
398
|
expect(result.API_KEY).toBe("${env:API_KEY, ''}");
|
|
315
399
|
expect(result.FRIGG_STACK).toBe('${self:service}');
|
|
@@ -333,11 +417,13 @@ describe('Environment Builder', () => {
|
|
|
333
417
|
auroraPort: 3306, // Number
|
|
334
418
|
};
|
|
335
419
|
|
|
336
|
-
const result = buildEnvironment(
|
|
420
|
+
const result = buildEnvironment(
|
|
421
|
+
appEnvironmentVars,
|
|
422
|
+
discoveredResources
|
|
423
|
+
);
|
|
337
424
|
|
|
338
425
|
expect(result.DATABASE_PORT).toBe('3306'); // String
|
|
339
426
|
expect(typeof result.DATABASE_PORT).toBe('string');
|
|
340
427
|
});
|
|
341
428
|
});
|
|
342
429
|
});
|
|
343
|
-
|
|
@@ -32,17 +32,30 @@ const {
|
|
|
32
32
|
* present at /var/task. esbuild-bundled functions (e.g. defaultWebsocket,
|
|
33
33
|
* adopter custom functions) do NOT ship it — and a missing --import target is a
|
|
34
34
|
* fatal Node startup error — so they are left with the handler-time loader
|
|
35
|
-
* fallback instead.
|
|
35
|
+
* fallback instead.
|
|
36
|
+
*
|
|
37
|
+
* Set at function scope (function env wins over provider env), APPENDED to any
|
|
38
|
+
* NODE_OPTIONS already on the function or provider — so an app's own flags
|
|
39
|
+
* (OTel auto-instrumentation, source maps, memory tuning) survive instead of
|
|
40
|
+
* being clobbered. A function-level assignment shadows provider env in Lambda,
|
|
41
|
+
* so the provider value must be folded in here. Only a value already in the
|
|
42
|
+
* definition is appended — never a synthesized ${env:NODE_OPTIONS}, which would
|
|
43
|
+
* leak the deploy host's shell into every Lambda.
|
|
36
44
|
*/
|
|
37
|
-
function applySsmPreloadNodeOptions(appDefinition, functions) {
|
|
45
|
+
function applySsmPreloadNodeOptions(appDefinition, functions, providerEnvironment = {}) {
|
|
38
46
|
if (!isSsmOffloadActive(appDefinition)) {
|
|
39
47
|
return;
|
|
40
48
|
}
|
|
41
49
|
for (const fn of Object.values(functions)) {
|
|
42
|
-
if (fn.skipEsbuild) {
|
|
43
|
-
|
|
44
|
-
fn.environment.NODE_OPTIONS = SSM_PRELOAD_NODE_OPTIONS;
|
|
50
|
+
if (!fn.skipEsbuild) {
|
|
51
|
+
continue;
|
|
45
52
|
}
|
|
53
|
+
fn.environment = fn.environment || {};
|
|
54
|
+
const existing =
|
|
55
|
+
fn.environment.NODE_OPTIONS ?? providerEnvironment.NODE_OPTIONS;
|
|
56
|
+
fn.environment.NODE_OPTIONS = existing
|
|
57
|
+
? `${existing} ${SSM_PRELOAD_NODE_OPTIONS}`
|
|
58
|
+
: SSM_PRELOAD_NODE_OPTIONS;
|
|
46
59
|
}
|
|
47
60
|
}
|
|
48
61
|
const { modifyHandlerPaths } = require('./domains/shared/utilities/handler-path-resolver');
|
|
@@ -104,7 +117,11 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
104
117
|
definition.functions,
|
|
105
118
|
merged.functionEnvironments
|
|
106
119
|
);
|
|
107
|
-
applySsmPreloadNodeOptions(
|
|
120
|
+
applySsmPreloadNodeOptions(
|
|
121
|
+
AppDefinition,
|
|
122
|
+
definition.functions,
|
|
123
|
+
definition.provider.environment
|
|
124
|
+
);
|
|
108
125
|
|
|
109
126
|
if (merged.vpcConfig) {
|
|
110
127
|
definition.provider.vpc = merged.vpcConfig;
|
|
@@ -147,5 +164,5 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
147
164
|
return definition;
|
|
148
165
|
};
|
|
149
166
|
|
|
150
|
-
module.exports = { composeServerlessDefinition };
|
|
167
|
+
module.exports = { composeServerlessDefinition, applySsmPreloadNodeOptions };
|
|
151
168
|
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
const {
|
|
1
|
+
const {
|
|
2
|
+
composeServerlessDefinition,
|
|
3
|
+
applySsmPreloadNodeOptions,
|
|
4
|
+
} = require('./infrastructure-composer');
|
|
5
|
+
const {
|
|
6
|
+
SSM_PRELOAD_NODE_OPTIONS,
|
|
7
|
+
} = require('./domains/parameters/offload-utils');
|
|
2
8
|
|
|
3
9
|
// Helper to build discovery responses with overridable fields
|
|
4
10
|
const createDiscoveryResponse = (overrides = {}) => ({
|
|
@@ -1949,3 +1955,88 @@ describe('composeServerlessDefinition', () => {
|
|
|
1949
1955
|
});
|
|
1950
1956
|
});
|
|
1951
1957
|
});
|
|
1958
|
+
|
|
1959
|
+
describe('applySsmPreloadNodeOptions', () => {
|
|
1960
|
+
const appDefinition = {
|
|
1961
|
+
ssm: { enable: true },
|
|
1962
|
+
environment: { FOO: 'ssm' },
|
|
1963
|
+
};
|
|
1964
|
+
const savedSkip = process.env.FRIGG_SKIP_AWS_DISCOVERY;
|
|
1965
|
+
|
|
1966
|
+
beforeEach(() => {
|
|
1967
|
+
delete process.env.FRIGG_SKIP_AWS_DISCOVERY;
|
|
1968
|
+
});
|
|
1969
|
+
|
|
1970
|
+
afterEach(() => {
|
|
1971
|
+
if (savedSkip === undefined) {
|
|
1972
|
+
delete process.env.FRIGG_SKIP_AWS_DISCOVERY;
|
|
1973
|
+
} else {
|
|
1974
|
+
process.env.FRIGG_SKIP_AWS_DISCOVERY = savedSkip;
|
|
1975
|
+
}
|
|
1976
|
+
});
|
|
1977
|
+
|
|
1978
|
+
it('sets the preload NODE_OPTIONS on a skipEsbuild function with no existing value', () => {
|
|
1979
|
+
const functions = { auth: { skipEsbuild: true } };
|
|
1980
|
+
applySsmPreloadNodeOptions(appDefinition, functions);
|
|
1981
|
+
expect(functions.auth.environment.NODE_OPTIONS).toBe(
|
|
1982
|
+
SSM_PRELOAD_NODE_OPTIONS
|
|
1983
|
+
);
|
|
1984
|
+
});
|
|
1985
|
+
|
|
1986
|
+
it('appends to an existing function-level NODE_OPTIONS instead of clobbering it', () => {
|
|
1987
|
+
const functions = {
|
|
1988
|
+
auth: {
|
|
1989
|
+
skipEsbuild: true,
|
|
1990
|
+
environment: { NODE_OPTIONS: '--enable-source-maps' },
|
|
1991
|
+
},
|
|
1992
|
+
};
|
|
1993
|
+
applySsmPreloadNodeOptions(appDefinition, functions);
|
|
1994
|
+
expect(functions.auth.environment.NODE_OPTIONS).toBe(
|
|
1995
|
+
`--enable-source-maps ${SSM_PRELOAD_NODE_OPTIONS}`
|
|
1996
|
+
);
|
|
1997
|
+
});
|
|
1998
|
+
|
|
1999
|
+
it('folds in a provider-level NODE_OPTIONS (which the function env would otherwise shadow)', () => {
|
|
2000
|
+
const functions = { auth: { skipEsbuild: true } };
|
|
2001
|
+
applySsmPreloadNodeOptions(appDefinition, functions, {
|
|
2002
|
+
NODE_OPTIONS: '--require ./otel.js',
|
|
2003
|
+
});
|
|
2004
|
+
expect(functions.auth.environment.NODE_OPTIONS).toBe(
|
|
2005
|
+
`--require ./otel.js ${SSM_PRELOAD_NODE_OPTIONS}`
|
|
2006
|
+
);
|
|
2007
|
+
});
|
|
2008
|
+
|
|
2009
|
+
it('prefers a function-level value over the provider-level one', () => {
|
|
2010
|
+
const functions = {
|
|
2011
|
+
auth: {
|
|
2012
|
+
skipEsbuild: true,
|
|
2013
|
+
environment: { NODE_OPTIONS: '--fn-flag' },
|
|
2014
|
+
},
|
|
2015
|
+
};
|
|
2016
|
+
applySsmPreloadNodeOptions(appDefinition, functions, {
|
|
2017
|
+
NODE_OPTIONS: '--provider-flag',
|
|
2018
|
+
});
|
|
2019
|
+
expect(functions.auth.environment.NODE_OPTIONS).toBe(
|
|
2020
|
+
`--fn-flag ${SSM_PRELOAD_NODE_OPTIONS}`
|
|
2021
|
+
);
|
|
2022
|
+
});
|
|
2023
|
+
|
|
2024
|
+
it('never touches esbuild-bundled functions', () => {
|
|
2025
|
+
const functions = {
|
|
2026
|
+
websocket: { environment: { NODE_OPTIONS: '--keep-me' } },
|
|
2027
|
+
};
|
|
2028
|
+
applySsmPreloadNodeOptions(appDefinition, functions, {
|
|
2029
|
+
NODE_OPTIONS: '--provider',
|
|
2030
|
+
});
|
|
2031
|
+
expect(functions.websocket.environment.NODE_OPTIONS).toBe('--keep-me');
|
|
2032
|
+
});
|
|
2033
|
+
|
|
2034
|
+
it('is a no-op when offload is inactive', () => {
|
|
2035
|
+
const functions = { auth: { skipEsbuild: true } };
|
|
2036
|
+
applySsmPreloadNodeOptions(
|
|
2037
|
+
{ ssm: { enable: true } }, // no offloaded keys → inactive
|
|
2038
|
+
functions
|
|
2039
|
+
);
|
|
2040
|
+
expect(functions.auth.environment).toBeUndefined();
|
|
2041
|
+
});
|
|
2042
|
+
});
|
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.622.8425dec.0",
|
|
5
5
|
"bin": {
|
|
6
6
|
"frigg": "./frigg-cli/index.js"
|
|
7
7
|
},
|
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
"@babel/eslint-parser": "^7.18.9",
|
|
27
27
|
"@babel/parser": "^7.25.3",
|
|
28
28
|
"@babel/traverse": "^7.25.3",
|
|
29
|
-
"@friggframework/core": "2.0.0--canary.
|
|
30
|
-
"@friggframework/schemas": "2.0.0--canary.
|
|
31
|
-
"@friggframework/test": "2.0.0--canary.
|
|
29
|
+
"@friggframework/core": "2.0.0--canary.622.8425dec.0",
|
|
30
|
+
"@friggframework/schemas": "2.0.0--canary.622.8425dec.0",
|
|
31
|
+
"@friggframework/test": "2.0.0--canary.622.8425dec.0",
|
|
32
32
|
"@hapi/boom": "^10.0.1",
|
|
33
33
|
"@inquirer/prompts": "^5.3.8",
|
|
34
34
|
"axios": "^1.18.0",
|
|
@@ -56,8 +56,8 @@
|
|
|
56
56
|
"validate-npm-package-name": "^5.0.0"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
|
-
"@friggframework/eslint-config": "2.0.0--canary.
|
|
60
|
-
"@friggframework/prettier-config": "2.0.0--canary.
|
|
59
|
+
"@friggframework/eslint-config": "2.0.0--canary.622.8425dec.0",
|
|
60
|
+
"@friggframework/prettier-config": "2.0.0--canary.622.8425dec.0",
|
|
61
61
|
"aws-sdk-client-mock": "^4.1.0",
|
|
62
62
|
"aws-sdk-client-mock-jest": "^4.1.0",
|
|
63
63
|
"jest": "^30.1.3",
|
|
@@ -89,5 +89,5 @@
|
|
|
89
89
|
"publishConfig": {
|
|
90
90
|
"access": "public"
|
|
91
91
|
},
|
|
92
|
-
"gitHead": "
|
|
92
|
+
"gitHead": "8425dec6d3f2c09f7906f1e36c6856f63e1e69f9"
|
|
93
93
|
}
|