Description
Versions
- sequelize: 6.37.3
- sequelize-typescript: 2.1.6
- typescript: 5.6.0
Issue type
- bug report
- feature request
The problem
While using Bun with sequelize-typescript
, using paths for the models
property fails to work when the relevant modules are ESM, throwing No default export defined for file "FILE" or export does not satisfy filename
.
This is because Bun allows using require
even if the target is an ES module:
In Bun's JavaScript runtime, require can be used by both ES Modules and CommonJS modules. If the target module is an ES Module, require returns the module namespace object (equivalent to import * as). If the target module is a CommonJS module, require returns the module.exports object (as in Node.js). Source
So what happens, is that the module is successfully imported through require
, but when sequelize-typescript
attempts to match over the attributes ( Object.keys(module)
), it fails to find any.
sequelize-typescript/src/sequelize/sequelize/sequelize-service.ts
Lines 51 to 62 in 8ded61a
Per spec, exports of ES modules aren't enumerable attributes, so Object.keys(module)
will return []
regardless of whether the attributes exist or not.
Steps to reproduce
index.ts
import { Sequelize } from "sequelize-typescript";
new Sequelize({
database: "some_db",
dialect: "sqlite",
username: "root",
password: "",
storage: ":memory:",
models: [__dirname + "/models"],
});
models/Person.ts
:
import { Table, Column, Model } from 'sequelize-typescript';
@Table
export class Person extends Model {
@Column
name: string;
@Column
birthday: Date;
}
$ bun run index.ts
45 | const module = require(fullPath);
46 | const fileName = (0, path_1.basename)(fullPath);
47 | const matchedMemberKey = Object.keys(module).find((m) => modelMatch(fileName, m));
48 | const matchedMember = matchedMemberKey ? module[matchedMemberKey] : undefined;
49 | if (!matchedMember && !module.default) {
50 | throw new Error(`No default export defined for file "${fileName}" or ` +
^
error: No default export defined for file "Person" or export does not satisfy filename.
at node_modules/sequelize-typescript/dist/sequelize/sequelize/sequelize-service.js:50:27
at map (1:11)
at node_modules/sequelize-typescript/dist/sequelize/sequelize/sequelize-service.js:43:18
at reduce (1:11)
at addModels (node_modules/sequelize-typescript/dist/sequelize/sequelize/sequelize.js:36:48)
at new Sequelize (node_modules/sequelize-typescript/dist/sequelize/sequelize/sequelize.js:20:22)
at index.ts:4:1
Bun v1.1.27 (Linux x64)
What to do about it
Instead of using Object.keys
, I believe we could just use for ... in
, which would pick up the inherited enumerable attributes:
const module = require(fullPath);
const fileName = (0, path_1.basename)(fullPath);
const exports = []
for (const key in module) {
exports.push(key);
}
const matchedMemberKey = exports.find((m) => modelMatch(fileName, m));
This works under Bun. That said, per #1660, I imagine this isn't a supported setup, so I mostly wanted to create this issue to prevent others from wasting several hours of their day trying to figure out what's wrong. If you're in this situation, you can get around this by importing the models directly and passing them to models
:
import { Person } from "models/Person";
import { Sequelize } from "sequelize-typescript";
new Sequelize({
database: "some_db",
dialect: "sqlite",
username: "root",
password: "",
storage: ":memory:",
models: [Person],
});