Skip to content

Commit

Permalink
Merge pull request #512 from Hexastack/feat/app-version
Browse files Browse the repository at this point in the history
feat: add metadata collection to store the db version
  • Loading branch information
marrouchi authored Jan 6, 2025
2 parents 5218325 + 4058743 commit 06e06a0
Show file tree
Hide file tree
Showing 23 changed files with 1,117 additions and 144 deletions.
2 changes: 1 addition & 1 deletion api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"typecheck": "tsc --noEmit",
"reset": "npm install && npm run containers:restart",
"reset:hard": "npm clean-install && npm run containers:rebuild",
"cli": "DEBUG=ts-node* ts-node --files --log-error --compiler-options '{\"diagnostics\": true}' src/cli.ts"
"cli": "HEXABOT_CLI=1 ts-node --files --log-error --compiler-options '{\"diagnostics\": true}' src/cli.ts"
},
"lint-staged": {
"*.{js,ts}": "eslint --fix -c \".eslintrc-staged.js\""
Expand Down
8 changes: 5 additions & 3 deletions api/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,11 @@ export const config: Config = {
process.env.MONGO_URI || 'mongodb://dev_only:dev_only@localhost:27017/',
dbName: process.env.MONGO_DB || 'hexabot',
autoMigrate:
process.env.MONGO_AUTO_MIGRATE === 'true'
? Boolean(process.env.MONGO_AUTO_MIGRATE)
: false,
// Either auto-migration is explicitly enabled and the node is primary (cluster case)
(process.env.MONGO_AUTO_MIGRATE === 'true' &&
(process.env.API_IS_PRIMARY_NODE || 'true') === 'true') ||
// Otherwise, run only in dev mode
!(process.env.NODE_ENV || 'development').toLowerCase().includes('prod'),
},
env: process.env.NODE_ENV || 'development',
authentication: {
Expand Down
1 change: 1 addition & 0 deletions api/src/migration/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ will apply migrations automatically but only if it's a dev environement and `con
- Track migration execution status in a MongoDB collection (`migrations`).
- Run individual or all migrations with ease.
- Built-in support for rollback logic.
- Keeps track of the database schema version in the metadata collection (SettingModule).

## Usage

Expand Down
33 changes: 24 additions & 9 deletions api/src/migration/migration.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,37 @@ export class MigrationCommand extends CommandRunner {
async run(passedParam: string[]): Promise<void> {
const [subcommand] = passedParam;
switch (subcommand) {
case 'create':
const [, filename] = passedParam;
return await this.migrationService.create(filename);
case 'migrate':
const [, action, name] = passedParam;
case 'create': {
const [, version] = passedParam;

if (!this.migrationService.isValidVersion(version)) {
throw new TypeError('Invalid version value.');
}

return this.migrationService.create(version);
}
case 'migrate': {
const [, action, version] = passedParam;

if (
!Object.values(MigrationAction).includes(action as MigrationAction)
) {
this.logger.error('Invalid Operation');
this.exit();
}
return await this.migrationService.run({
action: action as MigrationAction,
name,
});

if (
typeof version === 'undefined' ||
this.migrationService.isValidVersion(version)
) {
return await this.migrationService.run({
action: action as MigrationAction,
version,
});
} else {
throw new TypeError('Invalid version value.');
}
}
default:
this.logger.error('No valid command provided');
this.exit();
Expand Down
10 changes: 5 additions & 5 deletions api/src/migration/migration.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,28 @@

import { join } from 'path';

import { HttpModule } from '@nestjs/axios';
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';

import { LoggerModule } from '@/logger/logger.module';

import { MigrationCommand } from './migration.command';
import { Migration, MigrationSchema } from './migration.schema';
import { MigrationModel } from './migration.schema';
import { MigrationService } from './migration.service';

@Module({
imports: [
MongooseModule.forFeature([
{ name: Migration.name, schema: MigrationSchema },
]),
MongooseModule.forFeature([MigrationModel]),
LoggerModule,
HttpModule,
],
providers: [
MigrationService,
MigrationCommand,
{
provide: 'MONGO_MIGRATION_DIR',
useValue: join(process.cwd(), 'src', 'migration', 'migrations'),
useValue: join(__dirname, 'migrations'),
},
],
exports: [MigrationService],
Expand Down
25 changes: 15 additions & 10 deletions api/src/migration/migration.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,27 @@
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
*/

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document, Model } from 'mongoose';
import { ModelDefinition, Prop, Schema, SchemaFactory } from '@nestjs/mongoose';

import { MigrationAction } from './types';
import { LifecycleHookManager } from '@/utils/generics/lifecycle-hook-manager';
import { THydratedDocument } from '@/utils/types/filter.types';

import { MigrationAction, MigrationVersion } from './types';

@Schema({ timestamps: true })
export class Migration {
@Prop({ required: true, unique: true })
name: string;
@Prop({ type: String, required: true, unique: true })
version: MigrationVersion;

@Prop({ required: true, enum: MigrationAction })
status: string;
@Prop({ type: String, required: true, enum: Object.values(MigrationAction) })
status: MigrationAction;
}

export const MigrationSchema = SchemaFactory.createForClass(Migration);
export const MigrationModel: ModelDefinition = LifecycleHookManager.attach({
name: Migration.name,
schema: SchemaFactory.createForClass(Migration),
});

export type MigrationDocument = Migration & Document;
export default MigrationModel.schema;

export type MigrationModel = Model<MigrationDocument>;
export type MigrationDocument = THydratedDocument<Migration>;
Loading

0 comments on commit 06e06a0

Please sign in to comment.