Skip to content

Commit

Permalink
fix(mongoose): fix prehook when insertMany is used to hook method
Browse files Browse the repository at this point in the history
  • Loading branch information
Romakita committed Jan 15, 2025
1 parent 8c8cce7 commit ee211e7
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 50 deletions.
4 changes: 2 additions & 2 deletions packages/orm/mongoose/src/decorators/postHook.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ describe("@PostHook()", () => {
const fn = vi.fn();

// WHEN
@PostHook("method", fn)
@PostHook("save", fn)
class Test {}

// THEN
Expand All @@ -17,7 +17,7 @@ describe("@PostHook()", () => {
expect(options).toEqual({
post: [
{
method: "method",
method: "save",
fn,
options: undefined
}
Expand Down
10 changes: 5 additions & 5 deletions packages/orm/mongoose/src/decorators/postHook.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {decoratorTypeOf, DecoratorTypes, StaticMethodDecorator} from "@tsed/core";
import {MongooseHookOptions, MongoosePostHookCB} from "../interfaces/MongooseSchemaOptions.js";
import {MongooseHookOptions, MongooseMethods, MongoosePostHookCB} from "../interfaces/MongooseSchemaOptions.js";
import {schemaOptions} from "../utils/schemaOptions.js";

/**
Expand Down Expand Up @@ -45,10 +45,10 @@ import {schemaOptions} from "../utils/schemaOptions.js";
* @mongoose
* @class
*/
export function PostHook<T = any>(method: string, fn: MongoosePostHookCB<T>): ClassDecorator;
export function PostHook<T = any>(method: string, fn: MongoosePostHookCB<T>, options: MongooseHookOptions): ClassDecorator;
export function PostHook<T = any>(method: string, options: MongooseHookOptions): StaticMethodDecorator;
export function PostHook<T = any>(method: string, ...params: any[]): Function {
export function PostHook<T = any>(method: MongooseMethods, fn: MongoosePostHookCB<T>): ClassDecorator;
export function PostHook<T = any>(method: MongooseMethods, fn: MongoosePostHookCB<T>, options: MongooseHookOptions): ClassDecorator;
export function PostHook<T = any>(method: MongooseMethods, options: MongooseHookOptions): StaticMethodDecorator;
export function PostHook<T = any>(method: MongooseMethods, ...params: any[]): ClassDecorator | StaticMethodDecorator {
return ((...args: any[]) => {
let options: MongooseHookOptions = params[1];
let fn: MongoosePostHookCB<T> = params[0];
Expand Down
8 changes: 4 additions & 4 deletions packages/orm/mongoose/src/decorators/preHook.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ describe("@PreHook()", () => {
const fn = vi.fn();

// WHEN
@PreHook("method", fn, {query: true})
@PreHook("save", fn as any, {query: true})
class Test {}

// THEN
Expand All @@ -16,7 +16,7 @@ describe("@PreHook()", () => {
expect(options).toEqual({
pre: [
{
method: "method",
method: "save",
fn,
options: {
query: true
Expand All @@ -32,7 +32,7 @@ describe("@PreHook()", () => {
});

// WHEN
@PreHook("method", fn, {query: true})
@PreHook("save", fn, {query: true})
class Test {}

// THEN
Expand All @@ -41,7 +41,7 @@ describe("@PreHook()", () => {
expect(options).toEqual({
pre: [
{
method: "method",
method: "save",
fn,
options: {
query: true
Expand Down
45 changes: 27 additions & 18 deletions packages/orm/mongoose/src/decorators/preHook.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {decoratorTypeOf, DecoratorTypes} from "@tsed/core";
import {MongooseHookOptions, MongoosePreHookCB} from "../interfaces/MongooseSchemaOptions.js";
import {decoratorTypeOf, DecoratorTypes, StaticMethodDecorator} from "@tsed/core";
import type {MongooseHookOptions, MongooseMethods, MongoosePreHookCB} from "../interfaces/MongooseSchemaOptions.js";
import {schemaOptions} from "../utils/schemaOptions.js";

/**
Expand Down Expand Up @@ -42,28 +42,37 @@ import {schemaOptions} from "../utils/schemaOptions.js";
*
* This will execute the pre-save hook each time a `CarModel` document is saved.
*
* @param {string} method
* @param fn
* @param options
* @returns {Function}
* @decorator
* @class
* @param method
* @param fn
* @param options
*/
export function PreHook<T = any>(method: string, fn?: MongoosePreHookCB<T> | MongooseHookOptions, options?: MongooseHookOptions): Function {
export function PreHook<T = any>(method: MongooseMethods, fn: MongoosePreHookCB<T>, options?: MongooseHookOptions): ClassDecorator;
export function PreHook<T = any>(method: MongooseMethods, options?: MongooseHookOptions): StaticMethodDecorator;
export function PreHook<T = any>(method: MongooseMethods, ...decoratorArgs: any[]): ClassDecorator | StaticMethodDecorator {
return (...args: any[]) => {
if (decoratorTypeOf(args) === DecoratorTypes.METHOD_STC) {
options = fn as MongooseHookOptions;
fn = args[0][args[1]].bind(args[0]);
schemaOptions(args[0], {
pre: [
{
method,
fn: args[0][args[1]].bind(args[0]),
options: decoratorArgs[0]
}
]
});
} else {
schemaOptions(args[0], {
pre: [
{
method,
fn: decoratorArgs[0],
options: decoratorArgs[1]
}
]
});
}

schemaOptions(args[0], {
pre: [
{
method,
fn: fn as MongoosePreHookCB<T>,
options
}
]
});
};
}
46 changes: 28 additions & 18 deletions packages/orm/mongoose/src/interfaces/MongooseSchemaOptions.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,42 @@
import {type IndexOptions, Schema, SchemaOptions} from "mongoose";
import {MongooseDocument} from "./MongooseDocument.js";

export type MongooseNextCB = (err?: Error) => void;

export interface MongooseHookOptions {
document?: boolean;
query?: boolean;
parallel?: boolean;
}
export type MongooseMethod =
| "aggregate"
| "bulkWrite"
| "createCollection"
| "save"
| "insertMany"
| "estimatedDocumentCount"
| "countDocuments"
| "deleteMany"
| "distinct"
| "find"
| "findOne"
| "findOneAndDelete"
| "findOneAndReplace"
| "findOneAndUpdate"
| "replaceOne"
| "updateMany"
| "init"
| "validate";

export type MongooseMethods = MongooseMethod | RegExp | MongooseMethod[];

export type MongooseHookPromised<T = any> = (doc: T | MongooseDocument<T>) => Promise<void> | void;

export type MongoosePreHookCB<T = any> = ((doc: T | MongooseDocument<T>, next: MongooseNextCB) => void) | MongooseHookPromised;

export type MongoosePostHookCB<T = any> =
| ((doc: T | MongooseDocument<T>, error: Error, next: MongooseNextCB) => void)
| ((doc: T | MongooseDocument<T>, error: Error) => Promise<void> | void)
| ((doc: T | MongooseDocument<T>, next: MongooseNextCB) => void)
| MongooseHookPromised;
export type MongooseNextCB = (err?: Error) => void;
export type MongooseHookOptions = Record<string, unknown>;
export type MongooseHookPromised<T = any> = (doc: T | MongooseDocument<T>) => Promise<void>;
export type MongoosePreHookCB<T = any> = (doc: T | MongooseDocument<T>, ...args: unknown[]) => Promise<void> | void;
export type MongoosePostHookCB<T = any> = (doc: T | MongooseDocument<T>, ...args: unknown[]) => Promise<void> | void;

export interface MongoosePreHook<T = any> {
method: string | RegExp;
method: MongooseMethods;
fn: MongoosePreHookCB<T>;
options?: MongooseHookOptions;
}

export interface MongoosePostHook<T = any> {
method: string | RegExp;
method: MongooseMethods;
fn: MongoosePostHookCB<T>;
options?: MongooseHookOptions;
}
Expand Down
6 changes: 3 additions & 3 deletions packages/orm/mongoose/src/utils/schemaOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {Schema} from "mongoose";
import {MONGOOSE_SCHEMA_OPTIONS} from "../constants/constants.js";
import {
MongooseHookPromised,
MongooseNextCB,
MongoosePostHook,
MongoosePreHook,
MongoosePreHookCB,
Expand Down Expand Up @@ -39,8 +38,9 @@ export function buildPreHook(fn: MongoosePreHookCB) {
? function () {
return (fn as MongooseHookPromised)(this);
}
: function (next: MongooseNextCB) {
return fn(this, next);
: // we need to explicitly gives args to avoid a bug with mongoose
function (next: any, arg1: any, arg2: any) {
return (fn as any)(this, next, arg1, arg2);
};
}

Expand Down

0 comments on commit ee211e7

Please sign in to comment.