No collections found using sequelize-typescript when TS code built to JS

Feature(s) impacted

Build typescript to javascript & run it

Observed behavior

When running JS app after build using tsc it fails with error

Error: Collection 'Address' not found. List of available collections:

while when running with ts-node it runs fine

Expected behavior

No failure on JS run

Failure Logs

The full error stacktrace:

.../forest_ts/node_modules/@forestadmin/datasource-customizer/dist/decorators/composite-datasource.js:22
        throw new Error(`Collection '${name}' not found. List of available collections: ${this.collections
              ^

Error: Collection 'Address' not found. List of available collections:
    at CompositeDatasource.getCollection (.../forest_ts/node_modules/@forestadmin/datasource-customizer/dist/decorators/composite-datasource.js:22:15)
    at DataSourceDecorator.getCollection (.../forest_ts/node_modules/@forestadmin/datasource-toolkit/dist/src/decorators/datasource-decorator.js:16:49)
    at DataSourceDecorator.getCollection (.../forest_ts/node_modules/@forestadmin/datasource-toolkit/dist/src/decorators/datasource-decorator.js:16:49)
    at DataSourceDecorator.getCollection (.../forest_ts/node_modules/@forestadmin/datasource-toolkit/dist/src/decorators/datasource-decorator.js:16:49)
    at .../forest_ts/node_modules/@forestadmin/datasource-customizer/dist/collection-customizer.js:29:76
    at DecoratorsStack.applyQueuedCustomizations (.../forest_ts/node_modules/@forestadmin/datasource-customizer/dist/decorators/decorators-stack.js:75:47)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async DataSourceCustomizer.getDataSource (.../forest_ts/node_modules/@forestadmin/datasource-customizer/dist/datasource-customizer.js:126:9)
    at async .../forest_ts/node_modules/@forestadmin/datasource-customizer/dist/datasource-customizer.js:46:30
    at async DecoratorsStack.applyQueuedCustomizations (.../forest_ts/node_modules/@forestadmin/datasource-customizer/dist/decorators/decorators-stack.js:75:13)

Node.js v20.9.0

Context

We’ve done re-developped our current forestadmin setup using the new typescript engine in parallel to our current JS setup, we’re now preparing to deploy it on our target envs. Typescript to javascript build works fine but running the javascript built version fails with no collections found.

  • Project name: UC Typescript
  • Team name: -
  • Environment name: Development
  • Node version: 20.9.0
  • Agent (forest package) name & version:
    "@forestadmin/agent": "^1.28.3",
    "@forestadmin/datasource-customizer": "^1.28.2",
    "@forestadmin/datasource-sequelize": "^1.5.14",
    "@forestadmin/datasource-sql": "^1.7.26",
  • Database type: postgres
    "sequelize": "^6.32.1",
    "sequelize-typescript": "^2.1.5",
  • Recent changes made on your end if any: -
  • tsconfig.json:
{
  "extends": "@tsconfig/recommended/tsconfig.json",
  "compilerOptions": {
    "outDir": "./build/",
    "types": [
      "jest",
      "node"
    ],
    "typeRoots": [
      "node_modules/@types",
      "src/@types"
    ],
    "noImplicitAny": true,
    "moduleResolution": "node",
    "target": "es2020",
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "skipLibCheck": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
  },
  // ...
}
  • build command: tsc --project tsconfig.json
  • run command: node ./build/src/index.js
  • uncompiled run command: npx ts-node ./src/index.ts
  • collections declaration:
const sequelize = new Sequelize(process.env.DATABASE_URL ?? '', dbOptions)
sequelize.addModels([join(__dirname, '../collections/*/model.ts')])

export const forestAgent = createAgent({
  authSecret: process.env.FOREST_AUTH_SECRET ?? '',
  envSecret: process.env.FOREST_ENV_SECRET ?? '',
  isProduction: process.env.NODE_ENV === 'production',
  typingsPath: './typings.ts',
}).addDataSource(
  createSequelizeDataSource(sequelize),
)

Hello @cberez,

Thanks a lot for the very detailed post about your issue.

I’m just passing by, and this line looks suspicious to me:

sequelize.addModels([join(__dirname, '../collections/*/model.ts')])

Do you have the same code in JS? The documentation and code from sequelize indicates that a list of models is expected here, whereas this code is passing a unique path.

@GuillaumeGautreau I get this in JS which seems ok to me given the * path matching:

sequelize.addModels([(0, path_1.join)(__dirname, '../collections/*/model.ts')]);

Maybe I should rather explicitly list all the paths using glob, I’ll test that and come back to you

@GuillaumeGautreau changed for this

// ts
const sequelize = new Sequelize(process.env.DATABASE_URL ?? '', dbOptions)
const modelPaths = globSync(join(__dirname, '../collections/*/model.ts'))

sequelize.addModels(modelPaths)

// built js
const sequelize = new sequelize_typescript_1.Sequelize(process.env.DATABASE_URL ?? '', sequelize_options_1.default);
const modelPaths = (0, glob_1.globSync)((0, path_1.join)(__dirname, '../collections/*/model.ts'));
sequelize.addModels(modelPaths);

same issue, it works in TS but I get the error when running built JS files:

Error: Collection 'Address' not found. List of available collections:
    at CompositeDatasource.getCollection (/Users/cesar/dev/urbancampus/forest_ts/node_modules/@forestadmin/datasource-customizer/dist/decorators/composite-datasource.js:22:15)
  ...

I’m pretty sure the problem comes from this line, because when your code is compiled into JS, the files are not named *.ts anymore, but *.js. Even if ts files are present, typescript cannot be interpreted at runtime if you don’t register ts-node.

I did not know that we could load models this way, by passing paths instead of an array of actual objects, but if it worked on JS I guess that it’s possible.

Basically, the error that is thrown by Forest Admin says that it could not find any collection at all. As collections are generated from Sequelize models, I guess that the issue is that your models are not loaded correctly.

I think you could log the length of this array of paths, and chances are it’s empty. If not, then the cause is probably that you cannot interpret ts file at runtime.

1 Like

Ah damn your right :person_facepalming:

Changing for this worked:

const modelPaths = globSync(join(__dirname, '../collections/*/model.{js,ts}'))
2 Likes