Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using ESM migration files causes ERR_REQUIRE_ESM error #895

Open
markcellus opened this issue Jun 12, 2022 · 9 comments
Open

Using ESM migration files causes ERR_REQUIRE_ESM error #895

markcellus opened this issue Jun 12, 2022 · 9 comments
Labels
c: bug Something isn't working has workaround Workaround provided or linked help wanted Extra attention is needed p: 2-high Fix main branch s: accepted Accepted feature / Confirmed bug s: awaiting more info Additional information are requested
Milestone

Comments

@markcellus
Copy link

markcellus commented Jun 12, 2022

When a project is set to be an ES module (by setting type to module in package.json), adding a migration file that ends in .js extension in the migrations directory returns the following error when running migration. I suspect this is because the node-pg-migrate package itself is not an ES module?

/code/node_modules/node-pg-migrate/dist/runner.js:35
        throw new Error(`Can't get migration files: ${err.stack}`);
              ^

Error: Can't get migration files: Error [ERR_REQUIRE_ESM]: require() of ES Module /code/db/migrations/0000-instance-schema.js from /code/node_modules/node-pg-migrate/dist/runner.js not supported.
Instead change the require of 0000-instance-schema.js in /code/node_modules/node-pg-migrate/dist/runner.js to a dynamic import() which is available in all CommonJS modules.
    at /code/node_modules/node-pg-migrate/dist/runner.js:24:21
    at Array.map (<anonymous>)
    at loadMigrations (/code/node_modules/node-pg-migrate/dist/runner.js:19:41)
    at async Promise.all (index 0)
    at async Object.exports.default (/code/node_modules/node-pg-migrate/dist/runner.js:151:40)
    at loadMigrations (/code/node_modules/node-pg-migrate/dist/runner.js:35:15)
    at async Promise.all (index 0)
    at async Object.exports.default (/code/node_modules/node-pg-migrate/dist/runner.js:151:40)

Contents of migration file are just exporting async up and down functions:

export async function up() {
  // do stuff here
}

export async function down() {
  // do stuff here
}
@markcellus
Copy link
Author

Also note, I realize I can automatically create migration files with the node-pg-migrate create {migration-name} command. But I already had migration files before installing package, and rather not have to rewrite them all from scratch.

@markcellus
Copy link
Author

Just tried a workaround by renaming all the file extensions in the migrations directory from .js to .cjs. But then I get the following error, due to use of import/export:

SyntaxError: Cannot use import statement outside a module

@qaas
Copy link

qaas commented Nov 24, 2022

Hi @markcellus

I had the same error and this is how it works on my machine :) . My package.json has type: module and I use imports across the app. As yourself I changed the file extension to .cjs.

I generate the migrations with the migrate create cli command and my file will look something like:
exports.shorthands = undefined; exports.up = pgm => { pgm.createTable('tbl', { table properties .... }); }; exports.down = pgm => {};

When running migrate up the ESM complain will go away. Hope it will help you as well.
Am not sure if this would be still an open issue and maybe a doc update will solve this.

@WinterCore
Copy link

For anyone wondering how to solve this without changing any file extensions or config. The only requirement is that you need to have ts-node installed.

You can create a separate tsconfig.json file that'll only be used for migrations with the following contents, you can call the file any name you want but here I'll be using tsconfig.migrations.json

// tsconfig.migrations.json
{
    // Extend the original tsconfig.json
    "extends": "./tsconfig.json",
    "compilerOptions": {
        // Use commonjs instead of esm when compiling the migration files
        "module": "CommonJS",
        "moduleResolution": "Node"
    },
    // Tell ts-node to treat any file under the migrations directory as cjs instead of esm
    // this basically overrides the "type": "module" in your package.json file
    "ts-node": {
        "moduleTypes": {
            // Change the "migrations" key here to match the path of your migrations folder
            "migrations": "cjs"
        }
    },
    // Add the path of your migrations folder and exclude everything else
    "include": ["migrations"],
    "exclude": ["src"]
}

And now in your package.json file change your migrate script to the following

"scripts": {
    "migrate": "ts-node --project tsconfig.migrations.json node_modules/node-pg-migrate/bin/node-pg-migrate"
}

and voila.

@eplarson
Copy link

eplarson commented Feb 9, 2024

For anyone else going down this rabbit hole, I was able to get past this and use typescript files with the following recipe. What it basically does is transpiles the ts file into commonjs format, which is compatible with node-pg-migrate's runner.

  1. Create another top-level folder for migration stuff called db (this may not be strictly necessary but keeps things organized.
  2. Add 2 files inside db:
    package.json:
    {
      "name": "project-migrations",
      "type": "commonjs"
    }
    tsconfig.migrations.json:
    {
      "extends": "../tsconfig.json",
      "compilerOptions": {
        "verbatimModuleSyntax": false,
        "module": "CommonJS",
      },
    }
  3. Configure node-pg-migrate to use these files, using command line args, environment variables, or config. I did the latter:
    config/default.json:
    {
        "db": {
        "user": "postgres",
        "password": "password",
        "host": "localhost",
        "port": 5432,
        "database": "yourdb",
        "migration-filename-format": "utc",
        "migrations-dir": "./db/migrations",
        "tsconfig": "./db/tsconfig.migrations.json",
        "template-file-name": "./db/template.ts"
      }

That should do it. For reference, I'm using v6.2.2 and TS 5.

My main tsconfig file is this. I don't know if anything here is required, but I'm including it just in case.

{
	"extends": "./.svelte-kit/tsconfig.json",
	"compilerOptions": {
		"allowJs": true,
		"checkJs": true,
		"esModuleInterop": true,
		"forceConsistentCasingInFileNames": true,
		"resolveJsonModule": true,
		"skipLibCheck": true,
		"sourceMap": true,
		"strict": true,
		"moduleResolution": "bundler"
	}
}

Finally, template.ts listed above isn't strictly necessary, but adds import type to the import statement which quiets an error down in my editor.

@Shinigami92
Copy link
Collaborator

Is this still an issue with 7.0.0-alpha.0?

@Shinigami92 Shinigami92 added the s: awaiting more info Additional information are requested label Mar 8, 2024
@Apreche
Copy link

Apreche commented May 9, 2024

I'm new to node-pg-migrate. Coming here after encountering this problem. Disappointed, but not surprised, to see the issue is two years old.

@Shinigami92
Copy link
Collaborator

I'm new to node-pg-migrate. Coming here after encountering this problem. Disappointed, but not surprised, to see the issue is two years old.

@Apreche

Which version did you test?

If it is still an issue, let's tackle this and set prio to high for this one.

@Apreche
Copy link

Apreche commented May 9, 2024

I'm new to node-pg-migrate. Coming here after encountering this problem. Disappointed, but not surprised, to see the issue is two years old.

@Apreche

Which version did you test?

If it is still an issue, let's tackle this and set prio to high for this one.

I'm using node-pg-migrate version 7.3.2
node version 20.12.2
npm version 10.5.0
pg version 8.11.5
MacOS Sonoma 14.4.1 if that matters

My project has type: "module" in the package.json

The error appeared when I was following the getting started instructions.

npm run migrate create my-first-migration

Then when I do

npm run migrate up the error appears

Error: Can't get migration files: Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/apreche/Projects/test-app/migrations/1715218490179_my-first-migration.js from /Users/apreche/Projects/test-app/node_modules/node-pg-migrate/dist/runner.js not supported.
1715218490179_my-first-migration.js is treated as an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which declares all .js files in that package scope as ES modules.
Instead either rename 1715218490179_my-first-migration.js to end in .cjs, change the requiring code to use dynamic import() which is available in all CommonJS modules, or change "type": "module" to "type": "commonjs" in /Users/apreche/Projects/test-app/package.json to treat all .js files as CommonJS (using .mjs for all ES modules instead).```

I solved it by renaming the file to .cjs as per the instructions, and now it works just fine. Even so, I don't think it's great that this error should ever appear in the first place. Perhaps its as simple as naming the file .cjs by default?

@Shinigami92 Shinigami92 added c: bug Something isn't working help wanted Extra attention is needed p: 2-high Fix main branch s: accepted Accepted feature / Confirmed bug and removed s: pending triage Pending Triage labels May 9, 2024
@Shinigami92 Shinigami92 added this to the v7.x milestone May 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c: bug Something isn't working has workaround Workaround provided or linked help wanted Extra attention is needed p: 2-high Fix main branch s: accepted Accepted feature / Confirmed bug s: awaiting more info Additional information are requested
Projects
None yet
Development

No branches or pull requests

6 participants