Skip to content

Commit cdeee18

Browse files
authored
merge dev to main (v3.10.0) (#2895)
2 parents 5b54e49 + d44e489 commit cdeee18

109 files changed

Lines changed: 7509 additions & 1697 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎BREAKINGCHANGES.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
1. `@omit` and `@password` attributes have been removed
55
1. SWR plugin is removed
66
1. `makeModelSchema()` no longer includes relation fields by default — use `include` or `select` options to opt in, mirroring ORM behaviour
7+
1. ORM entity mutation catch-all hooks should now be registered under `onEntityMutation.$all` (the previous shape still works but emits a deprecation warning); entities passed to per-model hooks are typed as raw database rows (same as `$qb` results)

‎package.json‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "zenstack-v3",
33
"displayName": "ZenStack",
44
"description": "ZenStack",
5-
"version": "3.9.8",
5+
"version": "3.10.0",
66
"type": "module",
77
"author": {
88
"name": "ZenStack Team",
@@ -67,7 +67,7 @@
6767
"overrides": {
6868
"cookie@<0.7.0": ">=0.7.0",
6969
"lodash@>=4.0.0 <=4.17.23": ">=4.18.0",
70-
"@better-auth/core": "1.4.19"
70+
"@better-auth/core": "1.7.12"
7171
},
7272
"patchedDependencies": {
7373
"jsonschema@1.5.0": "patches/jsonschema@1.5.0.patch"

‎packages/auth-adapters/better-auth/README.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ const auth = new BetterAuth({
2626

2727
## Schema generation
2828

29-
You can use the `@better-auth/cli` to populate better-auth's data models into your ZModel schema.
29+
You can use the `auth` CLI (formerly `@better-auth/cli`) to populate better-auth's data models into your ZModel schema.
3030

3131
```bash
32-
npx @better-auth/cli generate
32+
npx auth generate
3333
```

‎packages/auth-adapters/better-auth/package.json‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "@zenstackhq/better-auth",
33
"displayName": "ZenStack Better Auth Adapter",
44
"description": "ZenStack Better Auth Adapter. This adapter is modified from better-auth's Prisma adapter.",
5-
"version": "3.9.8",
5+
"version": "3.10.0",
66
"type": "module",
77
"author": {
88
"name": "ZenStack Team",
@@ -65,15 +65,15 @@
6565
"better-auth": "^1.3.0"
6666
},
6767
"devDependencies": {
68-
"@better-auth/cli": "1.4.19",
69-
"@better-auth/core": "1.4.19",
68+
"@better-auth/core": "1.7.12",
69+
"auth": "1.7.12",
7070
"@types/tmp": "catalog:",
7171
"@zenstackhq/cli": "workspace:*",
7272
"@zenstackhq/eslint-config": "workspace:*",
7373
"@zenstackhq/tsdown-config": "workspace:*",
7474
"@zenstackhq/typescript-config": "workspace:*",
7575
"@zenstackhq/vitest-config": "workspace:*",
76-
"better-auth": "1.4.19",
76+
"better-auth": "1.7.12",
7777
"kysely": "catalog:",
7878
"tmp": "catalog:"
7979
},

‎packages/auth-adapters/better-auth/src/schema-generator.ts‎

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -97,15 +97,7 @@ async function updateSchema(
9797

9898
const supportsArrays = getSupportsArrays(config);
9999
for (const [name, table] of Object.entries(tables)) {
100-
const c = addOrUpdateModel(
101-
name,
102-
table,
103-
zmodel,
104-
tables,
105-
toManyRelations,
106-
supportsArrays,
107-
!!options.advanced?.database?.useNumberId,
108-
);
100+
const c = addOrUpdateModel(name, table, zmodel, tables, toManyRelations, supportsArrays, useNumberId(options));
109101
changed = changed || c;
110102
}
111103

@@ -583,3 +575,9 @@ function createStringAttributeArg(value: string) {
583575
arg.value = expr;
584576
return arg;
585577
}
578+
579+
function useNumberId(options: BetterAuthOptions) {
580+
const dbOptions = options.advanced?.database as { useNumberId?: boolean; generateId?: unknown } | undefined;
581+
// `useNumberId` was replaced by `generateId: 'serial'` in better-auth 1.7
582+
return !!dbOptions?.useNumberId || dbOptions?.generateId === 'serial';
583+
}

‎packages/cli/package.json‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "@zenstackhq/cli",
33
"displayName": "ZenStack CLI",
44
"description": "FullStack database toolkit with built-in access control and automatic API generation.",
5-
"version": "3.9.8",
5+
"version": "3.10.0",
66
"type": "module",
77
"author": {
88
"name": "ZenStack Team",
@@ -61,7 +61,7 @@
6161
"@zenstackhq/plugin-policy": "workspace:*",
6262
"@zenstackhq/server": "workspace:*",
6363
"@hono/node-server": "^1.13.8",
64-
"hono": "^4.11.10",
64+
"hono": "^4.13.7",
6565
"chokidar": "^5.0.0",
6666
"colors": "1.4.0",
6767
"commander": "^8.3.0",

‎packages/cli/test/prisma-schema-gen.test.ts‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,47 @@ model User {
9191
expect(prismaSchemaText.includes('@ds.JsonB')).toBe(true);
9292
expect(prismaSchemaText.includes('@ds.ByteA')).toBe(true);
9393
});
94+
95+
it('renames primitive type defs to match the base type', async () => {
96+
const model = await loadSchema(`
97+
model User {
98+
id String @id
99+
name UserName
100+
}
101+
102+
type UserName with String {
103+
this String
104+
}
105+
`);
106+
107+
const generator = new PrismaSchemaGenerator(model);
108+
const prismaSchemaText = await generator.generate();
109+
110+
expect(prismaSchemaText.includes('name UserName')).toBe(false);
111+
expect(prismaSchemaText.includes('name String')).toBe(true);
112+
});
113+
114+
it('renames primitive type defs to match the base type when used with lists', async () => {
115+
const model = await loadSchema(`
116+
datasource db {
117+
provider = 'postgresql'
118+
url = env('DATABASE_URL')
119+
}
120+
121+
model User {
122+
id String @id
123+
name UserName[]
124+
}
125+
126+
type UserName with String {
127+
this String
128+
}
129+
`);
130+
131+
const generator = new PrismaSchemaGenerator(model);
132+
const prismaSchemaText = await generator.generate();
133+
134+
expect(prismaSchemaText.includes('name UserName[]')).toBe(false);
135+
expect(prismaSchemaText.includes('name String[]')).toBe(true);
136+
});
94137
});

‎packages/cli/test/ts-schema-gen.test.ts‎

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,126 @@ model Post {
852852
});
853853
});
854854

855+
it('supports implicit conversions from enums to arrays', async () => {
856+
const { schema } = await generateTsSchema(`
857+
enum PostStatus {
858+
DRAFT
859+
ACTIVE
860+
CANCELLED
861+
}
862+
863+
model User {
864+
id Int @id @default(autoincrement())
865+
}
866+
867+
model Post {
868+
id String @id
869+
status String
870+
871+
@@validate(status in PostStatus)
872+
}
873+
`);
874+
875+
expect(schema.models['Post']?.attributes).toMatchObject([
876+
{
877+
name: '@@validate',
878+
args: [
879+
{
880+
name: 'value',
881+
value: {
882+
kind: 'binary',
883+
op: 'in',
884+
left: {
885+
kind: 'field',
886+
field: 'status',
887+
},
888+
right: {
889+
kind: 'array',
890+
type: 'PostStatus',
891+
items: [
892+
{
893+
kind: 'literal',
894+
value: 'DRAFT',
895+
},
896+
{
897+
kind: 'literal',
898+
value: 'ACTIVE',
899+
},
900+
{
901+
kind: 'literal',
902+
value: 'CANCELLED',
903+
},
904+
],
905+
},
906+
binding: undefined,
907+
},
908+
},
909+
],
910+
},
911+
]);
912+
});
913+
914+
it('emits enum names (not @map values) when converting enums to arrays', async () => {
915+
// enum values are represented by their names at runtime (TS values, auth(), Zod);
916+
// the ORM's name mapper translates them to `@map`-ed values at SQL execution time
917+
const { schema } = await generateTsSchema(`
918+
enum PostStatus {
919+
DRAFT @map('draft')
920+
ACTIVE @map('active')
921+
CANCELLED @map('cancelled')
922+
}
923+
924+
model User {
925+
id Int @id @default(autoincrement())
926+
}
927+
928+
model Post {
929+
id String @id
930+
status String
931+
932+
@@validate(status in PostStatus)
933+
}
934+
`);
935+
936+
expect(schema.models['Post']?.attributes).toMatchObject([
937+
{
938+
name: '@@validate',
939+
args: [
940+
{
941+
name: 'value',
942+
value: {
943+
kind: 'binary',
944+
op: 'in',
945+
left: {
946+
kind: 'field',
947+
field: 'status',
948+
},
949+
right: {
950+
kind: 'array',
951+
type: 'PostStatus',
952+
items: [
953+
{
954+
kind: 'literal',
955+
value: 'DRAFT',
956+
},
957+
{
958+
kind: 'literal',
959+
value: 'ACTIVE',
960+
},
961+
{
962+
kind: 'literal',
963+
value: 'CANCELLED',
964+
},
965+
],
966+
},
967+
binding: undefined,
968+
},
969+
},
970+
],
971+
},
972+
]);
973+
});
974+
855975
it('supports @@strict for type defs', async () => {
856976
const { schema } = await generateTsSchema(`
857977
model User {
@@ -895,4 +1015,61 @@ type Profile with Strict {
8951015
},
8961016
});
8971017
});
1018+
1019+
it('supports primitive type defs', async () => {
1020+
const { schema } = await generateTsSchema(`
1021+
model User {
1022+
id Int @id
1023+
name UserName
1024+
}
1025+
1026+
type UserName with String {
1027+
this String
1028+
}
1029+
`);
1030+
1031+
expect(schema).toMatchObject({
1032+
models: {
1033+
User: {
1034+
name: 'User',
1035+
fields: {
1036+
id: {
1037+
name: 'id',
1038+
type: 'Int',
1039+
id: true,
1040+
attributes: [
1041+
{
1042+
name: '@id',
1043+
},
1044+
],
1045+
},
1046+
name: {
1047+
name: 'name',
1048+
type: 'UserName',
1049+
},
1050+
},
1051+
idFields: ['id'],
1052+
uniqueFields: {
1053+
id: {
1054+
type: 'Int',
1055+
},
1056+
},
1057+
},
1058+
},
1059+
typeDefs: {
1060+
UserName: {
1061+
name: 'UserName',
1062+
base: 'String',
1063+
fields: {
1064+
this: {
1065+
name: 'this',
1066+
type: 'String',
1067+
},
1068+
},
1069+
},
1070+
},
1071+
authType: 'User',
1072+
plugins: {},
1073+
});
1074+
});
8981075
});

‎packages/clients/client-helpers/package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "@zenstackhq/client-helpers",
33
"displayName": "ZenStack Client Helpers",
44
"description": "Helpers for implementing clients that consume ZenStack's CRUD service",
5-
"version": "3.9.8",
5+
"version": "3.10.0",
66
"type": "module",
77
"author": {
88
"name": "ZenStack Team",

‎packages/clients/fetch-client/package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "@zenstackhq/fetch-client",
33
"displayName": "ZenStack Fetch Client",
44
"description": "Simple fetch-based client for consuming ZenStack's RPC-style CRUD API",
5-
"version": "3.9.8",
5+
"version": "3.10.0",
66
"type": "module",
77
"author": {
88
"name": "ZenStack Team",

0 commit comments

Comments
 (0)