diff --git a/packages/plugins/collection-manager/src/__tests__/remove-collection.test.ts b/packages/plugins/collection-manager/src/__tests__/remove-collection.test.ts new file mode 100644 index 0000000000..d23679c394 --- /dev/null +++ b/packages/plugins/collection-manager/src/__tests__/remove-collection.test.ts @@ -0,0 +1,50 @@ +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('should remove association field after collection destroy', async () => { + await Collection.repository.create({ + context: {}, + values: { + name: 'posts', + fields: [{ type: 'hasMany', name: 'comments', options: { target: 'comments' } }], + }, + }); + + await Collection.repository.create({ + context: {}, + values: { + name: 'comments', + fields: [{ type: 'string', name: 'content' }], + }, + }); + + await db.getRepository('collections').destroy({ + filter: { + name: 'comments', + }, + }); + + const fields = await db.getRepository('fields').find(); + + expect(fields.length).toEqual(0); + }); +}); diff --git a/packages/plugins/collection-manager/src/collections/fields.ts b/packages/plugins/collection-manager/src/collections/fields.ts index 7461b3c237..a308d7e39b 100644 --- a/packages/plugins/collection-manager/src/collections/fields.ts +++ b/packages/plugins/collection-manager/src/collections/fields.ts @@ -41,6 +41,7 @@ export default { target: 'collections', foreignKey: 'collectionName', targetKey: 'name', + onDelete: 'CASCADE', }, { type: 'hasMany', @@ -60,7 +61,7 @@ export default { type: 'belongsTo', name: 'uiSchema', target: 'uiSchemas', - foreignKey: 'uiSchemaUid' + foreignKey: 'uiSchemaUid', }, { type: 'json', diff --git a/packages/plugins/collection-manager/src/plugin.ts b/packages/plugins/collection-manager/src/plugin.ts index 6d1a950e6e..36a0e0d054 100644 --- a/packages/plugins/collection-manager/src/plugin.ts +++ b/packages/plugins/collection-manager/src/plugin.ts @@ -58,6 +58,28 @@ export class CollectionManagerPlugin extends Plugin { } }); + this.app.db.on('collections.afterDestroy', async (model, { transaction }) => { + const name = model.get('name'); + + const fields = await this.app.db.getRepository('fields').find({ + filter: { + 'type.$in': ['belongsToMany', 'belongsTo', 'hasMany', 'hasOne'], + }, + transaction, + }); + + const deleteFieldsKey = fields + .filter((field) => (field.get('options') as any)?.target === name) + .map((field) => field.get('key') as string); + + await this.app.db.getRepository('fields').destroy({ + filter: { + 'key.$in': deleteFieldsKey, + }, + transaction, + }); + }); + this.app.db.on('fields.afterCreate', async (model, { context, transaction }) => { if (context) { await model.migrate({ transaction });