-
Notifications
You must be signed in to change notification settings - Fork 189
Description
Bug Description
The default TypeScript migration template (templates/migration-template.ts) uses a value import for ColumnDefinitions, but ColumnDefinitions is only exported as a type from the package — it has no runtime representation in the compiled JavaScript bundle.
Template (current)
import { ColumnDefinitions, MigrationBuilder } from 'node-pg-migrate';
export const shorthands: ColumnDefinitions | undefined = undefined;
export async function up(pgm: MigrationBuilder): Promise<void> {}
export async function down(pgm: MigrationBuilder): Promise<void> {}Error
When running migrations with tsx (or Node.js 22.6+ --experimental-strip-types), the generated migration file fails at runtime:
SyntaxError: The requested module 'node-pg-migrate' does not provide an export named 'ColumnDefinitions'
Root Cause
In dist/bundle/index.d.ts, ColumnDefinitions is exported with the type modifier:
export { ..., type ColumnDefinitions, ... }In dist/bundle/index.js, ColumnDefinitions is not exported at all — it's a TypeScript interface with no runtime representation.
The library's own source code correctly uses import type { ColumnDefinitions } in src/migration.ts:
import type { ColumnDefinitions } from './operations/tables';But the template uses a value import (import { ColumnDefinitions }), which is inconsistent.
Why this breaks
- With traditional
tsccompilation, TypeScript erasesColumnDefinitionsfrom the import because it's only used as a type annotation → works - With tsx, swc, or Node.js native type stripping, the import binding is checked against the module's actual exports at the ESM level before types are erased → fails
Suggested Fix
Change the template to use import type:
import type { ColumnDefinitions, MigrationBuilder } from 'node-pg-migrate';
export const shorthands: ColumnDefinitions | undefined = undefined;
export async function up(pgm: MigrationBuilder): Promise<void> {}
export async function down(pgm: MigrationBuilder): Promise<void> {}Or split the imports:
import type { ColumnDefinitions } from 'node-pg-migrate';
import { MigrationBuilder } from 'node-pg-migrate';Note: MigrationBuilder IS a runtime export (it's a class), so it can remain a value import.
Environment
- node-pg-migrate: 8.0.4 (latest)
- Node.js: 22.x
- tsx: installed as loader
- Package type:
"type": "module"(ESM)
Workaround
Use the template-file-name config option with a custom template that uses import type:
{
"template-file-name": "database/migrations/template.ts",
"ignore-pattern": "template\\.ts"
}