Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions packages/orm/src/client/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,8 @@ export type AllModelOperations<
>(
args?: SelectSubset<
T,
CrudArgsType<Schema, Model, 'createManyAndReturn', Options, ExtQueryArgs, ExtResult>
CrudArgsType<Schema, Model, 'createManyAndReturn', Options, ExtQueryArgs, ExtResult>,
Options
>,
): ZenStackPromise<CrudReturnType<Schema, Model, 'createManyAndReturn', T, Options, ExtResult>>;

Expand Down Expand Up @@ -422,7 +423,11 @@ export type AllModelOperations<
updateManyAndReturn<
T extends CrudArgsType<Schema, Model, 'updateManyAndReturn', Options, ExtQueryArgs, ExtResult>,
>(
args: Subset<T, CrudArgsType<Schema, Model, 'updateManyAndReturn', Options, ExtQueryArgs, ExtResult>>,
args: Subset<
T,
CrudArgsType<Schema, Model, 'updateManyAndReturn', Options, ExtQueryArgs, ExtResult>,
Options
>,
): ZenStackPromise<CrudReturnType<Schema, Model, 'updateManyAndReturn', T, Options, ExtResult>>;
});

Expand Down Expand Up @@ -620,7 +625,7 @@ type CommonModelOperations<
* ```
*/
create<T extends CrudArgsType<Schema, Model, 'create', Options, ExtQueryArgs, ExtResult>>(
args: SelectSubset<T, CrudArgsType<Schema, Model, 'create', Options, ExtQueryArgs, ExtResult>>,
args: SelectSubset<T, CrudArgsType<Schema, Model, 'create', Options, ExtQueryArgs, ExtResult>, Options>,
): ZenStackPromise<CrudReturnType<Schema, Model, 'create', T, Options, ExtResult>>;

/**
Expand Down Expand Up @@ -649,7 +654,7 @@ type CommonModelOperations<
* ```
*/
createMany<T extends CrudArgsType<Schema, Model, 'createMany', Options, ExtQueryArgs, ExtResult>>(
args?: SelectSubset<T, CrudArgsType<Schema, Model, 'createMany', Options, ExtQueryArgs, ExtResult>>,
args?: SelectSubset<T, CrudArgsType<Schema, Model, 'createMany', Options, ExtQueryArgs, ExtResult>, Options>,
): ZenStackPromise<CrudReturnType<Schema, Model, 'createMany', T, Options, ExtResult>>;

/**
Expand Down Expand Up @@ -770,7 +775,7 @@ type CommonModelOperations<
* ```
*/
update<T extends CrudArgsType<Schema, Model, 'update', Options, ExtQueryArgs, ExtResult>>(
args: SelectSubset<T, CrudArgsType<Schema, Model, 'update', Options, ExtQueryArgs, ExtResult>>,
args: SelectSubset<T, CrudArgsType<Schema, Model, 'update', Options, ExtQueryArgs, ExtResult>, Options>,
): ZenStackPromise<CrudReturnType<Schema, Model, 'update', T, Options, ExtResult>>;

/**
Expand All @@ -794,7 +799,7 @@ type CommonModelOperations<
* });
*/
updateMany<T extends CrudArgsType<Schema, Model, 'updateMany', Options, ExtQueryArgs, ExtResult>>(
args: Subset<T, CrudArgsType<Schema, Model, 'updateMany', Options, ExtQueryArgs, ExtResult>>,
args: Subset<T, CrudArgsType<Schema, Model, 'updateMany', Options, ExtQueryArgs, ExtResult>, Options>,
): ZenStackPromise<CrudReturnType<Schema, Model, 'updateMany', T, Options, ExtResult>>;

/**
Expand All @@ -818,7 +823,7 @@ type CommonModelOperations<
* ```
*/
upsert<T extends CrudArgsType<Schema, Model, 'upsert', Options, ExtQueryArgs, ExtResult>>(
args: SelectSubset<T, CrudArgsType<Schema, Model, 'upsert', Options, ExtQueryArgs, ExtResult>>,
args: SelectSubset<T, CrudArgsType<Schema, Model, 'upsert', Options, ExtQueryArgs, ExtResult>, Options>,
): ZenStackPromise<CrudReturnType<Schema, Model, 'upsert', T, Options, ExtResult>>;

/**
Expand Down
28 changes: 19 additions & 9 deletions packages/orm/src/client/crud-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import type {
MapBaseType,
MaybePromise,
NonEmptyArray,
NoExtraProperties,
NullableIf,
Optional,
OrArray,
Expand Down Expand Up @@ -1311,17 +1312,22 @@ export type IncludeInput<
: {}
: {});

export type Subset<T, U> = {
type StrictArgs<T, U, Options> = Options extends { typing: { exactQueryArgs: true } }
? NoExtraProperties<T, U>
: unknown;

export type Subset<T, U, Options = {}> = {
[key in keyof T]: key extends keyof U ? T[key] : never;
};
} & StrictArgs<T, U, Options>;

export type SelectSubset<T, U> = {
export type SelectSubset<T, U, Options = {}> = {
[key in keyof T]: key extends keyof U ? T[key] : never;
} & (T extends { select: any; include: any }
? 'Please either choose `select` or `include`.'
: T extends { select: any; omit: any }
? 'Please either choose `select` or `omit`.'
: {});
} & StrictArgs<T, U, Options> &
(T extends { select: any; include: any }
? 'Please either choose `select` or `include`.'
: T extends { select: any; omit: any }
? 'Please either choose `select` or `omit`.'
: {});

type ToManyRelationFilter<
in out Schema extends SchemaDef,
Expand Down Expand Up @@ -1453,7 +1459,11 @@ type OppositeRelationAndFK<

//#region Find args

type FilterArgs<in out Schema extends SchemaDef, in out Model extends GetModels<Schema>, in out Options extends QueryOptions<Schema>> = {
type FilterArgs<
in out Schema extends SchemaDef,
in out Model extends GetModels<Schema>,
in out Options extends QueryOptions<Schema>,
> = {
/**
* Filter conditions
*/
Expand Down
13 changes: 12 additions & 1 deletion packages/orm/src/client/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,17 @@ type FieldSlicingOptions = {
* Partial ORM client options that defines customizable behaviors.
*/
export type QueryOptions<Schema extends SchemaDef> = {
/**
* Type-checking options for query arguments.
*/
typing?: {
/**
* Recursively rejects unknown properties in query arguments. This is opt-in because the
* additional precision requires more work from the TypeScript checker.
*/
exactQueryArgs?: boolean;
};

Comment thread
coderabbitai[bot] marked this conversation as resolved.
/**
* Options for omitting fields in ORM query results.
*/
Expand All @@ -158,7 +169,7 @@ export type QueryOptions<Schema extends SchemaDef> = {

/**
* Projects a (typically inferred) client options type down to only the members that influence
* ORM typing - the {@link QueryOptions} fields (`omit`, `allowQueryTimeOmitOverride`, `slicing`).
* ORM typing - the {@link QueryOptions} fields (`typing`, `omit`, `allowQueryTimeOmitOverride`, `slicing`).
*
* The full options object inferred at `new ZenStackClient(...)` carries heavy function types for
* `computedFields` and `procedures`. Those are never read by the model/operation types, but if the
Expand Down
29 changes: 29 additions & 0 deletions packages/orm/src/utils/type-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,32 @@ export type UnwrapTuplePromises<T extends readonly unknown[]> = {
};

export type Exact<T, Shape> = T extends Shape ? (Exclude<keyof T, keyof Shape> extends never ? T : never) : never;

type _ExactLeaf = Date | Function | Decimal | Uint8Array;
type _ObjectKeys<T> = T extends object ? keyof T : never;
type _ObjectValue<T, K extends PropertyKey> = T extends object ? (K extends keyof T ? T[K] : never) : never;
type _ArrayItem<T> = T extends readonly (infer Item)[] ? Item : never;

type _NoExtraObject<T extends object, Shape, Keys extends PropertyKey = _ObjectKeys<Shape>> = [Keys] extends [never]
? never
: string extends Keys
? unknown
: {
[K in keyof T]: K extends Keys ? NoExtraProperties<T[K], _ObjectValue<Shape, K>> : never;
};

/**
* Rejects unknown keys by walking only the finite inferred input. Expected unions are distributed
* only when looking up the current property, avoiding reconstruction of the input per union branch.
*/
export type NoExtraProperties<T, Shape> = unknown extends Shape
? unknown
: T extends _ExactLeaf
? unknown
: T extends readonly (infer Item)[]
? [_ArrayItem<Shape>] extends [never]
? never
: NoExtraProperties<Item, _ArrayItem<Shape>>[]
: T extends object
? _NoExtraObject<T, Shape>
: unknown;
Loading
Loading