From e51ee7d1e68e5650212ca84976c67cc555401976 Mon Sep 17 00:00:00 2001 From: chenos Date: Wed, 13 Jan 2021 15:43:41 +0800 Subject: [PATCH] refactor: table.extend() method --- packages/database/package.json | 1 + .../database/src/__tests__/tables.test.ts | 58 ++++++++++++++++++- packages/database/src/database.ts | 15 +++-- packages/database/src/table.ts | 54 ++++++++++------- 4 files changed, 97 insertions(+), 31 deletions(-) diff --git a/packages/database/package.json b/packages/database/package.json index d478f6f9d..b2da6a3f2 100644 --- a/packages/database/package.json +++ b/packages/database/package.json @@ -8,6 +8,7 @@ "license": "MIT", "dependencies": { "bcrypt": "^5.0.0", + "deepmerge": "^4.2.2", "glob": "^7.1.6", "sequelize": "^6.3.3" }, diff --git a/packages/database/src/__tests__/tables.test.ts b/packages/database/src/__tests__/tables.test.ts index 077838043..eea9c44ca 100644 --- a/packages/database/src/__tests__/tables.test.ts +++ b/packages/database/src/__tests__/tables.test.ts @@ -137,7 +137,7 @@ describe('tables', () => { }); describe('#extend()', () => { - it('should be extend', async () => { + it('extend options', async () => { db.table({ name: 'baz', }); @@ -151,7 +151,7 @@ describe('tables', () => { expect(db.getModel('baz').rawAttributes.created).toBeDefined(); expect(db.getModel('baz').rawAttributes.updated).toBeDefined(); }); - it('should be extend', async () => { + it('extend fields', async () => { db.table({ name: 'foos', }); @@ -187,6 +187,60 @@ describe('tables', () => { // await db.sync({force: true}); // await db.sequelize.close(); }); + + it('extend array options', async () => { + db.table({ + name: 'baz', + actions: [ + { + name: 'list', + } + ] + }); + db.extend({ + name: 'baz', + actions: [ + { + name: 'get', + } + ] + }); + + expect(db.getTable('baz').getOptions()).toEqual({ + name: 'baz', + actions: [ { name: 'get' } ] + }); + }); + + it('extend with customMerge', async () => { + db.table({ + name: 'baz', + actions: [ + { + name: 'list', + } + ] + }); + db.extend({ + name: 'baz', + actions: [ + { + name: 'get', + } + ] + }, { + customMerge: (key, options) => { + if (key !== 'actions') { + return; + } + return (source, target) => source.concat(target); + } + }); + expect(db.getTable('baz').getOptions()).toEqual({ + name: 'baz', + actions: [ { name: 'list' }, { name: 'get' } ] + }); + }); }); describe('associations', () => { diff --git a/packages/database/src/database.ts b/packages/database/src/database.ts index d68546631..d4b28e355 100644 --- a/packages/database/src/database.ts +++ b/packages/database/src/database.ts @@ -4,7 +4,7 @@ import { SyncOptions as SequelizeSyncOptions, } from 'sequelize'; import glob from 'glob'; -import Table, { TableOptions } from './table'; +import Table, { MergeOptions, TableOptions } from './table'; import { Model, ModelCtor } from './model'; import { requireModule } from './utils'; import _ from 'lodash'; @@ -76,9 +76,8 @@ export default class Database { }); const tables = new Map(); files.forEach((file: string) => { - const options = requireModule(file); - const table = this.table(typeof options === 'function' ? options(this) : options); - tables.set(table.getName(), table); + const result = requireModule(file); + this.extend(typeof result === 'function' ? result(this) : result); }); return tables; } @@ -107,12 +106,12 @@ export default class Database { * * @param options */ - public extend(options: TableOptions): Table { + public extend(options: TableOptions, mergeOptions?: MergeOptions): Table { const { name } = options; let table: Table; if (this.tables.has(name)) { table = this.tables.get(name); - table.extend(options); + table.extend(options, mergeOptions); } else { table = this.table(options); this.tables.set(name, table); @@ -146,7 +145,7 @@ export default class Database { * * @param names */ - public getModels(names: string[]): Array> { + public getModels(names: string[] = []): Array> { if (names.length === 0) { return this.sequelize.models as any; } @@ -171,7 +170,7 @@ export default class Database { * * @param names */ - public getTables(names: string[]): Array { + public getTables(names: string[] = []): Array
{ if (names.length === 0) { return [...this.tables.values()]; } diff --git a/packages/database/src/table.ts b/packages/database/src/table.ts index 487108aea..52e608375 100644 --- a/packages/database/src/table.ts +++ b/packages/database/src/table.ts @@ -17,6 +17,11 @@ import { import Database from './database'; import { Model, ModelCtor } from './model'; import _ from 'lodash'; +import merge from 'deepmerge'; + +export interface MergeOptions extends merge.Options { + +} const registeredModels = new Map(); @@ -136,20 +141,12 @@ export class Table { const { database } = context; database.runHooks('beforeTableInit', options); const { - name, + model, fields = [], indexes = [], - model, - ...restOptions } = options; this.options = options; this.database = database; - this.modelOptions = { - modelName: name, - tableName: name, - sequelize: database.sequelize, - ...restOptions, - }; // 初始化的时候获取 this.defaultModel = getRegisteredModel(model); this.modelAttributes = {}; @@ -204,7 +201,7 @@ export class Table { } public getTableName(): string { - return this.modelOptions.tableName; + return this.options.name; } public getOptions(): TableOptions { @@ -220,15 +217,22 @@ export class Table { } public getModelOptions(): InitOptions { - const { underscored = true } = this.modelOptions; + const { + name, + underscored = true, + ...restOptions + } = this.options; const hooks = _.get(this.getModel(), 'options.hooks') || this.options.hooks || {}; return { underscored, + modelName: name, + tableName: name, + sequelize: this.database.sequelize, createdAt: Utils.underscoredIf('createdAt', underscored), updatedAt: Utils.underscoredIf('updatedAt', underscored), indexes: Array.from(this.indexes.values()), // freezeTableName: true, - ...this.modelOptions, + ..._.omit(restOptions, ['model', 'fields', 'indexes']), hooks, }; } @@ -336,7 +340,8 @@ export class Table { }; } // @ts-ignore - const index = Utils.nameIndex(options, this.modelOptions.tableName); + const index = Utils.nameIndex(options, this.options.name); + console.log(this.options, { index, options }); this.indexes.set(index.name, { type: '', parser: null, @@ -363,14 +368,21 @@ export class Table { * * @param options */ - public extend(options: TableOptions) { - const { fields = [], indexes = [], ...restOptions } = options; - this.modelOptions = { - ...this.modelOptions, - ...restOptions as any, - }; - // @ts-ignore - this.options = Utils.merge(this.options, restOptions); + public extend(options: TableOptions, mergeOptions: MergeOptions = {}) { + const { + fields = [], + indexes = [], + model, + ...restOptions + } = options; + if (model) { + this.defaultModel = getRegisteredModel(model); + } + const { arrayMerge = (target: any[], source: any[]) => source } = mergeOptions; + this.options = merge(this.options, restOptions, { + arrayMerge, + ...mergeOptions, + }); for (const key in fields) { this.addField(fields[key], false); }