feat: beforeModelFind db hooks

This commit is contained in:
aaaaaajie 2025-04-07 23:29:14 +08:00
parent 5be0bb9807
commit c17ba532f5
6 changed files with 34 additions and 19 deletions

View File

@ -62,6 +62,10 @@ export abstract class Field {
abstract get dataType(): any;
get rawDataType() {
return this.dataType;
}
isRelationField() {
return false;
}
@ -179,7 +183,10 @@ export abstract class Field {
const opts = _.omit(this.options, ['name']);
if (this.dataType) {
// @ts-ignore
Object.assign(opts, { type: this.database.sequelize.normalizeDataType(this.dataType) });
Object.assign(opts, {
type: this.database.sequelize.normalizeDataType(this.dataType),
rawDataType: this.rawDataType,
});
}
Object.assign(opts, this.additionalSequelizeOptions());

View File

@ -8,7 +8,7 @@
*/
import lodash from 'lodash';
import { Model as SequelizeModel, ModelStatic } from 'sequelize';
import { Model as SequelizeModel, ModelStatic, FindOptions } from 'sequelize';
import { Collection } from './collection';
import { Database } from './database';
import { Field } from './fields';
@ -216,4 +216,9 @@ export class Model<TModelAttributes extends {} = any, TCreationAttributes extend
return lodash.orderBy(data, orderItems, orderDirections);
}
public static findAll(options?: FindOptions<any>): Promise<any[]> {
this.database.emit('beforeModelFind', this, options);
return super.findAll(options);
}
}

View File

@ -17,6 +17,7 @@ import {
} from 'sequelize';
import { Collection } from '../collection';
import Database from '../database';
import { Literal } from 'sequelize/types/utils';
export type TableInfo = {
tableName: string;
@ -167,7 +168,7 @@ export default abstract class QueryInterface {
}
}
public generateJsonPathExpression(field: string, path: string) {
return `${field}.${path}`;
public generateJsonPathExpression(field: string, path: string): Literal {
return this.db.sequelize.literal(`${field}.${path}`);
}
}

View File

@ -90,7 +90,7 @@ describe('sql collection', () => {
expect(res.body.data.sources).toEqual(['testSqlCollection']);
});
it.only('sqlCollection:update', async () => {
it('sqlCollection:update', async () => {
await agent.resource('collections').create({
values: {
name: 'fakeCollection',

View File

@ -252,7 +252,7 @@ describe('collections repository', () => {
expect(response1.body.data.length).toBe(2);
});
it('case 7', async () => {
it.only('case 7', async () => {
const response = await agent.resource('posts').create({
values: {
tags: [

View File

@ -7,7 +7,7 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import { Database } from '@nocobase/database';
import { Database, Op } from '@nocobase/database';
import { FieldIsDependedOnByOtherError } from '../errors/field-is-depended-on-by-other';
export function beforeDestoryField(db: Database) {
@ -18,20 +18,22 @@ export function beforeDestoryField(db: Database) {
if (['belongsTo', 'hasOne', 'hasMany', 'belongsToMany'].includes(type)) {
return;
}
const relatedFields = await db.getRepository('fields').find({
filter: {
$or: [
{
[db.queryInterface.generateJsonPathExpression('options', 'sourceKey')]: name,
collectionName,
},
{
[db.queryInterface.generateJsonPathExpression('options', 'targetKey')]: name,
[db.queryInterface.generateJsonPathExpression('options', 'targetKey')]: collectionName,
},
const $or = [
{
[Op.and]: [
db.sequelize.where(db.queryInterface.generateJsonPathExpression('options', 'sourceKey'), Op.eq, name),
{ collectionName },
],
},
{
[Op.and]: [
db.sequelize.where(db.queryInterface.generateJsonPathExpression('options', 'targetKey'), Op.eq, name),
db.sequelize.where(db.queryInterface.generateJsonPathExpression('options', 'target'), Op.eq, collectionName),
],
},
];
const relatedFields = await db.getRepository('fields').find({
filter: { $or },
transaction,
});