From 04dc3ca960a042a3abb772e6b6c279b62630a4ef Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Fri, 14 Nov 2025 22:36:55 -0800 Subject: [PATCH 1/3] fix(orm): reimplement typescript type display simplification --- packages/clients/tanstack-query/src/react.ts | 46 +-- packages/clients/tanstack-query/src/svelte.ts | 32 +- packages/clients/tanstack-query/src/vue.ts | 32 +- .../test/schemas/basic/schema-lite.ts | 8 +- packages/orm/src/client/contract.ts | 34 +- packages/orm/src/client/crud-types.ts | 322 ++++++------------ .../src/client/crud/dialects/base-dialect.ts | 16 +- packages/sdk/src/ts-schema-generator.ts | 54 ++- samples/next.js/zenstack/schema-lite.ts | 8 +- samples/next.js/zenstack/schema.ts | 8 +- samples/orm/zenstack/schema.ts | 8 +- tests/e2e/apps/rally/zenstack/schema.ts | 8 +- tests/e2e/orm/schemas/basic/schema.ts | 8 +- tests/e2e/orm/schemas/default-auth/schema.ts | 8 +- tests/e2e/orm/schemas/delegate/schema.ts | 8 +- tests/e2e/orm/schemas/name-mapping/schema.ts | 8 +- tests/e2e/orm/schemas/petstore/schema.ts | 8 +- tests/e2e/orm/schemas/todo/schema.ts | 8 +- tests/e2e/orm/schemas/typing/schema.ts | 8 +- 19 files changed, 311 insertions(+), 321 deletions(-) diff --git a/packages/clients/tanstack-query/src/react.ts b/packages/clients/tanstack-query/src/react.ts index b5763ce3..92af99b5 100644 --- a/packages/clients/tanstack-query/src/react.ts +++ b/packages/clients/tanstack-query/src/react.ts @@ -145,108 +145,108 @@ export type ModelQueryHooks>( + useFindUnique>( args: SelectSubset>, options?: ModelQueryOptions | null>, ): ModelQueryResult | null>; - useSuspenseFindUnique>( + useSuspenseFindUnique>( args: SelectSubset>, options?: ModelSuspenseQueryOptions | null>, ): ModelSuspenseQueryResult | null>; - useFindFirst>( + useFindFirst>( args?: SelectSubset>, options?: ModelQueryOptions | null>, ): ModelQueryResult | null>; - useSuspenseFindFirst>( + useSuspenseFindFirst>( args?: SelectSubset>, options?: ModelSuspenseQueryOptions | null>, ): ModelSuspenseQueryResult | null>; - useFindMany>( + useFindMany>( args?: SelectSubset>, options?: ModelQueryOptions[]>, ): ModelQueryResult[]>; - useSuspenseFindMany>( + useSuspenseFindMany>( args?: SelectSubset>, options?: ModelSuspenseQueryOptions[]>, ): ModelSuspenseQueryResult[]>; - useInfiniteFindMany>( + useInfiniteFindMany>( args?: SelectSubset>, options?: ModelInfiniteQueryOptions[]>, ): ModelInfiniteQueryResult[]>>; - useSuspenseInfiniteFindMany>( + useSuspenseInfiniteFindMany>( args?: SelectSubset>, options?: ModelSuspenseInfiniteQueryOptions[]>, ): ModelSuspenseInfiniteQueryResult[]>>; - useCreate>( + useCreate>( options?: ModelMutationOptions, T>, ): ModelMutationModelResult; - useCreateMany>( + useCreateMany>( options?: ModelMutationOptions, ): ModelMutationResult; - useCreateManyAndReturn>( + useCreateManyAndReturn>( options?: ModelMutationOptions[], T>, ): ModelMutationModelResult; - useUpdate>( + useUpdate>( options?: ModelMutationOptions, T>, ): ModelMutationModelResult; - useUpdateMany>( + useUpdateMany>( options?: ModelMutationOptions, ): ModelMutationResult; - useUpdateManyAndReturn>( + useUpdateManyAndReturn>( options?: ModelMutationOptions[], T>, ): ModelMutationModelResult; - useUpsert>( + useUpsert>( options?: ModelMutationOptions, T>, ): ModelMutationModelResult; - useDelete>( + useDelete>( options?: ModelMutationOptions, T>, ): ModelMutationModelResult; - useDeleteMany>( + useDeleteMany>( options?: ModelMutationOptions, ): ModelMutationResult; - useCount>( + useCount>( args?: Subset>, options?: ModelQueryOptions>, ): ModelQueryResult>; - useSuspenseCount>( + useSuspenseCount>( args?: Subset>, options?: ModelSuspenseQueryOptions>, ): ModelSuspenseQueryResult>; - useAggregate>( + useAggregate>( args: Subset>, options?: ModelQueryOptions>, ): ModelQueryResult>; - useSuspenseAggregate>( + useSuspenseAggregate>( args: Subset>, options?: ModelSuspenseQueryOptions>, ): ModelSuspenseQueryResult>; - useGroupBy>( + useGroupBy>( args: Subset>, options?: ModelQueryOptions>, ): ModelQueryResult>; - useSuspenseGroupBy>( + useSuspenseGroupBy>( args: Subset>, options?: ModelSuspenseQueryOptions>, ): ModelSuspenseQueryResult>; diff --git a/packages/clients/tanstack-query/src/svelte.ts b/packages/clients/tanstack-query/src/svelte.ts index e05840a2..8b40750c 100644 --- a/packages/clients/tanstack-query/src/svelte.ts +++ b/packages/clients/tanstack-query/src/svelte.ts @@ -138,73 +138,73 @@ export type ModelQueryHooks>( + useFindUnique>( args: SelectSubset>, options?: ModelQueryOptions | null>, ): ModelQueryResult | null>; - useFindFirst>( + useFindFirst>( args?: SelectSubset>, options?: ModelQueryOptions | null>, ): ModelQueryResult | null>; - useFindMany>( + useFindMany>( args?: SelectSubset>, options?: ModelQueryOptions[]>, ): ModelQueryResult[]>; - useInfiniteFindMany>( + useInfiniteFindMany>( args?: SelectSubset>, options?: ModelInfiniteQueryOptions[]>, ): ModelInfiniteQueryResult[]>>; - useCreate>( + useCreate>( options?: ModelMutationOptions, T>, ): ModelMutationModelResult; - useCreateMany>( + useCreateMany>( options?: ModelMutationOptions, ): ModelMutationResult; - useCreateManyAndReturn>( + useCreateManyAndReturn>( options?: ModelMutationOptions[], T>, ): ModelMutationModelResult; - useUpdate>( + useUpdate>( options?: ModelMutationOptions, T>, ): ModelMutationModelResult; - useUpdateMany>( + useUpdateMany>( options?: ModelMutationOptions, ): ModelMutationResult; - useUpdateManyAndReturn>( + useUpdateManyAndReturn>( options?: ModelMutationOptions[], T>, ): ModelMutationModelResult; - useUpsert>( + useUpsert>( options?: ModelMutationOptions, T>, ): ModelMutationModelResult; - useDelete>( + useDelete>( options?: ModelMutationOptions, T>, ): ModelMutationModelResult; - useDeleteMany>( + useDeleteMany>( options?: ModelMutationOptions, ): ModelMutationResult; - useCount>( + useCount>( args?: Subset>, options?: ModelQueryOptions>, ): ModelQueryResult>; - useAggregate>( + useAggregate>( args: Subset>, options?: ModelQueryOptions>, ): ModelQueryResult>; - useGroupBy>( + useGroupBy>( args: Subset>, options?: ModelQueryOptions>, ): ModelQueryResult>; diff --git a/packages/clients/tanstack-query/src/vue.ts b/packages/clients/tanstack-query/src/vue.ts index 5c71f319..e5051426 100644 --- a/packages/clients/tanstack-query/src/vue.ts +++ b/packages/clients/tanstack-query/src/vue.ts @@ -122,73 +122,73 @@ export type ModelQueryHooks>( + useFindUnique>( args: SelectSubset>, options?: ModelQueryOptions | null>, ): ModelQueryResult | null>; - useFindFirst>( + useFindFirst>( args?: SelectSubset>, options?: ModelQueryOptions | null>, ): ModelQueryResult | null>; - useFindMany>( + useFindMany>( args?: SelectSubset>, options?: ModelQueryOptions[]>, ): ModelQueryResult[]>; - useInfiniteFindMany>( + useInfiniteFindMany>( args?: SelectSubset>, options?: ModelInfiniteQueryOptions[]>, ): ModelInfiniteQueryResult[]>>; - useCreate>( + useCreate>( options?: ModelMutationOptions, T>, ): ModelMutationModelResult; - useCreateMany>( + useCreateMany>( options?: ModelMutationOptions, ): ModelMutationResult; - useCreateManyAndReturn>( + useCreateManyAndReturn>( options?: ModelMutationOptions[], T>, ): ModelMutationModelResult; - useUpdate>( + useUpdate>( options?: ModelMutationOptions, T>, ): ModelMutationModelResult; - useUpdateMany>( + useUpdateMany>( options?: ModelMutationOptions, ): ModelMutationResult; - useUpdateManyAndReturn>( + useUpdateManyAndReturn>( options?: ModelMutationOptions[], T>, ): ModelMutationModelResult; - useUpsert>( + useUpsert>( options?: ModelMutationOptions, T>, ): ModelMutationModelResult; - useDelete>( + useDelete>( options?: ModelMutationOptions, T>, ): ModelMutationModelResult; - useDeleteMany>( + useDeleteMany>( options?: ModelMutationOptions, ): ModelMutationResult; - useCount>( + useCount>( args?: Subset>, options?: ModelQueryOptions>, ): ModelQueryResult>; - useAggregate>( + useAggregate>( args: Subset>, options?: ModelQueryOptions>, ): ModelQueryResult>; - useGroupBy>( + useGroupBy>( args: Subset>, options?: ModelQueryOptions>, ): ModelQueryResult>; diff --git a/packages/clients/tanstack-query/test/schemas/basic/schema-lite.ts b/packages/clients/tanstack-query/test/schemas/basic/schema-lite.ts index ea44666f..3d826024 100644 --- a/packages/clients/tanstack-query/test/schemas/basic/schema-lite.ts +++ b/packages/clients/tanstack-query/test/schemas/basic/schema-lite.ts @@ -6,7 +6,7 @@ /* eslint-disable */ import { type SchemaDef, ExpressionUtils } from "@zenstackhq/orm/schema"; -export const schema = { +const _schema = { provider: { type: "sqlite" }, @@ -169,4 +169,8 @@ export const schema = { authType: "User", plugins: {} } as const satisfies SchemaDef; -export type SchemaType = typeof schema; +type Schema = typeof _schema & { + __brand?: "schema"; +}; +export const schema: Schema = _schema; +export type SchemaType = Schema; diff --git a/packages/orm/src/client/contract.ts b/packages/orm/src/client/contract.ts index 7f1fd48c..6db19953 100644 --- a/packages/orm/src/client/contract.ts +++ b/packages/orm/src/client/contract.ts @@ -325,7 +325,7 @@ export type AllModelOperations>( + findMany>( args?: SelectSubset>, ): ZenStackPromise[]>; @@ -335,7 +335,7 @@ export type AllModelOperations>( + findUnique>( args: SelectSubset>, ): ZenStackPromise | null>; @@ -345,7 +345,7 @@ export type AllModelOperations>( + findUniqueOrThrow>( args: SelectSubset>, ): ZenStackPromise>; @@ -355,7 +355,7 @@ export type AllModelOperations>( + findFirst>( args?: SelectSubset>, ): ZenStackPromise | null>; @@ -365,7 +365,7 @@ export type AllModelOperations>( + findFirstOrThrow>( args?: SelectSubset>, ): ZenStackPromise>; @@ -421,7 +421,7 @@ export type AllModelOperations>( + create>( args: SelectSubset>, ): ZenStackPromise>; @@ -450,7 +450,7 @@ export type AllModelOperations>( + createMany>( args?: SelectSubset>, ): ZenStackPromise; @@ -472,7 +472,7 @@ export type AllModelOperations>( + createManyAndReturn>( args?: SelectSubset>, ): ZenStackPromise[]>; @@ -593,7 +593,7 @@ export type AllModelOperations>( + update>( args: SelectSubset>, ): ZenStackPromise>; @@ -617,7 +617,7 @@ export type AllModelOperations>( + updateMany>( args: Subset>, ): ZenStackPromise; @@ -643,7 +643,7 @@ export type AllModelOperations>( + updateManyAndReturn>( args: Subset>, ): ZenStackPromise[]>; @@ -667,7 +667,7 @@ export type AllModelOperations>( + upsert>( args: SelectSubset>, ): ZenStackPromise>; @@ -690,7 +690,7 @@ export type AllModelOperations>( + delete>( args: SelectSubset>, ): ZenStackPromise>; @@ -713,7 +713,7 @@ export type AllModelOperations>( + deleteMany>( args?: Subset>, ): ZenStackPromise; @@ -735,7 +735,7 @@ export type AllModelOperations>( + count>( args?: Subset>, ): ZenStackPromise>>; @@ -756,7 +756,7 @@ export type AllModelOperations>( + aggregate>( args: Subset>, ): ZenStackPromise>>; @@ -793,7 +793,7 @@ export type AllModelOperations>( + groupBy>( args: Subset>, ): ZenStackPromise>>; }; diff --git a/packages/orm/src/client/crud-types.ts b/packages/orm/src/client/crud-types.ts index 944d6881..f4b5cd06 100644 --- a/packages/orm/src/client/crud-types.ts +++ b/packages/orm/src/client/crud-types.ts @@ -39,7 +39,6 @@ import type { Optional, OrArray, Simplify, - SimplifyIf, ValueOfPotentialTuple, WrapType, XOR, @@ -230,7 +229,6 @@ export type WhereInput< > : // primitive PrimitiveFilter< - Schema, GetModelFieldType, ModelFieldIsOptional, WithAggregations @@ -257,7 +255,7 @@ type EnumFilter< not?: EnumFilter; } & (WithAggregations extends true ? { - _count?: NumberFilter; + _count?: NumberFilter<'Int', false, false>; _min?: EnumFilter; _max?: EnumFilter; } @@ -275,27 +273,21 @@ type ArrayFilter = { type MapScalarType = T extends GetEnums ? keyof GetEnum : MapBaseType; -type PrimitiveFilter< - Schema extends SchemaDef, - T extends string, - Nullable extends boolean, - WithAggregations extends boolean, -> = T extends 'String' - ? StringFilter +type PrimitiveFilter = T extends 'String' + ? StringFilter : T extends 'Int' | 'Float' | 'Decimal' | 'BigInt' - ? NumberFilter + ? NumberFilter : T extends 'Boolean' - ? BooleanFilter + ? BooleanFilter : T extends 'DateTime' - ? DateTimeFilter + ? DateTimeFilter : T extends 'Bytes' - ? BytesFilter + ? BytesFilter : T extends 'Json' ? 'Not implemented yet' // TODO: Json filter : never; type CommonPrimitiveFilter< - Schema extends SchemaDef, DataType, T extends BuiltinType, Nullable extends boolean, @@ -308,82 +300,77 @@ type CommonPrimitiveFilter< lte?: DataType; gt?: DataType; gte?: DataType; - not?: PrimitiveFilter; + not?: PrimitiveFilter; }; -export type StringFilter = +export type StringFilter = | NullableIf - | (CommonPrimitiveFilter & { + | (CommonPrimitiveFilter & { contains?: string; startsWith?: string; endsWith?: string; + mode?: 'default' | 'insensitive'; } & (WithAggregations extends true ? { - _count?: NumberFilter; - _min?: StringFilter; - _max?: StringFilter; - } - : {}) & - (ProviderSupportsCaseSensitivity extends true - ? { - mode?: 'default' | 'insensitive'; + _count?: NumberFilter<'Int', false, false>; + _min?: StringFilter; + _max?: StringFilter; } : {})); export type NumberFilter< - Schema extends SchemaDef, T extends 'Int' | 'Float' | 'Decimal' | 'BigInt', Nullable extends boolean, WithAggregations extends boolean, > = | NullableIf - | (CommonPrimitiveFilter & + | (CommonPrimitiveFilter & (WithAggregations extends true ? { - _count?: NumberFilter; - _avg?: NumberFilter; - _sum?: NumberFilter; - _min?: NumberFilter; - _max?: NumberFilter; + _count?: NumberFilter<'Int', false, false>; + _avg?: NumberFilter; + _sum?: NumberFilter; + _min?: NumberFilter; + _max?: NumberFilter; } : {})); -export type DateTimeFilter = +export type DateTimeFilter = | NullableIf - | (CommonPrimitiveFilter & + | (CommonPrimitiveFilter & (WithAggregations extends true ? { - _count?: NumberFilter; - _min?: DateTimeFilter; - _max?: DateTimeFilter; + _count?: NumberFilter<'Int', false, false>; + _min?: DateTimeFilter; + _max?: DateTimeFilter; } : {})); -export type BytesFilter = +export type BytesFilter = | NullableIf | ({ equals?: NullableIf; in?: Uint8Array[]; notIn?: Uint8Array[]; - not?: BytesFilter; + not?: BytesFilter; } & (WithAggregations extends true ? { - _count?: NumberFilter; - _min?: BytesFilter; - _max?: BytesFilter; + _count?: NumberFilter<'Int', false, false>; + _min?: BytesFilter; + _max?: BytesFilter; } : {})); -export type BooleanFilter = +export type BooleanFilter = | NullableIf | ({ equals?: NullableIf; - not?: BooleanFilter; + not?: BooleanFilter; } & (WithAggregations extends true ? { - _count?: NumberFilter; - _min?: BooleanFilter; - _max?: BooleanFilter; + _count?: NumberFilter<'Int', false, false>; + _min?: BooleanFilter; + _max?: BooleanFilter; } : {})); @@ -669,58 +656,29 @@ export type FindArgs< (AllowFilter extends true ? FilterArgs : {}) & SelectIncludeOmit; -export type FindManyArgs< - Schema extends SchemaDef, - Model extends GetModels, - Simplify extends boolean = false, -> = SimplifyIf, Simplify>; +export type FindManyArgs> = FindArgs; -export type FindFirstArgs< - Schema extends SchemaDef, - Model extends GetModels, - Simplify extends boolean = false, -> = SimplifyIf, Simplify>; +export type FindFirstArgs> = FindArgs; -export type FindUniqueArgs< - Schema extends SchemaDef, - Model extends GetModels, - Simplify extends boolean = false, -> = SimplifyIf< - { - where?: WhereUniqueInput; - } & SelectIncludeOmit, - Simplify ->; +export type FindUniqueArgs> = { + where?: WhereUniqueInput; +} & SelectIncludeOmit; //#endregion //#region Create args -export type CreateArgs< - Schema extends SchemaDef, - Model extends GetModels, - Simplify extends boolean = false, -> = SimplifyIf< - { - data: CreateInput; - } & SelectIncludeOmit, - Simplify ->; +export type CreateArgs> = { + data: CreateInput; +} & SelectIncludeOmit; -export type CreateManyArgs< - Schema extends SchemaDef, - Model extends GetModels, - Simplify extends boolean = false, -> = SimplifyIf, Simplify>; +export type CreateManyArgs> = CreateManyInput; -export type CreateManyAndReturnArgs< - Schema extends SchemaDef, - Model extends GetModels, - Simplify extends boolean = false, -> = SimplifyIf< - CreateManyInput & Omit, 'include'>, - Simplify ->; +export type CreateManyAndReturnArgs> = CreateManyInput< + Schema, + Model +> & + Omit, 'include'>; type OptionalWrap, T extends object> = Optional< T, @@ -846,51 +804,33 @@ type NestedCreateManyInput< // #region Update args -export type UpdateArgs< - Schema extends SchemaDef, - Model extends GetModels, - Simplify extends boolean = false, -> = SimplifyIf< - { - data: UpdateInput; - where: WhereUniqueInput; - } & SelectIncludeOmit, - Simplify ->; - -export type UpdateManyArgs< - Schema extends SchemaDef, - Model extends GetModels, - Simplify extends boolean = false, -> = SimplifyIf, Simplify>; +export type UpdateArgs> = { + data: UpdateInput; + where: WhereUniqueInput; +} & SelectIncludeOmit; -export type UpdateManyAndReturnArgs< - Schema extends SchemaDef, - Model extends GetModels, - Simplify extends boolean = false, -> = SimplifyIf< - UpdateManyPayload & Omit, 'include'>, - Simplify +export type UpdateManyArgs> = UpdateManyPayload< + Schema, + Model >; +export type UpdateManyAndReturnArgs> = UpdateManyPayload< + Schema, + Model +> & + Omit, 'include'>; + type UpdateManyPayload, Without extends string = never> = { data: OrArray>; where?: WhereInput; limit?: number; }; -export type UpsertArgs< - Schema extends SchemaDef, - Model extends GetModels, - Simplify extends boolean = false, -> = SimplifyIf< - { - create: CreateInput; - update: UpdateInput; - where: WhereUniqueInput; - } & SelectIncludeOmit, - Simplify ->; +export type UpsertArgs> = { + create: CreateInput; + update: UpdateInput; + where: WhereUniqueInput; +} & SelectIncludeOmit; type UpdateScalarInput< Schema extends SchemaDef, @@ -1002,43 +942,25 @@ type ToOneRelationUpdateInput< // #region Delete args -export type DeleteArgs< - Schema extends SchemaDef, - Model extends GetModels, - Simplify extends boolean = false, -> = SimplifyIf< - { - where: WhereUniqueInput; - } & SelectIncludeOmit, - Simplify ->; +export type DeleteArgs> = { + where: WhereUniqueInput; +} & SelectIncludeOmit; -export type DeleteManyArgs< - Schema extends SchemaDef, - Model extends GetModels, - Simplify extends boolean = false, -> = SimplifyIf< - { - where?: WhereInput; - limit?: number; - }, - Simplify ->; +export type DeleteManyArgs> = { + where?: WhereInput; + limit?: number; +}; // #endregion // #region Count args -export type CountArgs< - Schema extends SchemaDef, - Model extends GetModels, - Simplify extends boolean = false, -> = SimplifyIf< - Omit, 'select' | 'include' | 'distinct' | 'omit'> & { - select?: CountAggregateInput | true; - }, - Simplify ->; +export type CountArgs> = Omit< + FindArgs, + 'select' | 'include' | 'distinct' | 'omit' +> & { + select?: CountAggregateInput | true; +}; type CountAggregateInput> = { [Key in NonRelationFields]?: true; @@ -1058,28 +980,21 @@ export type CountResult, - Simplify extends boolean = false, -> = SimplifyIf< - { - where?: WhereInput; - skip?: number; - take?: number; - orderBy?: OrArray>; - } & { - _count?: true | CountAggregateInput; - _min?: MinMaxInput; - _max?: MinMaxInput; - } & (NumericFields extends never - ? {} - : { - _avg?: SumAvgInput; - _sum?: SumAvgInput; - }), - Simplify ->; +export type AggregateArgs> = { + where?: WhereInput; + skip?: number; + take?: number; + orderBy?: OrArray>; +} & { + _count?: true | CountAggregateInput; + _min?: MinMaxInput; + _max?: MinMaxInput; +} & (NumericFields extends never + ? {} + : { + _avg?: SumAvgInput; + _sum?: SumAvgInput; + }); type NumericFields> = keyof { [Key in GetModelFields as GetModelFieldType extends @@ -1150,31 +1065,24 @@ type GroupByHaving> = '$expr' >; -export type GroupByArgs< - Schema extends SchemaDef, - Model extends GetModels, - Simplify extends boolean = false, -> = SimplifyIf< - { - where?: WhereInput; - orderBy?: OrArray>; - by: NonRelationFields | NonEmptyArray>; - having?: GroupByHaving; - take?: number; - skip?: number; - // aggregations - _count?: true | CountAggregateInput; - _min?: MinMaxInput; - _max?: MinMaxInput; - } & (NumericFields extends never - ? {} - : { - // aggregations specific to numeric fields - _avg?: SumAvgInput; - _sum?: SumAvgInput; - }), - Simplify ->; +export type GroupByArgs> = { + where?: WhereInput; + orderBy?: OrArray>; + by: NonRelationFields | NonEmptyArray>; + having?: GroupByHaving; + take?: number; + skip?: number; + // aggregations + _count?: true | CountAggregateInput; + _min?: MinMaxInput; + _max?: MinMaxInput; +} & (NumericFields extends never + ? {} + : { + // aggregations specific to numeric fields + _avg?: SumAvgInput; + _sum?: SumAvgInput; + }); export type GroupByResult< Schema extends SchemaDef, @@ -1350,10 +1258,6 @@ type HasToManyRelations = Schema['provider']['type'] extends 'postgresql' - ? true - : false; - type ProviderSupportsDistinct = Schema['provider']['type'] extends 'postgresql' ? true : false; diff --git a/packages/orm/src/client/crud/dialects/base-dialect.ts b/packages/orm/src/client/crud/dialects/base-dialect.ts index b9f557a7..2b96941e 100644 --- a/packages/orm/src/client/crud/dialects/base-dialect.ts +++ b/packages/orm/src/client/crud/dialects/base-dialect.ts @@ -604,7 +604,7 @@ export abstract class BaseCrudDialect { return { conditions, consumedKeys }; } - private buildStringFilter(fieldRef: Expression, payload: StringFilter) { + private buildStringFilter(fieldRef: Expression, payload: StringFilter) { let mode: 'default' | 'insensitive' | undefined; if (payload && typeof payload === 'object' && 'mode' in payload) { mode = payload.mode; @@ -615,7 +615,7 @@ export abstract class BaseCrudDialect { payload, mode === 'insensitive' ? this.eb.fn('lower', [fieldRef]) : fieldRef, (value) => this.prepStringCasing(this.eb, value, mode), - (value) => this.buildStringFilter(fieldRef, value as StringFilter), + (value) => this.buildStringFilter(fieldRef, value as StringFilter), ); if (payload && typeof payload === 'object') { @@ -683,38 +683,38 @@ export abstract class BaseCrudDialect { return this.and(...conditions); } - private buildBooleanFilter(fieldRef: Expression, payload: BooleanFilter) { + private buildBooleanFilter(fieldRef: Expression, payload: BooleanFilter) { const { conditions } = this.buildStandardFilter( 'Boolean', payload, fieldRef, (value) => this.transformPrimitive(value, 'Boolean', false), - (value) => this.buildBooleanFilter(fieldRef, value as BooleanFilter), + (value) => this.buildBooleanFilter(fieldRef, value as BooleanFilter), true, ['equals', 'not'], ); return this.and(...conditions); } - private buildDateTimeFilter(fieldRef: Expression, payload: DateTimeFilter) { + private buildDateTimeFilter(fieldRef: Expression, payload: DateTimeFilter) { const { conditions } = this.buildStandardFilter( 'DateTime', payload, fieldRef, (value) => this.transformPrimitive(value, 'DateTime', false), - (value) => this.buildDateTimeFilter(fieldRef, value as DateTimeFilter), + (value) => this.buildDateTimeFilter(fieldRef, value as DateTimeFilter), true, ); return this.and(...conditions); } - private buildBytesFilter(fieldRef: Expression, payload: BytesFilter) { + private buildBytesFilter(fieldRef: Expression, payload: BytesFilter) { const conditions = this.buildStandardFilter( 'Bytes', payload, fieldRef, (value) => this.transformPrimitive(value, 'Bytes', false), - (value) => this.buildBytesFilter(fieldRef, value as BytesFilter), + (value) => this.buildBytesFilter(fieldRef, value as BytesFilter), true, ['equals', 'in', 'notIn', 'not'], ); diff --git a/packages/sdk/src/ts-schema-generator.ts b/packages/sdk/src/ts-schema-generator.ts index 798b6dfe..d1d19fe1 100644 --- a/packages/sdk/src/ts-schema-generator.ts +++ b/packages/sdk/src/ts-schema-generator.ts @@ -148,12 +148,13 @@ export class TsSchemaGenerator { ); statements.push(runtimeImportDecl); - const declaration = ts.factory.createVariableStatement( - [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], + // const _schema = { ... } as const satisfies SchemaDef; + const _schemaDecl = ts.factory.createVariableStatement( + [], ts.factory.createVariableDeclarationList( [ ts.factory.createVariableDeclaration( - 'schema', + '_schema', undefined, undefined, ts.factory.createSatisfiesExpression( @@ -165,16 +166,53 @@ export class TsSchemaGenerator { ts.NodeFlags.Const, ), ); - statements.push(declaration); + statements.push(_schemaDecl); + + // type Schema = typeof _schema & { __brand?: 'schema' }; + // use a branded type to prevent typescript compiler from expanding the schema type + const brandedSchemaType = ts.factory.createTypeAliasDeclaration( + undefined, + 'Schema', + undefined, + ts.factory.createIntersectionTypeNode([ + ts.factory.createTypeQueryNode(ts.factory.createIdentifier('_schema')), + ts.factory.createTypeLiteralNode([ + ts.factory.createPropertySignature( + undefined, + '__brand', + ts.factory.createToken(ts.SyntaxKind.QuestionToken), + ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral('schema')), + ), + ]), + ]), + ); + statements.push(brandedSchemaType); + + // export const schema: Schema = _schema; + const schemaExportDecl = ts.factory.createVariableStatement( + [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], + ts.factory.createVariableDeclarationList( + [ + ts.factory.createVariableDeclaration( + 'schema', + undefined, + ts.factory.createTypeReferenceNode('Schema'), + ts.factory.createIdentifier('_schema'), + ), + ], + ts.NodeFlags.Const, + ), + ); + statements.push(schemaExportDecl); - // create statement "export type SchemaType = typeof schema;" - const typeDeclaration = ts.factory.createTypeAliasDeclaration( + // export type SchemaType = Schema; + const schemaTypeDeclaration = ts.factory.createTypeAliasDeclaration( [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], 'SchemaType', undefined, - ts.factory.createTypeReferenceNode('typeof schema'), + ts.factory.createTypeReferenceNode('Schema'), ); - statements.push(typeDeclaration); + statements.push(schemaTypeDeclaration); } private createExpressionUtilsCall(method: string, args?: ts.Expression[]): ts.CallExpression { diff --git a/samples/next.js/zenstack/schema-lite.ts b/samples/next.js/zenstack/schema-lite.ts index 87909373..e8b2f096 100644 --- a/samples/next.js/zenstack/schema-lite.ts +++ b/samples/next.js/zenstack/schema-lite.ts @@ -6,7 +6,7 @@ /* eslint-disable */ import { type SchemaDef, ExpressionUtils } from "@zenstackhq/orm/schema"; -export const schema = { +const _schema = { provider: { type: "sqlite" }, @@ -103,4 +103,8 @@ export const schema = { authType: "User", plugins: {} } as const satisfies SchemaDef; -export type SchemaType = typeof schema; +type Schema = typeof _schema & { + __brand?: "schema"; +}; +export const schema: Schema = _schema; +export type SchemaType = Schema; diff --git a/samples/next.js/zenstack/schema.ts b/samples/next.js/zenstack/schema.ts index 8a6632b0..6388c6c2 100644 --- a/samples/next.js/zenstack/schema.ts +++ b/samples/next.js/zenstack/schema.ts @@ -6,7 +6,7 @@ /* eslint-disable */ import { type SchemaDef, ExpressionUtils } from "@zenstackhq/orm/schema"; -export const schema = { +const _schema = { provider: { type: "sqlite" }, @@ -112,4 +112,8 @@ export const schema = { authType: "User", plugins: {} } as const satisfies SchemaDef; -export type SchemaType = typeof schema; +type Schema = typeof _schema & { + __brand?: "schema"; +}; +export const schema: Schema = _schema; +export type SchemaType = Schema; diff --git a/samples/orm/zenstack/schema.ts b/samples/orm/zenstack/schema.ts index 4c9134b9..1db7031c 100644 --- a/samples/orm/zenstack/schema.ts +++ b/samples/orm/zenstack/schema.ts @@ -6,7 +6,7 @@ /* eslint-disable */ import { type SchemaDef, type OperandExpression, ExpressionUtils } from "@zenstackhq/orm/schema"; -export const schema = { +const _schema = { provider: { type: "sqlite" }, @@ -241,4 +241,8 @@ export const schema = { authType: "User", plugins: {} } as const satisfies SchemaDef; -export type SchemaType = typeof schema; +type Schema = typeof _schema & { + __brand?: "schema"; +}; +export const schema: Schema = _schema; +export type SchemaType = Schema; diff --git a/tests/e2e/apps/rally/zenstack/schema.ts b/tests/e2e/apps/rally/zenstack/schema.ts index 1684a553..278bac74 100644 --- a/tests/e2e/apps/rally/zenstack/schema.ts +++ b/tests/e2e/apps/rally/zenstack/schema.ts @@ -6,7 +6,7 @@ /* eslint-disable */ import { type SchemaDef, ExpressionUtils } from "@zenstackhq/orm/schema"; -export const schema = { +const _schema = { provider: { type: "postgresql" }, @@ -2520,4 +2520,8 @@ export const schema = { authType: "User", plugins: {} } as const satisfies SchemaDef; -export type SchemaType = typeof schema; +type Schema = typeof _schema & { + __brand?: "schema"; +}; +export const schema: Schema = _schema; +export type SchemaType = Schema; diff --git a/tests/e2e/orm/schemas/basic/schema.ts b/tests/e2e/orm/schemas/basic/schema.ts index 6339ab0a..3774b207 100644 --- a/tests/e2e/orm/schemas/basic/schema.ts +++ b/tests/e2e/orm/schemas/basic/schema.ts @@ -6,7 +6,7 @@ /* eslint-disable */ import { type SchemaDef, ExpressionUtils } from "@zenstackhq/orm/schema"; -export const schema = { +const _schema = { provider: { type: "sqlite" }, @@ -284,4 +284,8 @@ export const schema = { authType: "User", plugins: {} } as const satisfies SchemaDef; -export type SchemaType = typeof schema; +type Schema = typeof _schema & { + __brand?: "schema"; +}; +export const schema: Schema = _schema; +export type SchemaType = Schema; diff --git a/tests/e2e/orm/schemas/default-auth/schema.ts b/tests/e2e/orm/schemas/default-auth/schema.ts index 42035b8b..c5610c0f 100644 --- a/tests/e2e/orm/schemas/default-auth/schema.ts +++ b/tests/e2e/orm/schemas/default-auth/schema.ts @@ -6,7 +6,7 @@ /* eslint-disable */ import { type SchemaDef, ExpressionUtils } from "@zenstackhq/orm/schema"; -export const schema = { +const _schema = { provider: { type: "sqlite" }, @@ -119,4 +119,8 @@ export const schema = { authType: "User", plugins: {} } as const satisfies SchemaDef; -export type SchemaType = typeof schema; +type Schema = typeof _schema & { + __brand?: "schema"; +}; +export const schema: Schema = _schema; +export type SchemaType = Schema; diff --git a/tests/e2e/orm/schemas/delegate/schema.ts b/tests/e2e/orm/schemas/delegate/schema.ts index 8767b8e1..eaf1725a 100644 --- a/tests/e2e/orm/schemas/delegate/schema.ts +++ b/tests/e2e/orm/schemas/delegate/schema.ts @@ -6,7 +6,7 @@ /* eslint-disable */ import { type SchemaDef, ExpressionUtils } from "@zenstackhq/orm/schema"; -export const schema = { +const _schema = { provider: { type: "sqlite" }, @@ -462,4 +462,8 @@ export const schema = { authType: "User", plugins: {} } as const satisfies SchemaDef; -export type SchemaType = typeof schema; +type Schema = typeof _schema & { + __brand?: "schema"; +}; +export const schema: Schema = _schema; +export type SchemaType = Schema; diff --git a/tests/e2e/orm/schemas/name-mapping/schema.ts b/tests/e2e/orm/schemas/name-mapping/schema.ts index b81c03ae..6b154ed7 100644 --- a/tests/e2e/orm/schemas/name-mapping/schema.ts +++ b/tests/e2e/orm/schemas/name-mapping/schema.ts @@ -6,7 +6,7 @@ /* eslint-disable */ import { type SchemaDef, ExpressionUtils } from "@zenstackhq/orm/schema"; -export const schema = { +const _schema = { provider: { type: "sqlite" }, @@ -120,4 +120,8 @@ export const schema = { authType: "User", plugins: {} } as const satisfies SchemaDef; -export type SchemaType = typeof schema; +type Schema = typeof _schema & { + __brand?: "schema"; +}; +export const schema: Schema = _schema; +export type SchemaType = Schema; diff --git a/tests/e2e/orm/schemas/petstore/schema.ts b/tests/e2e/orm/schemas/petstore/schema.ts index 747372a7..e3b9de6a 100644 --- a/tests/e2e/orm/schemas/petstore/schema.ts +++ b/tests/e2e/orm/schemas/petstore/schema.ts @@ -6,7 +6,7 @@ /* eslint-disable */ import { type SchemaDef, ExpressionUtils } from "@zenstackhq/orm/schema"; -export const schema = { +const _schema = { provider: { type: "sqlite" }, @@ -154,4 +154,8 @@ export const schema = { authType: "User", plugins: {} } as const satisfies SchemaDef; -export type SchemaType = typeof schema; +type Schema = typeof _schema & { + __brand?: "schema"; +}; +export const schema: Schema = _schema; +export type SchemaType = Schema; diff --git a/tests/e2e/orm/schemas/todo/schema.ts b/tests/e2e/orm/schemas/todo/schema.ts index 4a8f811c..458cf5c2 100644 --- a/tests/e2e/orm/schemas/todo/schema.ts +++ b/tests/e2e/orm/schemas/todo/schema.ts @@ -6,7 +6,7 @@ /* eslint-disable */ import { type SchemaDef, ExpressionUtils } from "@zenstackhq/orm/schema"; -export const schema = { +const _schema = { provider: { type: "sqlite" }, @@ -393,4 +393,8 @@ export const schema = { authType: "User", plugins: {} } as const satisfies SchemaDef; -export type SchemaType = typeof schema; +type Schema = typeof _schema & { + __brand?: "schema"; +}; +export const schema: Schema = _schema; +export type SchemaType = Schema; diff --git a/tests/e2e/orm/schemas/typing/schema.ts b/tests/e2e/orm/schemas/typing/schema.ts index 1a1212bd..57da73ec 100644 --- a/tests/e2e/orm/schemas/typing/schema.ts +++ b/tests/e2e/orm/schemas/typing/schema.ts @@ -6,7 +6,7 @@ /* eslint-disable */ import { type SchemaDef, type OperandExpression, ExpressionUtils } from "@zenstackhq/orm/schema"; -export const schema = { +const _schema = { provider: { type: "postgresql" }, @@ -344,4 +344,8 @@ export const schema = { authType: "User", plugins: {} } as const satisfies SchemaDef; -export type SchemaType = typeof schema; +type Schema = typeof _schema & { + __brand?: "schema"; +}; +export const schema: Schema = _schema; +export type SchemaType = Schema; From 9f20e3b85a03b31532f52c8947db9ebfe7e1ec81 Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Fri, 14 Nov 2025 22:44:18 -0800 Subject: [PATCH 2/3] update --- packages/orm/src/client/crud-types.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/orm/src/client/crud-types.ts b/packages/orm/src/client/crud-types.ts index f4b5cd06..831af6c7 100644 --- a/packages/orm/src/client/crud-types.ts +++ b/packages/orm/src/client/crud-types.ts @@ -309,6 +309,9 @@ export type StringFilter Date: Fri, 14 Nov 2025 22:57:19 -0800 Subject: [PATCH 3/3] fix(orm): findUnique arg typing --- packages/orm/src/client/crud-types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/orm/src/client/crud-types.ts b/packages/orm/src/client/crud-types.ts index 831af6c7..7f5defdf 100644 --- a/packages/orm/src/client/crud-types.ts +++ b/packages/orm/src/client/crud-types.ts @@ -664,7 +664,7 @@ export type FindManyArgs> = FindArgs; export type FindUniqueArgs> = { - where?: WhereUniqueInput; + where: WhereUniqueInput; } & SelectIncludeOmit; //#endregion