Cannot require() generated Models as ES modules
nemx opened this issue · comments
Issue
I'm having trouble getting my models to be imported correctly by sequelize-typescript. The error is:
Error [ERR_REQUIRE_ESM]: require() of ES Module <root>/packages/api/dist/models/my_model.js from <root>/node_modules/sequelize-typescript/dist/sequelize/sequelize/sequelize-service.js not supported.
Instead change the require of access_method.js in <root>/node_modules/sequelize-typescript/dist/sequelize/sequelize/sequelize-service.js to a dynamic import() which is available in all CommonJS modules.
at <root>/node_modules/sequelize-typescript/dist/sequelize/sequelize/sequelize-service.js:45:32
at Array.map (<anonymous>)
at <root>/node_modules/sequelize-typescript/dist/sequelize/sequelize/sequelize-service.js:43:18
at Array.reduce (<anonymous>)
at getModels (<root>/node_modules/sequelize-typescript/dist/sequelize/sequelize/sequelize-service.js:35:20)
at Sequelize.addModels (<root>/node_modules/sequelize-typescript/dist/sequelize/sequelize/sequelize.js:36:58)
at new Sequelize (<root>/node_modules/sequelize-typescript/dist/sequelize/sequelize/sequelize.js:20:22)
at file://<root>/packages/api/dist/db.js:12:26
at async Promise.all (index 0) {
code: 'ERR_REQUIRE_ESM'
}
I can see in the sequelize-typescript source that it's trying to require() my models (as opposed to a dynamic import).
Versions
- sequelize: 6.30.0
- sequelize-typescript: 2.1.5
- typescript: 5.0.3
- node: 16.15.1
Issue type
- bug report
- feature request
Actual behavior
After compiling with: npx tsc -p tsconfig.json
And running with: node --experimental-specifier-resolution=node dist/index.js
I'll get the above error.
Expected behavior
No error
Related code
I'm using the models
config option to load models like so:
export const sequelize = new Sequelize(svcConfig.databaseURL, {
// other config
models: [path.join(__dirname, '/models')],
});
My models are in the format of
@Table({ timestamps: true, tableName: 'MyModel' })
export default class MyModel extends Model {
@Column({ primaryKey: true, type: DataType.UUIDV4, defaultValue: DataType.UUIDV4 })
declare id: string;
@Column
name!: string;
}
My models get generated (by tsc) like so:
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var MyModel_1;
import { Column, DataType, ForeignKey, IsUUID, Table, Model, AllowNull } from 'sequelize-typescript';
let MyModel= MyModel_1 = class MyModel extends Model {
name;
};
__decorate([
Column({ primaryKey: true, type: DataType.UUIDV4, defaultValue: DataType.UUIDV4 }),
__metadata("design:type", String)
], MyModel.prototype, "id", void 0);
__decorate([
Column,
__metadata("design:type", String)
], MyModel.prototype, "name", void 0);
MyModel = MyModel_1 = __decorate([
Table({ timestamps: true })
], MyModel);
export default MyModel;
My tsconfig is:
{
"compilerOptions": {
"incremental": true,
"target": "es2022",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"module": "es2022",
"moduleResolution": "node",
"types": ["node"],
"sourceMap": true,
"outDir": "./dist",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"noImplicitAny": false,
"strictPropertyInitialization": false,
"skipLibCheck": true
},
"include": ["./src/**/*.ts"],
"exclude": ["node_modules", "**/node_modules/*", "./src/test"],
}
Did you set up "type": "module"
in package.json
?
Thanks @loss-and-quick. I do have that set. In the end, I think the issue is similar to what this PR is attempting to solve: #1206
I have a few cyclical dependencies arising from, for example, ModelA importing ModelB for a belongsTo declaration, and ModelB hasMany ModelA.
Using models: [path.join(__dirname, '/models')]
config, the loader gets stuck when trying to import Model A, which transitively imports B, which will wait until A resolves (it never does, as it's still waiting for B).
I worked around this by importing all the DB models directly in my sequelize config/setup file and passing the Model imports directly to the models option like so: models: [ModelA, ModelB, ModelC]
It's not ideal (as I like the idea of sequelize auto-discovering, importing new models, and not having to explicitly declare them all in a long list), but it does work around using sequelize's module loader code which seems to get stuck on dynamic imports.