From 10d520c22a01f030331ed62f1cbeb1575a78b91b Mon Sep 17 00:00:00 2001 From: chenos Date: Fri, 7 Jan 2022 22:06:31 +0800 Subject: [PATCH] feat: customizable magicAttribute --- .../__tests__/magic-attribute-model.test.ts | 40 +++++++++++++++++++ packages/database/src/collection.ts | 7 ++++ .../database/src/magic-attribute-model.ts | 21 ++++++---- 3 files changed, 61 insertions(+), 7 deletions(-) diff --git a/packages/database/src/__tests__/magic-attribute-model.test.ts b/packages/database/src/__tests__/magic-attribute-model.test.ts index d9ed1ee2b..ae2b33d5f 100644 --- a/packages/database/src/__tests__/magic-attribute-model.test.ts +++ b/packages/database/src/__tests__/magic-attribute-model.test.ts @@ -40,4 +40,44 @@ describe('magic-attribute-model', () => { 'x-decorator-props': { key1: 'val1' }, }); }); + + it('case 2', async () => { + const db = mockDatabase(); + db.registerModels({ MagicAttributeModel }); + + const Test = db.collection({ + name: 'tests', + model: 'MagicAttributeModel', + magicAttribute: 'schema', + fields: [ + { type: 'string', name: 'title' }, + { type: 'json', name: 'schema' }, + ], + }); + + await db.sync(); + + const test = await Test.model.create({ + title: 'aa', + 'x-component-props': { key1: 'val1', arr1: [1, 2, 3], arr2: [4, 5] }, + }); + + test.set({ + 'x-component-props': { key2: 'val2', arr1: [3, 4] }, + 'x-decorator-props': { key1: 'val1' }, + }); + + test.set('x-component-props', { arr2: [1, 2, 3] }); + + expect(test.toJSON()).toMatchObject({ + title: 'aa', + 'x-component-props': { + key1: 'val1', + key2: 'val2', + arr1: [3, 4], + arr2: [1, 2, 3], + }, + 'x-decorator-props': { key1: 'val1' }, + }); + }); }); diff --git a/packages/database/src/collection.ts b/packages/database/src/collection.ts index 9dc7f0249..0db522396 100644 --- a/packages/database/src/collection.ts +++ b/packages/database/src/collection.ts @@ -19,7 +19,14 @@ export interface CollectionOptions extends Omit { fields?: FieldOptions[]; model?: string | ModelCtor; repository?: string | RepositoryType; + /** + * @default true + */ autoGenId?: boolean; + /** + * @default 'options' + */ + magicAttribute?: string; [key: string]: any; } diff --git a/packages/database/src/magic-attribute-model.ts b/packages/database/src/magic-attribute-model.ts index dae165237..87b2dab0e 100644 --- a/packages/database/src/magic-attribute-model.ts +++ b/packages/database/src/magic-attribute-model.ts @@ -1,8 +1,15 @@ import { Model } from 'sequelize'; import { merge } from '@nocobase/utils'; import _ from 'lodash'; +import Database from './database'; export class MagicAttributeModel extends Model { + get magicAttribute() { + const db: Database = (this.constructor as any).database; + const collection = db.getCollection(this.constructor.name); + return collection.options.magicAttribute || 'options'; + } + set(key: any, value?: any, options?: any) { if (typeof key === 'string') { const [column] = key.split('.'); @@ -13,10 +20,10 @@ export class MagicAttributeModel extends Model { return super.set(key, value, options); } if (_.isPlainObject(value)) { - const opts = super.get(`options`) || {}; - return super.set(`options.${key}`, merge(opts?.[key], value), options); + const opts = super.get(this.magicAttribute) || {}; + return super.set(`${this.magicAttribute}.${key}`, merge(opts?.[key], value), options); } - return super.set(`options.${key}`, value, options); + return super.set(`${this.magicAttribute}.${key}`, value, options); } else { Object.keys(key).forEach((k) => { this.set(k, key[k], options); @@ -34,13 +41,13 @@ export class MagicAttributeModel extends Model { if ((this.constructor as any).rawAttributes[column]) { return super.get(key, value); } - const options = super.get(`options`); + const options = super.get(this.magicAttribute); return _.get(options, key); } const data = super.get(key, value); return { - ..._.omit(data, 'options'), - ...data.options, + ..._.omit(data, this.magicAttribute), + ...data[this.magicAttribute], }; } -} \ No newline at end of file +}