@nocobase/database 0.5.0-alpha.18 → 0.5.0-alpha.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["database.ts"],"names":[],"mappings":"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","file":"database.d.ts","sourcesContent":["import {\n Options,\n Sequelize,\n SyncOptions as SequelizeSyncOptions,\n} from 'sequelize';\nimport glob from 'glob';\nimport Table, { MergeOptions, TableOptions } from './table';\nimport { Model, ModelCtor } from './model';\nimport { requireModule } from './utils';\nimport _ from 'lodash';\nimport { EventEmitter } from 'events';\n\nexport interface SyncOptions extends SequelizeSyncOptions {\n\n /**\n * 指定需要更新字段的 tables\n */\n tables?: string[] | Table[] | Map<string, Table>;\n}\n\nexport interface ImportOptions {\n\n /**\n * 指定配置所在路径\n */\n directory: string;\n\n /**\n * 文件后缀,默认值 ['js', 'ts', 'json']\n */\n extensions?: string[];\n}\n\nexport interface DatabaseOptions extends Options {\n}\n\n// export type HookType = 'beforeTableInit' | 'afterTableInit' | 'beforeAddField' | 'afterAddField';\n\nexport class Extend {\n tableOptions: TableOptions;\n mergeOptions: MergeOptions\n constructor(tableOptions: TableOptions, mergeOptions?: MergeOptions) {\n this.tableOptions = tableOptions;\n this.mergeOptions = mergeOptions;\n }\n}\n\nexport function extend(tableOptions: TableOptions, mergeOptions: MergeOptions = {}) {\n return new Extend(tableOptions, mergeOptions);\n}\n\ntype HookType =\n 'beforeValidate' |\n 'afterValidate' |\n 'beforeCreate' |\n 'afterCreate' |\n 'beforeDestroy' |\n 'afterDestroy' |\n 'beforeRestore' |\n 'afterRestore' |\n 'beforeUpdate' |\n 'afterUpdate' |\n 'beforeSave' |\n 'afterSave' |\n 'beforeBulkCreate' |\n 'afterBulkCreate' |\n 'beforeBulkDestroy' |\n 'afterBulkDestroy' |\n 'beforeBulkRestore' |\n 'afterBulkRestore' |\n 'beforeBulkUpdate' |\n 'afterBulkUpdate' |\n 'beforeSync' |\n 'afterSync' |\n 'beforeBulkSync' |\n 'afterBulkSync' |\n 'beforeDefine' |\n 'afterDefine' |\n 'beforeInit' |\n 'afterInit' |\n 'beforeConnect' |\n 'afterConnect' |\n 'beforeDisconnect' |\n 'afterDisconnect';\n\n export default class Database extends EventEmitter {\n\n public readonly sequelize: Sequelize;\n\n /**\n * 哪些 Model 需要建立表关系\n */\n public readonly associating = new Set<string>();\n\n /**\n * 中间表\n */\n public readonly throughTables = new Map<string, Array<string>>();\n\n protected tables = new Map<string, Table>();\n\n protected options: DatabaseOptions;\n\n protected hooks = {};\n\n protected extTableOptions = new Map<string, any>();\n\n protected hookTypes = new Map(Object.entries({\n beforeValidate: 1,\n afterValidate: 1,\n beforeCreate: 1,\n afterCreate: 1,\n beforeDestroy: 1,\n afterDestroy: 1,\n beforeRestore: 1,\n afterRestore: 1,\n beforeUpdate: 1,\n afterUpdate: 1,\n beforeSave: 1,\n afterSave: 1,\n\n beforeBulkCreate: 2,\n afterBulkCreate: 2,\n\n beforeBulkDestroy: 3,\n afterBulkDestroy: 3,\n beforeBulkRestore: 3,\n afterBulkRestore: 3,\n beforeBulkUpdate: 3,\n afterBulkUpdate: 3,\n\n beforeSync: 4,\n afterSync: 4,\n beforeBulkSync: 4,\n afterBulkSync: 4,\n\n beforeDefine: 0,\n afterDefine: 0,\n beforeInit: 0,\n afterInit: 0,\n beforeConnect: 0,\n afterConnect: 0,\n beforeDisconnect: 0,\n afterDisconnect: 0,\n }));\n\n constructor(options?: DatabaseOptions) {\n super();\n this.options = options;\n this.sequelize = new Sequelize(options);\n }\n\n private _getHookType(event: any) {\n if (typeof event === 'string') {\n event = event.split('.');\n }\n if (!Array.isArray(event)) {\n return;\n }\n const hookType = [...event].pop();\n if (!this.hookTypes.has(hookType)) {\n return;\n }\n return hookType;\n }\n\n on(event: HookType | Omit<string, HookType> | symbol, listener: (...args: any[]) => void) {\n const hookType = this._getHookType(event);\n if (hookType) {\n const state = this.hookTypes.get(hookType);\n console.log('sequelize.addHook', event, hookType)\n this.sequelize.addHook(hookType, async (...args: any[]) => {\n let modelName: string;\n switch (state) {\n case 1:\n modelName = args?.[0]?.constructor?.name;\n break;\n case 2:\n modelName = args?.[1]?.model?.name;\n break;\n case 3:\n modelName = args?.[0]?.model?.name;\n break;\n }\n // console.log({ modelName, args });\n if (modelName) {\n await this.emitAsync(`${modelName}.${hookType}`, ...args);\n }\n await this.emitAsync(hookType, ...args);\n });\n this.hookTypes.delete(hookType);\n }\n return super.on(event as any, listener);\n }\n\n async emitAsync(event: string | symbol, ...args: any[]): Promise<boolean> {\n // @ts-ignore\n const events = this._events;\n let callbacks = events?.[event];\n if (!callbacks) {\n return false;\n }\n // helper function to reuse as much code as possible\n const run = (cb) => {\n switch (args.length) {\n // fast cases\n case 0:\n cb = cb.call(this);\n break;\n case 1:\n cb = cb.call(this, args[0]);\n break;\n case 2:\n cb = cb.call(this, args[0], args[1]);\n break;\n case 3:\n cb = cb.call(this, args[0], args[1], args[2]);\n break;\n // slower\n default:\n cb = cb.apply(this, args);\n }\n\n if (\n cb && (\n cb instanceof Promise ||\n typeof cb.then === 'function'\n )\n ) {\n return cb;\n }\n\n return Promise.resolve(true);\n };\n\n if (typeof callbacks === 'function') {\n await run(callbacks);\n } else if (typeof callbacks === 'object') {\n callbacks = callbacks.slice().filter(Boolean);\n await callbacks.reduce((prev, next) => {\n return prev.then((res) => {\n return run(next).then((result) => Promise.resolve(res.concat(result)));\n });\n }, Promise.resolve([]));\n }\n\n return true;\n }\n\n /**\n * 载入指定目录下 tables 配置(配置的文件驱动)\n * \n * TODO: 配置的文件驱动现在会全部初始化,大数据时可能存在性能瓶颈,后续可以加入动态加载\n * \n * @param {object} [options]\n * @param {string} [options.directory] 指定配置所在路径\n * @param {array} [options.extensions = ['js', 'ts', 'json']] 文件后缀\n */\n public import(options: ImportOptions): Map<string, Table> {\n const { extensions = ['js', 'ts', 'json'], directory } = options;\n const patten = `${directory}/*.{${extensions.join(',')}}`;\n const files = glob.sync(patten, {\n ignore: [\n '**/*.d.ts'\n ]\n });\n const tables = new Map<string, Table>();\n files.forEach((file: string) => {\n const result = requireModule(file);\n if (result instanceof Extend) {\n // 如果还没初始化,extend 的先暂存起来,后续处理\n if (!this.tables.has(result.tableOptions.name)) {\n this.extTableOptions.set(result.tableOptions.name, result);\n } else {\n const table = this.extend(result.tableOptions, result.mergeOptions);\n tables.set(table.getName(), table);\n }\n } else {\n let table = this.extend(typeof result === 'function' ? result(this) : result);\n // 如果有未处理的 extend 取回来合并\n if (this.extTableOptions.has(table.getName())) {\n const result = this.extTableOptions.get(table.getName());\n table = this.extend(result.tableOptions, result.mergeOptions);\n this.extTableOptions.delete(table.getName());\n }\n tables.set(table.getName(), table);\n }\n });\n return tables;\n }\n\n /**\n * 配置表\n *\n * @param options \n */\n public table(options: TableOptions): Table {\n const { name } = options;\n const table = new Table(options, { database: this });\n this.tables.set(name, table);\n // 在 source 或 target 之后定义 through,需要更新 source 和 target 的 model\n if (this.throughTables.has(name)) {\n const [sourceTable, targetTable] = this.getTables(this.throughTables.get(name));\n sourceTable && sourceTable.modelInit(true);\n targetTable && targetTable.modelInit(true);\n // this.throughTables.delete(name);\n }\n return table;\n }\n\n /**\n * 扩展配置(实验性 API)\n * \n * @param options \n */\n public extend(options: TableOptions, mergeOptions?: MergeOptions): Table {\n const { name } = options;\n let table: Table;\n if (this.tables.has(name)) {\n table = this.tables.get(name);\n table.extend(options, mergeOptions);\n } else {\n table = this.table(options);\n this.tables.set(name, table);\n }\n return table;\n }\n\n /**\n * 是否已配置\n * \n * @param name \n */\n public isDefined(name: string): boolean {\n return this.sequelize.isDefined(name);\n }\n\n /**\n * 获取 Model\n * \n * TODO: 动态初始化并加载配置(懒汉式)\n * 动态初始化需要支持文件驱动和数据库驱动\n *\n * @param name \n */\n public getModel(name: string): ModelCtor<Model> {\n return this.isDefined(name) ? this.sequelize.model(name) as any : undefined;\n }\n\n /**\n * 获取指定 names 的 Models\n *\n * @param names \n */\n public getModels(names: string[] = []): Array<ModelCtor<Model>> {\n if (names.length === 0) {\n return this.sequelize.models as any;\n }\n return names.map(name => this.getModel(name));\n }\n\n /**\n * 获取 table 配置\n * \n * TODO:\n * 未单独配置多对多中间表时,取不到中间表的 table,但是可以取到 Model\n * 动态初始化并加载配置(懒汉式),动态初始化需要支持文件驱动和数据库驱动\n * \n * @param name \n */\n public getTable(name: string): Table {\n return this.tables.has(name) ? this.tables.get(name) : undefined;\n }\n\n /**\n * 获取指定 names 的 table 配置\n *\n * @param names \n */\n public getTables(names: string[] = []): Array<Table> {\n if (names.length === 0) {\n return [...this.tables.values()];\n }\n return names.map(name => this.getTable(name));\n }\n\n /**\n * 建立表关系\n * \n * 表关系相关字段是在 Model.init 之后进行的\n */\n public associate() {\n for (const name of this.associating) {\n const Model: any = this.getModel(name);\n Model.associate && Model.associate(this.sequelize.models);\n }\n }\n\n /**\n * 插件扩展\n * \n * TODO: 细节待定\n *\n * @param plugin \n * @param options \n */\n public async plugin(plugin: any, options = {}) {\n await plugin(this, options);\n }\n\n /**\n * 表字段更新\n * \n * @param options \n */\n public async sync(options: SyncOptions = {}) {\n const { tables = [], ...restOptions } = options;\n let items: Array<any>;\n\n if (tables instanceof Map) {\n items = Array.from(tables.values());\n } else {\n items = tables;\n }\n\n /**\n * sequelize.sync 只能处理全部 model 的字段更新\n * Model.sync 只能处理当前 Model 的字段更新,不处理关系表\n * database.sync 可以指定 tables 进行字段更新,也可以自动处理关系表的字段更新\n */\n if (items.length > 0) {\n // 指定 tables 时,新建 sequelize 实例来单独处理这些 tables 相关 models 的 sync\n const sequelize = new Sequelize(this.options);\n const names = new Set<string>();\n for (const key in items) {\n let table = items[key];\n if (typeof table === 'string') {\n table = this.getTable(table);\n }\n if (table instanceof Table) {\n for (const name of table.getRelatedTableNames()) {\n names.add(name);\n }\n }\n }\n for (const name of names) {\n // @ts-ignore\n const model = this.getModel(name);\n if (model) {\n sequelize.modelManager.addModel(model);\n }\n }\n await sequelize.sync(restOptions);\n await sequelize.close();\n } else {\n await this.sequelize.sync(restOptions);\n }\n }\n\n /**\n * 关闭数据库连接\n */\n public async close() {\n this.removeAllListeners();\n return this.sequelize.close();\n }\n\n /**\n * 添加 hook\n * \n * @param hookType \n * @param fn \n */\n public addHook(hookType: HookType | string, fn: Function) {\n const hooks = this.hooks[hookType] || [];\n hooks.push(fn);\n this.hooks[hookType] = hooks;\n }\n\n /**\n * 运行 hook\n *\n * @param hookType \n * @param args \n */\n public async runHooks(hookType: HookType | string, ...args) {\n const hooks = this.hooks[hookType] || [];\n for (const hook of hooks) {\n if (typeof hook === 'function') {\n await hook(...args);\n }\n }\n }\n\n public getFieldByPath(fieldPath: string) {\n const [tableName, fieldName] = fieldPath.split('.');\n return this.getTable(tableName).getField(fieldName);\n }\n}\n"]}
1
+ {"version":3,"sources":["database.ts"],"names":[],"mappings":"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","file":"database.d.ts","sourcesContent":["import {\n Options,\n Sequelize,\n SyncOptions as SequelizeSyncOptions,\n} from 'sequelize';\nimport glob from 'glob';\nimport Table, { MergeOptions, TableOptions } from './table';\nimport { Model, ModelCtor } from './model';\nimport { requireModule } from './utils';\nimport _ from 'lodash';\nimport { EventEmitter } from 'events';\n\nexport interface SyncOptions extends SequelizeSyncOptions {\n\n /**\n * 指定需要更新字段的 tables\n */\n tables?: string[] | Table[] | Map<string, Table>;\n}\n\nexport interface ImportOptions {\n\n /**\n * 指定配置所在路径\n */\n directory: string;\n\n /**\n * 文件后缀,默认值 ['js', 'ts', 'json']\n */\n extensions?: string[];\n}\n\nexport interface DatabaseOptions extends Options {\n}\n\n// export type HookType = 'beforeTableInit' | 'afterTableInit' | 'beforeAddField' | 'afterAddField';\n\nexport class Extend {\n tableOptions: TableOptions;\n mergeOptions: MergeOptions\n constructor(tableOptions: TableOptions, mergeOptions?: MergeOptions) {\n this.tableOptions = tableOptions;\n this.mergeOptions = mergeOptions;\n }\n}\n\nexport function extend(tableOptions: TableOptions, mergeOptions: MergeOptions = {}) {\n return new Extend(tableOptions, mergeOptions);\n}\n\ntype HookType =\n 'beforeValidate' |\n 'afterValidate' |\n 'beforeCreate' |\n 'afterCreate' |\n 'beforeDestroy' |\n 'afterDestroy' |\n 'beforeRestore' |\n 'afterRestore' |\n 'beforeUpdate' |\n 'afterUpdate' |\n 'beforeSave' |\n 'afterSave' |\n 'beforeBulkCreate' |\n 'afterBulkCreate' |\n 'beforeBulkDestroy' |\n 'afterBulkDestroy' |\n 'beforeBulkRestore' |\n 'afterBulkRestore' |\n 'beforeBulkUpdate' |\n 'afterBulkUpdate' |\n 'beforeSync' |\n 'afterSync' |\n 'beforeBulkSync' |\n 'afterBulkSync' |\n 'beforeDefine' |\n 'afterDefine' |\n 'beforeInit' |\n 'afterInit' |\n 'beforeConnect' |\n 'afterConnect' |\n 'beforeDisconnect' |\n 'afterDisconnect';\n\n export default class Database extends EventEmitter {\n\n public readonly sequelize: Sequelize;\n\n /**\n * 哪些 Model 需要建立表关系\n */\n public readonly associating = new Set<string>();\n\n /**\n * 中间表\n */\n public readonly throughTables = new Map<string, Array<string>>();\n\n protected tables = new Map<string, Table>();\n\n protected options: DatabaseOptions;\n\n protected hooks = {};\n\n protected extTableOptions = new Map<string, any>();\n\n protected hookTypes = new Map(Object.entries({\n beforeValidate: 1,\n afterValidate: 1,\n beforeCreate: 1,\n afterCreate: 1,\n beforeDestroy: 1,\n afterDestroy: 1,\n beforeRestore: 1,\n afterRestore: 1,\n beforeUpdate: 1,\n afterUpdate: 1,\n beforeSave: 1,\n afterSave: 1,\n\n beforeBulkCreate: 2,\n afterBulkCreate: 2,\n\n beforeBulkDestroy: 3,\n afterBulkDestroy: 3,\n beforeBulkRestore: 3,\n afterBulkRestore: 3,\n beforeBulkUpdate: 3,\n afterBulkUpdate: 3,\n\n beforeSync: 4,\n afterSync: 4,\n beforeBulkSync: 4,\n afterBulkSync: 4,\n\n beforeDefine: 0,\n afterDefine: 0,\n beforeInit: 0,\n afterInit: 0,\n beforeConnect: 0,\n afterConnect: 0,\n beforeDisconnect: 0,\n afterDisconnect: 0,\n }));\n\n constructor(options?: DatabaseOptions) {\n super();\n this.options = options;\n this.sequelize = new Sequelize(options);\n }\n\n private _getHookType(event: any) {\n if (typeof event === 'string') {\n event = event.split('.');\n }\n if (!Array.isArray(event)) {\n return;\n }\n const hookType = [...event].pop();\n if (!this.hookTypes.has(hookType)) {\n return;\n }\n return hookType;\n }\n\n on(event: HookType | Omit<string, HookType> | symbol, listener: (...args: any[]) => void) {\n const hookType = this._getHookType(event);\n if (hookType) {\n const state = this.hookTypes.get(hookType);\n\n this.sequelize.addHook(hookType, async (...args: any[]) => {\n let modelName: string;\n switch (state) {\n case 1:\n modelName = args?.[0]?.constructor?.name;\n break;\n case 2:\n modelName = args?.[1]?.model?.name;\n break;\n case 3:\n modelName = args?.[0]?.model?.name;\n break;\n }\n // console.log({ modelName, args });\n if (modelName) {\n await this.emitAsync(`${modelName}.${hookType}`, ...args);\n }\n await this.emitAsync(hookType, ...args);\n });\n this.hookTypes.delete(hookType);\n }\n return super.on(event as any, listener);\n }\n\n async emitAsync(event: string | symbol, ...args: any[]): Promise<boolean> {\n // @ts-ignore\n const events = this._events;\n let callbacks = events?.[event];\n if (!callbacks) {\n return false;\n }\n // helper function to reuse as much code as possible\n const run = (cb) => {\n switch (args.length) {\n // fast cases\n case 0:\n cb = cb.call(this);\n break;\n case 1:\n cb = cb.call(this, args[0]);\n break;\n case 2:\n cb = cb.call(this, args[0], args[1]);\n break;\n case 3:\n cb = cb.call(this, args[0], args[1], args[2]);\n break;\n // slower\n default:\n cb = cb.apply(this, args);\n }\n\n if (\n cb && (\n cb instanceof Promise ||\n typeof cb.then === 'function'\n )\n ) {\n return cb;\n }\n\n return Promise.resolve(true);\n };\n\n if (typeof callbacks === 'function') {\n await run(callbacks);\n } else if (typeof callbacks === 'object') {\n callbacks = callbacks.slice().filter(Boolean);\n await callbacks.reduce((prev, next) => {\n return prev.then((res) => {\n return run(next).then((result) => Promise.resolve(res.concat(result)));\n });\n }, Promise.resolve([]));\n }\n\n return true;\n }\n\n /**\n * 载入指定目录下 tables 配置(配置的文件驱动)\n * \n * TODO: 配置的文件驱动现在会全部初始化,大数据时可能存在性能瓶颈,后续可以加入动态加载\n * \n * @param {object} [options]\n * @param {string} [options.directory] 指定配置所在路径\n * @param {array} [options.extensions = ['js', 'ts', 'json']] 文件后缀\n */\n public import(options: ImportOptions): Map<string, Table> {\n const { extensions = ['js', 'ts', 'json'], directory } = options;\n const patten = `${directory}/*.{${extensions.join(',')}}`;\n const files = glob.sync(patten, {\n ignore: [\n '**/*.d.ts'\n ]\n });\n const tables = new Map<string, Table>();\n files.forEach((file: string) => {\n const result = requireModule(file);\n if (result instanceof Extend) {\n // 如果还没初始化,extend 的先暂存起来,后续处理\n if (!this.tables.has(result.tableOptions.name)) {\n this.extTableOptions.set(result.tableOptions.name, result);\n } else {\n const table = this.extend(result.tableOptions, result.mergeOptions);\n tables.set(table.getName(), table);\n }\n } else {\n let table = this.extend(typeof result === 'function' ? result(this) : result);\n // 如果有未处理的 extend 取回来合并\n if (this.extTableOptions.has(table.getName())) {\n const result = this.extTableOptions.get(table.getName());\n table = this.extend(result.tableOptions, result.mergeOptions);\n this.extTableOptions.delete(table.getName());\n }\n tables.set(table.getName(), table);\n }\n });\n return tables;\n }\n\n /**\n * 配置表\n *\n * @param options \n */\n public table(options: TableOptions): Table {\n const { name } = options;\n const table = new Table(options, { database: this });\n this.tables.set(name, table);\n // 在 source 或 target 之后定义 through,需要更新 source 和 target 的 model\n if (this.throughTables.has(name)) {\n const [sourceTable, targetTable] = this.getTables(this.throughTables.get(name));\n sourceTable && sourceTable.modelInit(true);\n targetTable && targetTable.modelInit(true);\n // this.throughTables.delete(name);\n }\n return table;\n }\n\n /**\n * 扩展配置(实验性 API)\n * \n * @param options \n */\n public extend(options: TableOptions, mergeOptions?: MergeOptions): Table {\n const { name } = options;\n let table: Table;\n if (this.tables.has(name)) {\n table = this.tables.get(name);\n table.extend(options, mergeOptions);\n } else {\n table = this.table(options);\n this.tables.set(name, table);\n }\n return table;\n }\n\n /**\n * 是否已配置\n * \n * @param name \n */\n public isDefined(name: string): boolean {\n return this.sequelize.isDefined(name);\n }\n\n /**\n * 获取 Model\n * \n * TODO: 动态初始化并加载配置(懒汉式)\n * 动态初始化需要支持文件驱动和数据库驱动\n *\n * @param name \n */\n public getModel(name: string): ModelCtor<Model> {\n return this.isDefined(name) ? this.sequelize.model(name) as any : undefined;\n }\n\n /**\n * 获取指定 names 的 Models\n *\n * @param names \n */\n public getModels(names: string[] = []): Array<ModelCtor<Model>> {\n if (names.length === 0) {\n return this.sequelize.models as any;\n }\n return names.map(name => this.getModel(name));\n }\n\n /**\n * 获取 table 配置\n * \n * TODO:\n * 未单独配置多对多中间表时,取不到中间表的 table,但是可以取到 Model\n * 动态初始化并加载配置(懒汉式),动态初始化需要支持文件驱动和数据库驱动\n * \n * @param name \n */\n public getTable(name: string): Table {\n return this.tables.has(name) ? this.tables.get(name) : undefined;\n }\n\n /**\n * 获取指定 names 的 table 配置\n *\n * @param names \n */\n public getTables(names: string[] = []): Array<Table> {\n if (names.length === 0) {\n return [...this.tables.values()];\n }\n return names.map(name => this.getTable(name));\n }\n\n /**\n * 建立表关系\n * \n * 表关系相关字段是在 Model.init 之后进行的\n */\n public associate() {\n for (const name of this.associating) {\n const Model: any = this.getModel(name);\n Model.associate && Model.associate(this.sequelize.models);\n }\n }\n\n /**\n * 插件扩展\n * \n * TODO: 细节待定\n *\n * @param plugin \n * @param options \n */\n public async plugin(plugin: any, options = {}) {\n await plugin(this, options);\n }\n\n /**\n * 表字段更新\n * \n * @param options \n */\n public async sync(options: SyncOptions = {}) {\n const { tables = [], ...restOptions } = options;\n let items: Array<any>;\n\n if (tables instanceof Map) {\n items = Array.from(tables.values());\n } else {\n items = tables;\n }\n\n /**\n * sequelize.sync 只能处理全部 model 的字段更新\n * Model.sync 只能处理当前 Model 的字段更新,不处理关系表\n * database.sync 可以指定 tables 进行字段更新,也可以自动处理关系表的字段更新\n */\n if (items.length > 0) {\n // 指定 tables 时,新建 sequelize 实例来单独处理这些 tables 相关 models 的 sync\n const sequelize = new Sequelize(this.options);\n const names = new Set<string>();\n for (const key in items) {\n let table = items[key];\n if (typeof table === 'string') {\n table = this.getTable(table);\n }\n if (table instanceof Table) {\n for (const name of table.getRelatedTableNames()) {\n names.add(name);\n }\n }\n }\n for (const name of names) {\n // @ts-ignore\n const model = this.getModel(name);\n if (model) {\n sequelize.modelManager.addModel(model);\n }\n }\n await sequelize.sync(restOptions);\n await sequelize.close();\n } else {\n await this.sequelize.sync(restOptions);\n }\n }\n\n /**\n * 关闭数据库连接\n */\n public async close() {\n this.removeAllListeners();\n return this.sequelize.close();\n }\n\n /**\n * 添加 hook\n * \n * @param hookType \n * @param fn \n */\n public addHook(hookType: HookType | string, fn: Function) {\n const hooks = this.hooks[hookType] || [];\n hooks.push(fn);\n this.hooks[hookType] = hooks;\n }\n\n /**\n * 运行 hook\n *\n * @param hookType \n * @param args \n */\n public async runHooks(hookType: HookType | string, ...args) {\n const hooks = this.hooks[hookType] || [];\n for (const hook of hooks) {\n if (typeof hook === 'function') {\n await hook(...args);\n }\n }\n }\n\n public getFieldByPath(fieldPath: string) {\n const [tableName, fieldName] = fieldPath.split('.');\n return this.getTable(tableName).getField(fieldName);\n }\n}\n"]}
package/lib/database.js CHANGED
@@ -175,7 +175,6 @@ class Database extends events_1.EventEmitter {
175
175
 
176
176
  if (hookType) {
177
177
  const state = this.hookTypes.get(hookType);
178
- console.log('sequelize.addHook', event, hookType);
179
178
  this.sequelize.addHook(hookType, (...args) => __awaiter(this, void 0, void 0, function* () {
180
179
  var _a, _b, _c, _d, _e, _f;
181
180
 
@@ -1 +1 @@
1
- {"version":3,"sources":["database.ts"],"names":[],"mappings":"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","file":"database.js","sourcesContent":["import {\n Options,\n Sequelize,\n SyncOptions as SequelizeSyncOptions,\n} from 'sequelize';\nimport glob from 'glob';\nimport Table, { MergeOptions, TableOptions } from './table';\nimport { Model, ModelCtor } from './model';\nimport { requireModule } from './utils';\nimport _ from 'lodash';\nimport { EventEmitter } from 'events';\n\nexport interface SyncOptions extends SequelizeSyncOptions {\n\n /**\n * 指定需要更新字段的 tables\n */\n tables?: string[] | Table[] | Map<string, Table>;\n}\n\nexport interface ImportOptions {\n\n /**\n * 指定配置所在路径\n */\n directory: string;\n\n /**\n * 文件后缀,默认值 ['js', 'ts', 'json']\n */\n extensions?: string[];\n}\n\nexport interface DatabaseOptions extends Options {\n}\n\n// export type HookType = 'beforeTableInit' | 'afterTableInit' | 'beforeAddField' | 'afterAddField';\n\nexport class Extend {\n tableOptions: TableOptions;\n mergeOptions: MergeOptions\n constructor(tableOptions: TableOptions, mergeOptions?: MergeOptions) {\n this.tableOptions = tableOptions;\n this.mergeOptions = mergeOptions;\n }\n}\n\nexport function extend(tableOptions: TableOptions, mergeOptions: MergeOptions = {}) {\n return new Extend(tableOptions, mergeOptions);\n}\n\ntype HookType =\n 'beforeValidate' |\n 'afterValidate' |\n 'beforeCreate' |\n 'afterCreate' |\n 'beforeDestroy' |\n 'afterDestroy' |\n 'beforeRestore' |\n 'afterRestore' |\n 'beforeUpdate' |\n 'afterUpdate' |\n 'beforeSave' |\n 'afterSave' |\n 'beforeBulkCreate' |\n 'afterBulkCreate' |\n 'beforeBulkDestroy' |\n 'afterBulkDestroy' |\n 'beforeBulkRestore' |\n 'afterBulkRestore' |\n 'beforeBulkUpdate' |\n 'afterBulkUpdate' |\n 'beforeSync' |\n 'afterSync' |\n 'beforeBulkSync' |\n 'afterBulkSync' |\n 'beforeDefine' |\n 'afterDefine' |\n 'beforeInit' |\n 'afterInit' |\n 'beforeConnect' |\n 'afterConnect' |\n 'beforeDisconnect' |\n 'afterDisconnect';\n\n export default class Database extends EventEmitter {\n\n public readonly sequelize: Sequelize;\n\n /**\n * 哪些 Model 需要建立表关系\n */\n public readonly associating = new Set<string>();\n\n /**\n * 中间表\n */\n public readonly throughTables = new Map<string, Array<string>>();\n\n protected tables = new Map<string, Table>();\n\n protected options: DatabaseOptions;\n\n protected hooks = {};\n\n protected extTableOptions = new Map<string, any>();\n\n protected hookTypes = new Map(Object.entries({\n beforeValidate: 1,\n afterValidate: 1,\n beforeCreate: 1,\n afterCreate: 1,\n beforeDestroy: 1,\n afterDestroy: 1,\n beforeRestore: 1,\n afterRestore: 1,\n beforeUpdate: 1,\n afterUpdate: 1,\n beforeSave: 1,\n afterSave: 1,\n\n beforeBulkCreate: 2,\n afterBulkCreate: 2,\n\n beforeBulkDestroy: 3,\n afterBulkDestroy: 3,\n beforeBulkRestore: 3,\n afterBulkRestore: 3,\n beforeBulkUpdate: 3,\n afterBulkUpdate: 3,\n\n beforeSync: 4,\n afterSync: 4,\n beforeBulkSync: 4,\n afterBulkSync: 4,\n\n beforeDefine: 0,\n afterDefine: 0,\n beforeInit: 0,\n afterInit: 0,\n beforeConnect: 0,\n afterConnect: 0,\n beforeDisconnect: 0,\n afterDisconnect: 0,\n }));\n\n constructor(options?: DatabaseOptions) {\n super();\n this.options = options;\n this.sequelize = new Sequelize(options);\n }\n\n private _getHookType(event: any) {\n if (typeof event === 'string') {\n event = event.split('.');\n }\n if (!Array.isArray(event)) {\n return;\n }\n const hookType = [...event].pop();\n if (!this.hookTypes.has(hookType)) {\n return;\n }\n return hookType;\n }\n\n on(event: HookType | Omit<string, HookType> | symbol, listener: (...args: any[]) => void) {\n const hookType = this._getHookType(event);\n if (hookType) {\n const state = this.hookTypes.get(hookType);\n console.log('sequelize.addHook', event, hookType)\n this.sequelize.addHook(hookType, async (...args: any[]) => {\n let modelName: string;\n switch (state) {\n case 1:\n modelName = args?.[0]?.constructor?.name;\n break;\n case 2:\n modelName = args?.[1]?.model?.name;\n break;\n case 3:\n modelName = args?.[0]?.model?.name;\n break;\n }\n // console.log({ modelName, args });\n if (modelName) {\n await this.emitAsync(`${modelName}.${hookType}`, ...args);\n }\n await this.emitAsync(hookType, ...args);\n });\n this.hookTypes.delete(hookType);\n }\n return super.on(event as any, listener);\n }\n\n async emitAsync(event: string | symbol, ...args: any[]): Promise<boolean> {\n // @ts-ignore\n const events = this._events;\n let callbacks = events?.[event];\n if (!callbacks) {\n return false;\n }\n // helper function to reuse as much code as possible\n const run = (cb) => {\n switch (args.length) {\n // fast cases\n case 0:\n cb = cb.call(this);\n break;\n case 1:\n cb = cb.call(this, args[0]);\n break;\n case 2:\n cb = cb.call(this, args[0], args[1]);\n break;\n case 3:\n cb = cb.call(this, args[0], args[1], args[2]);\n break;\n // slower\n default:\n cb = cb.apply(this, args);\n }\n\n if (\n cb && (\n cb instanceof Promise ||\n typeof cb.then === 'function'\n )\n ) {\n return cb;\n }\n\n return Promise.resolve(true);\n };\n\n if (typeof callbacks === 'function') {\n await run(callbacks);\n } else if (typeof callbacks === 'object') {\n callbacks = callbacks.slice().filter(Boolean);\n await callbacks.reduce((prev, next) => {\n return prev.then((res) => {\n return run(next).then((result) => Promise.resolve(res.concat(result)));\n });\n }, Promise.resolve([]));\n }\n\n return true;\n }\n\n /**\n * 载入指定目录下 tables 配置(配置的文件驱动)\n * \n * TODO: 配置的文件驱动现在会全部初始化,大数据时可能存在性能瓶颈,后续可以加入动态加载\n * \n * @param {object} [options]\n * @param {string} [options.directory] 指定配置所在路径\n * @param {array} [options.extensions = ['js', 'ts', 'json']] 文件后缀\n */\n public import(options: ImportOptions): Map<string, Table> {\n const { extensions = ['js', 'ts', 'json'], directory } = options;\n const patten = `${directory}/*.{${extensions.join(',')}}`;\n const files = glob.sync(patten, {\n ignore: [\n '**/*.d.ts'\n ]\n });\n const tables = new Map<string, Table>();\n files.forEach((file: string) => {\n const result = requireModule(file);\n if (result instanceof Extend) {\n // 如果还没初始化,extend 的先暂存起来,后续处理\n if (!this.tables.has(result.tableOptions.name)) {\n this.extTableOptions.set(result.tableOptions.name, result);\n } else {\n const table = this.extend(result.tableOptions, result.mergeOptions);\n tables.set(table.getName(), table);\n }\n } else {\n let table = this.extend(typeof result === 'function' ? result(this) : result);\n // 如果有未处理的 extend 取回来合并\n if (this.extTableOptions.has(table.getName())) {\n const result = this.extTableOptions.get(table.getName());\n table = this.extend(result.tableOptions, result.mergeOptions);\n this.extTableOptions.delete(table.getName());\n }\n tables.set(table.getName(), table);\n }\n });\n return tables;\n }\n\n /**\n * 配置表\n *\n * @param options \n */\n public table(options: TableOptions): Table {\n const { name } = options;\n const table = new Table(options, { database: this });\n this.tables.set(name, table);\n // 在 source 或 target 之后定义 through,需要更新 source 和 target 的 model\n if (this.throughTables.has(name)) {\n const [sourceTable, targetTable] = this.getTables(this.throughTables.get(name));\n sourceTable && sourceTable.modelInit(true);\n targetTable && targetTable.modelInit(true);\n // this.throughTables.delete(name);\n }\n return table;\n }\n\n /**\n * 扩展配置(实验性 API)\n * \n * @param options \n */\n public extend(options: TableOptions, mergeOptions?: MergeOptions): Table {\n const { name } = options;\n let table: Table;\n if (this.tables.has(name)) {\n table = this.tables.get(name);\n table.extend(options, mergeOptions);\n } else {\n table = this.table(options);\n this.tables.set(name, table);\n }\n return table;\n }\n\n /**\n * 是否已配置\n * \n * @param name \n */\n public isDefined(name: string): boolean {\n return this.sequelize.isDefined(name);\n }\n\n /**\n * 获取 Model\n * \n * TODO: 动态初始化并加载配置(懒汉式)\n * 动态初始化需要支持文件驱动和数据库驱动\n *\n * @param name \n */\n public getModel(name: string): ModelCtor<Model> {\n return this.isDefined(name) ? this.sequelize.model(name) as any : undefined;\n }\n\n /**\n * 获取指定 names 的 Models\n *\n * @param names \n */\n public getModels(names: string[] = []): Array<ModelCtor<Model>> {\n if (names.length === 0) {\n return this.sequelize.models as any;\n }\n return names.map(name => this.getModel(name));\n }\n\n /**\n * 获取 table 配置\n * \n * TODO:\n * 未单独配置多对多中间表时,取不到中间表的 table,但是可以取到 Model\n * 动态初始化并加载配置(懒汉式),动态初始化需要支持文件驱动和数据库驱动\n * \n * @param name \n */\n public getTable(name: string): Table {\n return this.tables.has(name) ? this.tables.get(name) : undefined;\n }\n\n /**\n * 获取指定 names 的 table 配置\n *\n * @param names \n */\n public getTables(names: string[] = []): Array<Table> {\n if (names.length === 0) {\n return [...this.tables.values()];\n }\n return names.map(name => this.getTable(name));\n }\n\n /**\n * 建立表关系\n * \n * 表关系相关字段是在 Model.init 之后进行的\n */\n public associate() {\n for (const name of this.associating) {\n const Model: any = this.getModel(name);\n Model.associate && Model.associate(this.sequelize.models);\n }\n }\n\n /**\n * 插件扩展\n * \n * TODO: 细节待定\n *\n * @param plugin \n * @param options \n */\n public async plugin(plugin: any, options = {}) {\n await plugin(this, options);\n }\n\n /**\n * 表字段更新\n * \n * @param options \n */\n public async sync(options: SyncOptions = {}) {\n const { tables = [], ...restOptions } = options;\n let items: Array<any>;\n\n if (tables instanceof Map) {\n items = Array.from(tables.values());\n } else {\n items = tables;\n }\n\n /**\n * sequelize.sync 只能处理全部 model 的字段更新\n * Model.sync 只能处理当前 Model 的字段更新,不处理关系表\n * database.sync 可以指定 tables 进行字段更新,也可以自动处理关系表的字段更新\n */\n if (items.length > 0) {\n // 指定 tables 时,新建 sequelize 实例来单独处理这些 tables 相关 models 的 sync\n const sequelize = new Sequelize(this.options);\n const names = new Set<string>();\n for (const key in items) {\n let table = items[key];\n if (typeof table === 'string') {\n table = this.getTable(table);\n }\n if (table instanceof Table) {\n for (const name of table.getRelatedTableNames()) {\n names.add(name);\n }\n }\n }\n for (const name of names) {\n // @ts-ignore\n const model = this.getModel(name);\n if (model) {\n sequelize.modelManager.addModel(model);\n }\n }\n await sequelize.sync(restOptions);\n await sequelize.close();\n } else {\n await this.sequelize.sync(restOptions);\n }\n }\n\n /**\n * 关闭数据库连接\n */\n public async close() {\n this.removeAllListeners();\n return this.sequelize.close();\n }\n\n /**\n * 添加 hook\n * \n * @param hookType \n * @param fn \n */\n public addHook(hookType: HookType | string, fn: Function) {\n const hooks = this.hooks[hookType] || [];\n hooks.push(fn);\n this.hooks[hookType] = hooks;\n }\n\n /**\n * 运行 hook\n *\n * @param hookType \n * @param args \n */\n public async runHooks(hookType: HookType | string, ...args) {\n const hooks = this.hooks[hookType] || [];\n for (const hook of hooks) {\n if (typeof hook === 'function') {\n await hook(...args);\n }\n }\n }\n\n public getFieldByPath(fieldPath: string) {\n const [tableName, fieldName] = fieldPath.split('.');\n return this.getTable(tableName).getField(fieldName);\n }\n}\n"]}
1
+ {"version":3,"sources":["database.ts"],"names":[],"mappings":"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","file":"database.js","sourcesContent":["import {\n Options,\n Sequelize,\n SyncOptions as SequelizeSyncOptions,\n} from 'sequelize';\nimport glob from 'glob';\nimport Table, { MergeOptions, TableOptions } from './table';\nimport { Model, ModelCtor } from './model';\nimport { requireModule } from './utils';\nimport _ from 'lodash';\nimport { EventEmitter } from 'events';\n\nexport interface SyncOptions extends SequelizeSyncOptions {\n\n /**\n * 指定需要更新字段的 tables\n */\n tables?: string[] | Table[] | Map<string, Table>;\n}\n\nexport interface ImportOptions {\n\n /**\n * 指定配置所在路径\n */\n directory: string;\n\n /**\n * 文件后缀,默认值 ['js', 'ts', 'json']\n */\n extensions?: string[];\n}\n\nexport interface DatabaseOptions extends Options {\n}\n\n// export type HookType = 'beforeTableInit' | 'afterTableInit' | 'beforeAddField' | 'afterAddField';\n\nexport class Extend {\n tableOptions: TableOptions;\n mergeOptions: MergeOptions\n constructor(tableOptions: TableOptions, mergeOptions?: MergeOptions) {\n this.tableOptions = tableOptions;\n this.mergeOptions = mergeOptions;\n }\n}\n\nexport function extend(tableOptions: TableOptions, mergeOptions: MergeOptions = {}) {\n return new Extend(tableOptions, mergeOptions);\n}\n\ntype HookType =\n 'beforeValidate' |\n 'afterValidate' |\n 'beforeCreate' |\n 'afterCreate' |\n 'beforeDestroy' |\n 'afterDestroy' |\n 'beforeRestore' |\n 'afterRestore' |\n 'beforeUpdate' |\n 'afterUpdate' |\n 'beforeSave' |\n 'afterSave' |\n 'beforeBulkCreate' |\n 'afterBulkCreate' |\n 'beforeBulkDestroy' |\n 'afterBulkDestroy' |\n 'beforeBulkRestore' |\n 'afterBulkRestore' |\n 'beforeBulkUpdate' |\n 'afterBulkUpdate' |\n 'beforeSync' |\n 'afterSync' |\n 'beforeBulkSync' |\n 'afterBulkSync' |\n 'beforeDefine' |\n 'afterDefine' |\n 'beforeInit' |\n 'afterInit' |\n 'beforeConnect' |\n 'afterConnect' |\n 'beforeDisconnect' |\n 'afterDisconnect';\n\n export default class Database extends EventEmitter {\n\n public readonly sequelize: Sequelize;\n\n /**\n * 哪些 Model 需要建立表关系\n */\n public readonly associating = new Set<string>();\n\n /**\n * 中间表\n */\n public readonly throughTables = new Map<string, Array<string>>();\n\n protected tables = new Map<string, Table>();\n\n protected options: DatabaseOptions;\n\n protected hooks = {};\n\n protected extTableOptions = new Map<string, any>();\n\n protected hookTypes = new Map(Object.entries({\n beforeValidate: 1,\n afterValidate: 1,\n beforeCreate: 1,\n afterCreate: 1,\n beforeDestroy: 1,\n afterDestroy: 1,\n beforeRestore: 1,\n afterRestore: 1,\n beforeUpdate: 1,\n afterUpdate: 1,\n beforeSave: 1,\n afterSave: 1,\n\n beforeBulkCreate: 2,\n afterBulkCreate: 2,\n\n beforeBulkDestroy: 3,\n afterBulkDestroy: 3,\n beforeBulkRestore: 3,\n afterBulkRestore: 3,\n beforeBulkUpdate: 3,\n afterBulkUpdate: 3,\n\n beforeSync: 4,\n afterSync: 4,\n beforeBulkSync: 4,\n afterBulkSync: 4,\n\n beforeDefine: 0,\n afterDefine: 0,\n beforeInit: 0,\n afterInit: 0,\n beforeConnect: 0,\n afterConnect: 0,\n beforeDisconnect: 0,\n afterDisconnect: 0,\n }));\n\n constructor(options?: DatabaseOptions) {\n super();\n this.options = options;\n this.sequelize = new Sequelize(options);\n }\n\n private _getHookType(event: any) {\n if (typeof event === 'string') {\n event = event.split('.');\n }\n if (!Array.isArray(event)) {\n return;\n }\n const hookType = [...event].pop();\n if (!this.hookTypes.has(hookType)) {\n return;\n }\n return hookType;\n }\n\n on(event: HookType | Omit<string, HookType> | symbol, listener: (...args: any[]) => void) {\n const hookType = this._getHookType(event);\n if (hookType) {\n const state = this.hookTypes.get(hookType);\n\n this.sequelize.addHook(hookType, async (...args: any[]) => {\n let modelName: string;\n switch (state) {\n case 1:\n modelName = args?.[0]?.constructor?.name;\n break;\n case 2:\n modelName = args?.[1]?.model?.name;\n break;\n case 3:\n modelName = args?.[0]?.model?.name;\n break;\n }\n // console.log({ modelName, args });\n if (modelName) {\n await this.emitAsync(`${modelName}.${hookType}`, ...args);\n }\n await this.emitAsync(hookType, ...args);\n });\n this.hookTypes.delete(hookType);\n }\n return super.on(event as any, listener);\n }\n\n async emitAsync(event: string | symbol, ...args: any[]): Promise<boolean> {\n // @ts-ignore\n const events = this._events;\n let callbacks = events?.[event];\n if (!callbacks) {\n return false;\n }\n // helper function to reuse as much code as possible\n const run = (cb) => {\n switch (args.length) {\n // fast cases\n case 0:\n cb = cb.call(this);\n break;\n case 1:\n cb = cb.call(this, args[0]);\n break;\n case 2:\n cb = cb.call(this, args[0], args[1]);\n break;\n case 3:\n cb = cb.call(this, args[0], args[1], args[2]);\n break;\n // slower\n default:\n cb = cb.apply(this, args);\n }\n\n if (\n cb && (\n cb instanceof Promise ||\n typeof cb.then === 'function'\n )\n ) {\n return cb;\n }\n\n return Promise.resolve(true);\n };\n\n if (typeof callbacks === 'function') {\n await run(callbacks);\n } else if (typeof callbacks === 'object') {\n callbacks = callbacks.slice().filter(Boolean);\n await callbacks.reduce((prev, next) => {\n return prev.then((res) => {\n return run(next).then((result) => Promise.resolve(res.concat(result)));\n });\n }, Promise.resolve([]));\n }\n\n return true;\n }\n\n /**\n * 载入指定目录下 tables 配置(配置的文件驱动)\n * \n * TODO: 配置的文件驱动现在会全部初始化,大数据时可能存在性能瓶颈,后续可以加入动态加载\n * \n * @param {object} [options]\n * @param {string} [options.directory] 指定配置所在路径\n * @param {array} [options.extensions = ['js', 'ts', 'json']] 文件后缀\n */\n public import(options: ImportOptions): Map<string, Table> {\n const { extensions = ['js', 'ts', 'json'], directory } = options;\n const patten = `${directory}/*.{${extensions.join(',')}}`;\n const files = glob.sync(patten, {\n ignore: [\n '**/*.d.ts'\n ]\n });\n const tables = new Map<string, Table>();\n files.forEach((file: string) => {\n const result = requireModule(file);\n if (result instanceof Extend) {\n // 如果还没初始化,extend 的先暂存起来,后续处理\n if (!this.tables.has(result.tableOptions.name)) {\n this.extTableOptions.set(result.tableOptions.name, result);\n } else {\n const table = this.extend(result.tableOptions, result.mergeOptions);\n tables.set(table.getName(), table);\n }\n } else {\n let table = this.extend(typeof result === 'function' ? result(this) : result);\n // 如果有未处理的 extend 取回来合并\n if (this.extTableOptions.has(table.getName())) {\n const result = this.extTableOptions.get(table.getName());\n table = this.extend(result.tableOptions, result.mergeOptions);\n this.extTableOptions.delete(table.getName());\n }\n tables.set(table.getName(), table);\n }\n });\n return tables;\n }\n\n /**\n * 配置表\n *\n * @param options \n */\n public table(options: TableOptions): Table {\n const { name } = options;\n const table = new Table(options, { database: this });\n this.tables.set(name, table);\n // 在 source 或 target 之后定义 through,需要更新 source 和 target 的 model\n if (this.throughTables.has(name)) {\n const [sourceTable, targetTable] = this.getTables(this.throughTables.get(name));\n sourceTable && sourceTable.modelInit(true);\n targetTable && targetTable.modelInit(true);\n // this.throughTables.delete(name);\n }\n return table;\n }\n\n /**\n * 扩展配置(实验性 API)\n * \n * @param options \n */\n public extend(options: TableOptions, mergeOptions?: MergeOptions): Table {\n const { name } = options;\n let table: Table;\n if (this.tables.has(name)) {\n table = this.tables.get(name);\n table.extend(options, mergeOptions);\n } else {\n table = this.table(options);\n this.tables.set(name, table);\n }\n return table;\n }\n\n /**\n * 是否已配置\n * \n * @param name \n */\n public isDefined(name: string): boolean {\n return this.sequelize.isDefined(name);\n }\n\n /**\n * 获取 Model\n * \n * TODO: 动态初始化并加载配置(懒汉式)\n * 动态初始化需要支持文件驱动和数据库驱动\n *\n * @param name \n */\n public getModel(name: string): ModelCtor<Model> {\n return this.isDefined(name) ? this.sequelize.model(name) as any : undefined;\n }\n\n /**\n * 获取指定 names 的 Models\n *\n * @param names \n */\n public getModels(names: string[] = []): Array<ModelCtor<Model>> {\n if (names.length === 0) {\n return this.sequelize.models as any;\n }\n return names.map(name => this.getModel(name));\n }\n\n /**\n * 获取 table 配置\n * \n * TODO:\n * 未单独配置多对多中间表时,取不到中间表的 table,但是可以取到 Model\n * 动态初始化并加载配置(懒汉式),动态初始化需要支持文件驱动和数据库驱动\n * \n * @param name \n */\n public getTable(name: string): Table {\n return this.tables.has(name) ? this.tables.get(name) : undefined;\n }\n\n /**\n * 获取指定 names 的 table 配置\n *\n * @param names \n */\n public getTables(names: string[] = []): Array<Table> {\n if (names.length === 0) {\n return [...this.tables.values()];\n }\n return names.map(name => this.getTable(name));\n }\n\n /**\n * 建立表关系\n * \n * 表关系相关字段是在 Model.init 之后进行的\n */\n public associate() {\n for (const name of this.associating) {\n const Model: any = this.getModel(name);\n Model.associate && Model.associate(this.sequelize.models);\n }\n }\n\n /**\n * 插件扩展\n * \n * TODO: 细节待定\n *\n * @param plugin \n * @param options \n */\n public async plugin(plugin: any, options = {}) {\n await plugin(this, options);\n }\n\n /**\n * 表字段更新\n * \n * @param options \n */\n public async sync(options: SyncOptions = {}) {\n const { tables = [], ...restOptions } = options;\n let items: Array<any>;\n\n if (tables instanceof Map) {\n items = Array.from(tables.values());\n } else {\n items = tables;\n }\n\n /**\n * sequelize.sync 只能处理全部 model 的字段更新\n * Model.sync 只能处理当前 Model 的字段更新,不处理关系表\n * database.sync 可以指定 tables 进行字段更新,也可以自动处理关系表的字段更新\n */\n if (items.length > 0) {\n // 指定 tables 时,新建 sequelize 实例来单独处理这些 tables 相关 models 的 sync\n const sequelize = new Sequelize(this.options);\n const names = new Set<string>();\n for (const key in items) {\n let table = items[key];\n if (typeof table === 'string') {\n table = this.getTable(table);\n }\n if (table instanceof Table) {\n for (const name of table.getRelatedTableNames()) {\n names.add(name);\n }\n }\n }\n for (const name of names) {\n // @ts-ignore\n const model = this.getModel(name);\n if (model) {\n sequelize.modelManager.addModel(model);\n }\n }\n await sequelize.sync(restOptions);\n await sequelize.close();\n } else {\n await this.sequelize.sync(restOptions);\n }\n }\n\n /**\n * 关闭数据库连接\n */\n public async close() {\n this.removeAllListeners();\n return this.sequelize.close();\n }\n\n /**\n * 添加 hook\n * \n * @param hookType \n * @param fn \n */\n public addHook(hookType: HookType | string, fn: Function) {\n const hooks = this.hooks[hookType] || [];\n hooks.push(fn);\n this.hooks[hookType] = hooks;\n }\n\n /**\n * 运行 hook\n *\n * @param hookType \n * @param args \n */\n public async runHooks(hookType: HookType | string, ...args) {\n const hooks = this.hooks[hookType] || [];\n for (const hook of hooks) {\n if (typeof hook === 'function') {\n await hook(...args);\n }\n }\n }\n\n public getFieldByPath(fieldPath: string) {\n const [tableName, fieldName] = fieldPath.split('.');\n return this.getTable(tableName).getField(fieldName);\n }\n}\n"]}
package/lib/model.d.ts CHANGED
@@ -32,7 +32,7 @@ export declare abstract class Model extends SequelizeModel {
32
32
  [key: string]: any;
33
33
  static database: Database;
34
34
  get database(): Database;
35
- static withCountAttribute(options?: string | WithCountAttributeOptions): (string | ProjectionAlias);
35
+ static withCountAttribute(options?: string | WithCountAttributeOptions): string | ProjectionAlias;
36
36
  static selectQuery(options?: {}): string;
37
37
  static parseApiJson(options: ApiJsonOptions): any;
38
38
  getValuesByFieldNames(scope?: any[]): {};
@@ -1 +1 @@
1
- {"version":3,"sources":["model.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,IAAI,cAAc,EAAiB,eAAe,EAAS,WAAW,EAC5E,MAAM,WAAW,CAAC;AACnB,OAAO,QAAQ,MAAM,YAAY,CAAC;AAUlC,MAAM,WAAW,cAAc;IAoB7B,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG;QAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;KACpB,GAAG;QACF,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;KACpB,CAAC;IAwCF,MAAM,CAAC,EAAE,GAAG,CAAC;IASb,IAAI,CAAC,EAAE,GAAG,CAAC;IAKX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,OAAO,CAAC,EAAE,GAAG,CAAC;IAEd,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,yBAAyB;IAKxC,WAAW,EAAE,MAAM,CAAC;IAiBpB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,KAAK,CAAC,EAAE,GAAG,CAAC;IAKZ,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,eAAO,MAAM,cAAc,IAAI,CAAC;AAChC,eAAO,MAAM,aAAa,MAAM,CAAC;AACjC,eAAO,MAAM,SAAS,MAAM,CAAC;AAE7B,MAAM,WAAW,wBAAyB,SAAQ,WAAW;IAC3D,OAAO,CAAC,EAAE,GAAG,CAAC;CACf;AAQD,8BAAsB,KAAM,SAAQ,cAAc;IAKhD,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;IAOnB,OAAc,QAAQ,EAAE,QAAQ,CAAC;IAKjC,IAAI,QAAQ,IAAI,QAAQ,CAGvB;IASD,MAAM,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,yBAAyB,GAAG,CAAC,MAAM,GAAG,eAAe,CAAC;IA4DnG,MAAM,CAAC,WAAW,CAAC,OAAO,KAAK,GAAG,MAAM;IASxC,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,cAAc;IAmB3C,qBAAqB,CAAC,KAAK,QAAK;IAqB1B,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,GAAE,wBAA6B;IAoDtF,yBAAyB,CAAC,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,GAAE,wBAA6B;IAiKpG,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,GAAE,wBAA6B;IAkBhF,kBAAkB,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,GAAE,wBAA6B;CAuB3E;AAKD,oBAAY,SAAS,CAAC,CAAC,SAAS,KAAK,IAAI,OAAO,KAAK,GAAG;IAAE,QAAO,CAAC,CAAA;CAAE,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,CAAC;AAE9F,eAAe,KAAK,CAAC","file":"model.d.ts","sourcesContent":["import {\n Model as SequelizeModel, Op, Sequelize, ProjectionAlias, Utils, SaveOptions\n} from 'sequelize';\nimport Database from './database';\nimport {\n getDataTypeKey,\n HASONE,\n HASMANY,\n BELONGSTO,\n BELONGSTOMANY,\n} from './fields';\nimport { toInclude } from './utils';\n\nexport interface ApiJsonOptions {\n\n /**\n * 字段\n * \n * 数组式:\n * ['col', 'association.col1', 'association_count'],\n * \n * 白名单:\n * {\n * only: ['col1'],\n * appends: ['association_count'],\n * }\n * \n * 黑名单:\n * {\n * except: ['col1'],\n * appends: ['association_count'],\n * }\n */\n fields?: string[] | {\n only?: string[];\n appends?: string[];\n } | {\n except?: string[];\n appends?: string[];\n };\n\n /**\n * 过滤\n * \n * 常规用法:\n * {\n * col1: {\n * $eq: 'val1'\n * },\n * }\n * \n * scope 的用法(如果 scope 与 col 同名,只会执行 scope):\n * {\n * scope1: value\n * }\n * \n * json 数据 & 关系数据,可以用点号:\n * {\n * 'association.col1': {\n * $eq: 'val1'\n * },\n * }\n *\n * meta 为 json 字段时\n * {\n * 'meta.key': {\n * $eq: 'val1'\n * },\n * }\n * \n * json 数据 & 关系数据的查询也可以不用点号:\n * {\n * association: {\n * col1: {\n * $eq: 'val1'\n * },\n * },\n * }\n */\n filter?: any;\n\n /**\n * 排序\n * \n * TODO\n * \n * ['col1', '-col2', 'association.col1', '-association.col2']\n */\n sort?: any;\n\n /**\n * 页码\n */\n page?: number;\n perPage?: number;\n\n context?: any;\n\n [key: string]: any;\n}\n\nexport interface WithCountAttributeOptions {\n\n /**\n * 关系名\n */\n association: string;\n\n /**\n * SourceModel 别名\n * \n * 在 include 里使用时,需要指定,一般与 include 的 association 同名\n * \n * include: {\n * association: 'user', // Post.belongsTo(User)\n * attributes: [\n * User.withCountAttribute({\n * association: 'posts',\n * sourceAlias: 'user', // 内嵌时,需要指定 source 别名\n * })\n * ]\n * }\n */\n sourceAlias?: string;\n\n where?: any;\n\n /**\n * 别名,默认为 association_count\n */\n alias?: string;\n\n [key: string]: any;\n}\n\nexport const DEFAULT_OFFSET = 0;\nexport const DEFAULT_LIMIT = 100;\nexport const MAX_LIMIT = 500;\n\nexport interface UpdateAssociationOptions extends SaveOptions {\n context?: any;\n}\n\n/**\n * Model 相关\n * \n * TODO: 自定义 model 时的提示问题\n */\n// @ts-ignore\nexport abstract class Model extends SequelizeModel {\n\n /**\n * 防止 ts 报错提示\n */\n [key: string]: any;\n\n /**\n * 当前 Model 的 database\n * \n * 与 Model.sequelize 对应,database 也用了 public static readonly\n */\n public static database: Database;\n\n /**\n * 供 model 实例访问的 database\n */\n get database(): Database {\n // @ts-ignore\n return this.constructor.database;\n }\n\n /**\n * sub query 关联数据的数量\n * \n * TODO: 关联字段暂不支持主键以外的字段\n * \n * @param options \n */\n static withCountAttribute(options?: string | WithCountAttributeOptions): (string | ProjectionAlias) {\n if (typeof options === 'string') {\n options = { association: options };\n }\n\n const { sourceAlias, association, where = {}, alias, ...restOptions } = options;\n const associator = this.associations[association];\n const table = this.database.getTable(this.name);\n const field = table.getField(association);\n const { targetKey, otherKey, foreignKey, sourceKey } = field.options as any;\n\n if (associator.associationType === 'HasMany') {\n where[foreignKey as string] = {\n [Op.eq]: Sequelize.col(`${sourceAlias || this.name}.${sourceKey}`),\n };\n } else if (associator.associationType === 'BelongsToMany') {\n where[targetKey] = {\n // @ts-ignore\n [Op.in]: Sequelize.literal(`(${associator.through.model.selectQuery({\n attributes: [otherKey],\n where: {\n [foreignKey]: {\n [Op.eq]: Sequelize.col(`${sourceAlias || this.name}.${sourceKey}`),\n },\n // @ts-ignore\n ...(associator.through.scope || {}),\n },\n })})`),\n };\n }\n\n let countLiteral = 'count(*)';\n\n if (this.database.sequelize.getDialect() === 'postgres') {\n countLiteral = 'cast(count(*) as integer)';\n }\n\n const attribute = [\n Sequelize.literal(\n // @ts-ignore\n `(${associator.target.selectQuery({\n ...restOptions,\n attributes: [[Sequelize.literal(countLiteral), 'count']],\n where: {\n // @ts-ignore\n ...where, ...(associator.scope || {}),\n },\n })})`\n ),\n alias || Utils.underscoredIf(`${association}Count`, this.options.underscored),\n ].filter(Boolean);\n\n return attribute as unknown as ProjectionAlias;\n }\n\n /**\n * 当前 Model 的 SQL\n * \n * @param options \n */\n static selectQuery(options = {}): string {\n // @ts-ignore\n return this.queryGenerator.selectQuery(\n this.getTableName(),\n options,\n this,\n ).replace(/;$/, '');\n }\n\n static parseApiJson(options: ApiJsonOptions) {\n const { fields, filter, sort, context, page, perPage } = options;\n const data = toInclude({ fields, filter, sort }, {\n model: this,\n associations: this.associations,\n dialect: this.sequelize.getDialect(),\n ctx: context,\n database: this.database,\n });\n if (page || perPage) {\n data.limit = perPage === -1 ? MAX_LIMIT : Math.min(perPage || DEFAULT_LIMIT, MAX_LIMIT);\n data.offset = data.limit * (page > 0 ? page - 1 : DEFAULT_OFFSET);\n }\n if (data.attributes && data.attributes.length === 0) {\n delete data.attributes;\n }\n return data;\n }\n\n getValuesByFieldNames(scope = []) {\n const table = this.database.getTable(this.constructor.name);\n const Model = table.getModel();\n const associations = table.getAssociations();\n const where = {};\n scope.forEach(col => {\n const association = associations.get(col);\n const dataKey = association && association instanceof BELONGSTO\n ? association.options.foreignKey\n : col;\n if (!Model.rawAttributes[dataKey]) {\n return;\n }\n const value = this.getDataValue(dataKey);\n if (typeof value !== 'undefined') {\n where[dataKey] = value;\n }\n });\n return where;\n }\n\n async updateSingleAssociation(key: string, data: any, options: UpdateAssociationOptions = {}) {\n const {\n fields,\n transaction = await this.sequelize.transaction(),\n ...opts\n } = options;\n Object.assign(opts, { transaction });\n\n const table = this.database.getTable(this.constructor.name);\n const association = table.getAssociations().get(key);\n const accessors = association.getAccessors();\n\n if (data == null) {\n await this[accessors.set](null, opts);\n return;\n }\n\n if (typeof data === 'number' || typeof data === 'string' || data instanceof SequelizeModel) {\n await this[accessors.set](data, opts);\n } else if (typeof data === 'object') {\n const Target = association.getTargetModel();\n const targetAttribute = association instanceof BELONGSTO\n ? association.options.targetKey\n : association.options.sourceKey;\n if (data[targetAttribute]) {\n if (Object.keys(data).length > 0) {\n const target = await Target.findOne({\n where: {\n [targetAttribute]: data[targetAttribute],\n },\n transaction\n });\n if (target) {\n await this[accessors.set](data[targetAttribute], opts);\n await target.update(data, opts);\n // @ts-ignore\n await target.updateAssociations(data, opts);\n } else {\n const t = await this[accessors.create](data, opts);\n await t.updateAssociations(data, opts);\n }\n }\n } else {\n const t = await this[accessors.create](data, opts);\n await t.updateAssociations(data, opts);\n }\n }\n if (!options.transaction) {\n await transaction.commit();\n }\n }\n\n async updateMultipleAssociation(associationName: string, data: any, options: UpdateAssociationOptions = {}) {\n const items = Array.isArray(data) ? data : data == null ? [] : [data];\n\n const {\n fields,\n transaction = await this.sequelize.transaction(),\n ...opts\n } = options;\n Object.assign(opts, { transaction });\n\n const table = this.database.getTable(this.constructor.name);\n const association = table.getAssociations().get(associationName);\n const accessors = association.getAccessors();\n\n if (!items.length) {\n await this[accessors.set](null, opts);\n return;\n }\n\n const Target = association.getTargetModel();\n // 当前表关联 target 表的外键(大部分情况与 target 表主键相同,但可以设置为不同的,要考虑)\n const { targetKey = Target.primaryKeyAttribute } = association.options;\n // target 表的主键\n const targetPk = Target.primaryKeyAttribute;\n const targetKeyIsPk = targetKey === targetPk;\n // 准备设置的关联主键\n const toSetPks = new Set();\n const toSetUks = new Set();\n // 筛选后准备设置的关联主键\n const toSetItems = new Set();\n // 准备添加的关联对象\n const toUpsertObjects = [];\n\n // 遍历所有值成员准备数据\n items.forEach(item => {\n if (item instanceof SequelizeModel) {\n if (targetKeyIsPk) {\n toSetPks.add(item.getDataValue(targetPk));\n } else {\n toSetUks.add(item.getDataValue(targetKey));\n }\n return;\n }\n if (typeof item === 'number' || typeof item === 'string') {\n let targetKeyType = getDataTypeKey(Target.rawAttributes[targetKey].type).toLocaleLowerCase();\n if (targetKeyType === 'integer') {\n targetKeyType = 'number';\n }\n // 如果传值类型与之前在 Model 上定义的 targetKey 不同,则报错。\n // 不应兼容定义的 targetKey 不是 primaryKey 却传了 primaryKey 的值的情况。\n if (typeof item !== targetKeyType) {\n throw new Error(`target key type [${typeof item}] does not match to [${targetKeyType}]`);\n }\n if (targetKeyIsPk) {\n toSetPks.add(item);\n } else {\n toSetUks.add(item);\n }\n return;\n }\n if (typeof item === 'object') {\n toUpsertObjects.push(item);\n }\n });\n\n /* 仅传关联键处理开始 */\n // 查找已存在的数据\n const byPkExistItems = toSetPks.size ? await Target.findAll({\n ...opts,\n // @ts-ignore\n where: {\n [targetPk]: {\n [Op.in]: Array.from(toSetPks)\n }\n },\n attributes: [targetPk]\n }) : [];\n byPkExistItems.forEach(item => {\n toSetItems.add(item);\n });\n\n const byUkExistItems = toSetUks.size ? await Target.findAll({\n ...opts,\n // @ts-ignore\n where: {\n [targetKey]: {\n [Op.in]: Array.from(toSetUks)\n }\n },\n attributes: [targetPk, targetKey]\n }) : [];\n byUkExistItems.forEach(item => {\n toSetItems.add(item);\n });\n /* 仅传关联键处理结束 */\n\n const belongsToManyList = [];\n /* 值为对象处理开始 */\n for (const item of toUpsertObjects) {\n let target;\n if (typeof item[targetKey] === 'undefined') {\n target = await this[accessors.create](item, opts);\n } else {\n target = await Target.findOne({\n ...opts,\n where: { [targetKey]: item[targetKey] },\n });\n if (!target) {\n target = await this[accessors.create](item, opts);\n } else {\n await target.update(item, opts);\n }\n }\n // TODO(optimize): 此处添加的对象其实已经创建了关联,\n // 但考虑到单条 create 的 hook 要求带上关联键,且后面的 set,\n // 所以仍然交给 set 再调用关联一次。\n toSetItems.add(target);\n\n if (association instanceof BELONGSTOMANY) {\n belongsToManyList.push({\n item,\n target\n });\n }\n\n await target.updateAssociations(item, opts);\n }\n /* 值为对象处理结束 */\n\n // 添加所有计算后的关联\n await this[accessors.set](Array.from(toSetItems), opts);\n\n // 后处理 belongsToMany 的更新内容\n if (belongsToManyList.length) {\n const ThroughModel = (association as BELONGSTOMANY).getThroughModel();\n const throughName = (association as BELONGSTOMANY).getThroughName();\n\n\n for (const { item, target } of belongsToManyList) {\n const throughValues = item[throughName];\n if (throughValues && typeof throughValues === 'object') {\n const { foreignKey, sourceKey, otherKey } = association.options;\n const through = await ThroughModel.findOne({\n where: {\n [foreignKey]: this.get(sourceKey),\n [otherKey]: target.get(targetKey),\n },\n transaction\n });\n await through.update(throughValues, opts);\n // TODO:有 BUG,未知\n // await through.updateAssociations(throughValues, opts);\n }\n }\n }\n\n if (!options.transaction) {\n await transaction.commit();\n }\n }\n\n async updateAssociation(key: string, data: any, options: UpdateAssociationOptions = {}) {\n const table = this.database.getTable(this.constructor.name);\n const association = table.getAssociations().get(key);\n switch (true) {\n case association instanceof BELONGSTO:\n case association instanceof HASONE:\n return this.updateSingleAssociation(key, data, options);\n case association instanceof HASMANY:\n case association instanceof BELONGSTOMANY:\n return this.updateMultipleAssociation(key, data, options);\n }\n }\n\n /**\n * 关联数据的更新\n * \n * @param data\n */\n async updateAssociations(data: any, options: UpdateAssociationOptions = {}) {\n const { transaction = await this.sequelize.transaction() } = options;\n // @ts-ignore 判断 Model.associations 更准确\n for (const key of Object.keys(this.constructor.associations)) {\n // 如果 key 不存在才跳过\n if (!Object.keys(data).includes(key)) {\n continue;\n }\n await this.updateAssociation(key, data[key], {\n ...options,\n transaction\n });\n }\n\n await this.database.emitAsync('afterUpdateAssociations', this, {\n ...options,\n transaction,\n });\n\n if (!options.transaction) {\n await transaction.commit();\n }\n }\n}\n\n/**\n * ModelCtor 需要为当前 Model 的\n */\nexport type ModelCtor<M extends Model> = typeof Model & { new(): M } & { [key: string]: any };\n\nexport default Model;\n"]}
1
+ {"version":3,"sources":["model.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,IAAI,cAAc,EAGvB,eAAe,EAEf,WAAW,EACZ,MAAM,WAAW,CAAC;AACnB,OAAO,QAAQ,MAAM,YAAY,CAAC;AAUlC,MAAM,WAAW,cAAc;IAmB7B,MAAM,CAAC,EACH,MAAM,EAAE,GACR;QACE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;KACpB,GACD;QACE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;KACpB,CAAC;IAwCN,MAAM,CAAC,EAAE,GAAG,CAAC;IASb,IAAI,CAAC,EAAE,GAAG,CAAC;IAKX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,OAAO,CAAC,EAAE,GAAG,CAAC;IAEd,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,yBAAyB;IAIxC,WAAW,EAAE,MAAM,CAAC;IAiBpB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,KAAK,CAAC,EAAE,GAAG,CAAC;IAKZ,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,eAAO,MAAM,cAAc,IAAI,CAAC;AAChC,eAAO,MAAM,aAAa,MAAM,CAAC;AACjC,eAAO,MAAM,SAAS,MAAM,CAAC;AAE7B,MAAM,WAAW,wBAAyB,SAAQ,WAAW;IAC3D,OAAO,CAAC,EAAE,GAAG,CAAC;CACf;AAQD,8BAAsB,KAAM,SAAQ,cAAc;IAIhD,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;IAOnB,OAAc,QAAQ,EAAE,QAAQ,CAAC;IAKjC,IAAI,QAAQ,IAAI,QAAQ,CAGvB;IASD,MAAM,CAAC,kBAAkB,CACvB,OAAO,CAAC,EAAE,MAAM,GAAG,yBAAyB,GAC3C,MAAM,GAAG,eAAe;IAuE3B,MAAM,CAAC,WAAW,CAAC,OAAO,KAAK,GAAG,MAAM;IAOxC,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,cAAc;IAyB3C,qBAAqB,CAAC,KAAK,QAAK;IAsB1B,uBAAuB,CAC3B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,GAAG,EACT,OAAO,GAAE,wBAA6B;IA0DlC,yBAAyB,CAC7B,eAAe,EAAE,MAAM,EACvB,IAAI,EAAE,GAAG,EACT,OAAO,GAAE,wBAA6B;IAyKlC,iBAAiB,CACrB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,GAAG,EACT,OAAO,GAAE,wBAA6B;IAmBlC,kBAAkB,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,GAAE,wBAA6B;CAuB3E;AAKD,oBAAY,SAAS,CAAC,CAAC,SAAS,KAAK,IAAI,OAAO,KAAK,GAAG;IAAE,QAAQ,CAAC,CAAA;CAAE,GAAG;IACtE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB,CAAC;AAEF,eAAe,KAAK,CAAC","file":"model.d.ts","sourcesContent":["import {\n Model as SequelizeModel,\n Op,\n Sequelize,\n ProjectionAlias,\n Utils,\n SaveOptions,\n} from 'sequelize';\nimport Database from './database';\nimport {\n getDataTypeKey,\n HASONE,\n HASMANY,\n BELONGSTO,\n BELONGSTOMANY,\n} from './fields';\nimport { toInclude } from './utils';\n\nexport interface ApiJsonOptions {\n /**\n * 字段\n *\n * 数组式:\n * ['col', 'association.col1', 'association_count'],\n *\n * 白名单:\n * {\n * only: ['col1'],\n * appends: ['association_count'],\n * }\n *\n * 黑名单:\n * {\n * except: ['col1'],\n * appends: ['association_count'],\n * }\n */\n fields?:\n | string[]\n | {\n only?: string[];\n appends?: string[];\n }\n | {\n except?: string[];\n appends?: string[];\n };\n\n /**\n * 过滤\n *\n * 常规用法:\n * {\n * col1: {\n * $eq: 'val1'\n * },\n * }\n *\n * scope 的用法(如果 scope 与 col 同名,只会执行 scope):\n * {\n * scope1: value\n * }\n *\n * json 数据 & 关系数据,可以用点号:\n * {\n * 'association.col1': {\n * $eq: 'val1'\n * },\n * }\n *\n * meta 为 json 字段时\n * {\n * 'meta.key': {\n * $eq: 'val1'\n * },\n * }\n *\n * json 数据 & 关系数据的查询也可以不用点号:\n * {\n * association: {\n * col1: {\n * $eq: 'val1'\n * },\n * },\n * }\n */\n filter?: any;\n\n /**\n * 排序\n *\n * TODO\n *\n * ['col1', '-col2', 'association.col1', '-association.col2']\n */\n sort?: any;\n\n /**\n * 页码\n */\n page?: number;\n perPage?: number;\n\n context?: any;\n\n [key: string]: any;\n}\n\nexport interface WithCountAttributeOptions {\n /**\n * 关系名\n */\n association: string;\n\n /**\n * SourceModel 别名\n *\n * 在 include 里使用时,需要指定,一般与 include 的 association 同名\n *\n * include: {\n * association: 'user', // Post.belongsTo(User)\n * attributes: [\n * User.withCountAttribute({\n * association: 'posts',\n * sourceAlias: 'user', // 内嵌时,需要指定 source 别名\n * })\n * ]\n * }\n */\n sourceAlias?: string;\n\n where?: any;\n\n /**\n * 别名,默认为 association_count\n */\n alias?: string;\n\n [key: string]: any;\n}\n\nexport const DEFAULT_OFFSET = 0;\nexport const DEFAULT_LIMIT = 100;\nexport const MAX_LIMIT = 500;\n\nexport interface UpdateAssociationOptions extends SaveOptions {\n context?: any;\n}\n\n/**\n * Model 相关\n *\n * TODO: 自定义 model 时的提示问题\n */\n// @ts-ignore\nexport abstract class Model extends SequelizeModel {\n /**\n * 防止 ts 报错提示\n */\n [key: string]: any;\n\n /**\n * 当前 Model 的 database\n *\n * 与 Model.sequelize 对应,database 也用了 public static readonly\n */\n public static database: Database;\n\n /**\n * 供 model 实例访问的 database\n */\n get database(): Database {\n // @ts-ignore\n return this.constructor.database;\n }\n\n /**\n * sub query 关联数据的数量\n *\n * TODO: 关联字段暂不支持主键以外的字段\n *\n * @param options\n */\n static withCountAttribute(\n options?: string | WithCountAttributeOptions,\n ): string | ProjectionAlias {\n if (typeof options === 'string') {\n options = { association: options };\n }\n\n const {\n sourceAlias,\n association,\n where = {},\n alias,\n ...restOptions\n } = options;\n const associator = this.associations[association];\n const table = this.database.getTable(this.name);\n const field = table.getField(association);\n const { targetKey, otherKey, foreignKey, sourceKey } = field.options as any;\n\n if (associator.associationType === 'HasMany') {\n where[foreignKey as string] = {\n [Op.eq]: Sequelize.col(`${sourceAlias || this.name}.${sourceKey}`),\n };\n } else if (associator.associationType === 'BelongsToMany') {\n where[targetKey] = {\n [Op.in]: Sequelize.literal(\n `(${(associator as any).through.model.selectQuery({\n attributes: [otherKey],\n where: {\n [foreignKey]: {\n [Op.eq]: Sequelize.col(\n `${sourceAlias || this.name}.${sourceKey}`,\n ),\n },\n // @ts-ignore\n ...(associator.through.scope || {}),\n },\n })})`,\n ),\n };\n }\n\n let countLiteral = 'count(*)';\n\n if (this.database.sequelize.getDialect() === 'postgres') {\n countLiteral = 'cast(count(*) as integer)';\n }\n\n const attribute = [\n Sequelize.literal(\n // @ts-ignore\n `(${associator.target.selectQuery({\n ...restOptions,\n attributes: [[Sequelize.literal(countLiteral), 'count']],\n where: {\n // @ts-ignore\n ...where,\n ...((associator as any).scope || {}),\n },\n })})`,\n ),\n alias ||\n Utils.underscoredIf(`${association}Count`, this.options.underscored),\n ].filter(Boolean);\n\n return (attribute as unknown) as ProjectionAlias;\n }\n\n /**\n * 当前 Model 的 SQL\n *\n * @param options\n */\n static selectQuery(options = {}): string {\n // @ts-ignore\n return this.queryGenerator\n .selectQuery(this.getTableName(), options, this)\n .replace(/;$/, '');\n }\n\n static parseApiJson(options: ApiJsonOptions) {\n const { fields, filter, sort, context, page, perPage } = options;\n const data = toInclude(\n { fields, filter, sort },\n {\n model: this,\n associations: this.associations,\n dialect: this.sequelize.getDialect(),\n ctx: context,\n database: this.database,\n },\n );\n if (page || perPage) {\n data.limit =\n perPage === -1\n ? MAX_LIMIT\n : Math.min(perPage || DEFAULT_LIMIT, MAX_LIMIT);\n data.offset = data.limit * (page > 0 ? page - 1 : DEFAULT_OFFSET);\n }\n if (data.attributes && data.attributes.length === 0) {\n delete data.attributes;\n }\n return data;\n }\n\n getValuesByFieldNames(scope = []) {\n const table = this.database.getTable(this.constructor.name);\n const Model = table.getModel();\n const associations = table.getAssociations();\n const where = {};\n scope.forEach((col) => {\n const association = associations.get(col);\n const dataKey =\n association && association instanceof BELONGSTO\n ? association.options.foreignKey\n : col;\n if (!Model.rawAttributes[dataKey]) {\n return;\n }\n const value = this.getDataValue(dataKey);\n if (typeof value !== 'undefined') {\n where[dataKey] = value;\n }\n });\n return where;\n }\n\n async updateSingleAssociation(\n key: string,\n data: any,\n options: UpdateAssociationOptions = {},\n ) {\n const {\n fields,\n transaction = await this.sequelize.transaction(),\n ...opts\n } = options;\n Object.assign(opts, { transaction });\n\n const table = this.database.getTable(this.constructor.name);\n const association = table.getAssociations().get(key);\n const accessors = association.getAccessors();\n\n if (data == null) {\n await this[accessors.set](null, opts);\n return;\n }\n\n if (\n typeof data === 'number' ||\n typeof data === 'string' ||\n data instanceof SequelizeModel\n ) {\n await this[accessors.set](data, opts);\n } else if (typeof data === 'object') {\n const Target = association.getTargetModel();\n const targetAttribute =\n association instanceof BELONGSTO\n ? association.options.targetKey\n : association.options.sourceKey;\n if (data[targetAttribute]) {\n if (Object.keys(data).length > 0) {\n const target = await Target.findOne({\n where: {\n [targetAttribute]: data[targetAttribute],\n },\n transaction,\n });\n if (target) {\n await this[accessors.set](data[targetAttribute], opts);\n await target.update(data, opts);\n // @ts-ignore\n await target.updateAssociations(data, opts);\n } else {\n const t = await this[accessors.create](data, opts);\n await t.updateAssociations(data, opts);\n }\n }\n } else {\n const t = await this[accessors.create](data, opts);\n await t.updateAssociations(data, opts);\n }\n }\n if (!options.transaction) {\n await transaction.commit();\n }\n }\n\n async updateMultipleAssociation(\n associationName: string,\n data: any,\n options: UpdateAssociationOptions = {},\n ) {\n const items = Array.isArray(data) ? data : data == null ? [] : [data];\n\n const {\n fields,\n transaction = await this.sequelize.transaction(),\n ...opts\n } = options;\n Object.assign(opts, { transaction });\n\n const table = this.database.getTable(this.constructor.name);\n const association = table.getAssociations().get(associationName);\n const accessors = association.getAccessors();\n\n if (!items.length) {\n await this[accessors.set](null, opts);\n return;\n }\n\n const Target = association.getTargetModel();\n // 当前表关联 target 表的外键(大部分情况与 target 表主键相同,但可以设置为不同的,要考虑)\n const { targetKey = Target.primaryKeyAttribute } = association.options;\n // target 表的主键\n const targetPk = Target.primaryKeyAttribute;\n const targetKeyIsPk = targetKey === targetPk;\n // 准备设置的关联主键\n const toSetPks = new Set();\n const toSetUks = new Set();\n // 筛选后准备设置的关联主键\n const toSetItems = new Set();\n // 准备添加的关联对象\n const toUpsertObjects = [];\n\n // 遍历所有值成员准备数据\n items.forEach((item) => {\n if (item instanceof SequelizeModel) {\n if (targetKeyIsPk) {\n toSetPks.add(item.getDataValue(targetPk));\n } else {\n toSetUks.add(item.getDataValue(targetKey));\n }\n return;\n }\n if (typeof item === 'number' || typeof item === 'string') {\n let targetKeyType = getDataTypeKey(\n Target.rawAttributes[targetKey].type,\n ).toLocaleLowerCase();\n if (targetKeyType === 'integer') {\n targetKeyType = 'number';\n }\n // 如果传值类型与之前在 Model 上定义的 targetKey 不同,则报错。\n // 不应兼容定义的 targetKey 不是 primaryKey 却传了 primaryKey 的值的情况。\n if (typeof item !== targetKeyType) {\n throw new Error(\n `target key type [${typeof item}] does not match to [${targetKeyType}]`,\n );\n }\n if (targetKeyIsPk) {\n toSetPks.add(item);\n } else {\n toSetUks.add(item);\n }\n return;\n }\n if (typeof item === 'object') {\n toUpsertObjects.push(item);\n }\n });\n\n /* 仅传关联键处理开始 */\n // 查找已存在的数据\n const byPkExistItems = toSetPks.size\n ? await Target.findAll({\n ...opts,\n // @ts-ignore\n where: {\n [targetPk]: {\n [Op.in]: Array.from(toSetPks),\n },\n },\n attributes: [targetPk],\n })\n : [];\n byPkExistItems.forEach((item) => {\n toSetItems.add(item);\n });\n\n const byUkExistItems = toSetUks.size\n ? await Target.findAll({\n ...opts,\n // @ts-ignore\n where: {\n [targetKey]: {\n [Op.in]: Array.from(toSetUks),\n },\n },\n attributes: [targetPk, targetKey],\n })\n : [];\n byUkExistItems.forEach((item) => {\n toSetItems.add(item);\n });\n /* 仅传关联键处理结束 */\n\n const belongsToManyList = [];\n /* 值为对象处理开始 */\n for (const item of toUpsertObjects) {\n let target;\n if (typeof item[targetKey] === 'undefined') {\n target = await this[accessors.create](item, opts);\n } else {\n target = await Target.findOne({\n ...opts,\n where: { [targetKey]: item[targetKey] },\n });\n if (!target) {\n target = await this[accessors.create](item, opts);\n } else {\n await target.update(item, opts);\n }\n }\n // TODO(optimize): 此处添加的对象其实已经创建了关联,\n // 但考虑到单条 create 的 hook 要求带上关联键,且后面的 set,\n // 所以仍然交给 set 再调用关联一次。\n toSetItems.add(target);\n\n if (association instanceof BELONGSTOMANY) {\n belongsToManyList.push({\n item,\n target,\n });\n }\n\n await target.updateAssociations(item, opts);\n }\n /* 值为对象处理结束 */\n\n // 添加所有计算后的关联\n await this[accessors.set](Array.from(toSetItems), opts);\n\n // 后处理 belongsToMany 的更新内容\n if (belongsToManyList.length) {\n const ThroughModel = (association as BELONGSTOMANY).getThroughModel();\n const throughName = (association as BELONGSTOMANY).getThroughName();\n\n for (const { item, target } of belongsToManyList) {\n const throughValues = item[throughName];\n if (throughValues && typeof throughValues === 'object') {\n const { foreignKey, sourceKey, otherKey } = association.options;\n const through = await ThroughModel.findOne({\n where: {\n [foreignKey]: this.get(sourceKey),\n [otherKey]: target.get(targetKey),\n },\n transaction,\n });\n await through.update(throughValues, opts);\n // TODO:有 BUG,未知\n // await through.updateAssociations(throughValues, opts);\n }\n }\n }\n\n if (!options.transaction) {\n await transaction.commit();\n }\n }\n\n async updateAssociation(\n key: string,\n data: any,\n options: UpdateAssociationOptions = {},\n ) {\n const table = this.database.getTable(this.constructor.name);\n const association = table.getAssociations().get(key);\n switch (true) {\n case association instanceof BELONGSTO:\n case association instanceof HASONE:\n return this.updateSingleAssociation(key, data, options);\n case association instanceof HASMANY:\n case association instanceof BELONGSTOMANY:\n return this.updateMultipleAssociation(key, data, options);\n }\n }\n\n /**\n * 关联数据的更新\n *\n * @param data\n */\n async updateAssociations(data: any, options: UpdateAssociationOptions = {}) {\n const { transaction = await this.sequelize.transaction() } = options;\n // @ts-ignore 判断 Model.associations 更准确\n for (const key of Object.keys(this.constructor.associations)) {\n // 如果 key 不存在才跳过\n if (!Object.keys(data).includes(key)) {\n continue;\n }\n await this.updateAssociation(key, data[key], {\n ...options,\n transaction,\n });\n }\n\n await this.database.emitAsync('afterUpdateAssociations', this, {\n ...options,\n transaction,\n });\n\n if (!options.transaction) {\n await transaction.commit();\n }\n }\n}\n\n/**\n * ModelCtor 需要为当前 Model 的\n */\nexport type ModelCtor<M extends Model> = typeof Model & { new (): M } & {\n [key: string]: any;\n};\n\nexport default Model;\n"]}
package/lib/model.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["model.ts"],"names":[],"mappings":"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","file":"model.js","sourcesContent":["import {\n Model as SequelizeModel, Op, Sequelize, ProjectionAlias, Utils, SaveOptions\n} from 'sequelize';\nimport Database from './database';\nimport {\n getDataTypeKey,\n HASONE,\n HASMANY,\n BELONGSTO,\n BELONGSTOMANY,\n} from './fields';\nimport { toInclude } from './utils';\n\nexport interface ApiJsonOptions {\n\n /**\n * 字段\n * \n * 数组式:\n * ['col', 'association.col1', 'association_count'],\n * \n * 白名单:\n * {\n * only: ['col1'],\n * appends: ['association_count'],\n * }\n * \n * 黑名单:\n * {\n * except: ['col1'],\n * appends: ['association_count'],\n * }\n */\n fields?: string[] | {\n only?: string[];\n appends?: string[];\n } | {\n except?: string[];\n appends?: string[];\n };\n\n /**\n * 过滤\n * \n * 常规用法:\n * {\n * col1: {\n * $eq: 'val1'\n * },\n * }\n * \n * scope 的用法(如果 scope 与 col 同名,只会执行 scope):\n * {\n * scope1: value\n * }\n * \n * json 数据 & 关系数据,可以用点号:\n * {\n * 'association.col1': {\n * $eq: 'val1'\n * },\n * }\n *\n * meta 为 json 字段时\n * {\n * 'meta.key': {\n * $eq: 'val1'\n * },\n * }\n * \n * json 数据 & 关系数据的查询也可以不用点号:\n * {\n * association: {\n * col1: {\n * $eq: 'val1'\n * },\n * },\n * }\n */\n filter?: any;\n\n /**\n * 排序\n * \n * TODO\n * \n * ['col1', '-col2', 'association.col1', '-association.col2']\n */\n sort?: any;\n\n /**\n * 页码\n */\n page?: number;\n perPage?: number;\n\n context?: any;\n\n [key: string]: any;\n}\n\nexport interface WithCountAttributeOptions {\n\n /**\n * 关系名\n */\n association: string;\n\n /**\n * SourceModel 别名\n * \n * 在 include 里使用时,需要指定,一般与 include 的 association 同名\n * \n * include: {\n * association: 'user', // Post.belongsTo(User)\n * attributes: [\n * User.withCountAttribute({\n * association: 'posts',\n * sourceAlias: 'user', // 内嵌时,需要指定 source 别名\n * })\n * ]\n * }\n */\n sourceAlias?: string;\n\n where?: any;\n\n /**\n * 别名,默认为 association_count\n */\n alias?: string;\n\n [key: string]: any;\n}\n\nexport const DEFAULT_OFFSET = 0;\nexport const DEFAULT_LIMIT = 100;\nexport const MAX_LIMIT = 500;\n\nexport interface UpdateAssociationOptions extends SaveOptions {\n context?: any;\n}\n\n/**\n * Model 相关\n * \n * TODO: 自定义 model 时的提示问题\n */\n// @ts-ignore\nexport abstract class Model extends SequelizeModel {\n\n /**\n * 防止 ts 报错提示\n */\n [key: string]: any;\n\n /**\n * 当前 Model 的 database\n * \n * 与 Model.sequelize 对应,database 也用了 public static readonly\n */\n public static database: Database;\n\n /**\n * 供 model 实例访问的 database\n */\n get database(): Database {\n // @ts-ignore\n return this.constructor.database;\n }\n\n /**\n * sub query 关联数据的数量\n * \n * TODO: 关联字段暂不支持主键以外的字段\n * \n * @param options \n */\n static withCountAttribute(options?: string | WithCountAttributeOptions): (string | ProjectionAlias) {\n if (typeof options === 'string') {\n options = { association: options };\n }\n\n const { sourceAlias, association, where = {}, alias, ...restOptions } = options;\n const associator = this.associations[association];\n const table = this.database.getTable(this.name);\n const field = table.getField(association);\n const { targetKey, otherKey, foreignKey, sourceKey } = field.options as any;\n\n if (associator.associationType === 'HasMany') {\n where[foreignKey as string] = {\n [Op.eq]: Sequelize.col(`${sourceAlias || this.name}.${sourceKey}`),\n };\n } else if (associator.associationType === 'BelongsToMany') {\n where[targetKey] = {\n // @ts-ignore\n [Op.in]: Sequelize.literal(`(${associator.through.model.selectQuery({\n attributes: [otherKey],\n where: {\n [foreignKey]: {\n [Op.eq]: Sequelize.col(`${sourceAlias || this.name}.${sourceKey}`),\n },\n // @ts-ignore\n ...(associator.through.scope || {}),\n },\n })})`),\n };\n }\n\n let countLiteral = 'count(*)';\n\n if (this.database.sequelize.getDialect() === 'postgres') {\n countLiteral = 'cast(count(*) as integer)';\n }\n\n const attribute = [\n Sequelize.literal(\n // @ts-ignore\n `(${associator.target.selectQuery({\n ...restOptions,\n attributes: [[Sequelize.literal(countLiteral), 'count']],\n where: {\n // @ts-ignore\n ...where, ...(associator.scope || {}),\n },\n })})`\n ),\n alias || Utils.underscoredIf(`${association}Count`, this.options.underscored),\n ].filter(Boolean);\n\n return attribute as unknown as ProjectionAlias;\n }\n\n /**\n * 当前 Model 的 SQL\n * \n * @param options \n */\n static selectQuery(options = {}): string {\n // @ts-ignore\n return this.queryGenerator.selectQuery(\n this.getTableName(),\n options,\n this,\n ).replace(/;$/, '');\n }\n\n static parseApiJson(options: ApiJsonOptions) {\n const { fields, filter, sort, context, page, perPage } = options;\n const data = toInclude({ fields, filter, sort }, {\n model: this,\n associations: this.associations,\n dialect: this.sequelize.getDialect(),\n ctx: context,\n database: this.database,\n });\n if (page || perPage) {\n data.limit = perPage === -1 ? MAX_LIMIT : Math.min(perPage || DEFAULT_LIMIT, MAX_LIMIT);\n data.offset = data.limit * (page > 0 ? page - 1 : DEFAULT_OFFSET);\n }\n if (data.attributes && data.attributes.length === 0) {\n delete data.attributes;\n }\n return data;\n }\n\n getValuesByFieldNames(scope = []) {\n const table = this.database.getTable(this.constructor.name);\n const Model = table.getModel();\n const associations = table.getAssociations();\n const where = {};\n scope.forEach(col => {\n const association = associations.get(col);\n const dataKey = association && association instanceof BELONGSTO\n ? association.options.foreignKey\n : col;\n if (!Model.rawAttributes[dataKey]) {\n return;\n }\n const value = this.getDataValue(dataKey);\n if (typeof value !== 'undefined') {\n where[dataKey] = value;\n }\n });\n return where;\n }\n\n async updateSingleAssociation(key: string, data: any, options: UpdateAssociationOptions = {}) {\n const {\n fields,\n transaction = await this.sequelize.transaction(),\n ...opts\n } = options;\n Object.assign(opts, { transaction });\n\n const table = this.database.getTable(this.constructor.name);\n const association = table.getAssociations().get(key);\n const accessors = association.getAccessors();\n\n if (data == null) {\n await this[accessors.set](null, opts);\n return;\n }\n\n if (typeof data === 'number' || typeof data === 'string' || data instanceof SequelizeModel) {\n await this[accessors.set](data, opts);\n } else if (typeof data === 'object') {\n const Target = association.getTargetModel();\n const targetAttribute = association instanceof BELONGSTO\n ? association.options.targetKey\n : association.options.sourceKey;\n if (data[targetAttribute]) {\n if (Object.keys(data).length > 0) {\n const target = await Target.findOne({\n where: {\n [targetAttribute]: data[targetAttribute],\n },\n transaction\n });\n if (target) {\n await this[accessors.set](data[targetAttribute], opts);\n await target.update(data, opts);\n // @ts-ignore\n await target.updateAssociations(data, opts);\n } else {\n const t = await this[accessors.create](data, opts);\n await t.updateAssociations(data, opts);\n }\n }\n } else {\n const t = await this[accessors.create](data, opts);\n await t.updateAssociations(data, opts);\n }\n }\n if (!options.transaction) {\n await transaction.commit();\n }\n }\n\n async updateMultipleAssociation(associationName: string, data: any, options: UpdateAssociationOptions = {}) {\n const items = Array.isArray(data) ? data : data == null ? [] : [data];\n\n const {\n fields,\n transaction = await this.sequelize.transaction(),\n ...opts\n } = options;\n Object.assign(opts, { transaction });\n\n const table = this.database.getTable(this.constructor.name);\n const association = table.getAssociations().get(associationName);\n const accessors = association.getAccessors();\n\n if (!items.length) {\n await this[accessors.set](null, opts);\n return;\n }\n\n const Target = association.getTargetModel();\n // 当前表关联 target 表的外键(大部分情况与 target 表主键相同,但可以设置为不同的,要考虑)\n const { targetKey = Target.primaryKeyAttribute } = association.options;\n // target 表的主键\n const targetPk = Target.primaryKeyAttribute;\n const targetKeyIsPk = targetKey === targetPk;\n // 准备设置的关联主键\n const toSetPks = new Set();\n const toSetUks = new Set();\n // 筛选后准备设置的关联主键\n const toSetItems = new Set();\n // 准备添加的关联对象\n const toUpsertObjects = [];\n\n // 遍历所有值成员准备数据\n items.forEach(item => {\n if (item instanceof SequelizeModel) {\n if (targetKeyIsPk) {\n toSetPks.add(item.getDataValue(targetPk));\n } else {\n toSetUks.add(item.getDataValue(targetKey));\n }\n return;\n }\n if (typeof item === 'number' || typeof item === 'string') {\n let targetKeyType = getDataTypeKey(Target.rawAttributes[targetKey].type).toLocaleLowerCase();\n if (targetKeyType === 'integer') {\n targetKeyType = 'number';\n }\n // 如果传值类型与之前在 Model 上定义的 targetKey 不同,则报错。\n // 不应兼容定义的 targetKey 不是 primaryKey 却传了 primaryKey 的值的情况。\n if (typeof item !== targetKeyType) {\n throw new Error(`target key type [${typeof item}] does not match to [${targetKeyType}]`);\n }\n if (targetKeyIsPk) {\n toSetPks.add(item);\n } else {\n toSetUks.add(item);\n }\n return;\n }\n if (typeof item === 'object') {\n toUpsertObjects.push(item);\n }\n });\n\n /* 仅传关联键处理开始 */\n // 查找已存在的数据\n const byPkExistItems = toSetPks.size ? await Target.findAll({\n ...opts,\n // @ts-ignore\n where: {\n [targetPk]: {\n [Op.in]: Array.from(toSetPks)\n }\n },\n attributes: [targetPk]\n }) : [];\n byPkExistItems.forEach(item => {\n toSetItems.add(item);\n });\n\n const byUkExistItems = toSetUks.size ? await Target.findAll({\n ...opts,\n // @ts-ignore\n where: {\n [targetKey]: {\n [Op.in]: Array.from(toSetUks)\n }\n },\n attributes: [targetPk, targetKey]\n }) : [];\n byUkExistItems.forEach(item => {\n toSetItems.add(item);\n });\n /* 仅传关联键处理结束 */\n\n const belongsToManyList = [];\n /* 值为对象处理开始 */\n for (const item of toUpsertObjects) {\n let target;\n if (typeof item[targetKey] === 'undefined') {\n target = await this[accessors.create](item, opts);\n } else {\n target = await Target.findOne({\n ...opts,\n where: { [targetKey]: item[targetKey] },\n });\n if (!target) {\n target = await this[accessors.create](item, opts);\n } else {\n await target.update(item, opts);\n }\n }\n // TODO(optimize): 此处添加的对象其实已经创建了关联,\n // 但考虑到单条 create 的 hook 要求带上关联键,且后面的 set,\n // 所以仍然交给 set 再调用关联一次。\n toSetItems.add(target);\n\n if (association instanceof BELONGSTOMANY) {\n belongsToManyList.push({\n item,\n target\n });\n }\n\n await target.updateAssociations(item, opts);\n }\n /* 值为对象处理结束 */\n\n // 添加所有计算后的关联\n await this[accessors.set](Array.from(toSetItems), opts);\n\n // 后处理 belongsToMany 的更新内容\n if (belongsToManyList.length) {\n const ThroughModel = (association as BELONGSTOMANY).getThroughModel();\n const throughName = (association as BELONGSTOMANY).getThroughName();\n\n\n for (const { item, target } of belongsToManyList) {\n const throughValues = item[throughName];\n if (throughValues && typeof throughValues === 'object') {\n const { foreignKey, sourceKey, otherKey } = association.options;\n const through = await ThroughModel.findOne({\n where: {\n [foreignKey]: this.get(sourceKey),\n [otherKey]: target.get(targetKey),\n },\n transaction\n });\n await through.update(throughValues, opts);\n // TODO:有 BUG,未知\n // await through.updateAssociations(throughValues, opts);\n }\n }\n }\n\n if (!options.transaction) {\n await transaction.commit();\n }\n }\n\n async updateAssociation(key: string, data: any, options: UpdateAssociationOptions = {}) {\n const table = this.database.getTable(this.constructor.name);\n const association = table.getAssociations().get(key);\n switch (true) {\n case association instanceof BELONGSTO:\n case association instanceof HASONE:\n return this.updateSingleAssociation(key, data, options);\n case association instanceof HASMANY:\n case association instanceof BELONGSTOMANY:\n return this.updateMultipleAssociation(key, data, options);\n }\n }\n\n /**\n * 关联数据的更新\n * \n * @param data\n */\n async updateAssociations(data: any, options: UpdateAssociationOptions = {}) {\n const { transaction = await this.sequelize.transaction() } = options;\n // @ts-ignore 判断 Model.associations 更准确\n for (const key of Object.keys(this.constructor.associations)) {\n // 如果 key 不存在才跳过\n if (!Object.keys(data).includes(key)) {\n continue;\n }\n await this.updateAssociation(key, data[key], {\n ...options,\n transaction\n });\n }\n\n await this.database.emitAsync('afterUpdateAssociations', this, {\n ...options,\n transaction,\n });\n\n if (!options.transaction) {\n await transaction.commit();\n }\n }\n}\n\n/**\n * ModelCtor 需要为当前 Model 的\n */\nexport type ModelCtor<M extends Model> = typeof Model & { new(): M } & { [key: string]: any };\n\nexport default Model;\n"]}
1
+ {"version":3,"sources":["model.ts"],"names":[],"mappings":"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","file":"model.js","sourcesContent":["import {\n Model as SequelizeModel,\n Op,\n Sequelize,\n ProjectionAlias,\n Utils,\n SaveOptions,\n} from 'sequelize';\nimport Database from './database';\nimport {\n getDataTypeKey,\n HASONE,\n HASMANY,\n BELONGSTO,\n BELONGSTOMANY,\n} from './fields';\nimport { toInclude } from './utils';\n\nexport interface ApiJsonOptions {\n /**\n * 字段\n *\n * 数组式:\n * ['col', 'association.col1', 'association_count'],\n *\n * 白名单:\n * {\n * only: ['col1'],\n * appends: ['association_count'],\n * }\n *\n * 黑名单:\n * {\n * except: ['col1'],\n * appends: ['association_count'],\n * }\n */\n fields?:\n | string[]\n | {\n only?: string[];\n appends?: string[];\n }\n | {\n except?: string[];\n appends?: string[];\n };\n\n /**\n * 过滤\n *\n * 常规用法:\n * {\n * col1: {\n * $eq: 'val1'\n * },\n * }\n *\n * scope 的用法(如果 scope 与 col 同名,只会执行 scope):\n * {\n * scope1: value\n * }\n *\n * json 数据 & 关系数据,可以用点号:\n * {\n * 'association.col1': {\n * $eq: 'val1'\n * },\n * }\n *\n * meta 为 json 字段时\n * {\n * 'meta.key': {\n * $eq: 'val1'\n * },\n * }\n *\n * json 数据 & 关系数据的查询也可以不用点号:\n * {\n * association: {\n * col1: {\n * $eq: 'val1'\n * },\n * },\n * }\n */\n filter?: any;\n\n /**\n * 排序\n *\n * TODO\n *\n * ['col1', '-col2', 'association.col1', '-association.col2']\n */\n sort?: any;\n\n /**\n * 页码\n */\n page?: number;\n perPage?: number;\n\n context?: any;\n\n [key: string]: any;\n}\n\nexport interface WithCountAttributeOptions {\n /**\n * 关系名\n */\n association: string;\n\n /**\n * SourceModel 别名\n *\n * 在 include 里使用时,需要指定,一般与 include 的 association 同名\n *\n * include: {\n * association: 'user', // Post.belongsTo(User)\n * attributes: [\n * User.withCountAttribute({\n * association: 'posts',\n * sourceAlias: 'user', // 内嵌时,需要指定 source 别名\n * })\n * ]\n * }\n */\n sourceAlias?: string;\n\n where?: any;\n\n /**\n * 别名,默认为 association_count\n */\n alias?: string;\n\n [key: string]: any;\n}\n\nexport const DEFAULT_OFFSET = 0;\nexport const DEFAULT_LIMIT = 100;\nexport const MAX_LIMIT = 500;\n\nexport interface UpdateAssociationOptions extends SaveOptions {\n context?: any;\n}\n\n/**\n * Model 相关\n *\n * TODO: 自定义 model 时的提示问题\n */\n// @ts-ignore\nexport abstract class Model extends SequelizeModel {\n /**\n * 防止 ts 报错提示\n */\n [key: string]: any;\n\n /**\n * 当前 Model 的 database\n *\n * 与 Model.sequelize 对应,database 也用了 public static readonly\n */\n public static database: Database;\n\n /**\n * 供 model 实例访问的 database\n */\n get database(): Database {\n // @ts-ignore\n return this.constructor.database;\n }\n\n /**\n * sub query 关联数据的数量\n *\n * TODO: 关联字段暂不支持主键以外的字段\n *\n * @param options\n */\n static withCountAttribute(\n options?: string | WithCountAttributeOptions,\n ): string | ProjectionAlias {\n if (typeof options === 'string') {\n options = { association: options };\n }\n\n const {\n sourceAlias,\n association,\n where = {},\n alias,\n ...restOptions\n } = options;\n const associator = this.associations[association];\n const table = this.database.getTable(this.name);\n const field = table.getField(association);\n const { targetKey, otherKey, foreignKey, sourceKey } = field.options as any;\n\n if (associator.associationType === 'HasMany') {\n where[foreignKey as string] = {\n [Op.eq]: Sequelize.col(`${sourceAlias || this.name}.${sourceKey}`),\n };\n } else if (associator.associationType === 'BelongsToMany') {\n where[targetKey] = {\n [Op.in]: Sequelize.literal(\n `(${(associator as any).through.model.selectQuery({\n attributes: [otherKey],\n where: {\n [foreignKey]: {\n [Op.eq]: Sequelize.col(\n `${sourceAlias || this.name}.${sourceKey}`,\n ),\n },\n // @ts-ignore\n ...(associator.through.scope || {}),\n },\n })})`,\n ),\n };\n }\n\n let countLiteral = 'count(*)';\n\n if (this.database.sequelize.getDialect() === 'postgres') {\n countLiteral = 'cast(count(*) as integer)';\n }\n\n const attribute = [\n Sequelize.literal(\n // @ts-ignore\n `(${associator.target.selectQuery({\n ...restOptions,\n attributes: [[Sequelize.literal(countLiteral), 'count']],\n where: {\n // @ts-ignore\n ...where,\n ...((associator as any).scope || {}),\n },\n })})`,\n ),\n alias ||\n Utils.underscoredIf(`${association}Count`, this.options.underscored),\n ].filter(Boolean);\n\n return (attribute as unknown) as ProjectionAlias;\n }\n\n /**\n * 当前 Model 的 SQL\n *\n * @param options\n */\n static selectQuery(options = {}): string {\n // @ts-ignore\n return this.queryGenerator\n .selectQuery(this.getTableName(), options, this)\n .replace(/;$/, '');\n }\n\n static parseApiJson(options: ApiJsonOptions) {\n const { fields, filter, sort, context, page, perPage } = options;\n const data = toInclude(\n { fields, filter, sort },\n {\n model: this,\n associations: this.associations,\n dialect: this.sequelize.getDialect(),\n ctx: context,\n database: this.database,\n },\n );\n if (page || perPage) {\n data.limit =\n perPage === -1\n ? MAX_LIMIT\n : Math.min(perPage || DEFAULT_LIMIT, MAX_LIMIT);\n data.offset = data.limit * (page > 0 ? page - 1 : DEFAULT_OFFSET);\n }\n if (data.attributes && data.attributes.length === 0) {\n delete data.attributes;\n }\n return data;\n }\n\n getValuesByFieldNames(scope = []) {\n const table = this.database.getTable(this.constructor.name);\n const Model = table.getModel();\n const associations = table.getAssociations();\n const where = {};\n scope.forEach((col) => {\n const association = associations.get(col);\n const dataKey =\n association && association instanceof BELONGSTO\n ? association.options.foreignKey\n : col;\n if (!Model.rawAttributes[dataKey]) {\n return;\n }\n const value = this.getDataValue(dataKey);\n if (typeof value !== 'undefined') {\n where[dataKey] = value;\n }\n });\n return where;\n }\n\n async updateSingleAssociation(\n key: string,\n data: any,\n options: UpdateAssociationOptions = {},\n ) {\n const {\n fields,\n transaction = await this.sequelize.transaction(),\n ...opts\n } = options;\n Object.assign(opts, { transaction });\n\n const table = this.database.getTable(this.constructor.name);\n const association = table.getAssociations().get(key);\n const accessors = association.getAccessors();\n\n if (data == null) {\n await this[accessors.set](null, opts);\n return;\n }\n\n if (\n typeof data === 'number' ||\n typeof data === 'string' ||\n data instanceof SequelizeModel\n ) {\n await this[accessors.set](data, opts);\n } else if (typeof data === 'object') {\n const Target = association.getTargetModel();\n const targetAttribute =\n association instanceof BELONGSTO\n ? association.options.targetKey\n : association.options.sourceKey;\n if (data[targetAttribute]) {\n if (Object.keys(data).length > 0) {\n const target = await Target.findOne({\n where: {\n [targetAttribute]: data[targetAttribute],\n },\n transaction,\n });\n if (target) {\n await this[accessors.set](data[targetAttribute], opts);\n await target.update(data, opts);\n // @ts-ignore\n await target.updateAssociations(data, opts);\n } else {\n const t = await this[accessors.create](data, opts);\n await t.updateAssociations(data, opts);\n }\n }\n } else {\n const t = await this[accessors.create](data, opts);\n await t.updateAssociations(data, opts);\n }\n }\n if (!options.transaction) {\n await transaction.commit();\n }\n }\n\n async updateMultipleAssociation(\n associationName: string,\n data: any,\n options: UpdateAssociationOptions = {},\n ) {\n const items = Array.isArray(data) ? data : data == null ? [] : [data];\n\n const {\n fields,\n transaction = await this.sequelize.transaction(),\n ...opts\n } = options;\n Object.assign(opts, { transaction });\n\n const table = this.database.getTable(this.constructor.name);\n const association = table.getAssociations().get(associationName);\n const accessors = association.getAccessors();\n\n if (!items.length) {\n await this[accessors.set](null, opts);\n return;\n }\n\n const Target = association.getTargetModel();\n // 当前表关联 target 表的外键(大部分情况与 target 表主键相同,但可以设置为不同的,要考虑)\n const { targetKey = Target.primaryKeyAttribute } = association.options;\n // target 表的主键\n const targetPk = Target.primaryKeyAttribute;\n const targetKeyIsPk = targetKey === targetPk;\n // 准备设置的关联主键\n const toSetPks = new Set();\n const toSetUks = new Set();\n // 筛选后准备设置的关联主键\n const toSetItems = new Set();\n // 准备添加的关联对象\n const toUpsertObjects = [];\n\n // 遍历所有值成员准备数据\n items.forEach((item) => {\n if (item instanceof SequelizeModel) {\n if (targetKeyIsPk) {\n toSetPks.add(item.getDataValue(targetPk));\n } else {\n toSetUks.add(item.getDataValue(targetKey));\n }\n return;\n }\n if (typeof item === 'number' || typeof item === 'string') {\n let targetKeyType = getDataTypeKey(\n Target.rawAttributes[targetKey].type,\n ).toLocaleLowerCase();\n if (targetKeyType === 'integer') {\n targetKeyType = 'number';\n }\n // 如果传值类型与之前在 Model 上定义的 targetKey 不同,则报错。\n // 不应兼容定义的 targetKey 不是 primaryKey 却传了 primaryKey 的值的情况。\n if (typeof item !== targetKeyType) {\n throw new Error(\n `target key type [${typeof item}] does not match to [${targetKeyType}]`,\n );\n }\n if (targetKeyIsPk) {\n toSetPks.add(item);\n } else {\n toSetUks.add(item);\n }\n return;\n }\n if (typeof item === 'object') {\n toUpsertObjects.push(item);\n }\n });\n\n /* 仅传关联键处理开始 */\n // 查找已存在的数据\n const byPkExistItems = toSetPks.size\n ? await Target.findAll({\n ...opts,\n // @ts-ignore\n where: {\n [targetPk]: {\n [Op.in]: Array.from(toSetPks),\n },\n },\n attributes: [targetPk],\n })\n : [];\n byPkExistItems.forEach((item) => {\n toSetItems.add(item);\n });\n\n const byUkExistItems = toSetUks.size\n ? await Target.findAll({\n ...opts,\n // @ts-ignore\n where: {\n [targetKey]: {\n [Op.in]: Array.from(toSetUks),\n },\n },\n attributes: [targetPk, targetKey],\n })\n : [];\n byUkExistItems.forEach((item) => {\n toSetItems.add(item);\n });\n /* 仅传关联键处理结束 */\n\n const belongsToManyList = [];\n /* 值为对象处理开始 */\n for (const item of toUpsertObjects) {\n let target;\n if (typeof item[targetKey] === 'undefined') {\n target = await this[accessors.create](item, opts);\n } else {\n target = await Target.findOne({\n ...opts,\n where: { [targetKey]: item[targetKey] },\n });\n if (!target) {\n target = await this[accessors.create](item, opts);\n } else {\n await target.update(item, opts);\n }\n }\n // TODO(optimize): 此处添加的对象其实已经创建了关联,\n // 但考虑到单条 create 的 hook 要求带上关联键,且后面的 set,\n // 所以仍然交给 set 再调用关联一次。\n toSetItems.add(target);\n\n if (association instanceof BELONGSTOMANY) {\n belongsToManyList.push({\n item,\n target,\n });\n }\n\n await target.updateAssociations(item, opts);\n }\n /* 值为对象处理结束 */\n\n // 添加所有计算后的关联\n await this[accessors.set](Array.from(toSetItems), opts);\n\n // 后处理 belongsToMany 的更新内容\n if (belongsToManyList.length) {\n const ThroughModel = (association as BELONGSTOMANY).getThroughModel();\n const throughName = (association as BELONGSTOMANY).getThroughName();\n\n for (const { item, target } of belongsToManyList) {\n const throughValues = item[throughName];\n if (throughValues && typeof throughValues === 'object') {\n const { foreignKey, sourceKey, otherKey } = association.options;\n const through = await ThroughModel.findOne({\n where: {\n [foreignKey]: this.get(sourceKey),\n [otherKey]: target.get(targetKey),\n },\n transaction,\n });\n await through.update(throughValues, opts);\n // TODO:有 BUG,未知\n // await through.updateAssociations(throughValues, opts);\n }\n }\n }\n\n if (!options.transaction) {\n await transaction.commit();\n }\n }\n\n async updateAssociation(\n key: string,\n data: any,\n options: UpdateAssociationOptions = {},\n ) {\n const table = this.database.getTable(this.constructor.name);\n const association = table.getAssociations().get(key);\n switch (true) {\n case association instanceof BELONGSTO:\n case association instanceof HASONE:\n return this.updateSingleAssociation(key, data, options);\n case association instanceof HASMANY:\n case association instanceof BELONGSTOMANY:\n return this.updateMultipleAssociation(key, data, options);\n }\n }\n\n /**\n * 关联数据的更新\n *\n * @param data\n */\n async updateAssociations(data: any, options: UpdateAssociationOptions = {}) {\n const { transaction = await this.sequelize.transaction() } = options;\n // @ts-ignore 判断 Model.associations 更准确\n for (const key of Object.keys(this.constructor.associations)) {\n // 如果 key 不存在才跳过\n if (!Object.keys(data).includes(key)) {\n continue;\n }\n await this.updateAssociation(key, data[key], {\n ...options,\n transaction,\n });\n }\n\n await this.database.emitAsync('afterUpdateAssociations', this, {\n ...options,\n transaction,\n });\n\n if (!options.transaction) {\n await transaction.commit();\n }\n }\n}\n\n/**\n * ModelCtor 需要为当前 Model 的\n */\nexport type ModelCtor<M extends Model> = typeof Model & { new (): M } & {\n [key: string]: any;\n};\n\nexport default Model;\n"]}
package/lib/op.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["op.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAoB,MAAM,WAAW,CAAC;AA+IjD,MAAM,CAAC,OAAO,OAAO,QAAQ;WACb,GAAG,CAAC,GAAG,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAIf,GAAG,CAAC,GAAG,EAAE,MAAM;WAIf,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ;CAGjD","file":"op.d.ts","sourcesContent":["import { Op, Utils, Sequelize } from 'sequelize';\nimport moment, { MomentInput } from 'moment';\n\nfunction toArray(value: any): any[] {\n if (value == null) {\n return [];\n }\n return Array.isArray(value) ? value : [value];\n}\n\nfunction stringToDate(value: string): Date {\n return moment(value).toDate();\n}\n\nfunction getNextDay(value: MomentInput): Date {\n return moment(value).add(1, 'd').toDate();\n}\n\nconst op = new Map<string, typeof Op | Function>();\n\n// Sequelize 内置\nfor (const key in Op) {\n op.set(key, Op[key]);\n const val = Utils.underscoredIf(key, true);\n op.set(val, Op[key]);\n op.set(val.replace(/_/g, ''), Op[key]);\n}\n\n// 通用\n\n// 是否为空:数据库意义的 null\nop.set('$null', (value, { fieldPath, database }) => {\n // const field = database.getFieldByPath(fieldPath);\n // console.log({field});\n return { [Op.is]: null };\n});\nop.set('$notNull', () => ({ [Op.not]: null }));\n\nop.set('$isTruly', () => ({\n [Op.eq]: true,\n}));\nop.set('$isFalsy', () => ({\n [Op.or]: [\n {\n [Op.eq]: false,\n },\n {\n [Op.is]: null,\n },\n ],\n}));\n\n// 字符串\n\n// 包含:指对应字段的值包含某个子串\nop.set('$includes', (value: string) => ({ [Op.iLike]: `%${value}%` }));\n// 不包含:指对应字段的值不包含某个子串(慎用:性能问题)\nop.set('$notIncludes', (value: string) => ({ [Op.notILike]: `%${value}%` }));\n// 以之起始\nop.set('$startsWith', (value: string) => ({ [Op.iLike]: `${value}%` }));\n// 不以之起始\nop.set('$notStartsWith', (value: string) => ({ [Op.notILike]: `${value}%` }));\n// 以之结束\nop.set('$endsWith', (value: string) => ({ [Op.iLike]: `%${value}` }));\n// 不以之结束\nop.set('$notEndsWith', (value: string) => ({ [Op.notILike]: `%${value}` }));\n\n// 仅日期\n\n// 在某日\nop.set('$dateOn', (value: string) => ({ [Op.and]: [{ [Op.gte]: stringToDate(value) }, { [Op.lt]: getNextDay(value) }] }));\n// 不在某日\nop.set('$dateNotOn', (value: string) => ({ [Op.or]: [{ [Op.lt]: stringToDate(value) }, { [Op.gte]: getNextDay(value) }] }));\n// 某日前\nop.set('$dateBefore', (value: string) => ({ [Op.lt]: stringToDate(value) }));\n// 某日后\nop.set('$dateAfter', (value: string) => ({ [Op.gte]: getNextDay(value) }));\n// 不早于(含当天)\nop.set('$dateNotBefore', (value: string) => ({ [Op.gte]: stringToDate(value) }));\n// 不晚于(含当天)\nop.set('$dateNotAfter', (value: string) => ({ [Op.lt]: getNextDay(value) }));\n// 在期间\nop.set('$dateBetween', ([from, to]: string[]) => ({ [Op.and]: [{ [Op.gte]: stringToDate(from) }, { [Op.lt]: getNextDay(to) }] }));\n// 不在期间\nop.set('$dateNotBetween', ([from, to]: string[]) => ({ [Op.or]: [{ [Op.lt]: stringToDate(from) }, { [Op.gte]: getNextDay(to) }] }));\n\n// 多选(JSON)类型\n\n// 包含组中任意值(命名来源:`Array.prototype.some`)\nop.set('$anyOf', (values: any[], options) => {\n if (!values) {\n return Sequelize.literal('');\n }\n values = Array.isArray(values) ? values : [values];\n if (values.length === 0) {\n return Sequelize.literal('');\n }\n const { field, fieldPath } = options;\n const column = fieldPath.split('.').map(name => `\"${name}\"`).join('.');\n const sql = values.map(value => `(${column})::jsonb @> '${JSON.stringify(value)}'`).join(' OR ');\n console.log(sql);\n return Sequelize.literal(sql);\n});\n// 包含组中所有值\nop.set('$allOf', (values: any) => ({ [Op.contains]: toArray(values) }));\n// TODO(bug): 不包含组中任意值\nop.set('$noneOf', (values: any[], options) => {\n if (!values) {\n return Sequelize.literal('');\n }\n values = Array.isArray(values) ? values : [values];\n if (values.length === 0) {\n return Sequelize.literal('');\n }\n const { field, fieldPath } = options;\n const column = fieldPath.split('.').map(name => `\"${name}\"`).join('.');\n const sql = values.map(value => `(${column})::jsonb @> '${JSON.stringify(value)}'`).join(' OR ');\n console.log(sql);\n return Sequelize.literal(`not (${sql})`);\n});\n// 与组中值匹配\nop.set('$match', (values: any[], options) => {\n const array = toArray(values);\n if (values.length === 0) {\n return Sequelize.literal('');\n }\n const { field, fieldPath } = options;\n const column = fieldPath.split('.').map(name => `\"${name}\"`).join('.');\n const sql = `(${column})::jsonb @> '${JSON.stringify(array)}' AND (${column})::jsonb <@ '${JSON.stringify(array)}'`\n return Sequelize.literal(sql);\n});\nop.set('$notMatch', (values: any[], options) => {\n const array = toArray(values);\n if (values.length === 0) {\n return Sequelize.literal('');\n }\n const { field, fieldPath } = options;\n const column = fieldPath.split('.').map(name => `\"${name}\"`).join('.');\n const sql = `(${column})::jsonb @> '${JSON.stringify(array)}' AND (${column})::jsonb <@ '${JSON.stringify(array)}'`\n return Sequelize.literal(`not (${sql})`);\n // return Sequelize.literal(`(not (${sql})) AND ${column} IS NULL`);\n});\n\nexport default class Operator {\n public static get(key: string) {\n return op.get(key);\n }\n\n public static has(key: string) {\n return op.has(key);\n }\n\n public static register(key: string, fn: Function) {\n op.set(key, fn);\n }\n};\n"]}
1
+ {"version":3,"sources":["op.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAoB,MAAM,WAAW,CAAC;AAuLjD,MAAM,CAAC,OAAO,OAAO,QAAQ;WACb,GAAG,CAAC,GAAG,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAIf,GAAG,CAAC,GAAG,EAAE,MAAM;WAIf,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ;CAGjD","file":"op.d.ts","sourcesContent":["import { Op, Utils, Sequelize } from 'sequelize';\nimport moment, { MomentInput } from 'moment';\n\nfunction toArray(value: any): any[] {\n if (value == null) {\n return [];\n }\n return Array.isArray(value) ? value : [value];\n}\n\nfunction stringToDate(value: string): Date {\n return moment(value).toDate();\n}\n\nfunction getNextDay(value: MomentInput): Date {\n return moment(value).add(1, 'd').toDate();\n}\n\nconst op = new Map<string, typeof Op | Function>();\n\n// Sequelize 内置\nfor (const key in Op) {\n op.set(key, Op[key]);\n const val = Utils.underscoredIf(key, true);\n op.set(val, Op[key]);\n op.set(val.replace(/_/g, ''), Op[key]);\n}\n\n// 通用\n\n// 是否为空:数据库意义的 null\nop.set('$null', (value, { fieldPath, database }) => {\n // const field = database.getFieldByPath(fieldPath);\n // console.log({field});\n return { [Op.is]: null };\n});\nop.set('$notNull', () => ({ [Op.not]: null }));\n\nop.set('$isTruly', () => ({\n [Op.eq]: true,\n}));\nop.set('$isFalsy', () => ({\n [Op.or]: [\n {\n [Op.eq]: false,\n },\n {\n [Op.is]: null,\n },\n ],\n}));\n\n// 字符串\n\n// 包含:指对应字段的值包含某个子串\nop.set('$includes', (value: string, { dialect }) => ({\n [dialect === 'postgres' ? Op.iLike : Op.like]: `%${value}%`,\n}));\n// 不包含:指对应字段的值不包含某个子串(慎用:性能问题)\nop.set('$notIncludes', (value: string, { dialect }) => ({\n [dialect === 'postgres' ? Op.notILike : Op.notLike]: `%${value}%`,\n}));\n// 以之起始\nop.set('$startsWith', (value: string, { dialect }) => ({\n [dialect === 'postgres' ? Op.iLike : Op.like]: `${value}%`,\n}));\n// 不以之起始\nop.set('$notStartsWith', (value: string, { dialect }) => ({\n [dialect === 'postgres' ? Op.notILike : Op.notLike]: `${value}%`,\n}));\n// 以之结束\nop.set('$endsWith', (value: string, { dialect }) => ({\n [dialect === 'postgres' ? Op.iLike : Op.like]: `%${value}`,\n}));\n// 不以之结束\nop.set('$notEndsWith', (value: string, { dialect }) => ({\n [dialect === 'postgres' ? Op.notILike : Op.notLike]: `%${value}`,\n}));\n\n// 仅日期\n\n// 在某日\nop.set('$dateOn', (value: string) => ({\n [Op.and]: [{ [Op.gte]: stringToDate(value) }, { [Op.lt]: getNextDay(value) }],\n}));\n// 不在某日\nop.set('$dateNotOn', (value: string) => ({\n [Op.or]: [{ [Op.lt]: stringToDate(value) }, { [Op.gte]: getNextDay(value) }],\n}));\n// 某日前\nop.set('$dateBefore', (value: string) => ({ [Op.lt]: stringToDate(value) }));\n// 某日后\nop.set('$dateAfter', (value: string) => ({ [Op.gte]: getNextDay(value) }));\n// 不早于(含当天)\nop.set('$dateNotBefore', (value: string) => ({\n [Op.gte]: stringToDate(value),\n}));\n// 不晚于(含当天)\nop.set('$dateNotAfter', (value: string) => ({ [Op.lt]: getNextDay(value) }));\n// 在期间\nop.set('$dateBetween', ([from, to]: string[]) => ({\n [Op.and]: [{ [Op.gte]: stringToDate(from) }, { [Op.lt]: getNextDay(to) }],\n}));\n// 不在期间\nop.set('$dateNotBetween', ([from, to]: string[]) => ({\n [Op.or]: [{ [Op.lt]: stringToDate(from) }, { [Op.gte]: getNextDay(to) }],\n}));\n\n// 多选(JSON)类型\n\n// 包含组中任意值(命名来源:`Array.prototype.some`)\nop.set('$anyOf', (values: any[], options) => {\n if (!values) {\n return Sequelize.literal('');\n }\n values = Array.isArray(values) ? values : [values];\n if (values.length === 0) {\n return Sequelize.literal('');\n }\n const { field, fieldPath } = options;\n const column = fieldPath\n .split('.')\n .map((name) => `\"${name}\"`)\n .join('.');\n const sql = values\n .map((value) => `(${column})::jsonb @> '${JSON.stringify(value)}'`)\n .join(' OR ');\n return Sequelize.literal(sql);\n});\n// 包含组中所有值\nop.set('$allOf', (values: any) => ({ [Op.contains]: toArray(values) }));\n// TODO(bug): 不包含组中任意值\nop.set('$noneOf', (values: any[], options) => {\n if (!values) {\n return Sequelize.literal('');\n }\n values = Array.isArray(values) ? values : [values];\n if (values.length === 0) {\n return Sequelize.literal('');\n }\n const { field, fieldPath } = options;\n const column = fieldPath\n .split('.')\n .map((name) => `\"${name}\"`)\n .join('.');\n const sql = values\n .map((value) => `(${column})::jsonb @> '${JSON.stringify(value)}'`)\n .join(' OR ');\n return Sequelize.literal(`not (${sql})`);\n});\n// 与组中值匹配\nop.set('$match', (values: any[], options) => {\n const array = toArray(values);\n if (values.length === 0) {\n return Sequelize.literal('');\n }\n const { field, fieldPath } = options;\n const column = fieldPath\n .split('.')\n .map((name) => `\"${name}\"`)\n .join('.');\n const sql = `(${column})::jsonb @> '${JSON.stringify(\n array,\n )}' AND (${column})::jsonb <@ '${JSON.stringify(array)}'`;\n return Sequelize.literal(sql);\n});\nop.set('$notMatch', (values: any[], options) => {\n const array = toArray(values);\n if (values.length === 0) {\n return Sequelize.literal('');\n }\n const { field, fieldPath } = options;\n const column = fieldPath\n .split('.')\n .map((name) => `\"${name}\"`)\n .join('.');\n const sql = `(${column})::jsonb @> '${JSON.stringify(\n array,\n )}' AND (${column})::jsonb <@ '${JSON.stringify(array)}'`;\n return Sequelize.literal(`not (${sql})`);\n // return Sequelize.literal(`(not (${sql})) AND ${column} IS NULL`);\n});\n\nexport default class Operator {\n public static get(key: string) {\n return op.get(key);\n }\n\n public static has(key: string) {\n return op.has(key);\n }\n\n public static register(key: string, fn: Function) {\n op.set(key, fn);\n }\n}\n"]}
package/lib/op.js CHANGED
@@ -72,23 +72,35 @@ op.set('$isFalsy', () => ({
72
72
  [sequelize_1.Op.is]: null
73
73
  }]
74
74
  }));
75
- op.set('$includes', value => ({
76
- [sequelize_1.Op.iLike]: `%${value}%`
77
- }));
78
- op.set('$notIncludes', value => ({
79
- [sequelize_1.Op.notILike]: `%${value}%`
80
- }));
81
- op.set('$startsWith', value => ({
82
- [sequelize_1.Op.iLike]: `${value}%`
83
- }));
84
- op.set('$notStartsWith', value => ({
85
- [sequelize_1.Op.notILike]: `${value}%`
86
- }));
87
- op.set('$endsWith', value => ({
88
- [sequelize_1.Op.iLike]: `%${value}`
89
- }));
90
- op.set('$notEndsWith', value => ({
91
- [sequelize_1.Op.notILike]: `%${value}`
75
+ op.set('$includes', (value, {
76
+ dialect
77
+ }) => ({
78
+ [dialect === 'postgres' ? sequelize_1.Op.iLike : sequelize_1.Op.like]: `%${value}%`
79
+ }));
80
+ op.set('$notIncludes', (value, {
81
+ dialect
82
+ }) => ({
83
+ [dialect === 'postgres' ? sequelize_1.Op.notILike : sequelize_1.Op.notLike]: `%${value}%`
84
+ }));
85
+ op.set('$startsWith', (value, {
86
+ dialect
87
+ }) => ({
88
+ [dialect === 'postgres' ? sequelize_1.Op.iLike : sequelize_1.Op.like]: `${value}%`
89
+ }));
90
+ op.set('$notStartsWith', (value, {
91
+ dialect
92
+ }) => ({
93
+ [dialect === 'postgres' ? sequelize_1.Op.notILike : sequelize_1.Op.notLike]: `${value}%`
94
+ }));
95
+ op.set('$endsWith', (value, {
96
+ dialect
97
+ }) => ({
98
+ [dialect === 'postgres' ? sequelize_1.Op.iLike : sequelize_1.Op.like]: `%${value}`
99
+ }));
100
+ op.set('$notEndsWith', (value, {
101
+ dialect
102
+ }) => ({
103
+ [dialect === 'postgres' ? sequelize_1.Op.notILike : sequelize_1.Op.notLike]: `%${value}`
92
104
  }));
93
105
  op.set('$dateOn', value => ({
94
106
  [sequelize_1.Op.and]: [{
@@ -145,7 +157,6 @@ op.set('$anyOf', (values, options) => {
145
157
  fieldPath = options.fieldPath;
146
158
  const column = fieldPath.split('.').map(name => `"${name}"`).join('.');
147
159
  const sql = values.map(value => `(${column})::jsonb @> '${JSON.stringify(value)}'`).join(' OR ');
148
- console.log(sql);
149
160
  return sequelize_1.Sequelize.literal(sql);
150
161
  });
151
162
  op.set('$allOf', values => ({
@@ -166,7 +177,6 @@ op.set('$noneOf', (values, options) => {
166
177
  fieldPath = options.fieldPath;
167
178
  const column = fieldPath.split('.').map(name => `"${name}"`).join('.');
168
179
  const sql = values.map(value => `(${column})::jsonb @> '${JSON.stringify(value)}'`).join(' OR ');
169
- console.log(sql);
170
180
  return sequelize_1.Sequelize.literal(`not (${sql})`);
171
181
  });
172
182
  op.set('$match', (values, options) => {
@@ -212,5 +222,4 @@ class Operator {
212
222
  }
213
223
 
214
224
  exports.default = Operator;
215
- ;
216
225
  //# sourceMappingURL=op.js.map
package/lib/op.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["op.ts"],"names":[],"mappings":"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","file":"op.js","sourcesContent":["import { Op, Utils, Sequelize } from 'sequelize';\nimport moment, { MomentInput } from 'moment';\n\nfunction toArray(value: any): any[] {\n if (value == null) {\n return [];\n }\n return Array.isArray(value) ? value : [value];\n}\n\nfunction stringToDate(value: string): Date {\n return moment(value).toDate();\n}\n\nfunction getNextDay(value: MomentInput): Date {\n return moment(value).add(1, 'd').toDate();\n}\n\nconst op = new Map<string, typeof Op | Function>();\n\n// Sequelize 内置\nfor (const key in Op) {\n op.set(key, Op[key]);\n const val = Utils.underscoredIf(key, true);\n op.set(val, Op[key]);\n op.set(val.replace(/_/g, ''), Op[key]);\n}\n\n// 通用\n\n// 是否为空:数据库意义的 null\nop.set('$null', (value, { fieldPath, database }) => {\n // const field = database.getFieldByPath(fieldPath);\n // console.log({field});\n return { [Op.is]: null };\n});\nop.set('$notNull', () => ({ [Op.not]: null }));\n\nop.set('$isTruly', () => ({\n [Op.eq]: true,\n}));\nop.set('$isFalsy', () => ({\n [Op.or]: [\n {\n [Op.eq]: false,\n },\n {\n [Op.is]: null,\n },\n ],\n}));\n\n// 字符串\n\n// 包含:指对应字段的值包含某个子串\nop.set('$includes', (value: string) => ({ [Op.iLike]: `%${value}%` }));\n// 不包含:指对应字段的值不包含某个子串(慎用:性能问题)\nop.set('$notIncludes', (value: string) => ({ [Op.notILike]: `%${value}%` }));\n// 以之起始\nop.set('$startsWith', (value: string) => ({ [Op.iLike]: `${value}%` }));\n// 不以之起始\nop.set('$notStartsWith', (value: string) => ({ [Op.notILike]: `${value}%` }));\n// 以之结束\nop.set('$endsWith', (value: string) => ({ [Op.iLike]: `%${value}` }));\n// 不以之结束\nop.set('$notEndsWith', (value: string) => ({ [Op.notILike]: `%${value}` }));\n\n// 仅日期\n\n// 在某日\nop.set('$dateOn', (value: string) => ({ [Op.and]: [{ [Op.gte]: stringToDate(value) }, { [Op.lt]: getNextDay(value) }] }));\n// 不在某日\nop.set('$dateNotOn', (value: string) => ({ [Op.or]: [{ [Op.lt]: stringToDate(value) }, { [Op.gte]: getNextDay(value) }] }));\n// 某日前\nop.set('$dateBefore', (value: string) => ({ [Op.lt]: stringToDate(value) }));\n// 某日后\nop.set('$dateAfter', (value: string) => ({ [Op.gte]: getNextDay(value) }));\n// 不早于(含当天)\nop.set('$dateNotBefore', (value: string) => ({ [Op.gte]: stringToDate(value) }));\n// 不晚于(含当天)\nop.set('$dateNotAfter', (value: string) => ({ [Op.lt]: getNextDay(value) }));\n// 在期间\nop.set('$dateBetween', ([from, to]: string[]) => ({ [Op.and]: [{ [Op.gte]: stringToDate(from) }, { [Op.lt]: getNextDay(to) }] }));\n// 不在期间\nop.set('$dateNotBetween', ([from, to]: string[]) => ({ [Op.or]: [{ [Op.lt]: stringToDate(from) }, { [Op.gte]: getNextDay(to) }] }));\n\n// 多选(JSON)类型\n\n// 包含组中任意值(命名来源:`Array.prototype.some`)\nop.set('$anyOf', (values: any[], options) => {\n if (!values) {\n return Sequelize.literal('');\n }\n values = Array.isArray(values) ? values : [values];\n if (values.length === 0) {\n return Sequelize.literal('');\n }\n const { field, fieldPath } = options;\n const column = fieldPath.split('.').map(name => `\"${name}\"`).join('.');\n const sql = values.map(value => `(${column})::jsonb @> '${JSON.stringify(value)}'`).join(' OR ');\n console.log(sql);\n return Sequelize.literal(sql);\n});\n// 包含组中所有值\nop.set('$allOf', (values: any) => ({ [Op.contains]: toArray(values) }));\n// TODO(bug): 不包含组中任意值\nop.set('$noneOf', (values: any[], options) => {\n if (!values) {\n return Sequelize.literal('');\n }\n values = Array.isArray(values) ? values : [values];\n if (values.length === 0) {\n return Sequelize.literal('');\n }\n const { field, fieldPath } = options;\n const column = fieldPath.split('.').map(name => `\"${name}\"`).join('.');\n const sql = values.map(value => `(${column})::jsonb @> '${JSON.stringify(value)}'`).join(' OR ');\n console.log(sql);\n return Sequelize.literal(`not (${sql})`);\n});\n// 与组中值匹配\nop.set('$match', (values: any[], options) => {\n const array = toArray(values);\n if (values.length === 0) {\n return Sequelize.literal('');\n }\n const { field, fieldPath } = options;\n const column = fieldPath.split('.').map(name => `\"${name}\"`).join('.');\n const sql = `(${column})::jsonb @> '${JSON.stringify(array)}' AND (${column})::jsonb <@ '${JSON.stringify(array)}'`\n return Sequelize.literal(sql);\n});\nop.set('$notMatch', (values: any[], options) => {\n const array = toArray(values);\n if (values.length === 0) {\n return Sequelize.literal('');\n }\n const { field, fieldPath } = options;\n const column = fieldPath.split('.').map(name => `\"${name}\"`).join('.');\n const sql = `(${column})::jsonb @> '${JSON.stringify(array)}' AND (${column})::jsonb <@ '${JSON.stringify(array)}'`\n return Sequelize.literal(`not (${sql})`);\n // return Sequelize.literal(`(not (${sql})) AND ${column} IS NULL`);\n});\n\nexport default class Operator {\n public static get(key: string) {\n return op.get(key);\n }\n\n public static has(key: string) {\n return op.has(key);\n }\n\n public static register(key: string, fn: Function) {\n op.set(key, fn);\n }\n};\n"]}
1
+ {"version":3,"sources":["op.ts"],"names":[],"mappings":"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","file":"op.js","sourcesContent":["import { Op, Utils, Sequelize } from 'sequelize';\nimport moment, { MomentInput } from 'moment';\n\nfunction toArray(value: any): any[] {\n if (value == null) {\n return [];\n }\n return Array.isArray(value) ? value : [value];\n}\n\nfunction stringToDate(value: string): Date {\n return moment(value).toDate();\n}\n\nfunction getNextDay(value: MomentInput): Date {\n return moment(value).add(1, 'd').toDate();\n}\n\nconst op = new Map<string, typeof Op | Function>();\n\n// Sequelize 内置\nfor (const key in Op) {\n op.set(key, Op[key]);\n const val = Utils.underscoredIf(key, true);\n op.set(val, Op[key]);\n op.set(val.replace(/_/g, ''), Op[key]);\n}\n\n// 通用\n\n// 是否为空:数据库意义的 null\nop.set('$null', (value, { fieldPath, database }) => {\n // const field = database.getFieldByPath(fieldPath);\n // console.log({field});\n return { [Op.is]: null };\n});\nop.set('$notNull', () => ({ [Op.not]: null }));\n\nop.set('$isTruly', () => ({\n [Op.eq]: true,\n}));\nop.set('$isFalsy', () => ({\n [Op.or]: [\n {\n [Op.eq]: false,\n },\n {\n [Op.is]: null,\n },\n ],\n}));\n\n// 字符串\n\n// 包含:指对应字段的值包含某个子串\nop.set('$includes', (value: string, { dialect }) => ({\n [dialect === 'postgres' ? Op.iLike : Op.like]: `%${value}%`,\n}));\n// 不包含:指对应字段的值不包含某个子串(慎用:性能问题)\nop.set('$notIncludes', (value: string, { dialect }) => ({\n [dialect === 'postgres' ? Op.notILike : Op.notLike]: `%${value}%`,\n}));\n// 以之起始\nop.set('$startsWith', (value: string, { dialect }) => ({\n [dialect === 'postgres' ? Op.iLike : Op.like]: `${value}%`,\n}));\n// 不以之起始\nop.set('$notStartsWith', (value: string, { dialect }) => ({\n [dialect === 'postgres' ? Op.notILike : Op.notLike]: `${value}%`,\n}));\n// 以之结束\nop.set('$endsWith', (value: string, { dialect }) => ({\n [dialect === 'postgres' ? Op.iLike : Op.like]: `%${value}`,\n}));\n// 不以之结束\nop.set('$notEndsWith', (value: string, { dialect }) => ({\n [dialect === 'postgres' ? Op.notILike : Op.notLike]: `%${value}`,\n}));\n\n// 仅日期\n\n// 在某日\nop.set('$dateOn', (value: string) => ({\n [Op.and]: [{ [Op.gte]: stringToDate(value) }, { [Op.lt]: getNextDay(value) }],\n}));\n// 不在某日\nop.set('$dateNotOn', (value: string) => ({\n [Op.or]: [{ [Op.lt]: stringToDate(value) }, { [Op.gte]: getNextDay(value) }],\n}));\n// 某日前\nop.set('$dateBefore', (value: string) => ({ [Op.lt]: stringToDate(value) }));\n// 某日后\nop.set('$dateAfter', (value: string) => ({ [Op.gte]: getNextDay(value) }));\n// 不早于(含当天)\nop.set('$dateNotBefore', (value: string) => ({\n [Op.gte]: stringToDate(value),\n}));\n// 不晚于(含当天)\nop.set('$dateNotAfter', (value: string) => ({ [Op.lt]: getNextDay(value) }));\n// 在期间\nop.set('$dateBetween', ([from, to]: string[]) => ({\n [Op.and]: [{ [Op.gte]: stringToDate(from) }, { [Op.lt]: getNextDay(to) }],\n}));\n// 不在期间\nop.set('$dateNotBetween', ([from, to]: string[]) => ({\n [Op.or]: [{ [Op.lt]: stringToDate(from) }, { [Op.gte]: getNextDay(to) }],\n}));\n\n// 多选(JSON)类型\n\n// 包含组中任意值(命名来源:`Array.prototype.some`)\nop.set('$anyOf', (values: any[], options) => {\n if (!values) {\n return Sequelize.literal('');\n }\n values = Array.isArray(values) ? values : [values];\n if (values.length === 0) {\n return Sequelize.literal('');\n }\n const { field, fieldPath } = options;\n const column = fieldPath\n .split('.')\n .map((name) => `\"${name}\"`)\n .join('.');\n const sql = values\n .map((value) => `(${column})::jsonb @> '${JSON.stringify(value)}'`)\n .join(' OR ');\n return Sequelize.literal(sql);\n});\n// 包含组中所有值\nop.set('$allOf', (values: any) => ({ [Op.contains]: toArray(values) }));\n// TODO(bug): 不包含组中任意值\nop.set('$noneOf', (values: any[], options) => {\n if (!values) {\n return Sequelize.literal('');\n }\n values = Array.isArray(values) ? values : [values];\n if (values.length === 0) {\n return Sequelize.literal('');\n }\n const { field, fieldPath } = options;\n const column = fieldPath\n .split('.')\n .map((name) => `\"${name}\"`)\n .join('.');\n const sql = values\n .map((value) => `(${column})::jsonb @> '${JSON.stringify(value)}'`)\n .join(' OR ');\n return Sequelize.literal(`not (${sql})`);\n});\n// 与组中值匹配\nop.set('$match', (values: any[], options) => {\n const array = toArray(values);\n if (values.length === 0) {\n return Sequelize.literal('');\n }\n const { field, fieldPath } = options;\n const column = fieldPath\n .split('.')\n .map((name) => `\"${name}\"`)\n .join('.');\n const sql = `(${column})::jsonb @> '${JSON.stringify(\n array,\n )}' AND (${column})::jsonb <@ '${JSON.stringify(array)}'`;\n return Sequelize.literal(sql);\n});\nop.set('$notMatch', (values: any[], options) => {\n const array = toArray(values);\n if (values.length === 0) {\n return Sequelize.literal('');\n }\n const { field, fieldPath } = options;\n const column = fieldPath\n .split('.')\n .map((name) => `\"${name}\"`)\n .join('.');\n const sql = `(${column})::jsonb @> '${JSON.stringify(\n array,\n )}' AND (${column})::jsonb <@ '${JSON.stringify(array)}'`;\n return Sequelize.literal(`not (${sql})`);\n // return Sequelize.literal(`(not (${sql})) AND ${column} IS NULL`);\n});\n\nexport default class Operator {\n public static get(key: string) {\n return op.get(key);\n }\n\n public static has(key: string) {\n return op.has(key);\n }\n\n public static register(key: string, fn: Function) {\n op.set(key, fn);\n }\n}\n"]}
package/lib/table.d.ts CHANGED
@@ -14,7 +14,7 @@ export interface TableOptions extends Omit<ModelOptions<Model>, 'name' | 'modelN
14
14
  fields?: Array<FieldOptions>;
15
15
  [key: string]: any;
16
16
  }
17
- export interface TabelContext {
17
+ export interface TableContext {
18
18
  database: Database;
19
19
  }
20
20
  export declare type Reinitialize = boolean | 'modelOnly';
@@ -32,7 +32,7 @@ export declare class Table {
32
32
  isThroughTable: boolean;
33
33
  relationTables: Set<string>;
34
34
  get sortable(): boolean;
35
- constructor(options: TableOptions, context: TabelContext);
35
+ constructor(options: TableOptions, context: TableContext);
36
36
  initSortable(): void;
37
37
  modelInit(reinitialize?: Reinitialize): void;
38
38
  getName(): string;
@@ -1 +1 @@
1
- {"version":3,"sources":["table.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,eAAe,EACf,YAAY,EACZ,mBAAmB,EAEnB,WAAW,EACZ,MAAM,WAAW,CAAC;AACnB,OAAO,EAEL,YAAY,EACZ,QAAQ,EAIT,MAAM,UAAU,CAAC;AAClB,OAAO,QAAQ,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAE3C,OAAO,KAAK,MAAM,WAAW,CAAC;AAE9B,MAAM,WAAW,YAAa,SAAQ,KAAK,CAAC,OAAO;CAElD;AAID,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,QAEpD;AAED,wBAAgB,cAAc,CAAC,MAAM,KAAA,QAMpC;AAGD,wBAAgB,kBAAkB,CAAC,GAAG,KAAA,OAKrC;AAED,MAAM,WAAW,YAAa,SAAQ,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IAWnF,IAAI,EAAE,MAAM,CAAC;IAKb,KAAK,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC;IAKlC,MAAM,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;IAK7B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAKD,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,QAAQ,CAAC;CACpB;AASD,oBAAY,YAAY,GAAG,OAAO,GAAG,WAAW,CAAC;AAOjD,qBAAa,KAAK;IAEhB,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAE7B,SAAS,CAAC,OAAO,EAAE,YAAY,CAAC;IAEhC,SAAS,CAAC,MAAM,mBAA0B;IAE1C,SAAS,CAAC,eAAe,EAAE,eAAe,CAAC;IAE3C,SAAS,CAAC,YAAY,EAAE,WAAW,CAAC;IAKpC,SAAS,CAAC,YAAY,wBAA+B;IAKrD,SAAS,CAAC,WAAW,wBAA+B;IAKpD,SAAS,CAAC,OAAO,mBAA0B;IAE3C,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC;IAElC,SAAS,CAAC,YAAY,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC;IAKlC,cAAc,EAAE,OAAO,CAAS;IAEhC,cAAc,cAAqB;IAE1C,IAAI,QAAQ,IAAI,OAAO,CAEtB;gBAEW,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY;IAyBjD,YAAY;IAkBZ,SAAS,CAAC,YAAY,GAAE,YAAoB;IAwC5C,OAAO,IAAI,MAAM;IAIjB,YAAY,IAAI,MAAM;IAQtB,UAAU,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,YAAY;IAInC,QAAQ,IAAI,SAAS,CAAC,KAAK,CAAC;IAI5B,kBAAkB,IAAI,eAAe;IAIrC,eAAe,IAAI,WAAW;IAwB9B,oBAAoB,IAAI,GAAG,CAAC,MAAM,CAAC;IAcnC,eAAe;IAIf,SAAS;IAIT,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,YAAY,CAAC;IAUrC,QAAQ,CAAC,IAAI,EAAE,MAAM;IAIrB,QAAQ,CAAC,IAAI,EAAE,MAAM;IAUrB,QAAQ,CAAC,OAAO,EAAE,YAAY,EAAE,YAAY,GAAE,YAAmB;IAiDjE,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,mBAAmB,EAAE,YAAY,GAAE,YAAmB;IAqBtF,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,GAAG,mBAAmB,CAAC,EAAE,YAAY,GAAE,YAAmB;IAY1F,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,YAAY,GAAE,YAAiB;IA6BvD,IAAI,CAAC,OAAO,GAAE,WAAgB;CAU5C;AAED,eAAe,KAAK,CAAC","file":"table.d.ts","sourcesContent":["import {\n InitOptions,\n ModelAttributes,\n ModelOptions,\n ModelIndexesOptions,\n Utils,\n SyncOptions,\n} from 'sequelize';\nimport {\n buildField,\n FieldOptions,\n Relation,\n BELONGSTO,\n BELONGSTOMANY,\n SORT\n} from './fields';\nimport Database from './database';\nimport { Model, ModelCtor } from './model';\nimport _ from 'lodash';\nimport merge from 'deepmerge';\n\nexport interface MergeOptions extends merge.Options {\n\n}\n\nconst registeredModels = new Map<string, any>();\n\nexport function registerModel(key: string, model: any) {\n registeredModels.set(key, model);\n}\n\nexport function registerModels(models) {\n for (const key in models) {\n if (models.hasOwnProperty(key)) {\n registerModel(key, models[key]);\n }\n }\n}\n\n// TODO: 判断如果 key 是 model 直接返回\nexport function getRegisteredModel(key) {\n if (typeof key === 'string') {\n return registeredModels.get(key);\n }\n return key;\n}\n\nexport interface TableOptions extends Omit<ModelOptions<Model>, 'name' | 'modelName'> {\n\n /**\n * 唯一标识,与 ModelOptions 的 name 有区别\n * \n * 注意:name 可用于初始化 tableName、modelName,但是 tableName 和 modelName 可能有所不同\n * name 主要用于获取指定的 tables 和 models\n * 如果没有特殊指定 tableName 时,name、tableName、modelName 都是一个值\n * \n * TODO: name, tableName, modelName,freezeTableName,underscored,单复数等等情况还比较混乱\n */\n name: string;\n\n /**\n * 自定义 model\n */\n model?: ModelCtor<Model> | string;\n\n /**\n * 字段配置\n */\n fields?: Array<FieldOptions>;\n\n /**\n * 其他的一些情况\n */\n [key: string]: any;\n}\n\n/**\n * 上下文,Tabel 配置需要的其他变量\n */\nexport interface TabelContext {\n database: Database;\n}\n\n/**\n * 是否重新初始化 Model。配置更新时,需要重新初始化 model。\n *\n * - reinitialize = false 只执行 Model.init\n * - reinitialize = true 重新初始化 Model 并执行 Model.init 和 Model.associate\n * - reinitialize = modelOnly 只初始化 Model 并执行 Model.init\n */\nexport type Reinitialize = boolean | 'modelOnly';\n\n/**\n * 表配置\n * \n * 用于处理相关 Model 的配置\n */\nexport class Table {\n\n protected database: Database;\n\n protected options: TableOptions;\n\n protected fields = new Map<string, any>();\n\n protected modelAttributes: ModelAttributes;\n\n protected modelOptions: InitOptions;\n\n /**\n * 全部关系字段的配置\n */\n protected associations = new Map<string, Relation>();\n\n /**\n * 待建立关系的 association\n */\n protected associating = new Map<string, Relation>();\n\n /**\n * 索引\n */\n protected indexes = new Map<string, any>();\n\n protected Model: ModelCtor<Model>;\n\n protected defaultModel: ModelCtor<Model>;\n\n /**\n * 是否是中间表\n */\n public isThroughTable: boolean = false;\n\n public relationTables = new Set<string>();\n\n get sortable(): boolean {\n return Array.from(this.fields.values()).some(field => field instanceof SORT);\n }\n\n constructor(options: TableOptions, context: TabelContext) {\n const { database } = context;\n database.runHooks('beforeTableInit', options);\n database.emit('beforeTableInit', options);\n const {\n model,\n fields = [],\n indexes = [],\n sortable,\n } = options;\n this.options = options;\n this.database = database;\n // 初始化的时候获取\n this.defaultModel = getRegisteredModel(model);\n this.modelAttributes = {};\n // 在 set fields 之前 model init 的原因是因为关系字段可能需要用到 model 的相关配置\n // @ts-ignore\n this.addIndexes(indexes, 'modelOnly');\n // this.modelInit('modelOnly');\n this.setFields(fields);\n this.initSortable();\n database.emit('afterTableInit', this);\n database.runHooks('afterTableInit', this);\n }\n\n public initSortable() {\n const { sortable } = this.options;\n if (!sortable) {\n return;\n }\n if (typeof sortable === 'string') {\n this.addField({\n type: 'sort',\n name: sortable,\n });\n } else if (typeof sortable === 'object') {\n this.addField({\n ...sortable,\n type: 'sort',\n });\n }\n }\n\n public modelInit(reinitialize: Reinitialize = false) {\n if (reinitialize || !this.Model) {\n let DefaultModel = this.defaultModel;\n this.Model = DefaultModel ? (class extends DefaultModel {}) : (class extends Model { });\n this.Model.database = this.database;\n // 关系的建立是在 model.init 之后,在配置中表字段(Column)和关系(Relation)都在 fields,\n // 所以需要单独提炼出 associations 字段,并在 Model.init 之后执行 Model.associate\n // @ts-ignore\n this.Model.associate = (models: { [key: string]: ModelCtor<Model> }) => {\n for (const [key, association] of this.associating) {\n const { type, target } = association.getAssociationArguments();\n if (this.database.isDefined(target)) {\n const TargetModel = this.database.getModel(target);\n // 如果关系表在之后才定义,未设置 targetKey 时,targetKey 默认值需要在 target model 初始化之后才能取到\n if (association instanceof BELONGSTO || association instanceof BELONGSTOMANY) {\n association.updateOptionsAfterTargetModelBeDefined();\n }\n this.Model[type](TargetModel, association.getAssociationOptions());\n // 建立关系之后,需要删除待处理的 associating,避免重复和提高效率\n this.associating.delete(key);\n }\n }\n }\n }\n\n this.Model.init(this.getModelAttributes(), this.getModelOptions());\n\n if (reinitialize === true) {\n this.associating = new Map(this.associations);\n // 需要额外处理 associating 的情况\n // 建立表关系需要遍历多个 Model,所以在这里需要标记哪些已定义的 Model 需要建立表关系\n if (this.associating.size > 0) {\n this.database.associating.add(this.options.name);\n } else {\n this.database.associating.delete(this.options.name);\n }\n this.database.associate();\n }\n }\n\n public getName(): string {\n return this.options.name;\n }\n\n public getTableName(): string {\n return this.options.name;\n }\n\n /**\n * \n * @param key 获取数据表配置,也可以指定 key\n */\n public getOptions(key?: any): TableOptions {\n return key ? _.get(this.options, key) : this.options;\n }\n\n public getModel(): ModelCtor<Model> {\n return this.database.getModel(this.getName());\n }\n\n public getModelAttributes(): ModelAttributes {\n return this.modelAttributes;\n }\n\n public getModelOptions(): InitOptions {\n const {\n name,\n underscored = true,\n ...restOptions\n } = this.options;\n const hooks = _.get(this.getModel(), 'options.hooks') || this.options.hooks || {};\n return {\n underscored,\n modelName: name,\n tableName: name,\n sequelize: this.database.sequelize,\n createdAt: Utils.underscoredIf('createdAt', underscored),\n updatedAt: Utils.underscoredIf('updatedAt', underscored),\n indexes: Array.from(this.indexes.values()),\n // freezeTableName: true,\n ..._.omit(restOptions, ['model', 'fields', 'indexes']),\n hooks,\n };\n }\n\n /**\n * 获取相关 table names,一般用于 sync\n */\n public getRelatedTableNames(): Set<string> {\n const names = new Set<string>();\n this.options.name && names.add(this.options.name);\n for (const association of this.associations.values()) {\n const target = association.getTarget();\n target && names.add(target);\n if (association instanceof BELONGSTOMANY) {\n const throughName = association.getThroughName();\n throughName && names.add(throughName);\n }\n }\n return names;\n }\n\n public getAssociations() {\n return this.associations;\n }\n\n public getFields() {\n return this.fields;\n }\n\n public setFields(fields: Array<FieldOptions>) {\n this.fields.clear();\n this.associating.clear();\n this.associations.clear();\n for (const key in fields) {\n this.addField(fields[key], false);\n }\n this.modelInit(true);\n }\n\n public hasField(name: string) {\n return this.fields.has(name);\n }\n\n public getField(name: string) {\n return this.fields.get(name);\n }\n\n /**\n * 添加字段\n * \n * @param options \n * @param reinitialize \n */\n public addField(options: FieldOptions, reinitialize: Reinitialize = true) {\n this.database.runHooks('beforeAddField', options, this);\n this.database.emit('beforeAddField', options, this);\n const { name, index } = options;\n const field = buildField(options, {\n sourceTable: this,\n database: this.database,\n });\n // 添加字段后 table.options 中的 fields 并不会更新,这导致 table.getOptions() 拿不到最新的字段配置\n // 所以在同时更新 table.options.fields 数组\n if (!this.options.fields) {\n this.options.fields = [];\n }\n const existIndex = this.options.fields.findIndex(field => field.name === name);\n if (existIndex !== -1) {\n this.options.fields.splice(existIndex, 1, options);\n } else {\n this.options.fields.push(options);\n }\n\n this.fields.set(name, field);\n\n if (field instanceof Relation) {\n // 关系字段先放到 associating 里待处理,等相关 target model 初始化之后,再通过 associate 建立关系\n this.associating.set(name, field);\n this.associations.set(name, field);\n } else {\n if (index === true) {\n this.addIndex(name, false);\n } else if (typeof index === 'object') {\n this.addIndex({\n fields: [name],\n ...index,\n }, false);\n }\n this.modelAttributes[name] = field.getAttributeOptions();\n }\n this.modelInit(reinitialize);\n this.database.emit('afterAddField', field, this);\n this.database.runHooks('afterAddField', field, this);\n return field;\n }\n\n /**\n * 添加索引\n * \n * @param indexOptions \n * @param reinitialize \n */\n public addIndex(indexOptions: string | ModelIndexesOptions, reinitialize: Reinitialize = true) {\n const options = typeof indexOptions === 'string' ? {\n fields: [indexOptions],\n } : indexOptions;\n // @ts-ignore\n const index = Utils.nameIndex(options, this.options.name);\n console.log(this.options, { index, options });\n this.indexes.set(index.name, {\n type: '',\n parser: null,\n ...index,\n });\n this.modelInit(reinitialize);\n }\n\n /**\n * 批量添加索引\n * \n * @param indexes \n * @param reinitialize \n */\n public addIndexes(indexes: Array<string | ModelIndexesOptions>, reinitialize: Reinitialize = true) {\n for (const index in indexes) {\n this.addIndex(indexes[index], false);\n }\n this.modelInit(reinitialize);\n }\n\n /**\n * 扩展(实验性 API)\n * \n * @param options \n */\n public extend(options: TableOptions, mergeOptions: MergeOptions = {}) {\n const {\n fields = [],\n indexes = [],\n model,\n ...restOptions\n } = options;\n if (model) {\n this.defaultModel = getRegisteredModel(model);\n }\n const { arrayMerge = (target: any[], source: any[]) => source } = mergeOptions;\n this.options = merge(this.options, restOptions, {\n arrayMerge,\n ...mergeOptions,\n });\n for (const key in fields) {\n this.addField(fields[key], false);\n }\n this.initSortable();\n // @ts-ignore\n this.addIndexes(indexes, false);\n this.modelInit(true);\n }\n\n /**\n * 相关表字段更新\n * \n * @param options \n */\n public async sync(options: SyncOptions = {}) {\n const tables = [];\n for (const name of this.getRelatedTableNames()) {\n tables.push(name);\n }\n return this.database.sync({\n ...options,\n tables,\n });\n }\n}\n\nexport default Table;\n"]}
1
+ {"version":3,"sources":["table.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,eAAe,EACf,YAAY,EACZ,mBAAmB,EAEnB,WAAW,EACZ,MAAM,WAAW,CAAC;AACnB,OAAO,EAEL,YAAY,EACZ,QAAQ,EAIT,MAAM,UAAU,CAAC;AAClB,OAAO,QAAQ,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAE3C,OAAO,KAAK,MAAM,WAAW,CAAC;AAE9B,MAAM,WAAW,YAAa,SAAQ,KAAK,CAAC,OAAO;CAAG;AAItD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,QAEpD;AAED,wBAAgB,cAAc,CAAC,MAAM,KAAA,QAMpC;AAGD,wBAAgB,kBAAkB,CAAC,GAAG,KAAA,OAKrC;AAED,MAAM,WAAW,YACf,SAAQ,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IAUvD,IAAI,EAAE,MAAM,CAAC;IAKb,KAAK,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC;IAKlC,MAAM,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;IAK7B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAKD,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,QAAQ,CAAC;CACpB;AASD,oBAAY,YAAY,GAAG,OAAO,GAAG,WAAW,CAAC;AAOjD,qBAAa,KAAK;IAChB,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAE7B,SAAS,CAAC,OAAO,EAAE,YAAY,CAAC;IAEhC,SAAS,CAAC,MAAM,mBAA0B;IAE1C,SAAS,CAAC,eAAe,EAAE,eAAe,CAAC;IAE3C,SAAS,CAAC,YAAY,EAAE,WAAW,CAAC;IAKpC,SAAS,CAAC,YAAY,wBAA+B;IAKrD,SAAS,CAAC,WAAW,wBAA+B;IAKpD,SAAS,CAAC,OAAO,mBAA0B;IAE3C,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC;IAElC,SAAS,CAAC,YAAY,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC;IAKlC,cAAc,EAAE,OAAO,CAAS;IAEhC,cAAc,cAAqB;IAE1C,IAAI,QAAQ,IAAI,OAAO,CAItB;gBAEW,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY;IAoBjD,YAAY;IAkBZ,SAAS,CAAC,YAAY,GAAE,YAAoB;IA6C5C,OAAO,IAAI,MAAM;IAIjB,YAAY,IAAI,MAAM;IAQtB,UAAU,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,YAAY;IAInC,QAAQ,IAAI,SAAS,CAAC,KAAK,CAAC;IAI5B,kBAAkB,IAAI,eAAe;IAIrC,eAAe,IAAI,WAAW;IAqB9B,oBAAoB,IAAI,GAAG,CAAC,MAAM,CAAC;IAcnC,eAAe;IAIf,SAAS;IAIT,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,YAAY,CAAC;IAYrC,QAAQ,CAAC,IAAI,EAAE,MAAM;IAIrB,QAAQ,CAAC,IAAI,EAAE,MAAM;IAUrB,QAAQ,CAAC,OAAO,EAAE,YAAY,EAAE,YAAY,GAAE,YAAmB;IAsDjE,QAAQ,CACb,YAAY,EAAE,MAAM,GAAG,mBAAmB,EAC1C,YAAY,GAAE,YAAmB;IAyB5B,UAAU,CACf,OAAO,EAAE,KAAK,CAAC,MAAM,GAAG,mBAAmB,CAAC,EAC5C,YAAY,GAAE,YAAmB;IAa5B,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,YAAY,GAAE,YAAiB;IAyBvD,IAAI,CAAC,OAAO,GAAE,WAAgB;CAU5C;AAED,eAAe,KAAK,CAAC","file":"table.d.ts","sourcesContent":["import {\n InitOptions,\n ModelAttributes,\n ModelOptions,\n ModelIndexesOptions,\n Utils,\n SyncOptions,\n} from 'sequelize';\nimport {\n buildField,\n FieldOptions,\n Relation,\n BELONGSTO,\n BELONGSTOMANY,\n SORT,\n} from './fields';\nimport Database from './database';\nimport { Model, ModelCtor } from './model';\nimport _ from 'lodash';\nimport merge from 'deepmerge';\n\nexport interface MergeOptions extends merge.Options {}\n\nconst registeredModels = new Map<string, any>();\n\nexport function registerModel(key: string, model: any) {\n registeredModels.set(key, model);\n}\n\nexport function registerModels(models) {\n for (const key in models) {\n if (models.hasOwnProperty(key)) {\n registerModel(key, models[key]);\n }\n }\n}\n\n// TODO: 判断如果 key 是 model 直接返回\nexport function getRegisteredModel(key) {\n if (typeof key === 'string') {\n return registeredModels.get(key);\n }\n return key;\n}\n\nexport interface TableOptions\n extends Omit<ModelOptions<Model>, 'name' | 'modelName'> {\n /**\n * 唯一标识,与 ModelOptions 的 name 有区别\n *\n * 注意:name 可用于初始化 tableName、modelName,但是 tableName 和 modelName 可能有所不同\n * name 主要用于获取指定的 tables 和 models\n * 如果没有特殊指定 tableName 时,name、tableName、modelName 都是一个值\n *\n * TODO: name, tableName, modelName,freezeTableName,underscored,单复数等等情况还比较混乱\n */\n name: string;\n\n /**\n * 自定义 model\n */\n model?: ModelCtor<Model> | string;\n\n /**\n * 字段配置\n */\n fields?: Array<FieldOptions>;\n\n /**\n * 其他的一些情况\n */\n [key: string]: any;\n}\n\n/**\n * 上下文,Tabel 配置需要的其他变量\n */\nexport interface TableContext {\n database: Database;\n}\n\n/**\n * 是否重新初始化 Model。配置更新时,需要重新初始化 model。\n *\n * - reinitialize = false 只执行 Model.init\n * - reinitialize = true 重新初始化 Model 并执行 Model.init 和 Model.associate\n * - reinitialize = modelOnly 只初始化 Model 并执行 Model.init\n */\nexport type Reinitialize = boolean | 'modelOnly';\n\n/**\n * 表配置\n *\n * 用于处理相关 Model 的配置\n */\nexport class Table {\n protected database: Database;\n\n protected options: TableOptions;\n\n protected fields = new Map<string, any>();\n\n protected modelAttributes: ModelAttributes;\n\n protected modelOptions: InitOptions;\n\n /**\n * 全部关系字段的配置\n */\n protected associations = new Map<string, Relation>();\n\n /**\n * 待建立关系的 association\n */\n protected associating = new Map<string, Relation>();\n\n /**\n * 索引\n */\n protected indexes = new Map<string, any>();\n\n protected Model: ModelCtor<Model>;\n\n protected defaultModel: ModelCtor<Model>;\n\n /**\n * 是否是中间表\n */\n public isThroughTable: boolean = false;\n\n public relationTables = new Set<string>();\n\n get sortable(): boolean {\n return Array.from(this.fields.values()).some(\n (field) => field instanceof SORT,\n );\n }\n\n constructor(options: TableOptions, context: TableContext) {\n const { database } = context;\n database.runHooks('beforeTableInit', options);\n database.emit('beforeTableInit', options);\n const { model, fields = [], indexes = [], sortable } = options;\n this.options = options;\n this.database = database;\n // 初始化的时候获取\n this.defaultModel = getRegisteredModel(model);\n this.modelAttributes = {};\n // 在 set fields 之前 model init 的原因是因为关系字段可能需要用到 model 的相关配置\n // @ts-ignore\n this.addIndexes(indexes, 'modelOnly');\n // this.modelInit('modelOnly');\n this.setFields(fields);\n this.initSortable();\n database.emit('afterTableInit', this);\n database.runHooks('afterTableInit', this);\n }\n\n public initSortable() {\n const { sortable } = this.options;\n if (!sortable) {\n return;\n }\n if (typeof sortable === 'string') {\n this.addField({\n type: 'sort',\n name: sortable,\n });\n } else if (typeof sortable === 'object') {\n this.addField({\n ...sortable,\n type: 'sort',\n });\n }\n }\n\n public modelInit(reinitialize: Reinitialize = false) {\n if (reinitialize || !this.Model) {\n let DefaultModel = this.defaultModel;\n this.Model = DefaultModel\n ? class extends DefaultModel {}\n : class extends Model {};\n this.Model.database = this.database;\n // 关系的建立是在 model.init 之后,在配置中表字段(Column)和关系(Relation)都在 fields,\n // 所以需要单独提炼出 associations 字段,并在 Model.init 之后执行 Model.associate\n // @ts-ignore\n this.Model.associate = (models: { [key: string]: ModelCtor<Model> }) => {\n for (const [key, association] of this.associating) {\n const { type, target } = association.getAssociationArguments();\n if (this.database.isDefined(target)) {\n const TargetModel = this.database.getModel(target);\n // 如果关系表在之后才定义,未设置 targetKey 时,targetKey 默认值需要在 target model 初始化之后才能取到\n if (\n association instanceof BELONGSTO ||\n association instanceof BELONGSTOMANY\n ) {\n association.updateOptionsAfterTargetModelBeDefined();\n }\n this.Model[type](TargetModel, association.getAssociationOptions());\n // 建立关系之后,需要删除待处理的 associating,避免重复和提高效率\n this.associating.delete(key);\n }\n }\n };\n }\n\n this.Model.init(this.getModelAttributes(), this.getModelOptions());\n\n if (reinitialize === true) {\n this.associating = new Map(this.associations);\n // 需要额外处理 associating 的情况\n // 建立表关系需要遍历多个 Model,所以在这里需要标记哪些已定义的 Model 需要建立表关系\n if (this.associating.size > 0) {\n this.database.associating.add(this.options.name);\n } else {\n this.database.associating.delete(this.options.name);\n }\n this.database.associate();\n }\n }\n\n public getName(): string {\n return this.options.name;\n }\n\n public getTableName(): string {\n return this.options.name;\n }\n\n /**\n *\n * @param key 获取数据表配置,也可以指定 key\n */\n public getOptions(key?: any): TableOptions {\n return key ? _.get(this.options, key) : this.options;\n }\n\n public getModel(): ModelCtor<Model> {\n return this.database.getModel(this.getName());\n }\n\n public getModelAttributes(): ModelAttributes {\n return this.modelAttributes;\n }\n\n public getModelOptions(): InitOptions {\n const { name, underscored = true, ...restOptions } = this.options;\n const hooks =\n _.get(this.getModel(), 'options.hooks') || this.options.hooks || {};\n return {\n underscored,\n modelName: name,\n tableName: name,\n sequelize: this.database.sequelize,\n createdAt: Utils.underscoredIf('createdAt', underscored),\n updatedAt: Utils.underscoredIf('updatedAt', underscored),\n indexes: Array.from(this.indexes.values()),\n // freezeTableName: true,\n ..._.omit(restOptions, ['model', 'fields', 'indexes']),\n hooks,\n };\n }\n\n /**\n * 获取相关 table names,一般用于 sync\n */\n public getRelatedTableNames(): Set<string> {\n const names = new Set<string>();\n this.options.name && names.add(this.options.name);\n for (const association of this.associations.values()) {\n const target = association.getTarget();\n target && names.add(target);\n if (association instanceof BELONGSTOMANY) {\n const throughName = association.getThroughName();\n throughName && names.add(throughName);\n }\n }\n return names;\n }\n\n public getAssociations() {\n return this.associations;\n }\n\n public getFields() {\n return this.fields;\n }\n\n public setFields(fields: Array<FieldOptions>) {\n this.fields.clear();\n this.associating.clear();\n this.associations.clear();\n\n for (const filed of fields) {\n this.addField(filed, false);\n }\n\n this.modelInit(true);\n }\n\n public hasField(name: string) {\n return this.fields.has(name);\n }\n\n public getField(name: string) {\n return this.fields.get(name);\n }\n\n /**\n * 添加字段\n *\n * @param options\n * @param reinitialize\n */\n public addField(options: FieldOptions, reinitialize: Reinitialize = true) {\n this.database.runHooks('beforeAddField', options, this);\n this.database.emit('beforeAddField', options, this);\n const { name, index } = options;\n const field = buildField(options, {\n sourceTable: this,\n database: this.database,\n });\n // 添加字段后 table.options 中的 fields 并不会更新,这导致 table.getOptions() 拿不到最新的字段配置\n // 所以在同时更新 table.options.fields 数组\n if (!this.options.fields) {\n this.options.fields = [];\n }\n const existIndex = this.options.fields.findIndex(\n (field) => field.name === name,\n );\n if (existIndex !== -1) {\n this.options.fields.splice(existIndex, 1, options);\n } else {\n this.options.fields.push(options);\n }\n\n this.fields.set(name, field);\n\n if (field instanceof Relation) {\n // 关系字段先放到 associating 里待处理,等相关 target model 初始化之后,再通过 associate 建立关系\n this.associating.set(name, field);\n this.associations.set(name, field);\n } else {\n if (index === true) {\n this.addIndex(name, false);\n } else if (typeof index === 'object') {\n this.addIndex(\n {\n fields: [name],\n ...index,\n },\n false,\n );\n }\n this.modelAttributes[name] = field.getAttributeOptions();\n }\n this.modelInit(reinitialize);\n this.database.emit('afterAddField', field, this);\n this.database.runHooks('afterAddField', field, this);\n return field;\n }\n\n /**\n * 添加索引\n *\n * @param indexOptions\n * @param reinitialize\n */\n public addIndex(\n indexOptions: string | ModelIndexesOptions,\n reinitialize: Reinitialize = true,\n ) {\n const options =\n typeof indexOptions === 'string'\n ? {\n fields: [indexOptions],\n }\n : indexOptions;\n // @ts-ignore\n const index = Utils.nameIndex(options, this.options.name);\n console.log(this.options, { index, options });\n this.indexes.set(index.name, {\n type: '',\n parser: null,\n ...index,\n });\n this.modelInit(reinitialize);\n }\n\n /**\n * 批量添加索引\n *\n * @param indexes\n * @param reinitialize\n */\n public addIndexes(\n indexes: Array<string | ModelIndexesOptions>,\n reinitialize: Reinitialize = true,\n ) {\n for (const index in indexes) {\n this.addIndex(indexes[index], false);\n }\n this.modelInit(reinitialize);\n }\n\n /**\n * 扩展(实验性 API)\n *\n * @param options\n */\n public extend(options: TableOptions, mergeOptions: MergeOptions = {}) {\n const { fields = [], indexes = [], model, ...restOptions } = options;\n if (model) {\n this.defaultModel = getRegisteredModel(model);\n }\n const { arrayMerge = (target: any[], source: any[]) => source } =\n mergeOptions;\n this.options = merge(this.options, restOptions, {\n arrayMerge,\n ...mergeOptions,\n });\n for (const key in fields) {\n this.addField(fields[key], false);\n }\n this.initSortable();\n // @ts-ignore\n this.addIndexes(indexes, false);\n this.modelInit(true);\n }\n\n /**\n * 相关表字段更新\n *\n * @param options\n */\n public async sync(options: SyncOptions = {}) {\n const tables = [];\n for (const name of this.getRelatedTableNames()) {\n tables.push(name);\n }\n return this.database.sync({\n ...options,\n tables,\n });\n }\n}\n\nexport default Table;\n"]}
package/lib/table.js CHANGED
@@ -304,8 +304,18 @@ class Table {
304
304
  this.associating.clear();
305
305
  this.associations.clear();
306
306
 
307
- for (const key in fields) {
308
- this.addField(fields[key], false);
307
+ var _iterator3 = _createForOfIteratorHelper(fields),
308
+ _step3;
309
+
310
+ try {
311
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
312
+ const filed = _step3.value;
313
+ this.addField(filed, false);
314
+ }
315
+ } catch (err) {
316
+ _iterator3.e(err);
317
+ } finally {
318
+ _iterator3.f();
309
319
  }
310
320
 
311
321
  this.modelInit(true);
@@ -419,18 +429,18 @@ class Table {
419
429
  return __awaiter(this, void 0, void 0, function* () {
420
430
  const tables = [];
421
431
 
422
- var _iterator3 = _createForOfIteratorHelper(this.getRelatedTableNames()),
423
- _step3;
432
+ var _iterator4 = _createForOfIteratorHelper(this.getRelatedTableNames()),
433
+ _step4;
424
434
 
425
435
  try {
426
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
427
- const name = _step3.value;
436
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
437
+ const name = _step4.value;
428
438
  tables.push(name);
429
439
  }
430
440
  } catch (err) {
431
- _iterator3.e(err);
441
+ _iterator4.e(err);
432
442
  } finally {
433
- _iterator3.f();
443
+ _iterator4.f();
434
444
  }
435
445
 
436
446
  return this.database.sync(Object.assign(Object.assign({}, options), {
package/lib/table.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["table.ts"],"names":[],"mappings":"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","file":"table.js","sourcesContent":["import {\n InitOptions,\n ModelAttributes,\n ModelOptions,\n ModelIndexesOptions,\n Utils,\n SyncOptions,\n} from 'sequelize';\nimport {\n buildField,\n FieldOptions,\n Relation,\n BELONGSTO,\n BELONGSTOMANY,\n SORT\n} from './fields';\nimport Database from './database';\nimport { Model, ModelCtor } from './model';\nimport _ from 'lodash';\nimport merge from 'deepmerge';\n\nexport interface MergeOptions extends merge.Options {\n\n}\n\nconst registeredModels = new Map<string, any>();\n\nexport function registerModel(key: string, model: any) {\n registeredModels.set(key, model);\n}\n\nexport function registerModels(models) {\n for (const key in models) {\n if (models.hasOwnProperty(key)) {\n registerModel(key, models[key]);\n }\n }\n}\n\n// TODO: 判断如果 key 是 model 直接返回\nexport function getRegisteredModel(key) {\n if (typeof key === 'string') {\n return registeredModels.get(key);\n }\n return key;\n}\n\nexport interface TableOptions extends Omit<ModelOptions<Model>, 'name' | 'modelName'> {\n\n /**\n * 唯一标识,与 ModelOptions 的 name 有区别\n * \n * 注意:name 可用于初始化 tableName、modelName,但是 tableName 和 modelName 可能有所不同\n * name 主要用于获取指定的 tables 和 models\n * 如果没有特殊指定 tableName 时,name、tableName、modelName 都是一个值\n * \n * TODO: name, tableName, modelName,freezeTableName,underscored,单复数等等情况还比较混乱\n */\n name: string;\n\n /**\n * 自定义 model\n */\n model?: ModelCtor<Model> | string;\n\n /**\n * 字段配置\n */\n fields?: Array<FieldOptions>;\n\n /**\n * 其他的一些情况\n */\n [key: string]: any;\n}\n\n/**\n * 上下文,Tabel 配置需要的其他变量\n */\nexport interface TabelContext {\n database: Database;\n}\n\n/**\n * 是否重新初始化 Model。配置更新时,需要重新初始化 model。\n *\n * - reinitialize = false 只执行 Model.init\n * - reinitialize = true 重新初始化 Model 并执行 Model.init 和 Model.associate\n * - reinitialize = modelOnly 只初始化 Model 并执行 Model.init\n */\nexport type Reinitialize = boolean | 'modelOnly';\n\n/**\n * 表配置\n * \n * 用于处理相关 Model 的配置\n */\nexport class Table {\n\n protected database: Database;\n\n protected options: TableOptions;\n\n protected fields = new Map<string, any>();\n\n protected modelAttributes: ModelAttributes;\n\n protected modelOptions: InitOptions;\n\n /**\n * 全部关系字段的配置\n */\n protected associations = new Map<string, Relation>();\n\n /**\n * 待建立关系的 association\n */\n protected associating = new Map<string, Relation>();\n\n /**\n * 索引\n */\n protected indexes = new Map<string, any>();\n\n protected Model: ModelCtor<Model>;\n\n protected defaultModel: ModelCtor<Model>;\n\n /**\n * 是否是中间表\n */\n public isThroughTable: boolean = false;\n\n public relationTables = new Set<string>();\n\n get sortable(): boolean {\n return Array.from(this.fields.values()).some(field => field instanceof SORT);\n }\n\n constructor(options: TableOptions, context: TabelContext) {\n const { database } = context;\n database.runHooks('beforeTableInit', options);\n database.emit('beforeTableInit', options);\n const {\n model,\n fields = [],\n indexes = [],\n sortable,\n } = options;\n this.options = options;\n this.database = database;\n // 初始化的时候获取\n this.defaultModel = getRegisteredModel(model);\n this.modelAttributes = {};\n // 在 set fields 之前 model init 的原因是因为关系字段可能需要用到 model 的相关配置\n // @ts-ignore\n this.addIndexes(indexes, 'modelOnly');\n // this.modelInit('modelOnly');\n this.setFields(fields);\n this.initSortable();\n database.emit('afterTableInit', this);\n database.runHooks('afterTableInit', this);\n }\n\n public initSortable() {\n const { sortable } = this.options;\n if (!sortable) {\n return;\n }\n if (typeof sortable === 'string') {\n this.addField({\n type: 'sort',\n name: sortable,\n });\n } else if (typeof sortable === 'object') {\n this.addField({\n ...sortable,\n type: 'sort',\n });\n }\n }\n\n public modelInit(reinitialize: Reinitialize = false) {\n if (reinitialize || !this.Model) {\n let DefaultModel = this.defaultModel;\n this.Model = DefaultModel ? (class extends DefaultModel {}) : (class extends Model { });\n this.Model.database = this.database;\n // 关系的建立是在 model.init 之后,在配置中表字段(Column)和关系(Relation)都在 fields,\n // 所以需要单独提炼出 associations 字段,并在 Model.init 之后执行 Model.associate\n // @ts-ignore\n this.Model.associate = (models: { [key: string]: ModelCtor<Model> }) => {\n for (const [key, association] of this.associating) {\n const { type, target } = association.getAssociationArguments();\n if (this.database.isDefined(target)) {\n const TargetModel = this.database.getModel(target);\n // 如果关系表在之后才定义,未设置 targetKey 时,targetKey 默认值需要在 target model 初始化之后才能取到\n if (association instanceof BELONGSTO || association instanceof BELONGSTOMANY) {\n association.updateOptionsAfterTargetModelBeDefined();\n }\n this.Model[type](TargetModel, association.getAssociationOptions());\n // 建立关系之后,需要删除待处理的 associating,避免重复和提高效率\n this.associating.delete(key);\n }\n }\n }\n }\n\n this.Model.init(this.getModelAttributes(), this.getModelOptions());\n\n if (reinitialize === true) {\n this.associating = new Map(this.associations);\n // 需要额外处理 associating 的情况\n // 建立表关系需要遍历多个 Model,所以在这里需要标记哪些已定义的 Model 需要建立表关系\n if (this.associating.size > 0) {\n this.database.associating.add(this.options.name);\n } else {\n this.database.associating.delete(this.options.name);\n }\n this.database.associate();\n }\n }\n\n public getName(): string {\n return this.options.name;\n }\n\n public getTableName(): string {\n return this.options.name;\n }\n\n /**\n * \n * @param key 获取数据表配置,也可以指定 key\n */\n public getOptions(key?: any): TableOptions {\n return key ? _.get(this.options, key) : this.options;\n }\n\n public getModel(): ModelCtor<Model> {\n return this.database.getModel(this.getName());\n }\n\n public getModelAttributes(): ModelAttributes {\n return this.modelAttributes;\n }\n\n public getModelOptions(): InitOptions {\n const {\n name,\n underscored = true,\n ...restOptions\n } = this.options;\n const hooks = _.get(this.getModel(), 'options.hooks') || this.options.hooks || {};\n return {\n underscored,\n modelName: name,\n tableName: name,\n sequelize: this.database.sequelize,\n createdAt: Utils.underscoredIf('createdAt', underscored),\n updatedAt: Utils.underscoredIf('updatedAt', underscored),\n indexes: Array.from(this.indexes.values()),\n // freezeTableName: true,\n ..._.omit(restOptions, ['model', 'fields', 'indexes']),\n hooks,\n };\n }\n\n /**\n * 获取相关 table names,一般用于 sync\n */\n public getRelatedTableNames(): Set<string> {\n const names = new Set<string>();\n this.options.name && names.add(this.options.name);\n for (const association of this.associations.values()) {\n const target = association.getTarget();\n target && names.add(target);\n if (association instanceof BELONGSTOMANY) {\n const throughName = association.getThroughName();\n throughName && names.add(throughName);\n }\n }\n return names;\n }\n\n public getAssociations() {\n return this.associations;\n }\n\n public getFields() {\n return this.fields;\n }\n\n public setFields(fields: Array<FieldOptions>) {\n this.fields.clear();\n this.associating.clear();\n this.associations.clear();\n for (const key in fields) {\n this.addField(fields[key], false);\n }\n this.modelInit(true);\n }\n\n public hasField(name: string) {\n return this.fields.has(name);\n }\n\n public getField(name: string) {\n return this.fields.get(name);\n }\n\n /**\n * 添加字段\n * \n * @param options \n * @param reinitialize \n */\n public addField(options: FieldOptions, reinitialize: Reinitialize = true) {\n this.database.runHooks('beforeAddField', options, this);\n this.database.emit('beforeAddField', options, this);\n const { name, index } = options;\n const field = buildField(options, {\n sourceTable: this,\n database: this.database,\n });\n // 添加字段后 table.options 中的 fields 并不会更新,这导致 table.getOptions() 拿不到最新的字段配置\n // 所以在同时更新 table.options.fields 数组\n if (!this.options.fields) {\n this.options.fields = [];\n }\n const existIndex = this.options.fields.findIndex(field => field.name === name);\n if (existIndex !== -1) {\n this.options.fields.splice(existIndex, 1, options);\n } else {\n this.options.fields.push(options);\n }\n\n this.fields.set(name, field);\n\n if (field instanceof Relation) {\n // 关系字段先放到 associating 里待处理,等相关 target model 初始化之后,再通过 associate 建立关系\n this.associating.set(name, field);\n this.associations.set(name, field);\n } else {\n if (index === true) {\n this.addIndex(name, false);\n } else if (typeof index === 'object') {\n this.addIndex({\n fields: [name],\n ...index,\n }, false);\n }\n this.modelAttributes[name] = field.getAttributeOptions();\n }\n this.modelInit(reinitialize);\n this.database.emit('afterAddField', field, this);\n this.database.runHooks('afterAddField', field, this);\n return field;\n }\n\n /**\n * 添加索引\n * \n * @param indexOptions \n * @param reinitialize \n */\n public addIndex(indexOptions: string | ModelIndexesOptions, reinitialize: Reinitialize = true) {\n const options = typeof indexOptions === 'string' ? {\n fields: [indexOptions],\n } : indexOptions;\n // @ts-ignore\n const index = Utils.nameIndex(options, this.options.name);\n console.log(this.options, { index, options });\n this.indexes.set(index.name, {\n type: '',\n parser: null,\n ...index,\n });\n this.modelInit(reinitialize);\n }\n\n /**\n * 批量添加索引\n * \n * @param indexes \n * @param reinitialize \n */\n public addIndexes(indexes: Array<string | ModelIndexesOptions>, reinitialize: Reinitialize = true) {\n for (const index in indexes) {\n this.addIndex(indexes[index], false);\n }\n this.modelInit(reinitialize);\n }\n\n /**\n * 扩展(实验性 API)\n * \n * @param options \n */\n public extend(options: TableOptions, mergeOptions: MergeOptions = {}) {\n const {\n fields = [],\n indexes = [],\n model,\n ...restOptions\n } = options;\n if (model) {\n this.defaultModel = getRegisteredModel(model);\n }\n const { arrayMerge = (target: any[], source: any[]) => source } = mergeOptions;\n this.options = merge(this.options, restOptions, {\n arrayMerge,\n ...mergeOptions,\n });\n for (const key in fields) {\n this.addField(fields[key], false);\n }\n this.initSortable();\n // @ts-ignore\n this.addIndexes(indexes, false);\n this.modelInit(true);\n }\n\n /**\n * 相关表字段更新\n * \n * @param options \n */\n public async sync(options: SyncOptions = {}) {\n const tables = [];\n for (const name of this.getRelatedTableNames()) {\n tables.push(name);\n }\n return this.database.sync({\n ...options,\n tables,\n });\n }\n}\n\nexport default Table;\n"]}
1
+ {"version":3,"sources":["table.ts"],"names":[],"mappings":"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","file":"table.js","sourcesContent":["import {\n InitOptions,\n ModelAttributes,\n ModelOptions,\n ModelIndexesOptions,\n Utils,\n SyncOptions,\n} from 'sequelize';\nimport {\n buildField,\n FieldOptions,\n Relation,\n BELONGSTO,\n BELONGSTOMANY,\n SORT,\n} from './fields';\nimport Database from './database';\nimport { Model, ModelCtor } from './model';\nimport _ from 'lodash';\nimport merge from 'deepmerge';\n\nexport interface MergeOptions extends merge.Options {}\n\nconst registeredModels = new Map<string, any>();\n\nexport function registerModel(key: string, model: any) {\n registeredModels.set(key, model);\n}\n\nexport function registerModels(models) {\n for (const key in models) {\n if (models.hasOwnProperty(key)) {\n registerModel(key, models[key]);\n }\n }\n}\n\n// TODO: 判断如果 key 是 model 直接返回\nexport function getRegisteredModel(key) {\n if (typeof key === 'string') {\n return registeredModels.get(key);\n }\n return key;\n}\n\nexport interface TableOptions\n extends Omit<ModelOptions<Model>, 'name' | 'modelName'> {\n /**\n * 唯一标识,与 ModelOptions 的 name 有区别\n *\n * 注意:name 可用于初始化 tableName、modelName,但是 tableName 和 modelName 可能有所不同\n * name 主要用于获取指定的 tables 和 models\n * 如果没有特殊指定 tableName 时,name、tableName、modelName 都是一个值\n *\n * TODO: name, tableName, modelName,freezeTableName,underscored,单复数等等情况还比较混乱\n */\n name: string;\n\n /**\n * 自定义 model\n */\n model?: ModelCtor<Model> | string;\n\n /**\n * 字段配置\n */\n fields?: Array<FieldOptions>;\n\n /**\n * 其他的一些情况\n */\n [key: string]: any;\n}\n\n/**\n * 上下文,Tabel 配置需要的其他变量\n */\nexport interface TableContext {\n database: Database;\n}\n\n/**\n * 是否重新初始化 Model。配置更新时,需要重新初始化 model。\n *\n * - reinitialize = false 只执行 Model.init\n * - reinitialize = true 重新初始化 Model 并执行 Model.init 和 Model.associate\n * - reinitialize = modelOnly 只初始化 Model 并执行 Model.init\n */\nexport type Reinitialize = boolean | 'modelOnly';\n\n/**\n * 表配置\n *\n * 用于处理相关 Model 的配置\n */\nexport class Table {\n protected database: Database;\n\n protected options: TableOptions;\n\n protected fields = new Map<string, any>();\n\n protected modelAttributes: ModelAttributes;\n\n protected modelOptions: InitOptions;\n\n /**\n * 全部关系字段的配置\n */\n protected associations = new Map<string, Relation>();\n\n /**\n * 待建立关系的 association\n */\n protected associating = new Map<string, Relation>();\n\n /**\n * 索引\n */\n protected indexes = new Map<string, any>();\n\n protected Model: ModelCtor<Model>;\n\n protected defaultModel: ModelCtor<Model>;\n\n /**\n * 是否是中间表\n */\n public isThroughTable: boolean = false;\n\n public relationTables = new Set<string>();\n\n get sortable(): boolean {\n return Array.from(this.fields.values()).some(\n (field) => field instanceof SORT,\n );\n }\n\n constructor(options: TableOptions, context: TableContext) {\n const { database } = context;\n database.runHooks('beforeTableInit', options);\n database.emit('beforeTableInit', options);\n const { model, fields = [], indexes = [], sortable } = options;\n this.options = options;\n this.database = database;\n // 初始化的时候获取\n this.defaultModel = getRegisteredModel(model);\n this.modelAttributes = {};\n // 在 set fields 之前 model init 的原因是因为关系字段可能需要用到 model 的相关配置\n // @ts-ignore\n this.addIndexes(indexes, 'modelOnly');\n // this.modelInit('modelOnly');\n this.setFields(fields);\n this.initSortable();\n database.emit('afterTableInit', this);\n database.runHooks('afterTableInit', this);\n }\n\n public initSortable() {\n const { sortable } = this.options;\n if (!sortable) {\n return;\n }\n if (typeof sortable === 'string') {\n this.addField({\n type: 'sort',\n name: sortable,\n });\n } else if (typeof sortable === 'object') {\n this.addField({\n ...sortable,\n type: 'sort',\n });\n }\n }\n\n public modelInit(reinitialize: Reinitialize = false) {\n if (reinitialize || !this.Model) {\n let DefaultModel = this.defaultModel;\n this.Model = DefaultModel\n ? class extends DefaultModel {}\n : class extends Model {};\n this.Model.database = this.database;\n // 关系的建立是在 model.init 之后,在配置中表字段(Column)和关系(Relation)都在 fields,\n // 所以需要单独提炼出 associations 字段,并在 Model.init 之后执行 Model.associate\n // @ts-ignore\n this.Model.associate = (models: { [key: string]: ModelCtor<Model> }) => {\n for (const [key, association] of this.associating) {\n const { type, target } = association.getAssociationArguments();\n if (this.database.isDefined(target)) {\n const TargetModel = this.database.getModel(target);\n // 如果关系表在之后才定义,未设置 targetKey 时,targetKey 默认值需要在 target model 初始化之后才能取到\n if (\n association instanceof BELONGSTO ||\n association instanceof BELONGSTOMANY\n ) {\n association.updateOptionsAfterTargetModelBeDefined();\n }\n this.Model[type](TargetModel, association.getAssociationOptions());\n // 建立关系之后,需要删除待处理的 associating,避免重复和提高效率\n this.associating.delete(key);\n }\n }\n };\n }\n\n this.Model.init(this.getModelAttributes(), this.getModelOptions());\n\n if (reinitialize === true) {\n this.associating = new Map(this.associations);\n // 需要额外处理 associating 的情况\n // 建立表关系需要遍历多个 Model,所以在这里需要标记哪些已定义的 Model 需要建立表关系\n if (this.associating.size > 0) {\n this.database.associating.add(this.options.name);\n } else {\n this.database.associating.delete(this.options.name);\n }\n this.database.associate();\n }\n }\n\n public getName(): string {\n return this.options.name;\n }\n\n public getTableName(): string {\n return this.options.name;\n }\n\n /**\n *\n * @param key 获取数据表配置,也可以指定 key\n */\n public getOptions(key?: any): TableOptions {\n return key ? _.get(this.options, key) : this.options;\n }\n\n public getModel(): ModelCtor<Model> {\n return this.database.getModel(this.getName());\n }\n\n public getModelAttributes(): ModelAttributes {\n return this.modelAttributes;\n }\n\n public getModelOptions(): InitOptions {\n const { name, underscored = true, ...restOptions } = this.options;\n const hooks =\n _.get(this.getModel(), 'options.hooks') || this.options.hooks || {};\n return {\n underscored,\n modelName: name,\n tableName: name,\n sequelize: this.database.sequelize,\n createdAt: Utils.underscoredIf('createdAt', underscored),\n updatedAt: Utils.underscoredIf('updatedAt', underscored),\n indexes: Array.from(this.indexes.values()),\n // freezeTableName: true,\n ..._.omit(restOptions, ['model', 'fields', 'indexes']),\n hooks,\n };\n }\n\n /**\n * 获取相关 table names,一般用于 sync\n */\n public getRelatedTableNames(): Set<string> {\n const names = new Set<string>();\n this.options.name && names.add(this.options.name);\n for (const association of this.associations.values()) {\n const target = association.getTarget();\n target && names.add(target);\n if (association instanceof BELONGSTOMANY) {\n const throughName = association.getThroughName();\n throughName && names.add(throughName);\n }\n }\n return names;\n }\n\n public getAssociations() {\n return this.associations;\n }\n\n public getFields() {\n return this.fields;\n }\n\n public setFields(fields: Array<FieldOptions>) {\n this.fields.clear();\n this.associating.clear();\n this.associations.clear();\n\n for (const filed of fields) {\n this.addField(filed, false);\n }\n\n this.modelInit(true);\n }\n\n public hasField(name: string) {\n return this.fields.has(name);\n }\n\n public getField(name: string) {\n return this.fields.get(name);\n }\n\n /**\n * 添加字段\n *\n * @param options\n * @param reinitialize\n */\n public addField(options: FieldOptions, reinitialize: Reinitialize = true) {\n this.database.runHooks('beforeAddField', options, this);\n this.database.emit('beforeAddField', options, this);\n const { name, index } = options;\n const field = buildField(options, {\n sourceTable: this,\n database: this.database,\n });\n // 添加字段后 table.options 中的 fields 并不会更新,这导致 table.getOptions() 拿不到最新的字段配置\n // 所以在同时更新 table.options.fields 数组\n if (!this.options.fields) {\n this.options.fields = [];\n }\n const existIndex = this.options.fields.findIndex(\n (field) => field.name === name,\n );\n if (existIndex !== -1) {\n this.options.fields.splice(existIndex, 1, options);\n } else {\n this.options.fields.push(options);\n }\n\n this.fields.set(name, field);\n\n if (field instanceof Relation) {\n // 关系字段先放到 associating 里待处理,等相关 target model 初始化之后,再通过 associate 建立关系\n this.associating.set(name, field);\n this.associations.set(name, field);\n } else {\n if (index === true) {\n this.addIndex(name, false);\n } else if (typeof index === 'object') {\n this.addIndex(\n {\n fields: [name],\n ...index,\n },\n false,\n );\n }\n this.modelAttributes[name] = field.getAttributeOptions();\n }\n this.modelInit(reinitialize);\n this.database.emit('afterAddField', field, this);\n this.database.runHooks('afterAddField', field, this);\n return field;\n }\n\n /**\n * 添加索引\n *\n * @param indexOptions\n * @param reinitialize\n */\n public addIndex(\n indexOptions: string | ModelIndexesOptions,\n reinitialize: Reinitialize = true,\n ) {\n const options =\n typeof indexOptions === 'string'\n ? {\n fields: [indexOptions],\n }\n : indexOptions;\n // @ts-ignore\n const index = Utils.nameIndex(options, this.options.name);\n console.log(this.options, { index, options });\n this.indexes.set(index.name, {\n type: '',\n parser: null,\n ...index,\n });\n this.modelInit(reinitialize);\n }\n\n /**\n * 批量添加索引\n *\n * @param indexes\n * @param reinitialize\n */\n public addIndexes(\n indexes: Array<string | ModelIndexesOptions>,\n reinitialize: Reinitialize = true,\n ) {\n for (const index in indexes) {\n this.addIndex(indexes[index], false);\n }\n this.modelInit(reinitialize);\n }\n\n /**\n * 扩展(实验性 API)\n *\n * @param options\n */\n public extend(options: TableOptions, mergeOptions: MergeOptions = {}) {\n const { fields = [], indexes = [], model, ...restOptions } = options;\n if (model) {\n this.defaultModel = getRegisteredModel(model);\n }\n const { arrayMerge = (target: any[], source: any[]) => source } =\n mergeOptions;\n this.options = merge(this.options, restOptions, {\n arrayMerge,\n ...mergeOptions,\n });\n for (const key in fields) {\n this.addField(fields[key], false);\n }\n this.initSortable();\n // @ts-ignore\n this.addIndexes(indexes, false);\n this.modelInit(true);\n }\n\n /**\n * 相关表字段更新\n *\n * @param options\n */\n public async sync(options: SyncOptions = {}) {\n const tables = [];\n for (const name of this.getRelatedTableNames()) {\n tables.push(name);\n }\n return this.database.sync({\n ...options,\n tables,\n });\n }\n}\n\nexport default Table;\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAG3C,OAAO,QAAQ,MAAM,YAAY,CAAC;AAElC,UAAU,cAAc;IACtB,KAAK,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,OAAO,KAAK,CAAC;IAChD,YAAY,CAAC,EAAE,GAAG,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,MAAM,CAAC,EAAE,GAAG,CAAC;CACd;AAED,wBAAgB,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,GAAE,cAAmB,OAgFjE;AAED,UAAU,gBAAgB;IACxB,KAAK,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,OAAO,KAAK,CAAC;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,GAAG,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,GAAG,CAAC,EAAE,GAAG,CAAA;CACV;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,GAAG,MAAM,EAAE,EAAE,CA8BvE;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,GAAE,gBAAqB,OA+KrE;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,GAAG,OAAO,CAEpD;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,GAAG,OAQxC;AAED,wBAAgB,QAAQ,CAAC,GAAG,KAAA,WAQ3B;AAMD,wBAAgB,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,UAK/B","file":"utils.d.ts","sourcesContent":["import { Utils, Sequelize, Op } from 'sequelize';\nimport Model, { ModelCtor } from './model';\nimport _ from 'lodash';\nimport op from './op';\nimport Database from './database';\n\ninterface ToWhereContext {\n model?: ModelCtor<Model> | Model | typeof Model;\n associations?: any;\n dialect?: string;\n database?: Database;\n ctx?: any;\n prefix?: any;\n}\n\nexport function toWhere(options: any, context: ToWhereContext = {}) {\n if (options === null || typeof options !== 'object') {\n return options;\n }\n if (Array.isArray(options)) {\n return options.map((item) => toWhere(item, context));\n }\n const { prefix, model, associations = {}, ctx, dialect, database } = context;\n const items = {};\n // 先处理「点号」的问题\n for (const key in options) {\n _.set(items, key, options[key]);\n }\n let values = {};\n for (const key in items) {\n const childPreifx = prefix ? `${prefix}.${key}` : key;\n if (associations[key]) {\n values['$__include'] = values['$__include'] || {}\n values['$__include'][key] = toWhere(items[key], {\n ...context,\n prefix: childPreifx,\n model: associations[key].target,\n associations: associations[key].target.associations,\n });\n }\n else if (model && model.options.scopes && model.options.scopes[key]) {\n values['$__scopes'] = values['$__scopes'] || [];\n const scope = model.options.scopes[key];\n if (typeof scope === 'function') {\n values['$__scopes'].push({ method: [key, items[key], ctx] });\n } else {\n values['$__scopes'].push(key);\n }\n }\n else {\n // TODO: to fix same op key as field name\n const opKey = op.get(key);\n let k;\n switch (typeof opKey) {\n case 'function':\n const name = model ? model.name : '';\n const result = opKey(items[key], {\n ctx,\n model,\n database,\n fieldPath: name ? `${name}.${prefix}` : prefix,\n });\n if (result.constructor.name === 'Literal') {\n values['$__literals'] = values['$__literals'] || [];\n values['$__literals'].push(result);\n } else {\n Object.assign(values, result);\n }\n // console.log(result.constructor.name === 'Literal');\n continue;\n case 'undefined':\n k = key;\n break;\n default:\n k = opKey;\n break;\n }\n values[k] = toWhere(items[key], {\n ...context,\n prefix: op.has(key) ? prefix : childPreifx,\n });\n }\n }\n if (values['$__literals']) {\n const $__literals = _.cloneDeep(values['$__literals']);\n delete values['$__literals'];\n console.log(Object.keys(values));\n return {\n [Op.and]: [\n ...$__literals,\n values,\n ],\n }\n }\n return values;\n}\n\ninterface ToIncludeContext {\n model?: ModelCtor<Model> | Model | typeof Model;\n sourceAlias?: string;\n associations?: any;\n dialect?: string;\n database?: Database;\n ctx?: any\n}\n\nexport function toOrder(sort: string | string[], model: any): string[][] {\n if (sort && typeof sort === 'string') {\n sort = sort.split(',');\n }\n\n const order = [];\n\n if (Array.isArray(sort) && sort.length > 0) {\n sort.forEach(key => {\n if (Array.isArray(key)) {\n order.push(key);\n } else {\n const direction = key[0] === '-' ? 'DESC' : 'ASC';\n const keys = key.replace(/^-/, '').split('.');\n const field = keys.pop();\n const by = [];\n let associationModel = model;\n for (let i = 0; i < keys.length; i++) {\n const association = model.associations[keys[i]];\n if (association && association.target) {\n associationModel = association.target;\n by.push(associationModel);\n }\n }\n order.push([...by, field, direction]);\n }\n });\n }\n\n return order;\n}\n\nexport function toInclude(options: any, context: ToIncludeContext = {}) {\n function makeFields(key: string) {\n if (!Array.isArray(items[key])) {\n return;\n }\n items[key].forEach(field => {\n // 按点分隔转化为数组\n const [col, ...arr]: string[] = Array.isArray(field) ? Utils.cloneDeep(field) : field.split('.');\n // 内嵌的情况\n if (arr.length > 0) {\n if (!children.has(col)) {\n children.set(col, {\n fields: {\n only: [],\n except: [],\n appends: [],\n },\n });\n }\n children.get(col).fields[key].push(arr);\n return;\n }\n if (key !== 'except') {\n // 关系字段\n if (associations[col]) {\n const includeItem: any = {\n association: col,\n };\n if (includeWhere[col]) {\n includeItem.where = includeWhere[col];\n }\n include.set(col, includeItem);\n return;\n }\n // 计数字段\n const matches: Array<any> = col.match(/(.+)_count$/);\n if (matches && associations[matches[1]]) {\n attributes[key].push(model.withCountAttribute({\n association: matches[1],\n sourceAlias: sourceAlias\n }));\n return;\n }\n } else {\n if (!attributes.except) {\n attributes.except = [];\n }\n }\n attributes[key].push(col);\n });\n }\n\n const { fields = [], filter } = options;\n const { model, sourceAlias, associations = {}, ctx, database, dialect } = context;\n\n let where = options.where || {};\n\n if (filter) {\n where = toWhere(filter, {\n model,\n associations,\n ctx,\n database,\n }) || {};\n }\n\n const includeWhere = Utils.cloneDeep(where.$__include || {});\n const scopes = Utils.cloneDeep(where.$__scopes || []);\n\n delete where.$__include;\n delete where.$__scopes;\n\n const attributes = {\n only: [],\n except: [],\n appends: [],\n };\n\n const include = new Map();\n const children = new Map();\n\n const items = Array.isArray(fields) ? { only: fields } : fields;\n items.appends = items.appends || [];\n\n makeFields('only');\n makeFields('appends');\n makeFields('except');\n\n for (const whereKey in includeWhere) {\n if (children.has(whereKey)) {\n children.get(whereKey).where = includeWhere[whereKey];\n } else {\n children.set(whereKey, {\n association: whereKey,\n fields: [],\n where: includeWhere[whereKey],\n });\n }\n }\n\n for (const [key, child] of children) {\n const result = toInclude(child, {\n ...context,\n model: associations[key].target,\n sourceAlias: key,\n associations: associations[key].target.associations,\n });\n const item: any = {\n association: key,\n }\n if (result.attributes) {\n item.attributes = result.attributes;\n }\n if (result.include) {\n item.include = result.include;\n }\n if (result.where) {\n item.where = result.where;\n }\n if (result.scopes) {\n item.model = associations[key].target.scope(result.scopes);\n }\n // 解决同时有关联和关联的子级关联时,关联的 attribute 被设置为空数组的问题\n // ['user.profile.age', 'user.status', 'user', 'title', 'status']\n if (include.has(key) && Array.isArray(item.attributes) && !item.attributes.length) {\n delete item.attributes;\n }\n include.set(key, item);\n }\n\n const data: any = {};\n\n // 存在黑名单时\n if (attributes.except.length) {\n data.attributes = {\n exclude: attributes.except,\n };\n if (attributes.appends.length) {\n data.attributes.include = attributes.appends;\n }\n }\n // 存在白名单时\n else if (attributes.only.length) {\n data.attributes = [...attributes.only, ...attributes.appends];\n }\n // 只有附加字段时\n else if (attributes.appends.length) {\n data.attributes = {\n include: attributes.appends,\n };\n }\n\n if (include.size) {\n if (!data.attributes) {\n data.attributes = [];\n }\n data.include = Array.from(include.values());\n data.distinct = true;\n }\n\n if (Reflect.ownKeys(where).length) {\n data.where = where;\n }\n\n if (scopes.length) {\n data.scopes = scopes;\n }\n\n const order = toOrder(options.sort, model);\n\n if (order.length) {\n data.order = order;\n }\n\n return data;\n}\n\nexport function whereCompare(a: any, b: any): boolean {\n return _.isEqual(a, b);\n}\n\nexport function requireModule(module: any) {\n if (typeof module === 'string') {\n module = require(module);\n }\n if (typeof module !== 'object') {\n return module;\n }\n return module.__esModule ? module.default : module;\n}\n\nexport function isNumber(num) {\n if (typeof num === 'number') {\n return num - num === 0;\n }\n if (typeof num === 'string' && num.trim() !== '') {\n return Number.isFinite ? Number.isFinite(+num) : isFinite(+num);\n }\n return false;\n};\n\nlet IDX = 36,\n HEX = ''\nwhile (IDX--) HEX += IDX.toString(36)\n\nexport function uid(len?: number) {\n let str = '',\n num = len || 11\n while (num--) str += HEX[(Math.random() * 36) | 0]\n return str\n}\n"]}
1
+ {"version":3,"sources":["utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAG3C,OAAO,QAAQ,MAAM,YAAY,CAAC;AAElC,UAAU,cAAc;IACtB,KAAK,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,OAAO,KAAK,CAAC;IAChD,YAAY,CAAC,EAAE,GAAG,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,MAAM,CAAC,EAAE,GAAG,CAAC;CACd;AAED,wBAAgB,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,GAAE,cAAmB,OAiFjE;AAED,UAAU,gBAAgB;IACxB,KAAK,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,OAAO,KAAK,CAAC;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,GAAG,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,GAAG,CAAC,EAAE,GAAG,CAAA;CACV;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,GAAG,MAAM,EAAE,EAAE,CA8BvE;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,GAAE,gBAAqB,OA+KrE;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,GAAG,OAAO,CAEpD;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,GAAG,OAQxC;AAED,wBAAgB,QAAQ,CAAC,GAAG,KAAA,WAQ3B;AAMD,wBAAgB,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,UAK/B","file":"utils.d.ts","sourcesContent":["import { Utils, Sequelize, Op } from 'sequelize';\nimport Model, { ModelCtor } from './model';\nimport _ from 'lodash';\nimport op from './op';\nimport Database from './database';\n\ninterface ToWhereContext {\n model?: ModelCtor<Model> | Model | typeof Model;\n associations?: any;\n dialect?: string;\n database?: Database;\n ctx?: any;\n prefix?: any;\n}\n\nexport function toWhere(options: any, context: ToWhereContext = {}) {\n if (options === null || typeof options !== 'object') {\n return options;\n }\n if (Array.isArray(options)) {\n return options.map((item) => toWhere(item, context));\n }\n const { prefix, model, associations = {}, ctx, dialect, database } = context;\n const items = {};\n // 先处理「点号」的问题\n for (const key in options) {\n _.set(items, key, options[key]);\n }\n let values = {};\n for (const key in items) {\n const childPreifx = prefix ? `${prefix}.${key}` : key;\n if (associations[key]) {\n values['$__include'] = values['$__include'] || {}\n values['$__include'][key] = toWhere(items[key], {\n ...context,\n prefix: childPreifx,\n model: associations[key].target,\n associations: associations[key].target.associations,\n });\n }\n else if (model && model.options.scopes && model.options.scopes[key]) {\n values['$__scopes'] = values['$__scopes'] || [];\n const scope = model.options.scopes[key];\n if (typeof scope === 'function') {\n values['$__scopes'].push({ method: [key, items[key], ctx] });\n } else {\n values['$__scopes'].push(key);\n }\n }\n else {\n // TODO: to fix same op key as field name\n const opKey = op.get(key);\n let k;\n switch (typeof opKey) {\n case 'function':\n const name = model ? model.name : '';\n const result = opKey(items[key], {\n ctx,\n model,\n database,\n dialect: database.sequelize.getDialect(),\n fieldPath: name ? `${name}.${prefix}` : prefix,\n });\n if (result.constructor.name === 'Literal') {\n values['$__literals'] = values['$__literals'] || [];\n values['$__literals'].push(result);\n } else {\n Object.assign(values, result);\n }\n // console.log(result.constructor.name === 'Literal');\n continue;\n case 'undefined':\n k = key;\n break;\n default:\n k = opKey;\n break;\n }\n values[k] = toWhere(items[key], {\n ...context,\n prefix: op.has(key) ? prefix : childPreifx,\n });\n }\n }\n if (values['$__literals']) {\n const $__literals = _.cloneDeep(values['$__literals']);\n delete values['$__literals'];\n console.log(Object.keys(values));\n return {\n [Op.and]: [\n ...$__literals,\n values,\n ],\n }\n }\n return values;\n}\n\ninterface ToIncludeContext {\n model?: ModelCtor<Model> | Model | typeof Model;\n sourceAlias?: string;\n associations?: any;\n dialect?: string;\n database?: Database;\n ctx?: any\n}\n\nexport function toOrder(sort: string | string[], model: any): string[][] {\n if (sort && typeof sort === 'string') {\n sort = sort.split(',');\n }\n\n const order = [];\n\n if (Array.isArray(sort) && sort.length > 0) {\n sort.forEach(key => {\n if (Array.isArray(key)) {\n order.push(key);\n } else {\n const direction = key[0] === '-' ? 'DESC' : 'ASC';\n const keys = key.replace(/^-/, '').split('.');\n const field = keys.pop();\n const by = [];\n let associationModel = model;\n for (let i = 0; i < keys.length; i++) {\n const association = model.associations[keys[i]];\n if (association && association.target) {\n associationModel = association.target;\n by.push(associationModel);\n }\n }\n order.push([...by, field, direction]);\n }\n });\n }\n\n return order;\n}\n\nexport function toInclude(options: any, context: ToIncludeContext = {}) {\n function makeFields(key: string) {\n if (!Array.isArray(items[key])) {\n return;\n }\n items[key].forEach(field => {\n // 按点分隔转化为数组\n const [col, ...arr]: string[] = Array.isArray(field) ? Utils.cloneDeep(field) : field.split('.');\n // 内嵌的情况\n if (arr.length > 0) {\n if (!children.has(col)) {\n children.set(col, {\n fields: {\n only: [],\n except: [],\n appends: [],\n },\n });\n }\n children.get(col).fields[key].push(arr);\n return;\n }\n if (key !== 'except') {\n // 关系字段\n if (associations[col]) {\n const includeItem: any = {\n association: col,\n };\n if (includeWhere[col]) {\n includeItem.where = includeWhere[col];\n }\n include.set(col, includeItem);\n return;\n }\n // 计数字段\n const matches: Array<any> = col.match(/(.+)_count$/);\n if (matches && associations[matches[1]]) {\n attributes[key].push(model.withCountAttribute({\n association: matches[1],\n sourceAlias: sourceAlias\n }));\n return;\n }\n } else {\n if (!attributes.except) {\n attributes.except = [];\n }\n }\n attributes[key].push(col);\n });\n }\n\n const { fields = [], filter } = options;\n const { model, sourceAlias, associations = {}, ctx, database, dialect } = context;\n\n let where = options.where || {};\n\n if (filter) {\n where = toWhere(filter, {\n model,\n associations,\n ctx,\n database,\n }) || {};\n }\n\n const includeWhere = Utils.cloneDeep(where.$__include || {});\n const scopes = Utils.cloneDeep(where.$__scopes || []);\n\n delete where.$__include;\n delete where.$__scopes;\n\n const attributes = {\n only: [],\n except: [],\n appends: [],\n };\n\n const include = new Map();\n const children = new Map();\n\n const items = Array.isArray(fields) ? { only: fields } : fields;\n items.appends = items.appends || [];\n\n makeFields('only');\n makeFields('appends');\n makeFields('except');\n\n for (const whereKey in includeWhere) {\n if (children.has(whereKey)) {\n children.get(whereKey).where = includeWhere[whereKey];\n } else {\n children.set(whereKey, {\n association: whereKey,\n fields: [],\n where: includeWhere[whereKey],\n });\n }\n }\n\n for (const [key, child] of children) {\n const result = toInclude(child, {\n ...context,\n model: associations[key].target,\n sourceAlias: key,\n associations: associations[key].target.associations,\n });\n const item: any = {\n association: key,\n }\n if (result.attributes) {\n item.attributes = result.attributes;\n }\n if (result.include) {\n item.include = result.include;\n }\n if (result.where) {\n item.where = result.where;\n }\n if (result.scopes) {\n item.model = associations[key].target.scope(result.scopes);\n }\n // 解决同时有关联和关联的子级关联时,关联的 attribute 被设置为空数组的问题\n // ['user.profile.age', 'user.status', 'user', 'title', 'status']\n if (include.has(key) && Array.isArray(item.attributes) && !item.attributes.length) {\n delete item.attributes;\n }\n include.set(key, item);\n }\n\n const data: any = {};\n\n // 存在黑名单时\n if (attributes.except.length) {\n data.attributes = {\n exclude: attributes.except,\n };\n if (attributes.appends.length) {\n data.attributes.include = attributes.appends;\n }\n }\n // 存在白名单时\n else if (attributes.only.length) {\n data.attributes = [...attributes.only, ...attributes.appends];\n }\n // 只有附加字段时\n else if (attributes.appends.length) {\n data.attributes = {\n include: attributes.appends,\n };\n }\n\n if (include.size) {\n if (!data.attributes) {\n data.attributes = [];\n }\n data.include = Array.from(include.values());\n data.distinct = true;\n }\n\n if (Reflect.ownKeys(where).length) {\n data.where = where;\n }\n\n if (scopes.length) {\n data.scopes = scopes;\n }\n\n const order = toOrder(options.sort, model);\n\n if (order.length) {\n data.order = order;\n }\n\n return data;\n}\n\nexport function whereCompare(a: any, b: any): boolean {\n return _.isEqual(a, b);\n}\n\nexport function requireModule(module: any) {\n if (typeof module === 'string') {\n module = require(module);\n }\n if (typeof module !== 'object') {\n return module;\n }\n return module.__esModule ? module.default : module;\n}\n\nexport function isNumber(num) {\n if (typeof num === 'number') {\n return num - num === 0;\n }\n if (typeof num === 'string' && num.trim() !== '') {\n return Number.isFinite ? Number.isFinite(+num) : isFinite(+num);\n }\n return false;\n};\n\nlet IDX = 36,\n HEX = ''\nwhile (IDX--) HEX += IDX.toString(36)\n\nexport function uid(len?: number) {\n let str = '',\n num = len || 11\n while (num--) str += HEX[(Math.random() * 36) | 0]\n return str\n}\n"]}
package/lib/utils.js CHANGED
@@ -103,6 +103,7 @@ function toWhere(options, context = {}) {
103
103
  ctx,
104
104
  model,
105
105
  database,
106
+ dialect: database.sequelize.getDialect(),
106
107
  fieldPath: name ? `${name}.${prefix}` : prefix
107
108
  });
108
109
 
package/lib/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["utils.ts"],"names":[],"mappings":"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","file":"utils.js","sourcesContent":["import { Utils, Sequelize, Op } from 'sequelize';\nimport Model, { ModelCtor } from './model';\nimport _ from 'lodash';\nimport op from './op';\nimport Database from './database';\n\ninterface ToWhereContext {\n model?: ModelCtor<Model> | Model | typeof Model;\n associations?: any;\n dialect?: string;\n database?: Database;\n ctx?: any;\n prefix?: any;\n}\n\nexport function toWhere(options: any, context: ToWhereContext = {}) {\n if (options === null || typeof options !== 'object') {\n return options;\n }\n if (Array.isArray(options)) {\n return options.map((item) => toWhere(item, context));\n }\n const { prefix, model, associations = {}, ctx, dialect, database } = context;\n const items = {};\n // 先处理「点号」的问题\n for (const key in options) {\n _.set(items, key, options[key]);\n }\n let values = {};\n for (const key in items) {\n const childPreifx = prefix ? `${prefix}.${key}` : key;\n if (associations[key]) {\n values['$__include'] = values['$__include'] || {}\n values['$__include'][key] = toWhere(items[key], {\n ...context,\n prefix: childPreifx,\n model: associations[key].target,\n associations: associations[key].target.associations,\n });\n }\n else if (model && model.options.scopes && model.options.scopes[key]) {\n values['$__scopes'] = values['$__scopes'] || [];\n const scope = model.options.scopes[key];\n if (typeof scope === 'function') {\n values['$__scopes'].push({ method: [key, items[key], ctx] });\n } else {\n values['$__scopes'].push(key);\n }\n }\n else {\n // TODO: to fix same op key as field name\n const opKey = op.get(key);\n let k;\n switch (typeof opKey) {\n case 'function':\n const name = model ? model.name : '';\n const result = opKey(items[key], {\n ctx,\n model,\n database,\n fieldPath: name ? `${name}.${prefix}` : prefix,\n });\n if (result.constructor.name === 'Literal') {\n values['$__literals'] = values['$__literals'] || [];\n values['$__literals'].push(result);\n } else {\n Object.assign(values, result);\n }\n // console.log(result.constructor.name === 'Literal');\n continue;\n case 'undefined':\n k = key;\n break;\n default:\n k = opKey;\n break;\n }\n values[k] = toWhere(items[key], {\n ...context,\n prefix: op.has(key) ? prefix : childPreifx,\n });\n }\n }\n if (values['$__literals']) {\n const $__literals = _.cloneDeep(values['$__literals']);\n delete values['$__literals'];\n console.log(Object.keys(values));\n return {\n [Op.and]: [\n ...$__literals,\n values,\n ],\n }\n }\n return values;\n}\n\ninterface ToIncludeContext {\n model?: ModelCtor<Model> | Model | typeof Model;\n sourceAlias?: string;\n associations?: any;\n dialect?: string;\n database?: Database;\n ctx?: any\n}\n\nexport function toOrder(sort: string | string[], model: any): string[][] {\n if (sort && typeof sort === 'string') {\n sort = sort.split(',');\n }\n\n const order = [];\n\n if (Array.isArray(sort) && sort.length > 0) {\n sort.forEach(key => {\n if (Array.isArray(key)) {\n order.push(key);\n } else {\n const direction = key[0] === '-' ? 'DESC' : 'ASC';\n const keys = key.replace(/^-/, '').split('.');\n const field = keys.pop();\n const by = [];\n let associationModel = model;\n for (let i = 0; i < keys.length; i++) {\n const association = model.associations[keys[i]];\n if (association && association.target) {\n associationModel = association.target;\n by.push(associationModel);\n }\n }\n order.push([...by, field, direction]);\n }\n });\n }\n\n return order;\n}\n\nexport function toInclude(options: any, context: ToIncludeContext = {}) {\n function makeFields(key: string) {\n if (!Array.isArray(items[key])) {\n return;\n }\n items[key].forEach(field => {\n // 按点分隔转化为数组\n const [col, ...arr]: string[] = Array.isArray(field) ? Utils.cloneDeep(field) : field.split('.');\n // 内嵌的情况\n if (arr.length > 0) {\n if (!children.has(col)) {\n children.set(col, {\n fields: {\n only: [],\n except: [],\n appends: [],\n },\n });\n }\n children.get(col).fields[key].push(arr);\n return;\n }\n if (key !== 'except') {\n // 关系字段\n if (associations[col]) {\n const includeItem: any = {\n association: col,\n };\n if (includeWhere[col]) {\n includeItem.where = includeWhere[col];\n }\n include.set(col, includeItem);\n return;\n }\n // 计数字段\n const matches: Array<any> = col.match(/(.+)_count$/);\n if (matches && associations[matches[1]]) {\n attributes[key].push(model.withCountAttribute({\n association: matches[1],\n sourceAlias: sourceAlias\n }));\n return;\n }\n } else {\n if (!attributes.except) {\n attributes.except = [];\n }\n }\n attributes[key].push(col);\n });\n }\n\n const { fields = [], filter } = options;\n const { model, sourceAlias, associations = {}, ctx, database, dialect } = context;\n\n let where = options.where || {};\n\n if (filter) {\n where = toWhere(filter, {\n model,\n associations,\n ctx,\n database,\n }) || {};\n }\n\n const includeWhere = Utils.cloneDeep(where.$__include || {});\n const scopes = Utils.cloneDeep(where.$__scopes || []);\n\n delete where.$__include;\n delete where.$__scopes;\n\n const attributes = {\n only: [],\n except: [],\n appends: [],\n };\n\n const include = new Map();\n const children = new Map();\n\n const items = Array.isArray(fields) ? { only: fields } : fields;\n items.appends = items.appends || [];\n\n makeFields('only');\n makeFields('appends');\n makeFields('except');\n\n for (const whereKey in includeWhere) {\n if (children.has(whereKey)) {\n children.get(whereKey).where = includeWhere[whereKey];\n } else {\n children.set(whereKey, {\n association: whereKey,\n fields: [],\n where: includeWhere[whereKey],\n });\n }\n }\n\n for (const [key, child] of children) {\n const result = toInclude(child, {\n ...context,\n model: associations[key].target,\n sourceAlias: key,\n associations: associations[key].target.associations,\n });\n const item: any = {\n association: key,\n }\n if (result.attributes) {\n item.attributes = result.attributes;\n }\n if (result.include) {\n item.include = result.include;\n }\n if (result.where) {\n item.where = result.where;\n }\n if (result.scopes) {\n item.model = associations[key].target.scope(result.scopes);\n }\n // 解决同时有关联和关联的子级关联时,关联的 attribute 被设置为空数组的问题\n // ['user.profile.age', 'user.status', 'user', 'title', 'status']\n if (include.has(key) && Array.isArray(item.attributes) && !item.attributes.length) {\n delete item.attributes;\n }\n include.set(key, item);\n }\n\n const data: any = {};\n\n // 存在黑名单时\n if (attributes.except.length) {\n data.attributes = {\n exclude: attributes.except,\n };\n if (attributes.appends.length) {\n data.attributes.include = attributes.appends;\n }\n }\n // 存在白名单时\n else if (attributes.only.length) {\n data.attributes = [...attributes.only, ...attributes.appends];\n }\n // 只有附加字段时\n else if (attributes.appends.length) {\n data.attributes = {\n include: attributes.appends,\n };\n }\n\n if (include.size) {\n if (!data.attributes) {\n data.attributes = [];\n }\n data.include = Array.from(include.values());\n data.distinct = true;\n }\n\n if (Reflect.ownKeys(where).length) {\n data.where = where;\n }\n\n if (scopes.length) {\n data.scopes = scopes;\n }\n\n const order = toOrder(options.sort, model);\n\n if (order.length) {\n data.order = order;\n }\n\n return data;\n}\n\nexport function whereCompare(a: any, b: any): boolean {\n return _.isEqual(a, b);\n}\n\nexport function requireModule(module: any) {\n if (typeof module === 'string') {\n module = require(module);\n }\n if (typeof module !== 'object') {\n return module;\n }\n return module.__esModule ? module.default : module;\n}\n\nexport function isNumber(num) {\n if (typeof num === 'number') {\n return num - num === 0;\n }\n if (typeof num === 'string' && num.trim() !== '') {\n return Number.isFinite ? Number.isFinite(+num) : isFinite(+num);\n }\n return false;\n};\n\nlet IDX = 36,\n HEX = ''\nwhile (IDX--) HEX += IDX.toString(36)\n\nexport function uid(len?: number) {\n let str = '',\n num = len || 11\n while (num--) str += HEX[(Math.random() * 36) | 0]\n return str\n}\n"]}
1
+ {"version":3,"sources":["utils.ts"],"names":[],"mappings":"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","file":"utils.js","sourcesContent":["import { Utils, Sequelize, Op } from 'sequelize';\nimport Model, { ModelCtor } from './model';\nimport _ from 'lodash';\nimport op from './op';\nimport Database from './database';\n\ninterface ToWhereContext {\n model?: ModelCtor<Model> | Model | typeof Model;\n associations?: any;\n dialect?: string;\n database?: Database;\n ctx?: any;\n prefix?: any;\n}\n\nexport function toWhere(options: any, context: ToWhereContext = {}) {\n if (options === null || typeof options !== 'object') {\n return options;\n }\n if (Array.isArray(options)) {\n return options.map((item) => toWhere(item, context));\n }\n const { prefix, model, associations = {}, ctx, dialect, database } = context;\n const items = {};\n // 先处理「点号」的问题\n for (const key in options) {\n _.set(items, key, options[key]);\n }\n let values = {};\n for (const key in items) {\n const childPreifx = prefix ? `${prefix}.${key}` : key;\n if (associations[key]) {\n values['$__include'] = values['$__include'] || {}\n values['$__include'][key] = toWhere(items[key], {\n ...context,\n prefix: childPreifx,\n model: associations[key].target,\n associations: associations[key].target.associations,\n });\n }\n else if (model && model.options.scopes && model.options.scopes[key]) {\n values['$__scopes'] = values['$__scopes'] || [];\n const scope = model.options.scopes[key];\n if (typeof scope === 'function') {\n values['$__scopes'].push({ method: [key, items[key], ctx] });\n } else {\n values['$__scopes'].push(key);\n }\n }\n else {\n // TODO: to fix same op key as field name\n const opKey = op.get(key);\n let k;\n switch (typeof opKey) {\n case 'function':\n const name = model ? model.name : '';\n const result = opKey(items[key], {\n ctx,\n model,\n database,\n dialect: database.sequelize.getDialect(),\n fieldPath: name ? `${name}.${prefix}` : prefix,\n });\n if (result.constructor.name === 'Literal') {\n values['$__literals'] = values['$__literals'] || [];\n values['$__literals'].push(result);\n } else {\n Object.assign(values, result);\n }\n // console.log(result.constructor.name === 'Literal');\n continue;\n case 'undefined':\n k = key;\n break;\n default:\n k = opKey;\n break;\n }\n values[k] = toWhere(items[key], {\n ...context,\n prefix: op.has(key) ? prefix : childPreifx,\n });\n }\n }\n if (values['$__literals']) {\n const $__literals = _.cloneDeep(values['$__literals']);\n delete values['$__literals'];\n console.log(Object.keys(values));\n return {\n [Op.and]: [\n ...$__literals,\n values,\n ],\n }\n }\n return values;\n}\n\ninterface ToIncludeContext {\n model?: ModelCtor<Model> | Model | typeof Model;\n sourceAlias?: string;\n associations?: any;\n dialect?: string;\n database?: Database;\n ctx?: any\n}\n\nexport function toOrder(sort: string | string[], model: any): string[][] {\n if (sort && typeof sort === 'string') {\n sort = sort.split(',');\n }\n\n const order = [];\n\n if (Array.isArray(sort) && sort.length > 0) {\n sort.forEach(key => {\n if (Array.isArray(key)) {\n order.push(key);\n } else {\n const direction = key[0] === '-' ? 'DESC' : 'ASC';\n const keys = key.replace(/^-/, '').split('.');\n const field = keys.pop();\n const by = [];\n let associationModel = model;\n for (let i = 0; i < keys.length; i++) {\n const association = model.associations[keys[i]];\n if (association && association.target) {\n associationModel = association.target;\n by.push(associationModel);\n }\n }\n order.push([...by, field, direction]);\n }\n });\n }\n\n return order;\n}\n\nexport function toInclude(options: any, context: ToIncludeContext = {}) {\n function makeFields(key: string) {\n if (!Array.isArray(items[key])) {\n return;\n }\n items[key].forEach(field => {\n // 按点分隔转化为数组\n const [col, ...arr]: string[] = Array.isArray(field) ? Utils.cloneDeep(field) : field.split('.');\n // 内嵌的情况\n if (arr.length > 0) {\n if (!children.has(col)) {\n children.set(col, {\n fields: {\n only: [],\n except: [],\n appends: [],\n },\n });\n }\n children.get(col).fields[key].push(arr);\n return;\n }\n if (key !== 'except') {\n // 关系字段\n if (associations[col]) {\n const includeItem: any = {\n association: col,\n };\n if (includeWhere[col]) {\n includeItem.where = includeWhere[col];\n }\n include.set(col, includeItem);\n return;\n }\n // 计数字段\n const matches: Array<any> = col.match(/(.+)_count$/);\n if (matches && associations[matches[1]]) {\n attributes[key].push(model.withCountAttribute({\n association: matches[1],\n sourceAlias: sourceAlias\n }));\n return;\n }\n } else {\n if (!attributes.except) {\n attributes.except = [];\n }\n }\n attributes[key].push(col);\n });\n }\n\n const { fields = [], filter } = options;\n const { model, sourceAlias, associations = {}, ctx, database, dialect } = context;\n\n let where = options.where || {};\n\n if (filter) {\n where = toWhere(filter, {\n model,\n associations,\n ctx,\n database,\n }) || {};\n }\n\n const includeWhere = Utils.cloneDeep(where.$__include || {});\n const scopes = Utils.cloneDeep(where.$__scopes || []);\n\n delete where.$__include;\n delete where.$__scopes;\n\n const attributes = {\n only: [],\n except: [],\n appends: [],\n };\n\n const include = new Map();\n const children = new Map();\n\n const items = Array.isArray(fields) ? { only: fields } : fields;\n items.appends = items.appends || [];\n\n makeFields('only');\n makeFields('appends');\n makeFields('except');\n\n for (const whereKey in includeWhere) {\n if (children.has(whereKey)) {\n children.get(whereKey).where = includeWhere[whereKey];\n } else {\n children.set(whereKey, {\n association: whereKey,\n fields: [],\n where: includeWhere[whereKey],\n });\n }\n }\n\n for (const [key, child] of children) {\n const result = toInclude(child, {\n ...context,\n model: associations[key].target,\n sourceAlias: key,\n associations: associations[key].target.associations,\n });\n const item: any = {\n association: key,\n }\n if (result.attributes) {\n item.attributes = result.attributes;\n }\n if (result.include) {\n item.include = result.include;\n }\n if (result.where) {\n item.where = result.where;\n }\n if (result.scopes) {\n item.model = associations[key].target.scope(result.scopes);\n }\n // 解决同时有关联和关联的子级关联时,关联的 attribute 被设置为空数组的问题\n // ['user.profile.age', 'user.status', 'user', 'title', 'status']\n if (include.has(key) && Array.isArray(item.attributes) && !item.attributes.length) {\n delete item.attributes;\n }\n include.set(key, item);\n }\n\n const data: any = {};\n\n // 存在黑名单时\n if (attributes.except.length) {\n data.attributes = {\n exclude: attributes.except,\n };\n if (attributes.appends.length) {\n data.attributes.include = attributes.appends;\n }\n }\n // 存在白名单时\n else if (attributes.only.length) {\n data.attributes = [...attributes.only, ...attributes.appends];\n }\n // 只有附加字段时\n else if (attributes.appends.length) {\n data.attributes = {\n include: attributes.appends,\n };\n }\n\n if (include.size) {\n if (!data.attributes) {\n data.attributes = [];\n }\n data.include = Array.from(include.values());\n data.distinct = true;\n }\n\n if (Reflect.ownKeys(where).length) {\n data.where = where;\n }\n\n if (scopes.length) {\n data.scopes = scopes;\n }\n\n const order = toOrder(options.sort, model);\n\n if (order.length) {\n data.order = order;\n }\n\n return data;\n}\n\nexport function whereCompare(a: any, b: any): boolean {\n return _.isEqual(a, b);\n}\n\nexport function requireModule(module: any) {\n if (typeof module === 'string') {\n module = require(module);\n }\n if (typeof module !== 'object') {\n return module;\n }\n return module.__esModule ? module.default : module;\n}\n\nexport function isNumber(num) {\n if (typeof num === 'number') {\n return num - num === 0;\n }\n if (typeof num === 'string' && num.trim() !== '') {\n return Number.isFinite ? Number.isFinite(+num) : isFinite(+num);\n }\n return false;\n};\n\nlet IDX = 36,\n HEX = ''\nwhile (IDX--) HEX += IDX.toString(36)\n\nexport function uid(len?: number) {\n let str = '',\n num = len || 11\n while (num--) str += HEX[(Math.random() * 36) | 0]\n return str\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocobase/database",
3
- "version": "0.5.0-alpha.18",
3
+ "version": "0.5.0-alpha.22",
4
4
  "description": "",
5
5
  "main": "./lib/index.js",
6
6
  "types": "./lib/index.d.ts",
@@ -10,12 +10,12 @@
10
10
  "bcrypt": "^5.0.0",
11
11
  "deepmerge": "^4.2.2",
12
12
  "glob": "^7.1.6",
13
- "sequelize": "^6.3.3"
13
+ "sequelize": "6.7.0"
14
14
  },
15
15
  "repository": {
16
16
  "type": "git",
17
17
  "url": "git+https://github.com/nocobase/nocobase.git",
18
18
  "directory": "packages/database"
19
19
  },
20
- "gitHead": "516c1be50dbe548be18a1433ea6e0a59e28bb8b8"
20
+ "gitHead": "22534716700c4ade1727b6e04543725c5e4f14f2"
21
21
  }