Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitlab/scripts/publish_npm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,4 @@ if [ -d "./dist" ]; then
rm -rf ./dist
fi
yarn build
cp ./dist/handler.cjs ./dist/handler.js
npm publish
7 changes: 7 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ RUN yarn install
# Build the lambda layer
RUN yarn build
RUN cp -r dist /nodejs/node_modules/datadog-lambda-js
# The CJS shim at dist/handler.js exists to route ESM Lambdas through
# handler.mjs when the npm package is used directly (the publish scripts no
# longer copy handler.cjs to handler.js). In the layer, Lambda's bootstrap
# resolves `handler.handler` to handler.mjs as long as handler.js is absent,
Comment thread
zarirhamza marked this conversation as resolved.
Outdated
# which handles both CJS and ESM user code via the async load(). Drop the
# shim here so the layer keeps that direct-to-mjs behavior.
RUN rm /nodejs/node_modules/datadog-lambda-js/handler.js
RUN cp ./src/runtime/module_importer.js /nodejs/node_modules/datadog-lambda-js/runtime
RUN node <<'EOF'
const fs = require("fs");
Expand Down
1 change: 0 additions & 1 deletion scripts/publish_prod.sh
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ else
rm -rf ./dist
fi
yarn build
cp ./dist/handler.cjs ./dist/handler.js
yarn publish --new-version "$NEW_VERSION"
fi

Expand Down
63 changes: 63 additions & 0 deletions src/handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// CJS entry shim used by AWS Lambda's bootstrap when the handler string
Comment thread
zarirhamza marked this conversation as resolved.
Outdated
// resolves to `node_modules/datadog-lambda-js/dist/handler.handler`.
//
// Lambda's resolver searches for `.js` before `.mjs`, so this file is what
// gets loaded for both CJS and ESM user functions. We branch at runtime:
//
// - CJS user code: synchronously delegate to handler.cjs (preserves the
// prior fast-path behavior — no extra dynamic import on cold start).
//
// - ESM user code: expose an async handler that lazily `import()`s
// handler.mjs on the first invocation. handler.mjs's async `load()`
// transparently handles both CJS and ESM user modules, so this also
// fixes the ERR_REQUIRE_ESM failure mode reported in
// https://github.com/DataDog/datadog-lambda-js/issues/782.

"use strict";

const fs = require("fs");
const path = require("path");

function userIsEsm() {
const handlerEnv = process.env.DD_LAMBDA_HANDLER || process.env._HANDLER || "";
Comment thread
zarirhamza marked this conversation as resolved.
Outdated
if (/\.mjs(\..*)?$/.test(handlerEnv)) {
return true;
}

const taskRoot = process.env.LAMBDA_TASK_ROOT || process.cwd();
try {
const pkgPath = path.join(taskRoot, "package.json");
const raw = fs.readFileSync(pkgPath, "utf8");
const pkg = JSON.parse(raw);
if (pkg && pkg.type === "module") {
return true;
}
} catch (_) {
// package.json missing or unreadable — assume CJS, matches prior behavior.
}

return false;
}

if (userIsEsm()) {
let cachedHandler;
let cachedError;

exports.handler = async function ddEsmHandler(event, context) {
if (cachedError) {
throw cachedError;
}
if (!cachedHandler) {
try {
const mod = await import("./handler.mjs");
cachedHandler = mod.handler;
} catch (error) {
cachedError = error;
throw error;
}
}
return cachedHandler(event, context);
};
} else {
module.exports = require("./handler.cjs");
Comment thread
zarirhamza marked this conversation as resolved.
Outdated
}
Loading