From 67e18352b68d4d23cd946e0925bc465a95f74808 Mon Sep 17 00:00:00 2001 From: chenos Date: Tue, 15 Dec 2020 20:16:55 +0800 Subject: [PATCH] add hooks for database --- .../database/src/__tests__/database.test.ts | 88 +++++++++++++++++++ packages/database/src/database.ts | 32 +++++++ packages/database/src/table.ts | 4 + 3 files changed, 124 insertions(+) create mode 100644 packages/database/src/__tests__/database.test.ts diff --git a/packages/database/src/__tests__/database.test.ts b/packages/database/src/__tests__/database.test.ts new file mode 100644 index 000000000..94af0e7b9 --- /dev/null +++ b/packages/database/src/__tests__/database.test.ts @@ -0,0 +1,88 @@ +import { getDatabase } from '.'; +import Database, { Field } from '../'; +import Table from '../table'; + +let db: Database; + +beforeEach(async () => { + db = getDatabase(); +}); + +afterEach(async () => { + await db.close(); +}); + +describe('database.addHook()', () => { + it('beforeTableInit', async () => { + db.addHook('beforeTableInit', (options) => { + options.title = 'abc'; + }); + const table = db.table({ + name: 'testHook', + createdBy: true, + fields: [ + { + type: 'json', + name: 'arr', + defaultValue: [], + }, + ], + }); + expect(table.getOptions().title).toBe('abc'); + }); + it('afterTableInit', async () => { + db.addHook('afterTableInit', (table: Table) => { + table.addField({ + type: 'string', + name: 'abc', + }); + }); + const table = db.table({ + name: 'testHook', + createdBy: true, + fields: [ + { + type: 'json', + name: 'arr', + defaultValue: [], + }, + ], + }); + expect(table.getField('abc')).toBeTruthy(); + }); + it('beforeAddField', async () => { + db.addHook('beforeAddField', (options) => { + options.title = 'f1'; + }); + const table = db.table({ + name: 'testHook', + createdBy: true, + fields: [ + { + type: 'string', + name: 'name', + }, + ], + }); + expect(table.getField('name').options.title).toBe('f1'); + }); + it('afterAddField', async () => { + db.addHook('afterAddField', (field: Field, table: Table) => { + if (field.options.name === 'name') { + const options = {...field.options, name: `${field.options.name}123`} + table.addField(options); + } + }); + const table = db.table({ + name: 'testHook', + createdBy: true, + fields: [ + { + type: 'string', + name: 'name', + }, + ], + }); + expect(table.getField('name123')).toBeTruthy(); + }); +}); diff --git a/packages/database/src/database.ts b/packages/database/src/database.ts index 511c1a24b..b1f516552 100644 --- a/packages/database/src/database.ts +++ b/packages/database/src/database.ts @@ -7,6 +7,7 @@ import glob from 'glob'; import Table, { TableOptions } from './table'; import { Model, ModelCtor } from './model'; import { requireModule } from './utils'; +import _ from 'lodash'; export interface SyncOptions extends SequelizeSyncOptions { @@ -29,6 +30,8 @@ export interface ImportOptions { extensions?: string[]; } +export type HookType = 'beforeTableInit' | 'afterTableInit' | 'beforeAddField' | 'afterAddField'; + export default class Database { public readonly sequelize: Sequelize; @@ -47,6 +50,8 @@ export default class Database { protected options: Options; + protected hooks = {}; + constructor(options: Options) { this.options = options; this.sequelize = new Sequelize(options); @@ -249,4 +254,31 @@ export default class Database { public async close() { return this.sequelize.close(); } + + /** + * 添加 hook + * + * @param hookType + * @param fn + */ + public addHook(hookType: HookType, fn: Function) { + const hooks = this.hooks[hookType] || []; + hooks.push(fn); + this.hooks[hookType] = hooks; + } + + /** + * 运行 hook + * + * @param hookType + * @param args + */ + public runHooks(hookType: HookType, ...args) { + const hooks = this.hooks[hookType] || []; + for (const hook of hooks) { + if (typeof hook === 'function') { + hook(...args); + } + } + } } diff --git a/packages/database/src/table.ts b/packages/database/src/table.ts index a7a37664b..278cf9a8a 100644 --- a/packages/database/src/table.ts +++ b/packages/database/src/table.ts @@ -134,6 +134,7 @@ export class Table { constructor(options: TableOptions, context: TabelContext) { const { database } = context; + database.runHooks('beforeTableInit', options); const { name, fields = [], @@ -156,6 +157,7 @@ export class Table { this.addIndexes(indexes, 'modelOnly'); // this.modelInit('modelOnly'); this.setFields(fields); + database.runHooks('afterTableInit', this); } public modelInit(reinitialize: Reinitialize = false) { @@ -280,6 +282,7 @@ export class Table { * @param reinitialize */ public addField(options: FieldOptions, reinitialize: Reinitialize = true) { + this.database.runHooks('beforeAddField', options, this); const { name, index } = options; const field = buildField(options, { sourceTable: this, @@ -315,6 +318,7 @@ export class Table { this.modelAttributes[name] = field.getAttributeOptions(); } this.modelInit(reinitialize); + this.database.runHooks('afterAddField', field, this); return field; }