From b92f3b3b95fe88248bea95540a51180dbc4377f6 Mon Sep 17 00:00:00 2001 From: Junyi Date: Sun, 11 Sep 2022 21:58:49 +0800 Subject: [PATCH] refactor(database): fix some fields and types (#820) * refactor(database): fix some fields and types * fix(database): fix operator ne to null --- packages/app/server/src/config/plugins.ts | 4 +- packages/core/cli/src/commands/doc.js | 1 + .../database/src/__tests__/database.test.ts | 2 + .../src/__tests__/operator/ne.test.ts | 12 +++++ packages/core/database/src/collection.ts | 4 +- .../core/database/src/fields/formula-field.ts | 26 +++++------ .../core/database/src/fields/number-field.ts | 10 ++++ .../core/database/src/fields/radio-field.ts | 46 +++++++++---------- .../core/database/src/fields/sort-field.ts | 18 ++++---- packages/core/database/src/operators/ne.ts | 16 ++++--- 10 files changed, 83 insertions(+), 56 deletions(-) diff --git a/packages/app/server/src/config/plugins.ts b/packages/app/server/src/config/plugins.ts index 6c6b41324..1d5be4c4b 100644 --- a/packages/app/server/src/config/plugins.ts +++ b/packages/app/server/src/config/plugins.ts @@ -1,3 +1,3 @@ -import { PluginsConfigurations } from '@nocobase/server'; +import { PluginConfiguration } from '@nocobase/server'; -export default ['@nocobase/preset-nocobase'] as PluginsConfigurations; +export default ['@nocobase/preset-nocobase'] as PluginConfiguration[]; diff --git a/packages/core/cli/src/commands/doc.js b/packages/core/cli/src/commands/doc.js index 3834b0a36..581f889a3 100644 --- a/packages/core/cli/src/commands/doc.js +++ b/packages/core/cli/src/commands/doc.js @@ -22,6 +22,7 @@ module.exports = (cli) => { } else { process.env.DUMI_THEME = isAbsolute(docThemePath) ? docThemePath : resolve(process.cwd(), docThemePath); } + // TODO(bug): space replace = not work const index = process.argv.indexOf(`--lang=${options.lang}`); if (index > 0) { process.argv.splice(index, 1); diff --git a/packages/core/database/src/__tests__/database.test.ts b/packages/core/database/src/__tests__/database.test.ts index 6dfe798ab..f2279d08b 100644 --- a/packages/core/database/src/__tests__/database.test.ts +++ b/packages/core/database/src/__tests__/database.test.ts @@ -268,8 +268,10 @@ describe('database', () => { }); await Test.sync(); + expect(Test.model.prototype).toBeInstanceOf(CustomModel); const test = await Test.model.create(); + expect(test).toBeInstanceOf(CustomModel); test.customMethod(); expect(test.get('abc')).toBe('abc'); }); diff --git a/packages/core/database/src/__tests__/operator/ne.test.ts b/packages/core/database/src/__tests__/operator/ne.test.ts index 59027ff98..ab262787d 100644 --- a/packages/core/database/src/__tests__/operator/ne.test.ts +++ b/packages/core/database/src/__tests__/operator/ne.test.ts @@ -30,4 +30,16 @@ describe('ne operator', () => { expect(results).toEqual(1); }); + + it('compare with null', async () => { + await db.getRepository('tests').create({}); + + const results = await db.getRepository('tests').count({ + filter: { + 'name.$ne': null, + }, + }); + + expect(results).toBe(0); + }); }); diff --git a/packages/core/database/src/collection.ts b/packages/core/database/src/collection.ts index 03e5f3353..e66c8531e 100644 --- a/packages/core/database/src/collection.ts +++ b/packages/core/database/src/collection.ts @@ -215,7 +215,7 @@ export class Collection< return this.db.collectionExistsInDb(this.name, options); } - removeField(name) { + removeField(name: string): void | Field { if (!this.fields.has(name)) { return; } @@ -347,7 +347,7 @@ export class Collection< async sync(syncOptions?: SyncOptions) { const modelNames = new Set([this.model.name]); - const associations = this.model.associations; + const { associations } = this.model; for (const associationKey in associations) { const association = associations[associationKey]; diff --git a/packages/core/database/src/fields/formula-field.ts b/packages/core/database/src/fields/formula-field.ts index a5bbff295..342392a0b 100644 --- a/packages/core/database/src/fields/formula-field.ts +++ b/packages/core/database/src/fields/formula-field.ts @@ -16,7 +16,7 @@ export class FormulaField extends Field { return result; } - async initFieldData({ transaction }) { + initFieldData = async ({ transaction }) => { const { expression, name } = this.options; const records = await this.collection.repository.find({ @@ -42,7 +42,7 @@ export class FormulaField extends Field { } } - async caculateField(instance) { + caculateField = async (instance) => { const { expression, name } = this.options; const scope = instance.toJSON(); let result; @@ -55,7 +55,7 @@ export class FormulaField extends Field { } } - async updateFieldData(instance, { transaction }) { + updateFieldData = async (instance, { transaction }) => { if (this.collection.name === instance.collectionName && instance.name === this.options.name) { this.options = Object.assign(this.options, instance.options); const { name, expression } = this.options; @@ -64,7 +64,7 @@ export class FormulaField extends Field { order: [this.collection.model.primaryKeyAttribute], transaction, }); - + for (const record of records) { const scope = record.toJSON(); const result = this.caculate(expression, scope); @@ -84,18 +84,18 @@ export class FormulaField extends Field { bind() { super.bind(); - this.on('afterSync', this.initFieldData.bind(this)); - this.database.on('fields.afterUpdate', this.updateFieldData.bind(this)); - this.on('beforeCreate', this.caculateField.bind(this)); - this.on('beforeUpdate', this.caculateField.bind(this)); + this.on('afterSync', this.initFieldData); + // TODO: should not depends on fields table (which is defined by other plugin) + this.database.on('fields.afterUpdate', this.updateFieldData); + this.on('beforeSave', this.caculateField); } unbind() { super.unbind(); - this.off('beforeCreate', this.caculateField.bind(this)); - this.off('beforeUpdate', this.caculateField.bind(this)); - this.database.off('fields.afterUpdate', this.updateFieldData.bind(this)); - this.off('afterSync', this.initFieldData.bind(this)); + this.off('beforeSave', this.caculateField); + // TODO: should not depends on fields table + this.database.off('fields.afterUpdate', this.updateFieldData); + this.off('afterSync', this.initFieldData); } } @@ -103,4 +103,4 @@ export interface FormulaFieldOptions extends BaseColumnFieldOptions { type: 'formula'; expression: string; -} \ No newline at end of file +} diff --git a/packages/core/database/src/fields/number-field.ts b/packages/core/database/src/fields/number-field.ts index 09b828000..4b316b481 100644 --- a/packages/core/database/src/fields/number-field.ts +++ b/packages/core/database/src/fields/number-field.ts @@ -11,6 +11,16 @@ export interface IntegerFieldOptions extends BaseColumnFieldOptions { type: 'integer'; } +export class BigIntField extends Field { + get dataType() { + return DataTypes.BIGINT; + } +} + +export interface BigIntFieldOptions extends BaseColumnFieldOptions { + type: 'bigInt'; +} + export class FloatField extends Field { get dataType() { return DataTypes.FLOAT; diff --git a/packages/core/database/src/fields/radio-field.ts b/packages/core/database/src/fields/radio-field.ts index 417928e8c..e6408c386 100644 --- a/packages/core/database/src/fields/radio-field.ts +++ b/packages/core/database/src/fields/radio-field.ts @@ -13,38 +13,36 @@ export class RadioField extends Field { return DataTypes.BOOLEAN; } - init() { + listener = async (model, { transaction }) => { const { name } = this.options; - this.listener = async (model, { transaction }) => { - if (!model.changed(name as any)) { - return; - } - const value = model.get(name) as boolean; - if (value) { - const M = this.collection.model; - await M.update( - { [name]: false }, - { - where: { - [name]: true, - }, - transaction, - hooks: false, + if (!model.changed(name as any)) { + return; + } + const value = model.get(name) as boolean; + if (value) { + const M = this.collection.model; + await M.update( + { [name]: false }, + { + where: { + [name]: true, }, - ); - } - }; - } + transaction, + hooks: false, + }, + ); + } + }; bind() { super.bind(); - this.on('beforeCreate', this.listener.bind(this)); - this.on('beforeUpdate', this.listener.bind(this)); + this.on('beforeCreate', this.listener); + this.on('beforeUpdate', this.listener); } unbind() { super.unbind(); - this.off('beforeCreate', this.listener.bind(this)); - this.off('beforeUpdate', this.listener.bind(this)); + this.off('beforeCreate', this.listener); + this.off('beforeUpdate', this.listener); } } diff --git a/packages/core/database/src/fields/sort-field.ts b/packages/core/database/src/fields/sort-field.ts index db1922608..131ba3dc9 100644 --- a/packages/core/database/src/fields/sort-field.ts +++ b/packages/core/database/src/fields/sort-field.ts @@ -10,7 +10,7 @@ export class SortField extends Field { return DataTypes.INTEGER; } - async setSortValue(instance, options) { + setSortValue = async (instance, options) => { const { name, scopeKey } = this.options; const { model } = this.context.collection; @@ -34,14 +34,14 @@ export class SortField extends Field { }); } - async onScopeChange(instance, options) { + onScopeChange = async (instance, options) => { const { scopeKey } = this.options; if (scopeKey && !instance.isNewRecord && instance._previousDataValues[scopeKey] != instance[scopeKey]) { await this.setSortValue(instance, options); } } - async initRecordsSortValue({ transaction }) { + initRecordsSortValue = async ({ transaction }) => { const totalCount = await this.collection.repository.count({ transaction, }); @@ -77,16 +77,16 @@ export class SortField extends Field { bind() { super.bind(); - this.on('afterSync', this.initRecordsSortValue.bind(this)); - this.on('beforeUpdate', this.onScopeChange.bind(this)); - this.on('beforeCreate', this.setSortValue.bind(this)); + this.on('afterSync', this.initRecordsSortValue); + this.on('beforeUpdate', this.onScopeChange); + this.on('beforeCreate', this.setSortValue); } unbind() { super.unbind(); - this.off('beforeUpdate', this.onScopeChange.bind(this)); - this.off('beforeCreate', this.setSortValue.bind(this)); - this.off('afterSync', this.initRecordsSortValue.bind(this)); + this.off('beforeUpdate', this.onScopeChange); + this.off('beforeCreate', this.setSortValue); + this.off('afterSync', this.initRecordsSortValue); } } diff --git a/packages/core/database/src/operators/ne.ts b/packages/core/database/src/operators/ne.ts index 7997d34db..17d079b07 100644 --- a/packages/core/database/src/operators/ne.ts +++ b/packages/core/database/src/operators/ne.ts @@ -2,11 +2,15 @@ import { Op } from 'sequelize'; export default { $ne(val, ctx) { - return { - [Op.or]: { - [Op.ne]: val, - [Op.is]: null, - }, - }; + return val === null + ? { + [Op.ne]: null, + } + : { + [Op.or]: { + [Op.ne]: val, + [Op.is]: null, + }, + }; }, };