add db migration
This commit is contained in:
parent
67e4466687
commit
13b5bc629a
@ -9,12 +9,15 @@ import { SearchService } from '@/modules/content/services';
|
||||
import { SanitizeService } from '@/modules/content/services/SanitizeService';
|
||||
|
||||
import { PostService } from '@/modules/content/services/post.service';
|
||||
import { PostSubscriber } from '@/modules/content/subscribers/post.subscriber';
|
||||
|
||||
import { DatabaseModule } from '@/modules/database/database.module';
|
||||
|
||||
import { addSubscribers } from '@/modules/database/utils';
|
||||
|
||||
import { Configure } from '../config/configure';
|
||||
|
||||
import { defauleContentConfig } from './config';
|
||||
import * as subscribers from './subscribers';
|
||||
import { ContentConfig } from './types';
|
||||
|
||||
@Module({})
|
||||
@ -23,7 +26,7 @@ export class ContentModule {
|
||||
const config = await configure.get<ContentConfig>('content', defauleContentConfig);
|
||||
const providers: ModuleMetadata['providers'] = [
|
||||
...Object.values(services),
|
||||
PostSubscriber,
|
||||
...(await addSubscribers(configure, Object.values(subscribers))),
|
||||
{
|
||||
provide: PostService,
|
||||
inject: [
|
||||
|
1
src/modules/content/subscribers/index.ts
Normal file
1
src/modules/content/subscribers/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './post.subscriber';
|
@ -1,33 +1,33 @@
|
||||
import { Optional } from '@nestjs/common';
|
||||
import { isNil } from 'lodash';
|
||||
import { DataSource, EventSubscriber, ObjectType } from 'typeorm';
|
||||
|
||||
import { Configure } from '@/modules/config/configure';
|
||||
import { PostBodyType } from '@/modules/content/constants';
|
||||
import { PostEntity } from '@/modules/content/entities/post.entity';
|
||||
import { PostRepository } from '@/modules/content/repositories/post.repository';
|
||||
import { SanitizeService } from '@/modules/content/services/SanitizeService';
|
||||
import { BaseSubscriber } from '@/modules/database/base/subscriber';
|
||||
|
||||
@EventSubscriber()
|
||||
export class PostSubscriber extends BaseSubscriber<PostEntity> {
|
||||
protected entity: ObjectType<PostEntity> = PostEntity;
|
||||
|
||||
constructor(
|
||||
protected dataSource: DataSource,
|
||||
protected postRepository: PostRepository,
|
||||
protected configure: Configure,
|
||||
@Optional() protected sanitizeService: SanitizeService,
|
||||
protected _configure: Configure,
|
||||
) {
|
||||
super(dataSource);
|
||||
super(dataSource, _configure);
|
||||
}
|
||||
|
||||
get configure(): Configure {
|
||||
return this._configure;
|
||||
}
|
||||
|
||||
async afterLoad(entity: PostEntity) {
|
||||
if (
|
||||
(await this.configure.get('content.htmlEnabled')) &&
|
||||
!isNil(this.sanitizeService) &&
|
||||
entity.type === PostBodyType.HTML
|
||||
) {
|
||||
entity.body = this.sanitizeService.sanitize(entity.body);
|
||||
const sanitizeService = (await this.configure.get('content.htmlEnabled'))
|
||||
? this.container.get(SanitizeService)
|
||||
: undefined;
|
||||
if (!isNil(sanitizeService) && entity.type === PostBodyType.HTML) {
|
||||
entity.body = sanitizeService.sanitize(entity.body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -76,8 +76,14 @@ export async function panic(option: PanicOption | string) {
|
||||
console.log(chalk.red(`\n❌ ${option}`));
|
||||
process.exit(1);
|
||||
}
|
||||
const { error, message, exit = true } = option;
|
||||
isNil(error) ? console.log(chalk.red(`\n❌ ${message}`)) : console.log(chalk.red(error));
|
||||
const { error, message, spinner, exit = true } = option;
|
||||
if (isNil(error)) {
|
||||
isNil(spinner)
|
||||
? console.log(chalk.red(`\n❌ ${message}`))
|
||||
: spinner.succeed(chalk.red(`\n❌ ${message}`));
|
||||
} else {
|
||||
isNil(spinner) ? console.log(chalk.red(error)) : spinner.fail(chalk.red(error));
|
||||
}
|
||||
if (exit) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { Optional } from '@nestjs/common';
|
||||
import { NestFastifyApplication } from '@nestjs/platform-fastify';
|
||||
import { isNil } from 'lodash';
|
||||
import {
|
||||
DataSource,
|
||||
@ -17,6 +18,10 @@ import {
|
||||
UpdateEvent,
|
||||
} from 'typeorm';
|
||||
|
||||
import { Configure } from '@/modules/config/configure';
|
||||
|
||||
import { app } from '@/modules/core/helpers/app';
|
||||
|
||||
import { RepositoryType } from '../types';
|
||||
import { getCustomRepository } from '../utils';
|
||||
|
||||
@ -36,12 +41,25 @@ export abstract class BaseSubscriber<T extends ObjectLiteral>
|
||||
{
|
||||
protected abstract entity: ObjectType<T>;
|
||||
|
||||
protected constructor(@Optional() protected dataSource?: DataSource) {
|
||||
protected constructor(
|
||||
@Optional() protected dataSource?: DataSource,
|
||||
@Optional() protected _configure?: Configure,
|
||||
) {
|
||||
if (!isNil(this.dataSource)) {
|
||||
this.dataSource.subscribers.push(this);
|
||||
}
|
||||
}
|
||||
|
||||
get configure() {
|
||||
return isNil(this._configure)
|
||||
? this.container.get(Configure, { strict: false })
|
||||
: this._configure;
|
||||
}
|
||||
|
||||
get container(): NestFastifyApplication {
|
||||
return app.container;
|
||||
}
|
||||
|
||||
protected getDataSource(event: SubscriberEvent<T>) {
|
||||
return this.dataSource ?? event.connection;
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { resolve } from 'path';
|
||||
|
||||
import { ConfigureFactory, ConfigureRegister } from '../config/types';
|
||||
import { createConnectionOptions } from '../config/utils';
|
||||
import { deepMerge } from '../core/helpers';
|
||||
@ -18,7 +20,11 @@ export const createDBConfig: (
|
||||
export const createDBOptions = (options: DBConfig) => {
|
||||
const newOptions: DBOptions = {
|
||||
common: deepMerge(
|
||||
{ charset: 'utf8mb4', logging: ['error'] },
|
||||
{
|
||||
charset: 'utf8mb4',
|
||||
logging: ['error'],
|
||||
paths: { migration: resolve(__dirname, '../../database/migrations') },
|
||||
},
|
||||
options.common ?? {},
|
||||
'replace',
|
||||
),
|
||||
@ -29,7 +35,7 @@ export const createDBOptions = (options: DBConfig) => {
|
||||
const newOption = { ...connection, entities };
|
||||
return deepMerge(
|
||||
newOptions.common,
|
||||
{ ...newOption, autoLoadEntities: true } as any,
|
||||
{ ...newOption, autoLoadEntities: true, synchronize: false } as any,
|
||||
'replace',
|
||||
) as TypeormOption;
|
||||
});
|
||||
|
@ -2,8 +2,8 @@ import { TypeOrmModuleOptions } from '@nestjs/typeorm';
|
||||
import {
|
||||
FindTreeOptions,
|
||||
ObjectLiteral,
|
||||
SelectQueryBuilder,
|
||||
Repository,
|
||||
SelectQueryBuilder,
|
||||
TreeRepository,
|
||||
} from 'typeorm';
|
||||
|
||||
@ -70,13 +70,21 @@ export type RepositoryType<T extends ObjectLiteral> =
|
||||
| BaseTreeRepository<T>;
|
||||
|
||||
export type DBConfig = {
|
||||
common: RecordAny;
|
||||
common: RecordAny & DBAdditionalOption;
|
||||
connections: Array<TypeOrmModuleOptions & { name?: string }>;
|
||||
};
|
||||
|
||||
export type TypeormOption = Omit<TypeOrmModuleOptions, 'name' | 'migrations'> & { name: string };
|
||||
export type TypeormOption = Omit<TypeOrmModuleOptions, 'name' | 'migrations'> & {
|
||||
name: string;
|
||||
} & DBAdditionalOption;
|
||||
|
||||
export type DBOptions = RecordAny & {
|
||||
common: RecordAny;
|
||||
connections: TypeormOption[];
|
||||
};
|
||||
|
||||
type DBAdditionalOption = {
|
||||
path?: {
|
||||
migration?: string;
|
||||
};
|
||||
};
|
||||
|
@ -1,7 +1,16 @@
|
||||
import { Type } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { EntityClassOrSchema } from '@nestjs/typeorm/dist/interfaces/entity-class-or-schema.type';
|
||||
import { isArray, isNil } from 'lodash';
|
||||
import { DataSource, ObjectLiteral, ObjectType, Repository, SelectQueryBuilder } from 'typeorm';
|
||||
|
||||
import { OrderQueryType, PaginateOptions, PaginateReturn } from '@/modules/database/types';
|
||||
import { Configure } from '@/modules/config/configure';
|
||||
import {
|
||||
DBOptions,
|
||||
OrderQueryType,
|
||||
PaginateOptions,
|
||||
PaginateReturn,
|
||||
} from '@/modules/database/types';
|
||||
|
||||
import { CUSTOM_REPOSITORY_METADATA } from './constants';
|
||||
|
||||
@ -97,3 +106,48 @@ export const getCustomRepository = <P extends Repository<T>, T extends ObjectLit
|
||||
const base = dataSource.getRepository<ObjectType<any>>(entity);
|
||||
return new Repo(base.target, base.manager, base.queryRunner) as P;
|
||||
};
|
||||
|
||||
export const addEntities = async (
|
||||
configure: Configure,
|
||||
entities: EntityClassOrSchema[] = [],
|
||||
dataSource = 'default',
|
||||
) => {
|
||||
const database = await configure.get<DBOptions>('database');
|
||||
if (isNil(database)) {
|
||||
throw new Error('Database not exists');
|
||||
}
|
||||
const dbConfig = database.connections.find(({ name }) => name === dataSource);
|
||||
if (isNil(dbConfig)) {
|
||||
throw new Error(`Database connection ${dataSource} not exists`);
|
||||
}
|
||||
|
||||
const oldEntities = (dbConfig.entities ?? []) as ObjectLiteral[];
|
||||
const newEntities = database.connections.map((conn) =>
|
||||
conn.name === dataSource ? { ...conn, entities: [...oldEntities, ...entities] } : conn,
|
||||
);
|
||||
configure.set('database.connections', newEntities);
|
||||
return TypeOrmModule.forFeature(entities, dataSource);
|
||||
};
|
||||
|
||||
export async function addSubscribers(
|
||||
configure: Configure,
|
||||
subscribers: Type<any>[] = [],
|
||||
dataSource = 'default',
|
||||
) {
|
||||
const database = await configure.get<DBOptions>('database');
|
||||
if (isNil(database)) {
|
||||
throw new Error('Database not exists');
|
||||
}
|
||||
const dbConfig = database.connections.find(({ name }) => name === dataSource);
|
||||
if (isNil(dbConfig)) {
|
||||
throw new Error(`Database connection ${dataSource} not exists`);
|
||||
}
|
||||
const oldSubscribers = (dbConfig.subscribers ?? []) as any[];
|
||||
const newSubscribers = database.connections.map((conn) =>
|
||||
conn.name === dataSource
|
||||
? { ...conn, subscribers: [...oldSubscribers, subscribers] }
|
||||
: conn,
|
||||
);
|
||||
configure.set('database.connections', newSubscribers);
|
||||
return subscribers;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user