diff --git a/src/runtimes/node/parser/exports.ts b/src/runtimes/node/parser/exports.ts index ec8842c66..742545e82 100644 --- a/src/runtimes/node/parser/exports.ts +++ b/src/runtimes/node/parser/exports.ts @@ -1,6 +1,5 @@ import type { Declaration, - ExportDefaultDeclaration, ExportNamedDeclaration, ExportSpecifier, Expression, @@ -167,9 +166,14 @@ const isNamedExport = (node: ExportNamedDeclaration['specifiers'][number], name: ) } -// Returns whether a given node is a default export declaration. -const isESMDefaultExport = (node: Statement): node is ExportDefaultDeclaration => - node.type === 'ExportDefaultDeclaration' +// Returns whether a given node is or contains a default export declaration. +const isESMDefaultExport = (node: Statement): boolean => + node.type === 'ExportDefaultDeclaration' || + (node.type === 'ExportNamedDeclaration' && + node.specifiers.some( + (exportSpecifier) => + exportSpecifier.exported.type === 'Identifier' && exportSpecifier.exported.name === 'default', + )) /** * Finds a `config` named CJS export that maps to an object variable diff --git a/tests/unit/runtimes/node/in_source_config.test.ts b/tests/unit/runtimes/node/in_source_config.test.ts index 4daedd447..f0684bee8 100644 --- a/tests/unit/runtimes/node/in_source_config.test.ts +++ b/tests/unit/runtimes/node/in_source_config.test.ts @@ -237,6 +237,30 @@ describe('V2 API', () => { }) }) + // Another version of the Remix handler + test('ESM file with handler generated by a function, exported in same expression as config, but handler is not called `handler`', () => { + const source = ` + const server_default = createRequestHandler({ build: server_build_exports, mode: "production" }) + export { server_default as default }; + ` + + const isc = parseSource(source, options) + expect(isc.runtimeAPIVersion).toEqual(2) + }) + + // Example for the Astro handler + test('ESM file with named `default` export renamed from a local binding', () => { + const source = ` + const _exports = adapter.createExports(_manifest, _args) + const _default = _exports['default'] + + export { _default as default }; + ` + + const isc = parseSource(source, options) + expect(isc.runtimeAPIVersion).toEqual(2) + }) + test('ESM file with default export wrapped in a literal from a function', () => { const source = ` async function handler(){ return { statusCode: 200, body: "Hello" }} @@ -252,7 +276,7 @@ describe('V2 API', () => { export { foo as default };` const isc = parseSource(source, options) - expect(isc).toEqual({ inputModuleFormat: 'esm', runtimeAPIVersion: 1 }) + expect(isc).toEqual({ inputModuleFormat: 'esm', routes: [], runtimeAPIVersion: 2 }) }) test('TypeScript file with a default export and no `handler` export', () => {