diff --git a/packages/runtime/src/client/client-impl.ts b/packages/runtime/src/client/client-impl.ts index 72404590..d5f65a46 100644 --- a/packages/runtime/src/client/client-impl.ts +++ b/packages/runtime/src/client/client-impl.ts @@ -358,9 +358,9 @@ function createModelCrudHandler { return createZenStackPromise(async (txClient?: ClientContract) => { - let proceed = async (_args?: unknown) => { + let proceed = async (_args: unknown) => { const _handler = txClient ? handler.withClient(txClient) : handler; - const r = await _handler.handle(operation, _args ?? args); + const r = await _handler.handle(operation, _args); if (!r && throwIfNoResult) { throw new NotFoundError(model); } @@ -379,7 +379,16 @@ function createModelCrudHandler onQuery({ client, model, operation, args, proceed: _proceed }) as Promise; + proceed = (_args: unknown) => + onQuery({ + client, + model, + operation, + // reflect the latest override if provided + args: _args, + // ensure inner overrides are propagated to the previous proceed + proceed: (nextArgs: unknown) => _proceed(nextArgs), + }) as Promise; } } diff --git a/packages/runtime/test/plugin/on-query-hooks.test.ts b/packages/runtime/test/plugin/on-query-hooks.test.ts index 5cb72c97..3e4c478b 100644 --- a/packages/runtime/test/plugin/on-query-hooks.test.ts +++ b/packages/runtime/test/plugin/on-query-hooks.test.ts @@ -211,4 +211,42 @@ describe('On query hooks tests', () => { ).resolves.toMatchObject(user); expect(findHookCalled).toBe(true); }); + + it('propagates overridden args across multiple onQuery plugins', async () => { + const user = await _client.user.create({ data: { email: 'u1@test.com' } }); + + let earlierSawOverridden = false; + + // Plugin A (registered first) should see the overridden args from Plugin B + const clientA = _client.$use({ + id: 'plugin-a', + onQuery: (ctx) => { + if (ctx.model === 'User' && ctx.operation === 'findFirst') { + // expect overridden where clause from Plugin B + // eslint-disable-next-line @typescript-eslint/no-explicit-any + earlierSawOverridden = (ctx.args as any)?.where?.id === 'non-exist'; + } + return ctx.proceed(ctx.args); + }, + }); + + // Plugin B (registered second) overrides args + const client = clientA.$use({ + id: 'plugin-b', + onQuery: (ctx) => { + if (ctx.model === 'User' && ctx.operation === 'findFirst') { + return ctx.proceed({ where: { id: 'non-exist' } }); + } + return ctx.proceed(ctx.args); + }, + }); + + await expect( + client.user.findFirst({ + where: { id: user.id }, + }), + ).toResolveNull(); + + expect(earlierSawOverridden).toBe(true); + }); });