Skip to content

Commit 25d6dbc

Browse files
committed
fix handling of ESM modules
1 parent 0309b1e commit 25d6dbc

File tree

4 files changed

+22
-10
lines changed

4 files changed

+22
-10
lines changed

_test-stacks/provisioned-lambda/stacktape.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@ export default defineConfig(() => {
1111
enabled: true
1212
}
1313
},
14-
runtime: 'nodejs24.x',
1514
provisionedConcurrency: 1
1615
});
1716

1817
return {
19-
resources: { lambda },
18+
resources: { lambda }
2019
};
2120
});

src/config/random.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ export const SENTRY_CAPTURE_EXCEPTION_WAIT_TIME_MS = 1500;
7575
export const DEFAULT_MAXIMUM_PARALLEL_ARTIFACT_UPLOADS = 10;
7676
export const DEFAULT_MAXIMUM_PARALLEL_BUCKET_SYNCS = 10;
7777
export const DEFAULT_CONTAINER_NODE_VERSION = 24;
78+
export const DEFAULT_LAMBDA_NODE_VERSION = 24;
7879

7980
// @todo
8081
export const linksMap = {

src/domain/config-manager/index.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { CfResourceTransform, FinalTransform } from './transforms-resolver';
12
import { isAbsolute, join } from 'node:path';
23
import { eventManager } from '@application-services/event-manager';
34
import { globalStateManager } from '@application-services/global-state-manager';
@@ -26,6 +27,7 @@ import { getApexDomain } from '@utils/domains';
2627
import { getConfigPath } from '@utils/file-loaders';
2728
import { builtInDirectives } from './built-in-directives';
2829
import { ConfigResolver } from './config-resolver';
30+
import { TransformsResolver } from './transforms-resolver';
2931
import { getAlarmsToBeAppliedToResource, isGlobalAlarmEligibleForStack } from './utils/alarms';
3032
import { DEFAULT_TEST_LISTENER_PORT } from './utils/application-load-balancers';
3133
import { getStacktapeOriginRequestLambdaIamStatement } from './utils/iam';
@@ -41,7 +43,6 @@ import {
4143
} from './utils/lambdas';
4244
import { cleanConfigForMinimalTemplateCompilerMode, mergeStacktapeDefaults } from './utils/misc';
4345
import { runInitialValidations, validateConfigStructure } from './utils/validation';
44-
import { CfResourceTransform, FinalTransform, TransformsResolver } from './transforms-resolver';
4546

4647
export class ConfigManager {
4748
config: StacktapeConfig;
@@ -76,7 +77,9 @@ export class ConfigManager {
7677
if (shouldLoadConfig) {
7778
// Only load transforms for TypeScript configs with defineConfig pattern
7879
if (this.transformsResolver.isDefineConfigStyle(globalStateManager.configPath)) {
79-
const { transforms, finalTransform } = await this.transformsResolver.loadTransforms(globalStateManager.configPath);
80+
const { transforms, finalTransform } = await this.transformsResolver.loadTransforms(
81+
globalStateManager.configPath
82+
);
8083
this.transforms = transforms;
8184
this.finalTransform = finalTransform;
8285
}
@@ -274,7 +277,8 @@ export class ConfigManager {
274277
handler: getLambdaHandler({ name, packaging }),
275278
resourceName: awsResourceNames.lambda(name, globalStateManager.targetStack.stackName),
276279
cfLogicalName: cfLogicalNames.lambda(name),
277-
aliasLogicalName: (definition.deployment || definition.provisionedConcurrency) && cfLogicalNames.lambdaStpAlias(name),
280+
aliasLogicalName:
281+
(definition.deployment || definition.provisionedConcurrency) && cfLogicalNames.lambdaStpAlias(name),
278282
events: definition.events || [],
279283
configParentResourceType: 'function'
280284
} as StpLambdaFunction;

src/domain/packaging-manager/index.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { join } from 'node:path';
22
import { eventManager } from '@application-services/event-manager';
33
import { globalStateManager } from '@application-services/global-state-manager';
4+
import { DEFAULT_CONTAINER_NODE_VERSION, DEFAULT_LAMBDA_NODE_VERSION } from '@config';
45
import { configManager } from '@domain-services/config-manager';
56
import { deployedStackOverviewManager } from '@domain-services/deployed-stack-overview-manager';
67
import { deploymentArtifactManager } from '@domain-services/deployment-artifact-manager';
@@ -368,16 +369,23 @@ export class PackagingManager {
368369
case 'jsx':
369370
case 'mjs':
370371
case 'tsx': {
371-
// Extract Node.js version from runtime (e.g., 'nodejs24.x' -> '24')
372-
const nodeVersion = runtime?.match(/nodejs(\d+)/)?.[1] || '22';
373-
const useEsm = Number(nodeVersion) >= 24;
372+
const languageSpecificConfig =
373+
(packaging.properties.languageSpecificConfig as EsLanguageSpecificConfig) || undefined;
374+
const nodeVersionFromRuntime = Number(runtime?.match(/nodejs(\d+)/)?.[1]) || null;
375+
const nodeVersionFromUser = languageSpecificConfig?.nodeVersion;
376+
const nodeVersion =
377+
packagingType === 'stacktape-image-buildpack'
378+
? nodeVersionFromUser || DEFAULT_CONTAINER_NODE_VERSION
379+
: nodeVersionFromUser || nodeVersionFromRuntime || DEFAULT_LAMBDA_NODE_VERSION;
380+
const useEsm = languageSpecificConfig?.outputModuleFormat === 'esm' || nodeVersion >= 24;
381+
console.log('useEsm', useEsm);
374382
const sharedStpBuildpackProps = {
375383
...packaging.properties,
376-
nodeTarget: nodeVersion,
377384
minify: false,
378385
keepNames: true,
386+
nodeTarget: String(nodeVersion),
379387
entryfilePath: join(globalStateManager.workingDir, packaging.properties.entryfilePath),
380-
// Node.js 24+ requires (and properly supports) ESM for proper default export handling
388+
// Node.js 24+ on lambda only works with ESM. It has interoperability with CJS, so we always use ESM
381389
...(useEsm && { outputModuleFormat: 'esm' as const })
382390
};
383391
const additionalDigestInput = objectHash(sharedStpBuildpackProps);

0 commit comments

Comments
 (0)