Skip to content
This repository was archived by the owner on Mar 1, 2026. It is now read-only.

Commit 233b47d

Browse files
authored
1 parent 154ba29 commit 233b47d

File tree

23 files changed

+729
-224
lines changed

23 files changed

+729
-224
lines changed

packages/orm/src/client/client-impl.ts

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ import type {
2121
TransactionIsolationLevel,
2222
} from './contract';
2323
import { AggregateOperationHandler } from './crud/operations/aggregate';
24-
import type { AllCrudOperation, CoreCrudOperation } from './crud/operations/base';
24+
import type { AllCrudOperations, CoreCrudOperations } from './crud/operations/base';
2525
import { BaseOperationHandler } from './crud/operations/base';
2626
import { CountOperationHandler } from './crud/operations/count';
2727
import { CreateOperationHandler } from './crud/operations/create';
2828
import { DeleteOperationHandler } from './crud/operations/delete';
29-
import { FindOperationHandler } from './crud/operations/find';
3029
import { ExistsOperationHandler } from './crud/operations/exists';
30+
import { FindOperationHandler } from './crud/operations/find';
3131
import { GroupByOperationHandler } from './crud/operations/group-by';
3232
import { UpdateOperationHandler } from './crud/operations/update';
3333
import { InputValidator } from './crud/validator';
@@ -59,6 +59,7 @@ export class ClientImpl {
5959
public readonly $schema: SchemaDef;
6060
readonly kyselyProps: KyselyProps;
6161
private auth: AuthType<SchemaDef> | undefined;
62+
inputValidator: InputValidator<SchemaDef>;
6263

6364
constructor(
6465
private readonly schema: SchemaDef,
@@ -114,6 +115,7 @@ export class ClientImpl {
114115
}
115116

116117
this.kysely = new Kysely(this.kyselyProps);
118+
this.inputValidator = baseClient?.inputValidator ?? new InputValidator(this as any);
117119

118120
return createClientProxy(this);
119121
}
@@ -242,8 +244,7 @@ export class ClientImpl {
242244
}
243245

244246
// Validate inputs using the same validator infrastructure as CRUD operations.
245-
const inputValidator = new InputValidator(this as any);
246-
const validatedInput = inputValidator.validateProcedureInput(name, input);
247+
const validatedInput = this.inputValidator.validateProcedureInput(name, input);
247248

248249
const handler = procOptions[name] as Function;
249250

@@ -292,19 +293,22 @@ export class ClientImpl {
292293
await new SchemaDbPusher(this.schema, this.kysely).push();
293294
}
294295

295-
$use(plugin: RuntimePlugin<SchemaDef>) {
296-
// tsc perf
297-
const newPlugins: RuntimePlugin<SchemaDef>[] = [...(this.$options.plugins ?? []), plugin];
296+
$use(plugin: RuntimePlugin<any, any>) {
297+
const newPlugins: RuntimePlugin<any, any>[] = [...(this.$options.plugins ?? []), plugin];
298298
const newOptions: ClientOptions<SchemaDef> = {
299299
...this.options,
300300
plugins: newPlugins,
301301
};
302-
return new ClientImpl(this.schema, newOptions, this);
302+
const newClient = new ClientImpl(this.schema, newOptions, this);
303+
// create a new validator to have a fresh schema cache, because plugins may extend the
304+
// query args schemas
305+
newClient.inputValidator = new InputValidator(newClient as any);
306+
return newClient;
303307
}
304308

305309
$unuse(pluginId: string) {
306310
// tsc perf
307-
const newPlugins: RuntimePlugin<SchemaDef>[] = [];
311+
const newPlugins: RuntimePlugin<any, any>[] = [];
308312
for (const plugin of this.options.plugins ?? []) {
309313
if (plugin.id !== pluginId) {
310314
newPlugins.push(plugin);
@@ -314,16 +318,24 @@ export class ClientImpl {
314318
...this.options,
315319
plugins: newPlugins,
316320
};
317-
return new ClientImpl(this.schema, newOptions, this);
321+
const newClient = new ClientImpl(this.schema, newOptions, this);
322+
// create a new validator to have a fresh schema cache, because plugins may
323+
// extend the query args schemas
324+
newClient.inputValidator = new InputValidator(newClient as any);
325+
return newClient;
318326
}
319327

320328
$unuseAll() {
321329
// tsc perf
322330
const newOptions: ClientOptions<SchemaDef> = {
323331
...this.options,
324-
plugins: [] as RuntimePlugin<SchemaDef>[],
332+
plugins: [] as RuntimePlugin<any, any>[],
325333
};
326-
return new ClientImpl(this.schema, newOptions, this);
334+
const newClient = new ClientImpl(this.schema, newOptions, this);
335+
// create a new validator to have a fresh schema cache, because plugins may
336+
// extend the query args schemas
337+
newClient.inputValidator = new InputValidator(newClient as any);
338+
return newClient;
327339
}
328340

329341
$setAuth(auth: AuthType<SchemaDef> | undefined) {
@@ -340,18 +352,18 @@ export class ClientImpl {
340352
}
341353

342354
$setOptions<Options extends ClientOptions<SchemaDef>>(options: Options): ClientContract<SchemaDef, Options> {
343-
return new ClientImpl(this.schema, options as ClientOptions<SchemaDef>, this) as unknown as ClientContract<
344-
SchemaDef,
345-
Options
346-
>;
355+
const newClient = new ClientImpl(this.schema, options as ClientOptions<SchemaDef>, this);
356+
// create a new validator to have a fresh schema cache, because options may change validation settings
357+
newClient.inputValidator = new InputValidator(newClient as any);
358+
return newClient as unknown as ClientContract<SchemaDef, Options>;
347359
}
348360

349361
$setInputValidation(enable: boolean) {
350362
const newOptions: ClientOptions<SchemaDef> = {
351363
...this.options,
352364
validateInput: enable,
353365
};
354-
return new ClientImpl(this.schema, newOptions, this);
366+
return this.$setOptions(newOptions);
355367
}
356368

357369
$executeRaw(query: TemplateStringsArray, ...values: any[]) {
@@ -391,7 +403,6 @@ export class ClientImpl {
391403
}
392404

393405
function createClientProxy(client: ClientImpl): ClientImpl {
394-
const inputValidator = new InputValidator(client as any);
395406
const resultProcessor = new ResultProcessor(client.$schema, client.$options);
396407

397408
return new Proxy(client, {
@@ -403,7 +414,7 @@ function createClientProxy(client: ClientImpl): ClientImpl {
403414
if (typeof prop === 'string') {
404415
const model = Object.keys(client.$schema.models).find((m) => m.toLowerCase() === prop.toLowerCase());
405416
if (model) {
406-
return createModelCrudHandler(client as any, model, inputValidator, resultProcessor);
417+
return createModelCrudHandler(client as any, model, client.inputValidator, resultProcessor);
407418
}
408419
}
409420

@@ -419,8 +430,8 @@ function createModelCrudHandler(
419430
resultProcessor: ResultProcessor<any>,
420431
): ModelOperations<any, any> {
421432
const createPromise = (
422-
operation: CoreCrudOperation,
423-
nominalOperation: AllCrudOperation,
433+
operation: CoreCrudOperations,
434+
nominalOperation: AllCrudOperations,
424435
args: unknown,
425436
handler: BaseOperationHandler<any>,
426437
postProcess = false,
@@ -448,16 +459,18 @@ function createModelCrudHandler(
448459
const onQuery = plugin.onQuery;
449460
if (onQuery) {
450461
const _proceed = proceed;
451-
proceed = (_args: unknown) =>
452-
onQuery({
462+
proceed = (_args: unknown) => {
463+
const ctx: any = {
453464
client,
454465
model,
455466
operation: nominalOperation,
456467
// reflect the latest override if provided
457468
args: _args,
458469
// ensure inner overrides are propagated to the previous proceed
459470
proceed: (nextArgs: unknown) => _proceed(nextArgs),
460-
}) as Promise<unknown>;
471+
};
472+
return (onQuery as (ctx: any) => Promise<unknown>)(ctx);
473+
};
461474
}
462475
}
463476

@@ -516,6 +529,7 @@ function createModelCrudHandler(
516529
args,
517530
new FindOperationHandler<any>(client, model, inputValidator),
518531
true,
532+
false,
519533
);
520534
},
521535

0 commit comments

Comments
 (0)