node-pg-migrate icon indicating copy to clipboard operation
node-pg-migrate copied to clipboard

Using ESM migration files causes `ERR_REQUIRE_ESM` error

Open markcellus opened this issue 2 years ago • 9 comments

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 avatar Jun 12 '22 14:06 markcellus

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 avatar Jun 12 '22 14:06 markcellus

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

markcellus avatar Jun 12 '22 14:06 markcellus

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.

qaas avatar Nov 24 '22 06:11 qaas

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.

WinterCore avatar Nov 24 '22 18:11 WinterCore

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.

eplarson avatar Feb 09 '24 21:02 eplarson

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

Shinigami92 avatar Mar 08 '24 21:03 Shinigami92