diff --git a/lib/plugins/aws/dev/local-lambda/index.js b/lib/plugins/aws/dev/local-lambda/index.js index 1141578e7..069eb1af8 100644 --- a/lib/plugins/aws/dev/local-lambda/index.js +++ b/lib/plugins/aws/dev/local-lambda/index.js @@ -288,7 +288,7 @@ const runtimeWrappers = [ { command: 'node', arguments: [], - path: path.join(__dirname, 'runtime-wrappers/node.cjs'), + path: path.join(__dirname, 'runtime-wrappers/node.js'), versions: ['nodejs14.x', 'nodejs16.x', 'nodejs18.x', 'nodejs20.x'], extensions: ['.js', '.mjs', '.cjs', '.ts', '.mts', '.cts'], }, diff --git a/lib/plugins/aws/dev/local-lambda/runtime-wrappers/node.cjs b/lib/plugins/aws/dev/local-lambda/runtime-wrappers/node.js similarity index 85% rename from lib/plugins/aws/dev/local-lambda/runtime-wrappers/node.cjs rename to lib/plugins/aws/dev/local-lambda/runtime-wrappers/node.js index 2a06f898d..9bb55dab8 100644 --- a/lib/plugins/aws/dev/local-lambda/runtime-wrappers/node.cjs +++ b/lib/plugins/aws/dev/local-lambda/runtime-wrappers/node.js @@ -1,7 +1,9 @@ -const path = require('path') -const os = require('os') -const fs = require('fs') -const { inspect } = require('util') +import { pathToFileURL } from 'url' +import path from 'path' +import os from 'os' +import fs from 'fs' +import { inspect } from 'util' +import ServerlessError from '@serverlessinc/sf-core/src/utils/errors/serverlessError.js' const originaStdoutlWrite = process.stdout.write const originaStderrlWrite = process.stderr.write @@ -94,32 +96,38 @@ const saveInvocationResult = (result) => { /** * Imports the user handler function from the specified file path. - * We first try to require the file, and if it fails with ERR_REQUIRE_ESM, we import it. * This supports both CommonJS and ESM handler files. - * If the file is already cached, it is deleted to ensure the latest version is imported - * as the user makes changes during the dev mode session * * @param {string} handlerFileAbsolutePath - Path to handler file * @param {string} handlerName - The Handler Name defined in the config file * @returns {Promise} */ const importFunction = async (handlerFileAbsolutePath, handlerName) => { - let handlerFunction - try { - handlerFunction = require(handlerFileAbsolutePath)[handlerName] - } catch (error) { - if (error.code === 'ERR_REQUIRE_ESM') { - handlerFunction = await import(handlerFileAbsolutePath)[handlerName] - } - - throw error + // Check if the file exists + if (!fs.existsSync(handlerFileAbsolutePath)) { + throw new ServerlessError( + `Handler file was not found: ${handlerFileAbsolutePath}`, + 'DEV_MODE_HANDLER_FILE_NOT_FOUND', + ) } + // Convert the file path to a file URL to ensure + // it works across different operating systems + // and for both CommonJS and ESM handler files + const fileUrl = pathToFileURL(handlerFileAbsolutePath).href + + // Import the handler file. This works for both CommonJS and ESM handler files + const handlerFunction = (await import(fileUrl))[handlerName] + // Make sure the handler is a function if (typeof handlerFunction !== 'function') { - throw new Error(`Handler is not a function`) + throw new ServerlessError( + `Handler is not a function`, + 'DEV_MODE_INVALID_HANDLER', + ) } + // return the function to be invoked return handlerFunction } /**