diff --git a/packages/plugin-collection-manager/src/__tests__/beforeInitOptions.test.ts b/packages/plugin-collection-manager/src/__tests__/beforeInitOptions.test.ts new file mode 100644 index 000000000..10ebfebd0 --- /dev/null +++ b/packages/plugin-collection-manager/src/__tests__/beforeInitOptions.test.ts @@ -0,0 +1,116 @@ +import Database, { Collection as DBCollection } from '@nocobase/database'; +import Application from '@nocobase/server'; +import { createApp } from '.'; + +describe('collections repository', () => { + let db: Database; + let app: Application; + let Collection: DBCollection; + let Field: DBCollection; + + beforeEach(async () => { + app = await createApp(); + await app.db.sync(); + db = app.db; + Collection = db.getCollection('collections'); + Field = db.getCollection('fields'); + }); + + afterEach(async () => { + await app.destroy(); + }); + + it('case 1', async () => { + await Collection.repository.create({ + context: {}, + values: { + name: 'foos', + autoGenId: false, + fields: [ + { + type: 'uid', + name: 'fkey', + primaryKey: true, + }, + ], + }, + }); + await Collection.repository.create({ + context: {}, + values: { + name: 'bars', + autoGenId: false, + fields: [ + { + type: 'uid', + name: 'bkey', + primaryKey: true, + }, + ], + }, + }); + const repo = db.getRepository('collections.fields', 'foos'); + + const field1 = await repo.create({ + values: { + type: 'belongsToMany', + target: 'bars', + }, + context: {}, + }); + expect(field1.toJSON()).toMatchObject({ + type: 'belongsToMany', + collectionName: 'foos', + target: 'bars', + targetKey: 'bkey', + sourceKey: 'fkey', + }); + + const field2 = await repo.create({ + values: { + type: 'belongsTo', + target: 'bars', + }, + context: {}, + }); + expect(field2.toJSON()).toMatchObject({ + type: 'belongsTo', + collectionName: 'foos', + target: 'bars', + targetKey: 'bkey', + }); + + const field3 = await repo.create({ + values: { + type: 'hasMany', + target: 'bars', + constraints: false, + }, + context: {}, + }); + expect(field3.toJSON()).toMatchObject({ + type: 'hasMany', + collectionName: 'foos', + target: 'bars', + targetKey: 'bkey', + sourceKey: 'fkey', + }); + + const field4 = await repo.create({ + values: { + type: 'hasOne', + target: 'bars', + constraints: false, + }, + context: {}, + }); + expect(field4.toJSON()).toMatchObject({ + type: 'hasOne', + collectionName: 'foos', + target: 'bars', + sourceKey: 'fkey', + }); + + await db.sync(); + }); +}); diff --git a/packages/plugin-collection-manager/src/hooks/beforeInitOptions.ts b/packages/plugin-collection-manager/src/hooks/beforeInitOptions.ts index 447b96d91..6898af98d 100644 --- a/packages/plugin-collection-manager/src/hooks/beforeInitOptions.ts +++ b/packages/plugin-collection-manager/src/hooks/beforeInitOptions.ts @@ -1,8 +1,25 @@ +import Database from '@nocobase/database'; import { uid } from '@nocobase/utils'; import { Model } from 'sequelize'; +const setTargetKey = (db: Database, model: Model) => { + const target = model.get('target') as any; + if (db.hasCollection(target)) { + const targetModel = db.getCollection(target).model; + model.set('targetKey', targetModel.primaryKeyAttribute || 'id'); + } +}; + +const setSourceKey = (db: Database, model: Model) => { + const source = model.get('collectionName') as any; + if (db.hasCollection(source)) { + const sourceModel = db.getCollection(source).model; + model.set('sourceKey', sourceModel.primaryKeyAttribute || 'id'); + } +}; + export const beforeInitOptions = { - belongsTo(model: Model) { + belongsTo(model: Model, { database }) { const defaults = { targetKey: 'id', foreignKey: `f_${uid()}`, @@ -13,8 +30,9 @@ export const beforeInitOptions = { } model.set(key, defaults[key]); } + setTargetKey(database, model); }, - belongsToMany(model: Model) { + belongsToMany(model: Model, { database }) { const defaults = { targetKey: 'id', sourceKey: 'id', @@ -28,8 +46,10 @@ export const beforeInitOptions = { } model.set(key, defaults[key]); } + setTargetKey(database, model); + setSourceKey(database, model); }, - hasMany(model: Model) { + hasMany(model: Model, { database }) { const defaults = { targetKey: 'id', sourceKey: 'id', @@ -42,8 +62,10 @@ export const beforeInitOptions = { } model.set(key, defaults[key]); } + setTargetKey(database, model); + setSourceKey(database, model); }, - hasOne(model: Model) { + hasOne(model: Model, { database }) { const defaults = { sourceKey: 'id', foreignKey: `f_${uid()}`, @@ -54,5 +76,6 @@ export const beforeInitOptions = { } model.set(key, defaults[key]); } + setSourceKey(database, model); }, }; diff --git a/packages/plugin-collection-manager/src/plugin.ts b/packages/plugin-collection-manager/src/plugin.ts index a0847182b..71bbeaf34 100644 --- a/packages/plugin-collection-manager/src/plugin.ts +++ b/packages/plugin-collection-manager/src/plugin.ts @@ -25,7 +25,10 @@ export class CollectionManagerPlugin extends Plugin { this.app.db.on('fields.beforeCreate', beforeCreateForChildrenCollection(this.app.db)); this.app.db.on('fields.beforeCreate', async (model, options) => { const type = model.get('type'); - await this.app.db.emitAsync(`fields.${type}.beforeInitOptions`, model, options); + await this.app.db.emitAsync(`fields.${type}.beforeInitOptions`, model, { + ...options, + database: this.app.db, + }); }); for (const key in beforeInitOptions) { if (Object.prototype.hasOwnProperty.call(beforeInitOptions, key)) {