11import { Injectable , Logger , OnModuleInit } from '@nestjs/common'
2- import { InjectModel } from '@nestjs/mongoose'
3- import { Model } from 'mongoose'
42import { glob } from 'glob'
5- import readline from 'readline'
63import chalk from 'chalk'
7-
8- function startLoader ( message ) {
9- let currentFrame = 0 ;
10- const spinnerFrames = [ '-' , '\\' , '|' , '/' ] ;
11-
12- const loaderInterval = setInterval ( ( ) => {
13- readline . cursorTo ( process . stdout , 0 ) ;
14- process . stdout . write ( `${ spinnerFrames [ currentFrame ] } ${ message } ` ) ;
15- currentFrame = ( currentFrame + 1 ) % spinnerFrames . length ;
16- } , 100 ) ;
17-
18- return loaderInterval ;
19- }
20-
21- function stopLoader ( loaderInterval ) {
22- clearInterval ( loaderInterval ) ;
23- readline . cursorTo ( process . stdout , 0 ) ;
24- process . stdout . clearLine ( 0 ) ;
25- }
4+ import { ModuleRef } from '@nestjs/core'
5+ import { startLoader , stopLoader } from './migration-loader.function'
6+ import { readFile , writeFile } from 'fs/promises'
267
278@Injectable ( )
289export class MigrationsService implements OnModuleInit {
2910 private readonly logger = new Logger ( `${ chalk . bold . red ( MigrationsService . name ) } \x1b[33m` )
3011
3112 protected migrations = new Map < string , any > ( )
3213
33- public constructor ( ) { }
14+ public constructor ( private readonly moduleRef : ModuleRef ) { }
3415
3516 public async onModuleInit ( ) {
36- await this . runMigrations ( )
37- }
38-
39- public async runMigrations ( ) {
17+ await this . _checkMigrationLockFile ( )
4018 this . logger . log ( chalk . yellow ( 'Checking migrations files...' ) ) ;
41- await this . _loadMigrationsFiles ( )
42-
19+ await this . _loadMigrationsFiles ( ) ;
4320
4421 const loader = startLoader ( 'Migration en cours...' ) ;
4522 await this . _executeMigrations ( ) ;
4623 stopLoader ( loader ) ;
4724 }
4825
26+ private async _checkMigrationLockFile ( ) {
27+ let migrationTimestamp = 0
28+
29+ try {
30+ const migration = await readFile ( './migrations.lock' , 'utf-8' )
31+ console . log ( 'migration' , migration )
32+ } catch ( error ) {
33+ this . logger . warn ( chalk . red ( 'No migration lock file found.' ) )
34+ }
35+
36+ if ( migrationTimestamp === 0 ) {
37+ try {
38+ await writeFile ( './migrations.lock' , migrationTimestamp . toString ( ) )
39+ this . logger . log ( chalk . green ( 'Migration lock file created.' ) )
40+ } catch ( error ) {
41+ this . logger . error ( chalk . red ( 'Error while creating migration lock file !' ) )
42+ }
43+ }
44+ }
45+
4946 private async _loadMigrationsFiles ( ) {
50- const files = await glob ( `./migrations/*.js` , {
47+ const currentTimestamp = 1729092659
48+ // const currentTimestamp = Date.now()
49+ let files = await glob ( `./jobs/*.js` , {
5150 cwd : __dirname ,
5251 root : __dirname ,
5352 } ) ;
5453
54+ files = files . filter ( ( file ) => {
55+ const [ timestampMatch ] = file . match ( / \d { 10 , } / ) || [ ]
56+
57+ if ( ! timestampMatch ) {
58+ this . logger . warn ( chalk . yellow ( `Migration ${ chalk . bold ( '<' + file . replace ( / .j s $ / , '' ) + '>' ) } does not have a timestamp in the filename !` ) ) ;
59+ return ;
60+ }
61+
62+ if ( parseInt ( timestampMatch ) < currentTimestamp ) {
63+ this . logger . debug ( chalk . yellow ( `Migration ${ chalk . bold ( '<' + file . replace ( / .j s $ / , '' ) + '>' ) } are already executed !` ) ) ;
64+ return false ;
65+ }
66+
67+ return true
68+ } )
69+
70+ files = files . sort ( ( a , b ) => {
71+ const [ aTimestamp ] = a . match ( / \d { 10 , } / ) || [ ]
72+ const [ bTimestamp ] = b . match ( / \d { 10 , } / ) || [ ]
73+
74+ return parseInt ( aTimestamp ) - parseInt ( bTimestamp )
75+ } )
76+
5577 for ( const file of files ) {
5678 const migration = await import ( `${ __dirname } /${ file } ` ) ;
79+ const [ timestampMatch ] = file . match ( / \d { 10 , } / ) || [ ]
80+
81+ console . log ( 'file' , timestampMatch )
5782
5883 if ( ! migration . default ) {
5984 this . logger . log ( chalk . yellow ( `Migration ${ chalk . bold ( '<' + file + '>' ) } does not have a default export !` ) ) ;
6085 return ;
6186 }
6287
63- this . migrations . set ( file , migration )
88+ this . migrations . set ( timestampMatch , migration )
6489 }
6590 }
6691
6792 private async _executeMigrations ( ) {
68- console . log ( 'this.migrations.keys()' , this . migrations . keys ( ) )
6993 for ( const key of this . migrations . keys ( ) ) {
94+ this . logger . log ( chalk . yellow ( `Running migration ${ chalk . bold ( '<' + key + '>' ) } ...` ) ) ;
95+
7096 const migration = this . migrations . get ( key ) ;
71- const instance = new migration . default ( ) ;
97+ const instance = await this . moduleRef . create ( migration . default ) ;
7298
7399 if ( typeof instance . up !== 'function' ) {
74100 this . logger . log ( chalk . yellow ( `Migration ${ chalk . bold ( '<' + key + '>' ) } does not have an up method !` ) ) ;
@@ -78,5 +104,7 @@ export class MigrationsService implements OnModuleInit {
78104 this . logger . log ( chalk . yellow ( `Running migration ${ chalk . bold ( '<' + key + '>' ) } ...` ) ) ;
79105 await instance . up ( ) ;
80106 }
107+
108+ this . logger . log ( chalk . green ( 'All migrations done.' ) ) ;
81109 }
82110}
0 commit comments