Skip to content

Commit 8b4511b

Browse files
genuymc9
andauthored
fix: enhance auth type (#429)
* chore: enhance auth type to include relations * chore: update * add a regression test --------- Co-authored-by: ymc9 <[email protected]>
1 parent 7a90d87 commit 8b4511b

File tree

7 files changed

+271
-3
lines changed

7 files changed

+271
-3
lines changed

packages/orm/src/client/contract.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
import type Decimal from 'decimal.js';
2-
import { type GetModels, type IsDelegateModel, type ProcedureDef, type SchemaDef } from '../schema';
2+
import {
3+
type FieldIsArray,
4+
type GetModels,
5+
type IsDelegateModel,
6+
type ProcedureDef,
7+
type RelationFields,
8+
type RelationFieldType,
9+
type SchemaDef,
10+
} from '../schema';
311
import type { AnyKysely } from '../utils/kysely-utils';
412
import type { OrUndefinedIf, Simplify, UnwrapTuplePromises } from '../utils/type-utils';
513
import type { TRANSACTION_UNSUPPORTED_METHODS } from './constants';
@@ -12,6 +20,7 @@ import type {
1220
CreateArgs,
1321
CreateManyAndReturnArgs,
1422
CreateManyArgs,
23+
DefaultModelResult,
1524
DeleteArgs,
1625
DeleteManyArgs,
1726
FindFirstArgs,
@@ -810,11 +819,23 @@ export type ModelOperations<Schema extends SchemaDef, Model extends GetModels<Sc
810819

811820
//#region Supporting types
812821

822+
/**
823+
* Type for auth context that includes both scalar and relation fields.
824+
* Relations are recursively included to allow nested auth data like { user: { profile: { ... } } }
825+
*/
826+
type AuthModelType<Schema extends SchemaDef, Model extends GetModels<Schema>> = Partial<
827+
DefaultModelResult<Schema, Model>
828+
> & {
829+
[Key in RelationFields<Schema, Model>]?: FieldIsArray<Schema, Model, Key> extends true
830+
? AuthModelType<Schema, RelationFieldType<Schema, Model, Key>>[]
831+
: AuthModelType<Schema, RelationFieldType<Schema, Model, Key>>;
832+
};
833+
813834
export type AuthType<Schema extends SchemaDef> =
814835
string extends GetModels<Schema>
815836
? Record<string, unknown>
816837
: Schema['authType'] extends GetModels<Schema>
817-
? Partial<ModelResult<Schema, Schema['authType']>>
838+
? AuthModelType<Schema, Schema['authType']>
818839
: never;
819840

820841
//#endregion

packages/orm/src/client/crud-types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ import type { ToKyselySchema } from './query-builder';
4747

4848
//#region Query results
4949

50-
type DefaultModelResult<
50+
export type DefaultModelResult<
5151
Schema extends SchemaDef,
5252
Model extends GetModels<Schema>,
5353
Omit = undefined,
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//////////////////////////////////////////////////////////////////////////////////////////////
2+
// DO NOT MODIFY THIS FILE //
3+
// This file is automatically generated by ZenStack CLI and should not be manually updated. //
4+
//////////////////////////////////////////////////////////////////////////////////////////////
5+
6+
/* eslint-disable */
7+
8+
import { type SchemaType as $Schema } from "./schema";
9+
import type { FindManyArgs as $FindManyArgs, FindUniqueArgs as $FindUniqueArgs, FindFirstArgs as $FindFirstArgs, CreateArgs as $CreateArgs, CreateManyArgs as $CreateManyArgs, CreateManyAndReturnArgs as $CreateManyAndReturnArgs, UpdateArgs as $UpdateArgs, UpdateManyArgs as $UpdateManyArgs, UpdateManyAndReturnArgs as $UpdateManyAndReturnArgs, UpsertArgs as $UpsertArgs, DeleteArgs as $DeleteArgs, DeleteManyArgs as $DeleteManyArgs, CountArgs as $CountArgs, AggregateArgs as $AggregateArgs, GroupByArgs as $GroupByArgs, WhereInput as $WhereInput, SelectInput as $SelectInput, IncludeInput as $IncludeInput, OmitInput as $OmitInput } from "@zenstackhq/orm";
10+
import type { SimplifiedModelResult as $SimplifiedModelResult, SelectIncludeOmit as $SelectIncludeOmit } from "@zenstackhq/orm";
11+
export type SessionFindManyArgs = $FindManyArgs<$Schema, "Session">;
12+
export type SessionFindUniqueArgs = $FindUniqueArgs<$Schema, "Session">;
13+
export type SessionFindFirstArgs = $FindFirstArgs<$Schema, "Session">;
14+
export type SessionCreateArgs = $CreateArgs<$Schema, "Session">;
15+
export type SessionCreateManyArgs = $CreateManyArgs<$Schema, "Session">;
16+
export type SessionCreateManyAndReturnArgs = $CreateManyAndReturnArgs<$Schema, "Session">;
17+
export type SessionUpdateArgs = $UpdateArgs<$Schema, "Session">;
18+
export type SessionUpdateManyArgs = $UpdateManyArgs<$Schema, "Session">;
19+
export type SessionUpdateManyAndReturnArgs = $UpdateManyAndReturnArgs<$Schema, "Session">;
20+
export type SessionUpsertArgs = $UpsertArgs<$Schema, "Session">;
21+
export type SessionDeleteArgs = $DeleteArgs<$Schema, "Session">;
22+
export type SessionDeleteManyArgs = $DeleteManyArgs<$Schema, "Session">;
23+
export type SessionCountArgs = $CountArgs<$Schema, "Session">;
24+
export type SessionAggregateArgs = $AggregateArgs<$Schema, "Session">;
25+
export type SessionGroupByArgs = $GroupByArgs<$Schema, "Session">;
26+
export type SessionWhereInput = $WhereInput<$Schema, "Session">;
27+
export type SessionSelect = $SelectInput<$Schema, "Session">;
28+
export type SessionInclude = $IncludeInput<$Schema, "Session">;
29+
export type SessionOmit = $OmitInput<$Schema, "Session">;
30+
export type SessionGetPayload<Args extends $SelectIncludeOmit<$Schema, "Session", true>> = $SimplifiedModelResult<$Schema, "Session", Args>;
31+
export type UserFindManyArgs = $FindManyArgs<$Schema, "User">;
32+
export type UserFindUniqueArgs = $FindUniqueArgs<$Schema, "User">;
33+
export type UserFindFirstArgs = $FindFirstArgs<$Schema, "User">;
34+
export type UserCreateArgs = $CreateArgs<$Schema, "User">;
35+
export type UserCreateManyArgs = $CreateManyArgs<$Schema, "User">;
36+
export type UserCreateManyAndReturnArgs = $CreateManyAndReturnArgs<$Schema, "User">;
37+
export type UserUpdateArgs = $UpdateArgs<$Schema, "User">;
38+
export type UserUpdateManyArgs = $UpdateManyArgs<$Schema, "User">;
39+
export type UserUpdateManyAndReturnArgs = $UpdateManyAndReturnArgs<$Schema, "User">;
40+
export type UserUpsertArgs = $UpsertArgs<$Schema, "User">;
41+
export type UserDeleteArgs = $DeleteArgs<$Schema, "User">;
42+
export type UserDeleteManyArgs = $DeleteManyArgs<$Schema, "User">;
43+
export type UserCountArgs = $CountArgs<$Schema, "User">;
44+
export type UserAggregateArgs = $AggregateArgs<$Schema, "User">;
45+
export type UserGroupByArgs = $GroupByArgs<$Schema, "User">;
46+
export type UserWhereInput = $WhereInput<$Schema, "User">;
47+
export type UserSelect = $SelectInput<$Schema, "User">;
48+
export type UserInclude = $IncludeInput<$Schema, "User">;
49+
export type UserOmit = $OmitInput<$Schema, "User">;
50+
export type UserGetPayload<Args extends $SelectIncludeOmit<$Schema, "User", true>> = $SimplifiedModelResult<$Schema, "User", Args>;
51+
export type ProfileFindManyArgs = $FindManyArgs<$Schema, "Profile">;
52+
export type ProfileFindUniqueArgs = $FindUniqueArgs<$Schema, "Profile">;
53+
export type ProfileFindFirstArgs = $FindFirstArgs<$Schema, "Profile">;
54+
export type ProfileCreateArgs = $CreateArgs<$Schema, "Profile">;
55+
export type ProfileCreateManyArgs = $CreateManyArgs<$Schema, "Profile">;
56+
export type ProfileCreateManyAndReturnArgs = $CreateManyAndReturnArgs<$Schema, "Profile">;
57+
export type ProfileUpdateArgs = $UpdateArgs<$Schema, "Profile">;
58+
export type ProfileUpdateManyArgs = $UpdateManyArgs<$Schema, "Profile">;
59+
export type ProfileUpdateManyAndReturnArgs = $UpdateManyAndReturnArgs<$Schema, "Profile">;
60+
export type ProfileUpsertArgs = $UpsertArgs<$Schema, "Profile">;
61+
export type ProfileDeleteArgs = $DeleteArgs<$Schema, "Profile">;
62+
export type ProfileDeleteManyArgs = $DeleteManyArgs<$Schema, "Profile">;
63+
export type ProfileCountArgs = $CountArgs<$Schema, "Profile">;
64+
export type ProfileAggregateArgs = $AggregateArgs<$Schema, "Profile">;
65+
export type ProfileGroupByArgs = $GroupByArgs<$Schema, "Profile">;
66+
export type ProfileWhereInput = $WhereInput<$Schema, "Profile">;
67+
export type ProfileSelect = $SelectInput<$Schema, "Profile">;
68+
export type ProfileInclude = $IncludeInput<$Schema, "Profile">;
69+
export type ProfileOmit = $OmitInput<$Schema, "Profile">;
70+
export type ProfileGetPayload<Args extends $SelectIncludeOmit<$Schema, "Profile", true>> = $SimplifiedModelResult<$Schema, "Profile", Args>;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//////////////////////////////////////////////////////////////////////////////////////////////
2+
// DO NOT MODIFY THIS FILE //
3+
// This file is automatically generated by ZenStack CLI and should not be manually updated. //
4+
//////////////////////////////////////////////////////////////////////////////////////////////
5+
6+
/* eslint-disable */
7+
8+
import { type SchemaType as $Schema } from "./schema";
9+
import { type ModelResult as $ModelResult } from "@zenstackhq/orm";
10+
export type Session = $ModelResult<$Schema, "Session">;
11+
export type User = $ModelResult<$Schema, "User">;
12+
export type Profile = $ModelResult<$Schema, "Profile">;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { createTestClient } from '@zenstackhq/testtools';
2+
import { describe, it } from 'vitest';
3+
import { schema } from './schema';
4+
5+
describe('Issue 422 regression tests', () => {
6+
it('should infer correct auth type', async () => {
7+
const db = await createTestClient(schema);
8+
9+
// all fields optional
10+
db.$setAuth({ id: 'session1' });
11+
12+
// relations are allowed
13+
db.$setAuth({ id: 'user1', user: { id: 'user1' } });
14+
15+
// nested relations are allowed
16+
db.$setAuth({ id: 'user1', user: { id: 'user1', profile: { name: 'User1' } } });
17+
});
18+
});
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
//////////////////////////////////////////////////////////////////////////////////////////////
2+
// DO NOT MODIFY THIS FILE //
3+
// This file is automatically generated by ZenStack CLI and should not be manually updated. //
4+
//////////////////////////////////////////////////////////////////////////////////////////////
5+
6+
/* eslint-disable */
7+
8+
import { type SchemaDef, ExpressionUtils } from "@zenstackhq/orm/schema";
9+
const _schema = {
10+
provider: {
11+
type: "sqlite"
12+
},
13+
models: {
14+
Session: {
15+
name: "Session",
16+
fields: {
17+
id: {
18+
name: "id",
19+
type: "String",
20+
id: true,
21+
attributes: [{ name: "@id" }]
22+
},
23+
token: {
24+
name: "token",
25+
type: "String"
26+
},
27+
userId: {
28+
name: "userId",
29+
type: "String",
30+
foreignKeyFor: [
31+
"user"
32+
]
33+
},
34+
user: {
35+
name: "user",
36+
type: "User",
37+
attributes: [{ name: "@relation", args: [{ name: "fields", value: ExpressionUtils.array([ExpressionUtils.field("userId")]) }, { name: "references", value: ExpressionUtils.array([ExpressionUtils.field("id")]) }, { name: "onDelete", value: ExpressionUtils.literal("Cascade") }] }],
38+
relation: { opposite: "sessions", fields: ["userId"], references: ["id"], onDelete: "Cascade" }
39+
}
40+
},
41+
attributes: [
42+
{ name: "@@auth" }
43+
],
44+
idFields: ["id"],
45+
uniqueFields: {
46+
id: { type: "String" }
47+
}
48+
},
49+
User: {
50+
name: "User",
51+
fields: {
52+
id: {
53+
name: "id",
54+
type: "String",
55+
id: true,
56+
attributes: [{ name: "@id" }, { name: "@default", args: [{ name: "value", value: ExpressionUtils.call("uuid") }] }],
57+
default: ExpressionUtils.call("uuid")
58+
},
59+
sessions: {
60+
name: "sessions",
61+
type: "Session",
62+
array: true,
63+
relation: { opposite: "user" }
64+
},
65+
profile: {
66+
name: "profile",
67+
type: "Profile",
68+
optional: true,
69+
relation: { opposite: "user" }
70+
}
71+
},
72+
idFields: ["id"],
73+
uniqueFields: {
74+
id: { type: "String" }
75+
}
76+
},
77+
Profile: {
78+
name: "Profile",
79+
fields: {
80+
id: {
81+
name: "id",
82+
type: "String",
83+
id: true,
84+
attributes: [{ name: "@id" }, { name: "@default", args: [{ name: "value", value: ExpressionUtils.call("uuid") }] }],
85+
default: ExpressionUtils.call("uuid")
86+
},
87+
name: {
88+
name: "name",
89+
type: "String",
90+
optional: true
91+
},
92+
userId: {
93+
name: "userId",
94+
type: "String",
95+
unique: true,
96+
attributes: [{ name: "@unique" }],
97+
foreignKeyFor: [
98+
"user"
99+
]
100+
},
101+
user: {
102+
name: "user",
103+
type: "User",
104+
attributes: [{ name: "@relation", args: [{ name: "fields", value: ExpressionUtils.array([ExpressionUtils.field("userId")]) }, { name: "references", value: ExpressionUtils.array([ExpressionUtils.field("id")]) }, { name: "onDelete", value: ExpressionUtils.literal("Cascade") }] }],
105+
relation: { opposite: "profile", fields: ["userId"], references: ["id"], onDelete: "Cascade" }
106+
}
107+
},
108+
idFields: ["id"],
109+
uniqueFields: {
110+
id: { type: "String" },
111+
userId: { type: "String" }
112+
}
113+
}
114+
},
115+
authType: "Session",
116+
plugins: {}
117+
} as const satisfies SchemaDef;
118+
type Schema = typeof _schema & {
119+
__brand?: "schema";
120+
};
121+
export const schema: Schema = _schema;
122+
export type SchemaType = Schema;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
datasource db {
2+
provider = "sqlite"
3+
url = "file:./dev.db"
4+
}
5+
6+
model Session {
7+
id String @id
8+
token String
9+
userId String
10+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
11+
@@auth
12+
}
13+
14+
model User {
15+
id String @id @default(uuid())
16+
sessions Session[]
17+
profile Profile?
18+
}
19+
20+
model Profile {
21+
id String @id @default(uuid())
22+
name String?
23+
userId String @unique
24+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
25+
}

0 commit comments

Comments
 (0)