From c3556754fa59ab5c34e42545fcd91cf20a5c6443 Mon Sep 17 00:00:00 2001 From: Max Kukartsev Date: Thu, 2 Oct 2025 13:16:00 -0700 Subject: [PATCH] Properly handle ERR_REQUIRE_ASYNC_MODULE Recent Node.js versions throw `ERR_REQUIRE_ASYNC_MODULE` instead of `ERR_REQUIRE_ESM` if `require()` is used to import a module with top- level await. --- lib/env/config.js | 2 +- lib/env/migrationsDir.js | 2 +- test/env/config.test.js | 9 +++++++++ test/env/migrationsDir.test.js | 9 +++++++++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/env/config.js b/lib/env/config.js index dda21d8..d06fed4 100644 --- a/lib/env/config.js +++ b/lib/env/config.js @@ -71,7 +71,7 @@ module.exports = { const result = await moduleLoader.require(configPath); return getModuleExports(result); } catch (e) { - if (e.code === 'ERR_REQUIRE_ESM') { + if (e.code === 'ERR_REQUIRE_ESM' || e.code === 'ERR_REQUIRE_ASYNC_MODULE') { const loadedImport = await moduleLoader.import(url.pathToFileURL(configPath)); return getModuleExports(loadedImport); } diff --git a/lib/env/migrationsDir.js b/lib/env/migrationsDir.js index 906234c..2447701 100644 --- a/lib/env/migrationsDir.js +++ b/lib/env/migrationsDir.js @@ -102,7 +102,7 @@ module.exports = { const result = moduleLoader.require(migrationPath); return getModuleExports(result); } catch (e) { - if (e.code === 'ERR_REQUIRE_ESM') { + if (e.code === 'ERR_REQUIRE_ESM' || e.code === 'ERR_REQUIRE_ASYNC_MODULE') { const loadedImport = moduleLoader.import(url.pathToFileURL(migrationPath)); return getModuleExports(loadedImport); } diff --git a/test/env/config.test.js b/test/env/config.test.js index e8cbb07..de575b3 100644 --- a/test/env/config.test.js +++ b/test/env/config.test.js @@ -143,6 +143,15 @@ describe("config", () => { expect(moduleLoader.import.called).to.equal(true); }); + it("should fall back to using 'import' if Node requires the use of ESM (top-level await)", async () => { + const error = new Error('ESM required'); + error.code = 'ERR_REQUIRE_ASYNC_MODULE'; + moduleLoader.require = sinon.stub().throws(error); + moduleLoader.import.returns({}); + await config.read(); + expect(moduleLoader.import.called).to.equal(true); + }); + it("should handle ESM modules with default export", async () => { const expectedConfig = { mongodb: { diff --git a/test/env/migrationsDir.test.js b/test/env/migrationsDir.test.js index 17d33ea..eb8fa34 100644 --- a/test/env/migrationsDir.test.js +++ b/test/env/migrationsDir.test.js @@ -202,6 +202,15 @@ describe("migrationsDir", () => { await migrationsDir.loadMigration("someFile.js"); expect(moduleLoader.import.called).to.equal(true); }); + + it("should fall back to using 'import' if Node requires the use of ESM (top-level await)", async () => { + const error = new Error('ESM required'); + error.code = 'ERR_REQUIRE_ASYNC_MODULE'; + moduleLoader.require = sinon.stub().throws(error); + moduleLoader.import = sinon.stub().returns({ up: sinon.stub(), down: sinon.stub() }); + await migrationsDir.loadMigration("someFile.js"); + expect(moduleLoader.import.called).to.equal(true); + }); }); describe("resolveMigrationFileExtension()", () => {