Skip to content

Export does not satisfy filename (Bun) #1731

Open
@agucova

Description

@agucova

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.

const module = require(fullPath);
const fileName = basename(fullPath);
const matchedMemberKey = Object.keys(module).find((m) => modelMatch(fileName, m));
const matchedMember = matchedMemberKey ? module[matchedMemberKey] : undefined;
if (!matchedMember && !module.default) {
throw new Error(
`No default export defined for file "${fileName}" or ` +
`export does not satisfy filename.`
);
}

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],
});

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions