This is an automated email from the ASF dual-hosted git repository.

jason810496 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 8b2ef80dcde Fix "Dynamic require" error for CommonJS packages in 
airflow-ts-pack (#75067)
8b2ef80dcde is described below

commit 8b2ef80dcde15d32d1a0ef5cae2b87dc13a3a6af
Author: Andrew Chang <[email protected]>
AuthorDate: Sun Oct 25 16:47:37 2026 +0900

    Fix "Dynamic require" error for CommonJS packages in airflow-ts-pack 
(#75067)
    
    * Fix airflow-ts-pack for CommonJS packages using Node built-ins
    
    airflow-ts-pack outputs an ESM bundle, and an ESM file has no
    `require`. esbuild turns a CommonJS dependency's `require("fs")` into
    a shim that throws `Dynamic require of "fs" is not supported` unless a
    `require` is in scope. So any Dag importing such a package (yaml, pg,
    axios, @aws-sdk/client-s3, ...) failed to pack, and users cannot pass
    esbuild options to work around it.
    
    * Move the require banner comment onto the esbuild option
---
 ts-sdk/src/cli/pack.ts        |  6 ++++++
 ts-sdk/tests/cli/pack.test.ts | 31 +++++++++++++++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/ts-sdk/src/cli/pack.ts b/ts-sdk/src/cli/pack.ts
index f1806909e0f..7eb0d108938 100644
--- a/ts-sdk/src/cli/pack.ts
+++ b/ts-sdk/src/cli/pack.ts
@@ -45,6 +45,9 @@ const BUNDLE_FILENAME = "bundle.min.mjs";
 const STAGING_FILENAME = "bundle.pack-staging.mjs";
 const MANIFEST_TIMEOUT_MS = 60_000;
 const MANIFEST_MAX_BUFFER_BYTES = 64 * 1024 * 1024;
+const ESM_REQUIRE_BANNER =
+  'import{createRequire as __airflowCreateRequire}from"node:module";' +
+  "const require=__airflowCreateRequire(import.meta.url);";
 
 const USAGE = `Usage: airflow-ts-pack <entry> [--outdir <dir> | --outfile 
<path>]
 
@@ -315,6 +318,9 @@ export async function runPack(argv: readonly string[]): 
Promise<void> {
       // that two modules both declare, so the name the SDK reads is pinned to
       // the one the author wrote.
       keepNames: true,
+      // esbuild's require shim in an ESM bundle throws `Dynamic require of 
"process" is not
+      // supported` for a CommonJS dependency's Node built-in unless a 
`require` is in scope.
+      banner: { js: ESM_REQUIRE_BANNER },
       // Tags each author-owned file with its own path before its `new 
Dag(...)`
       // constructor runs, so the encoder gets one Dag-defining file per source
       // region.
diff --git a/ts-sdk/tests/cli/pack.test.ts b/ts-sdk/tests/cli/pack.test.ts
index 7b428acaa44..0ff32ab6f83 100644
--- a/ts-sdk/tests/cli/pack.test.ts
+++ b/ts-sdk/tests/cli/pack.test.ts
@@ -765,6 +765,37 @@ describe("runPack", () => {
     );
   });
 
+  it("packs a CommonJS dependency that requires a Node built-in", async () => {
+    outdir = mkdtempSync(path.join(tmpdir(), "ts-pack-"));
+    const dependencyDir = path.join(outdir, "node_modules", "cjs-dependency");
+    mkdirSync(dependencyDir, { recursive: true });
+    writeFileSync(
+      path.join(dependencyDir, "package.json"),
+      JSON.stringify({ name: "cjs-dependency", main: "index.js" }),
+    );
+    writeFileSync(
+      path.join(dependencyDir, "index.js"),
+      'require("process");\nexports.dagId = "cjs_dag";\n',
+    );
+    const entry = path.join(outdir, "cjs-entry.ts");
+    writeFileSync(
+      entry,
+      [
+        `import { Bundle, Dag } from ${JSON.stringify(SDK_INDEX)};`,
+        'import { dagId } from "cjs-dependency";',
+        "const dag = new Dag(dagId);",
+        'dag.task("extract", async () => undefined)();',
+        "await new Bundle(dag).serve();",
+      ].join("\n"),
+    );
+
+    await runPack([entry, "--outdir", outdir]);
+
+    expect(JSON.parse(readEmbeddedMetadata(path.join(outdir, 
"bundle.min.mjs")))).toHaveProperty(
+      "dag_source_paths.cjs_dag",
+    );
+  });
+
   it("packs only the Dags the served bundle holds", async () => {
     outdir = mkdtempSync(path.join(tmpdir(), "ts-pack-"));
     const entry = path.join(outdir, "forgotten-entry.ts");

Reply via email to