fix: the firstOrCreate and updateOrCreate methods of the repository lose context (#5973)

This commit is contained in:
chenos 2024-12-31 09:44:16 +08:00 committed by GitHub
parent 98fb2063bc
commit e47f0ff342
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 26 additions and 23 deletions

View File

@ -18,8 +18,8 @@ import { Model } from '../model';
import { OptionsParser } from '../options-parser'; import { OptionsParser } from '../options-parser';
import { updateAssociations } from '../update-associations'; import { updateAssociations } from '../update-associations';
import { UpdateGuard } from '../update-guard'; import { UpdateGuard } from '../update-guard';
import { CreateOptions, Filter, FindOptions, TargetKey, UpdateOptions, FirstOrCreateOptions } from './types';
import { valuesToFilter } from '../utils/filter-utils'; import { valuesToFilter } from '../utils/filter-utils';
import { CreateOptions, Filter, FindOptions, FirstOrCreateOptions, TargetKey, UpdateOptions } from './types';
export const transaction = transactionWrapperBuilder(function () { export const transaction = transactionWrapperBuilder(function () {
return this.sourceCollection.model.sequelize.transaction(); return this.sourceCollection.model.sequelize.transaction();
@ -143,24 +143,24 @@ export abstract class RelationRepository {
@transaction() @transaction()
async firstOrCreate(options: FirstOrCreateOptions) { async firstOrCreate(options: FirstOrCreateOptions) {
const { filterKeys, values, transaction, hooks } = options; const { filterKeys, values, transaction, hooks, context } = options;
const filter = valuesToFilter(values, filterKeys); const filter = valuesToFilter(values, filterKeys);
const instance = await this.findOne({ filter, transaction }); const instance = await this.findOne({ filter, transaction, context });
if (instance) { if (instance) {
return instance; return instance;
} }
return this.create({ values, transaction, hooks }); return this.create({ values, transaction, hooks, context });
} }
@transaction() @transaction()
async updateOrCreate(options: FirstOrCreateOptions) { async updateOrCreate(options: FirstOrCreateOptions) {
const { filterKeys, values, transaction, hooks } = options; const { filterKeys, values, transaction, hooks, context } = options;
const filter = valuesToFilter(values, filterKeys); const filter = valuesToFilter(values, filterKeys);
const instance = await this.findOne({ filter, transaction }); const instance = await this.findOne({ filter, transaction, context });
if (instance) { if (instance) {
return await this.update({ return await this.update({
@ -170,10 +170,11 @@ export abstract class RelationRepository {
values, values,
transaction, transaction,
hooks, hooks,
context,
}); });
} }
return this.create({ values, transaction, hooks }); return this.create({ values, transaction, hooks, context });
} }
@transaction() @transaction()

View File

@ -7,12 +7,12 @@
* For more information, please refer to: https://www.nocobase.com/agreement. * For more information, please refer to: https://www.nocobase.com/agreement.
*/ */
import { AssociationKeysToBeUpdate, BlackList, Values, WhiteList } from '@nocobase/database';
import { Transaction } from 'sequelize'; import { Transaction } from 'sequelize';
import { import {
CreateOptions as SequelizeCreateOptions, CreateOptions as SequelizeCreateOptions,
UpdateOptions as SequelizeUpdateOptions, UpdateOptions as SequelizeUpdateOptions,
} from 'sequelize/types/model'; } from 'sequelize/types/model';
import { AssociationKeysToBeUpdate, BlackList, Values, WhiteList } from '@nocobase/database';
export type TargetKey = string | number | { [key: string]: any }; export type TargetKey = string | number | { [key: string]: any };
@ -80,6 +80,7 @@ export interface FirstOrCreateOptions extends CommonOptions {
filterKeys: string[]; filterKeys: string[];
values: any; values: any;
hooks?: boolean; hooks?: boolean;
context?: any;
} }
export interface ThroughValues { export interface ThroughValues {

View File

@ -7,24 +7,23 @@
* For more information, please refer to: https://www.nocobase.com/agreement. * For more information, please refer to: https://www.nocobase.com/agreement.
*/ */
import { flatten } from 'flat'; import { isValidFilter } from '@nocobase/utils';
import lodash from 'lodash'; import lodash from 'lodash';
import { import {
Association, Association,
BulkCreateOptions, BulkCreateOptions,
CountOptions as SequelizeCountOptions,
CreateOptions as SequelizeCreateOptions,
DestroyOptions as SequelizeDestroyOptions,
FindAndCountOptions as SequelizeAndCountOptions,
FindOptions as SequelizeFindOptions,
ModelStatic, ModelStatic,
Op, Op,
Sequelize, Sequelize,
Transactionable, FindAndCountOptions as SequelizeAndCountOptions,
CountOptions as SequelizeCountOptions,
CreateOptions as SequelizeCreateOptions,
DestroyOptions as SequelizeDestroyOptions,
FindOptions as SequelizeFindOptions,
UpdateOptions as SequelizeUpdateOptions, UpdateOptions as SequelizeUpdateOptions,
Transactionable,
WhereOperators, WhereOperators,
} from 'sequelize'; } from 'sequelize';
import { isValidFilter } from '@nocobase/utils';
import { Collection } from './collection'; import { Collection } from './collection';
import { Database } from './database'; import { Database } from './database';
@ -38,6 +37,7 @@ import FilterParser from './filter-parser';
import { Model } from './model'; import { Model } from './model';
import operators from './operators'; import operators from './operators';
import { OptionsParser } from './options-parser'; import { OptionsParser } from './options-parser';
import { BelongsToArrayRepository } from './relation-repository/belongs-to-array-repository';
import { BelongsToManyRepository } from './relation-repository/belongs-to-many-repository'; import { BelongsToManyRepository } from './relation-repository/belongs-to-many-repository';
import { BelongsToRepository } from './relation-repository/belongs-to-repository'; import { BelongsToRepository } from './relation-repository/belongs-to-repository';
import { HasManyRepository } from './relation-repository/hasmany-repository'; import { HasManyRepository } from './relation-repository/hasmany-repository';
@ -45,7 +45,6 @@ import { HasOneRepository } from './relation-repository/hasone-repository';
import { RelationRepository } from './relation-repository/relation-repository'; import { RelationRepository } from './relation-repository/relation-repository';
import { updateAssociations, updateModelByValues } from './update-associations'; import { updateAssociations, updateModelByValues } from './update-associations';
import { UpdateGuard } from './update-guard'; import { UpdateGuard } from './update-guard';
import { BelongsToArrayRepository } from './relation-repository/belongs-to-array-repository';
import { valuesToFilter } from './utils/filter-utils'; import { valuesToFilter } from './utils/filter-utils';
const debug = require('debug')('noco-database'); const debug = require('debug')('noco-database');
@ -239,6 +238,7 @@ export interface FirstOrCreateOptions extends Transactionable {
filterKeys: string[]; filterKeys: string[];
values?: Values; values?: Values;
hooks?: boolean; hooks?: boolean;
context?: any;
} }
export class Repository<TModelAttributes extends {} = any, TCreationAttributes extends {} = TModelAttributes> { export class Repository<TModelAttributes extends {} = any, TCreationAttributes extends {} = TModelAttributes> {
@ -479,23 +479,23 @@ export class Repository<TModelAttributes extends {} = any, TCreationAttributes e
* Get the first record matching the attributes or create it. * Get the first record matching the attributes or create it.
*/ */
async firstOrCreate(options: FirstOrCreateOptions) { async firstOrCreate(options: FirstOrCreateOptions) {
const { filterKeys, values, transaction, hooks } = options; const { filterKeys, values, transaction, hooks, context } = options;
const filter = Repository.valuesToFilter(values, filterKeys); const filter = Repository.valuesToFilter(values, filterKeys);
const instance = await this.findOne({ filter, transaction }); const instance = await this.findOne({ filter, transaction, context });
if (instance) { if (instance) {
return instance; return instance;
} }
return this.create({ values, transaction, hooks }); return this.create({ values, transaction, hooks, context });
} }
async updateOrCreate(options: FirstOrCreateOptions) { async updateOrCreate(options: FirstOrCreateOptions) {
const { filterKeys, values, transaction, hooks } = options; const { filterKeys, values, transaction, hooks, context } = options;
const filter = Repository.valuesToFilter(values, filterKeys); const filter = Repository.valuesToFilter(values, filterKeys);
const instance = await this.findOne({ filter, transaction }); const instance = await this.findOne({ filter, transaction, context });
if (instance) { if (instance) {
return await this.update({ return await this.update({
@ -503,10 +503,11 @@ export class Repository<TModelAttributes extends {} = any, TCreationAttributes e
values, values,
transaction, transaction,
hooks, hooks,
context,
}); });
} }
return this.create({ values, transaction, hooks }); return this.create({ values, transaction, hooks, context });
} }
/** /**