ilovepixelart / ts-migrate-mongoose

A node/typescript based migration framework for mongoose
MIT License
72 stars 6 forks source link

Using tsyringe in migration file #275

Closed FantinRaimbault closed 7 months ago

FantinRaimbault commented 7 months ago

Is your feature request related to a problem? Please describe. Hi! First I would like to thank you, I've just set up your lib in the project of my company, this is dope! I came across an issue when using tsyringe in db migration files

import 'reflect-metadata';

import { UsersRepository } from '@modules/users/users.repository';

import { autoInjectable, container } from 'tsyringe';

@autoInjectable()
class Migration {
    constructor(private userRepo: UsersRepository) {}

    // eslint-disable-next-line no-empty-function
    async up() {
        const users = await this.userRepo.find({ filter: { }});
        console.log(users.length);
        console.log('Migration up usersssss');
    }

    // eslint-disable-next-line no-empty-function
    async down() {}
}

const migration = container.resolve(Migration);

export async function up(): Promise<void> {
    await migration.up();
}

export async function down(): Promise<void> {
    await migration.down();
}

but when I try to run the migrations, I have this error

npx migrate up -f .env.local

Synchronizing database with file system migrations...
Failed to run migration with name '1' due to an error
Cannot read properties of undefined (reading 'find')

It's like, it can't resolve the class with the depedencies (userRepo is undefined here)

maybe its due to

Describe alternatives you've considered I've considered to just instanciate class and not using tsyringe but it would be awesome to be able to do this.

FantinRaimbault commented 7 months ago

It's ok I've found a workaround

I added a .swcrc file

{
     "jsc": {
        "parser": {
            "syntax": "typescript",
            "decorators": true,
            "dynamicImport": true
        },
        "target": "es2022",
        "keepClassNames": true,
        "loose": true,
        "baseUrl": "./src",
        "paths": {
            "@config": [
                "config.ts"
            ],
            "@main": [
                "main.ts"
            ],
            "@helpers/*": [
                "helpers/*"
            ],
            "@microservices/*": [
                "microservices/*"
            ],
            "@modules/*": [
                "modules/*"
            ],
            "@plugins/*": [
                "plugins/*"
            ],
            "@services/*": [
                "services/*"
            ],
            "@agenda-jobs/*": [
                "agenda-jobs/*"
            ],
            "@tasks/*": [
                "tasks/*"
            ]
        }
    },
    "module": {
        "type": "commonjs"
    },
    "sourceMaps": true
}

and I use the keywork @inject provided by tsyringe and it works!

import { UsersRepository } from '@modules/users/users.repository';
import 'reflect-metadata';

import { autoInjectable, container, inject } from 'tsyringe';

@autoInjectable()
class Migration {
    constructor(@inject(UsersRepository) private userRepo: UsersRepository) {}

    // eslint-disable-next-line no-empty-function
    async up() {
        const users = await this.userRepo.find({});
        ...
    }

    // eslint-disable-next-line no-empty-function
    async down() {

    }
}

const migration = container.resolve(Migration);

export async function up(): Promise<void> {
    await migration.up();
}

export async function down(): Promise<void> {
    await migration.down();
}