diff --git a/packages/core/database/src/__tests__/database.test.ts b/packages/core/database/src/__tests__/database.test.ts index f0c84b8b3e..d13ee113d2 100644 --- a/packages/core/database/src/__tests__/database.test.ts +++ b/packages/core/database/src/__tests__/database.test.ts @@ -285,4 +285,36 @@ describe('database', () => { test.customMethod(); expect(test.get('abc')).toBe('abc'); }); + + test('getFieldByPath', () => { + db.collection({ + name: 'users', + fields: [{ type: 'hasMany', name: 'p', target: 'posts' }], + }); + db.collection({ + name: 'comments', + fields: [{ type: 'string', name: 'title' }], + }); + db.collection({ + name: 'posts', + fields: [ + { type: 'hasMany', name: 'c', target: 'comments' }, + { type: 'belongsToMany', name: 't', target: 'tags' }, + ], + }); + db.collection({ + name: 'tags', + fields: [{ type: 'string', name: 'title' }], + }); + const f1 = db.getFieldByPath('users.p.t'); + const f2 = db.getFieldByPath('users.p.c'); + const f3 = db.getFieldByPath('users.p'); + expect(f1.name).toBe('t'); + expect(f2.name).toBe('c'); + expect(f3.name).toBe('p'); + expect(db.getFieldByPath('users.d')).toBeNull; + expect(db.getFieldByPath('users.d.e')).toBeNull; + expect(db.getFieldByPath('users.p.f')).toBeNull; + expect(db.getFieldByPath('users.p.c.j')).toBeNull; + }); }); diff --git a/packages/core/database/src/database.ts b/packages/core/database/src/database.ts index 625186df29..270c43ccbf 100644 --- a/packages/core/database/src/database.ts +++ b/packages/core/database/src/database.ts @@ -15,7 +15,7 @@ import { Sequelize, SyncOptions, Transactionable, - Utils, + Utils } from 'sequelize'; import { SequelizeStorage, Umzug } from 'umzug'; import { Collection, CollectionOptions, RepositoryType } from './collection'; @@ -58,7 +58,7 @@ import { SyncListener, UpdateListener, UpdateWithAssociationsListener, - ValidateListener, + ValidateListener } from './types'; import { patchSequelizeQueryInterface, snakeCase } from './utils'; @@ -399,6 +399,31 @@ export class Database extends EventEmitter implements AsyncEmitter { return this.options.tablePrefix || ''; } + getFieldByPath(path: string) { + if (!path) { + return; + } + + const [collectionName, associationName, ...args] = path.split('.'); + let collection = this.getCollection(collectionName); + + if (!collection) { + return; + } + + const field = collection.getField(associationName); + + if (!field) { + return; + } + + if (args.length > 0) { + return this.getFieldByPath(`${field?.target}.${args.join('.')}`); + } + + return field; + } + /** * get exists collection by its name * @param name diff --git a/packages/plugins/snapshot-field/src/server/fields/snapshot-field.ts b/packages/plugins/snapshot-field/src/server/fields/snapshot-field.ts index 2738f72ac8..2c377e31bc 100644 --- a/packages/plugins/snapshot-field/src/server/fields/snapshot-field.ts +++ b/packages/plugins/snapshot-field/src/server/fields/snapshot-field.ts @@ -17,7 +17,7 @@ export class SnapshotField extends Field { const repository = this.database.getRepository(`${collectionName}.${targetField}`, model.get(primaryKey)); const appends = (this.options.appends || []).filter((appendName) => - repository.targetCollection.hasField(appendName), + this.database.getFieldByPath(`${repository.targetCollection.name}.${appendName}`), ); let data = await repository.find({ diff --git a/packages/plugins/snapshot-field/src/server/plugin.ts b/packages/plugins/snapshot-field/src/server/plugin.ts index 310bc728cf..9520f6adfd 100644 --- a/packages/plugins/snapshot-field/src/server/plugin.ts +++ b/packages/plugins/snapshot-field/src/server/plugin.ts @@ -53,7 +53,7 @@ export class SnapshotFieldPlugin extends Plugin { }); } await fieldsHistoryRepository.create({ - values: fieldDoc, + values: JSON.parse(JSON.stringify(fieldDoc)), transaction, }); };