Skip to content

Commit eff4263

Browse files
ymc9claude
andauthored
refactor(tanstack-query, orm): thread plugin generics through transactions (#2645)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 679f91f commit eff4263

16 files changed

Lines changed: 5324 additions & 321 deletions

File tree

packages/clients/client-helpers/src/types.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { ClientContract, QueryOptions } from '@zenstackhq/orm';
1+
import { ExtQueryArgsMarker, ExtResultMarker, type QueryOptions } from '@zenstackhq/orm';
22
import type { SchemaDef } from '@zenstackhq/schema';
33

44
/**
@@ -11,10 +11,15 @@ export type MaybePromise<T> = T | Promise<T> | PromiseLike<T>;
1111
*/
1212
export type InferSchema<T> = T extends { $schema: infer S extends SchemaDef } ? S : T extends SchemaDef ? T : never;
1313

14+
/**
15+
* Extracts the ExtQueryArgs type from a client contract, or defaults to `{}`.
16+
*/
17+
export type InferExtQueryArgs<T> = T extends { [ExtQueryArgsMarker]?: infer E } ? (unknown extends E ? {} : E) : {};
18+
1419
/**
1520
* Extracts the ExtResult type from a client contract, or defaults to `{}`.
1621
*/
17-
export type InferExtResult<T> = T extends ClientContract<any, any, any, any, infer E> ? E : {};
22+
export type InferExtResult<T> = T extends { [ExtResultMarker]?: infer E } ? (unknown extends E ? {} : E) : {};
1823

1924
/**
2025
* Infers query options from a client contract type, or defaults to `QueryOptions<Schema>`.

packages/clients/tanstack-query/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
"@zenstackhq/client-helpers": "workspace:*",
5858
"@zenstackhq/common-helpers": "workspace:*",
5959
"@zenstackhq/schema": "workspace:*",
60+
"@zenstackhq/orm": "workspace:*",
6061
"decimal.js": "catalog:"
6162
},
6263
"devDependencies": {
@@ -71,7 +72,6 @@
7172
"@zenstackhq/cli": "workspace:*",
7273
"@zenstackhq/eslint-config": "workspace:*",
7374
"@zenstackhq/language": "workspace:*",
74-
"@zenstackhq/orm": "workspace:*",
7575
"@zenstackhq/sdk": "workspace:*",
7676
"@zenstackhq/typescript-config": "workspace:*",
7777
"@zenstackhq/vitest-config": "workspace:*",

packages/clients/tanstack-query/src/common/types.ts

Lines changed: 50 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,17 @@
11
import type { Logger, OptimisticDataProvider } from '@zenstackhq/client-helpers';
22
import type { FetchFn } from '@zenstackhq/client-helpers/fetch';
33
import type {
4-
AggregateArgs,
5-
CountArgs,
6-
CreateArgs,
7-
CreateManyAndReturnArgs,
8-
CreateManyArgs,
9-
DeleteArgs,
10-
DeleteManyArgs,
11-
ExistsArgs,
12-
FindFirstArgs,
13-
FindManyArgs,
14-
FindUniqueArgs,
4+
CoreCrudOperations,
5+
CrudArgsMap,
6+
CrudReturnMap,
7+
ExtQueryArgsBase,
8+
ExtResultBase,
159
GetProcedureNames,
1610
GetSlicedOperations,
17-
GroupByArgs,
1811
ModelAllowsCreate,
1912
OperationsRequiringCreate,
2013
ProcedureFunc,
2114
QueryOptions,
22-
UpdateArgs,
23-
UpdateManyAndReturnArgs,
24-
UpdateManyArgs,
25-
UpsertArgs,
2615
} from '@zenstackhq/orm';
2716
import type { GetModels, SchemaDef } from '@zenstackhq/schema';
2817

@@ -118,46 +107,58 @@ export type ProcedureReturn<Schema extends SchemaDef, Name extends GetProcedureN
118107
>;
119108

120109
/**
121-
* Maps each core CRUD operation to its argument type for a given model.
110+
* Operations available in a sequential transaction.
122111
*/
123-
type CrudArgsMap<Schema extends SchemaDef, Model extends GetModels<Schema>> = {
124-
findMany: FindManyArgs<Schema, Model>;
125-
findUnique: FindUniqueArgs<Schema, Model>;
126-
findFirst: FindFirstArgs<Schema, Model>;
127-
create: CreateArgs<Schema, Model>;
128-
createMany: CreateManyArgs<Schema, Model>;
129-
createManyAndReturn: CreateManyAndReturnArgs<Schema, Model>;
130-
update: UpdateArgs<Schema, Model>;
131-
updateMany: UpdateManyArgs<Schema, Model>;
132-
updateManyAndReturn: UpdateManyAndReturnArgs<Schema, Model>;
133-
upsert: UpsertArgs<Schema, Model>;
134-
delete: DeleteArgs<Schema, Model>;
135-
deleteMany: DeleteManyArgs<Schema, Model>;
136-
count: CountArgs<Schema, Model>;
137-
aggregate: AggregateArgs<Schema, Model>;
138-
groupBy: GroupByArgs<Schema, Model>;
139-
exists: ExistsArgs<Schema, Model>;
140-
};
141-
142-
/**
143-
* Operations available for a given model, omitting create-style operations
144-
* for models that don't allow them (e.g. delegate models).
145-
*/
146-
type AllowedTransactionOps<Schema extends SchemaDef, Model extends GetModels<Schema>> =
112+
type AllowedTransactionOps<
113+
Schema extends SchemaDef,
114+
Model extends GetModels<Schema>,
115+
Options extends QueryOptions<Schema> = QueryOptions<Schema>,
116+
> =
147117
ModelAllowsCreate<Schema, Model> extends true
148-
? keyof CrudArgsMap<Schema, Model>
149-
: Exclude<keyof CrudArgsMap<Schema, Model>, OperationsRequiringCreate>;
118+
? GetSlicedOperations<Schema, Model, Options> & CoreCrudOperations
119+
: Exclude<GetSlicedOperations<Schema, Model, Options> & CoreCrudOperations, OperationsRequiringCreate>;
150120

151121
/**
152122
* Represents a single operation to execute within a sequential transaction.
153123
*
154124
* The `model`, `op`, and `args` fields are correlated: `op` is constrained to
155-
* the CRUD operations available on `model`, and `args` is typed accordingly.
125+
* the CRUD operations available on `model` (respecting `Options['slicing']`), and
126+
* `args` is typed accordingly.
156127
*/
157-
export type TransactionOperation<Schema extends SchemaDef> = {
128+
export type TransactionOperation<
129+
Schema extends SchemaDef,
130+
Options extends QueryOptions<Schema> = QueryOptions<Schema>,
131+
ExtQueryArgs extends ExtQueryArgsBase = {},
132+
ExtResult extends ExtResultBase<Schema> = {},
133+
> = {
158134
[Model in GetModels<Schema>]: {
159-
[Op in AllowedTransactionOps<Schema, Model>]: {} extends CrudArgsMap<Schema, Model>[Op]
160-
? { model: Model; op: Op; args?: CrudArgsMap<Schema, Model>[Op] }
161-
: { model: Model; op: Op; args: CrudArgsMap<Schema, Model>[Op] };
162-
}[AllowedTransactionOps<Schema, Model>];
135+
[Op in AllowedTransactionOps<Schema, Model, Options>]: {} extends CrudArgsMap<
136+
Schema,
137+
Model,
138+
Options,
139+
ExtQueryArgs,
140+
ExtResult
141+
>[Op]
142+
? { model: Model; op: Op; args?: CrudArgsMap<Schema, Model, Options, ExtQueryArgs, ExtResult>[Op] }
143+
: { model: Model; op: Op; args: CrudArgsMap<Schema, Model, Options, ExtQueryArgs, ExtResult>[Op] };
144+
}[AllowedTransactionOps<Schema, Model, Options>];
163145
}[GetModels<Schema>];
146+
147+
/**
148+
* Maps each operation in a transaction tuple to its precise result type, preserving
149+
* per-position typing.
150+
*/
151+
export type TransactionResults<
152+
Schema extends SchemaDef,
153+
Ops extends readonly TransactionOperation<Schema, any, any, any>[],
154+
Options extends QueryOptions<Schema> = QueryOptions<Schema>,
155+
ExtResult extends ExtResultBase<Schema> = {},
156+
> = {
157+
[K in keyof Ops]: Ops[K] extends { model: infer M; op: infer O; args?: infer A }
158+
? M extends GetModels<Schema>
159+
? O extends keyof CrudReturnMap<Schema, M, A, Options, ExtResult>
160+
? CrudReturnMap<Schema, M, A, Options, ExtResult>[O]
161+
: never
162+
: never
163+
: never;
164+
};

0 commit comments

Comments
 (0)