refactor: table.extend() method

This commit is contained in:
chenos 2021-01-13 15:43:41 +08:00
parent b9f74197d3
commit e51ee7d1e6
4 changed files with 97 additions and 31 deletions

View File

@ -8,6 +8,7 @@
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"bcrypt": "^5.0.0", "bcrypt": "^5.0.0",
"deepmerge": "^4.2.2",
"glob": "^7.1.6", "glob": "^7.1.6",
"sequelize": "^6.3.3" "sequelize": "^6.3.3"
}, },

View File

@ -137,7 +137,7 @@ describe('tables', () => {
}); });
describe('#extend()', () => { describe('#extend()', () => {
it('should be extend', async () => { it('extend options', async () => {
db.table({ db.table({
name: 'baz', name: 'baz',
}); });
@ -151,7 +151,7 @@ describe('tables', () => {
expect(db.getModel('baz').rawAttributes.created).toBeDefined(); expect(db.getModel('baz').rawAttributes.created).toBeDefined();
expect(db.getModel('baz').rawAttributes.updated).toBeDefined(); expect(db.getModel('baz').rawAttributes.updated).toBeDefined();
}); });
it('should be extend', async () => { it('extend fields', async () => {
db.table({ db.table({
name: 'foos', name: 'foos',
}); });
@ -187,6 +187,60 @@ describe('tables', () => {
// await db.sync({force: true}); // await db.sync({force: true});
// await db.sequelize.close(); // 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', () => { describe('associations', () => {

View File

@ -4,7 +4,7 @@ import {
SyncOptions as SequelizeSyncOptions, SyncOptions as SequelizeSyncOptions,
} from 'sequelize'; } from 'sequelize';
import glob from 'glob'; import glob from 'glob';
import Table, { TableOptions } from './table'; import Table, { MergeOptions, TableOptions } from './table';
import { Model, ModelCtor } from './model'; import { Model, ModelCtor } from './model';
import { requireModule } from './utils'; import { requireModule } from './utils';
import _ from 'lodash'; import _ from 'lodash';
@ -76,9 +76,8 @@ export default class Database {
}); });
const tables = new Map<string, Table>(); const tables = new Map<string, Table>();
files.forEach((file: string) => { files.forEach((file: string) => {
const options = requireModule(file); const result = requireModule(file);
const table = this.table(typeof options === 'function' ? options(this) : options); this.extend(typeof result === 'function' ? result(this) : result);
tables.set(table.getName(), table);
}); });
return tables; return tables;
} }
@ -107,12 +106,12 @@ export default class Database {
* *
* @param options * @param options
*/ */
public extend(options: TableOptions): Table { public extend(options: TableOptions, mergeOptions?: MergeOptions): Table {
const { name } = options; const { name } = options;
let table: Table; let table: Table;
if (this.tables.has(name)) { if (this.tables.has(name)) {
table = this.tables.get(name); table = this.tables.get(name);
table.extend(options); table.extend(options, mergeOptions);
} else { } else {
table = this.table(options); table = this.table(options);
this.tables.set(name, table); this.tables.set(name, table);
@ -146,7 +145,7 @@ export default class Database {
* *
* @param names * @param names
*/ */
public getModels(names: string[]): Array<ModelCtor<Model>> { public getModels(names: string[] = []): Array<ModelCtor<Model>> {
if (names.length === 0) { if (names.length === 0) {
return this.sequelize.models as any; return this.sequelize.models as any;
} }
@ -171,7 +170,7 @@ export default class Database {
* *
* @param names * @param names
*/ */
public getTables(names: string[]): Array<Table> { public getTables(names: string[] = []): Array<Table> {
if (names.length === 0) { if (names.length === 0) {
return [...this.tables.values()]; return [...this.tables.values()];
} }

View File

@ -17,6 +17,11 @@ import {
import Database from './database'; import Database from './database';
import { Model, ModelCtor } from './model'; import { Model, ModelCtor } from './model';
import _ from 'lodash'; import _ from 'lodash';
import merge from 'deepmerge';
export interface MergeOptions extends merge.Options {
}
const registeredModels = new Map<string, any>(); const registeredModels = new Map<string, any>();
@ -136,20 +141,12 @@ export class Table {
const { database } = context; const { database } = context;
database.runHooks('beforeTableInit', options); database.runHooks('beforeTableInit', options);
const { const {
name, model,
fields = [], fields = [],
indexes = [], indexes = [],
model,
...restOptions
} = options; } = options;
this.options = options; this.options = options;
this.database = database; this.database = database;
this.modelOptions = {
modelName: name,
tableName: name,
sequelize: database.sequelize,
...restOptions,
};
// 初始化的时候获取 // 初始化的时候获取
this.defaultModel = getRegisteredModel(model); this.defaultModel = getRegisteredModel(model);
this.modelAttributes = {}; this.modelAttributes = {};
@ -204,7 +201,7 @@ export class Table {
} }
public getTableName(): string { public getTableName(): string {
return this.modelOptions.tableName; return this.options.name;
} }
public getOptions(): TableOptions { public getOptions(): TableOptions {
@ -220,15 +217,22 @@ export class Table {
} }
public getModelOptions(): InitOptions { 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 || {}; const hooks = _.get(this.getModel(), 'options.hooks') || this.options.hooks || {};
return { return {
underscored, underscored,
modelName: name,
tableName: name,
sequelize: this.database.sequelize,
createdAt: Utils.underscoredIf('createdAt', underscored), createdAt: Utils.underscoredIf('createdAt', underscored),
updatedAt: Utils.underscoredIf('updatedAt', underscored), updatedAt: Utils.underscoredIf('updatedAt', underscored),
indexes: Array.from(this.indexes.values()), indexes: Array.from(this.indexes.values()),
// freezeTableName: true, // freezeTableName: true,
...this.modelOptions, ..._.omit(restOptions, ['model', 'fields', 'indexes']),
hooks, hooks,
}; };
} }
@ -336,7 +340,8 @@ export class Table {
}; };
} }
// @ts-ignore // @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, { this.indexes.set(index.name, {
type: '', type: '',
parser: null, parser: null,
@ -363,14 +368,21 @@ export class Table {
* *
* @param options * @param options
*/ */
public extend(options: TableOptions) { public extend(options: TableOptions, mergeOptions: MergeOptions = {}) {
const { fields = [], indexes = [], ...restOptions } = options; const {
this.modelOptions = { fields = [],
...this.modelOptions, indexes = [],
...restOptions as any, model,
}; ...restOptions
// @ts-ignore } = options;
this.options = Utils.merge(this.options, restOptions); 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) { for (const key in fields) {
this.addField(fields[key], false); this.addField(fields[key], false);
} }