Skip to content

Commit b06cee6

Browse files
authored
merge dev to main (v2.2.4) (#1527)
2 parents 0fa292c + 3e77974 commit b06cee6

File tree

19 files changed

+272
-36
lines changed

19 files changed

+272
-36
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "zenstack-monorepo",
3-
"version": "2.2.3",
3+
"version": "2.2.4",
44
"description": "",
55
"scripts": {
66
"build": "pnpm -r build",

packages/ide/jetbrains/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ plugins {
99
}
1010

1111
group = "dev.zenstack"
12-
version = "2.2.3"
12+
version = "2.2.4"
1313

1414
repositories {
1515
mavenCentral()

packages/ide/jetbrains/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "jetbrains",
3-
"version": "2.2.3",
3+
"version": "2.2.4",
44
"displayName": "ZenStack JetBrains IDE Plugin",
55
"description": "ZenStack JetBrains IDE plugin",
66
"homepage": "https://zenstack.dev",

packages/language/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@zenstackhq/language",
3-
"version": "2.2.3",
3+
"version": "2.2.4",
44
"displayName": "ZenStack modeling language compiler",
55
"description": "ZenStack modeling language compiler",
66
"homepage": "https://zenstack.dev",

packages/misc/redwood/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@zenstackhq/redwood",
33
"displayName": "ZenStack RedwoodJS Integration",
4-
"version": "2.2.3",
4+
"version": "2.2.4",
55
"description": "CLI and runtime for integrating ZenStack with RedwoodJS projects.",
66
"repository": {
77
"type": "git",

packages/plugins/openapi/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@zenstackhq/openapi",
33
"displayName": "ZenStack Plugin and Runtime for OpenAPI",
4-
"version": "2.2.3",
4+
"version": "2.2.4",
55
"description": "ZenStack plugin and runtime supporting OpenAPI",
66
"main": "index.js",
77
"repository": {

packages/plugins/swr/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@zenstackhq/swr",
33
"displayName": "ZenStack plugin for generating SWR hooks",
4-
"version": "2.2.3",
4+
"version": "2.2.4",
55
"description": "ZenStack plugin for generating SWR hooks",
66
"main": "index.js",
77
"repository": {

packages/plugins/tanstack-query/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@zenstackhq/tanstack-query",
33
"displayName": "ZenStack plugin for generating tanstack-query hooks",
4-
"version": "2.2.3",
4+
"version": "2.2.4",
55
"description": "ZenStack plugin for generating tanstack-query hooks",
66
"main": "index.js",
77
"exports": {

packages/plugins/trpc/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@zenstackhq/trpc",
33
"displayName": "ZenStack plugin for tRPC",
4-
"version": "2.2.3",
4+
"version": "2.2.4",
55
"description": "ZenStack plugin for tRPC",
66
"main": "index.js",
77
"repository": {

packages/runtime/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@zenstackhq/runtime",
33
"displayName": "ZenStack Runtime Library",
4-
"version": "2.2.3",
4+
"version": "2.2.4",
55
"description": "Runtime of ZenStack for both client-side and server-side environments.",
66
"repository": {
77
"type": "git",

packages/runtime/src/enhancements/delegate.ts

Lines changed: 49 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -194,15 +194,13 @@ export class DelegateProxyHandler extends DefaultPrismaProxyHandler {
194194

195195
if (this.injectBaseFieldSelect(model, field, value, args, kind)) {
196196
delete args[kind][field];
197-
} else {
198-
if (fieldInfo && this.isDelegateOrDescendantOfDelegate(fieldInfo.type)) {
199-
let nextValue = value;
200-
if (nextValue === true) {
201-
// make sure the payload is an object
202-
args[kind][field] = nextValue = {};
203-
}
204-
this.injectSelectIncludeHierarchy(fieldInfo.type, nextValue);
197+
} else if (fieldInfo.isDataModel) {
198+
let nextValue = value;
199+
if (nextValue === true) {
200+
// make sure the payload is an object
201+
args[kind][field] = nextValue = {};
205202
}
203+
this.injectSelectIncludeHierarchy(fieldInfo.type, nextValue);
206204
}
207205
}
208206
}
@@ -392,8 +390,11 @@ export class DelegateProxyHandler extends DefaultPrismaProxyHandler {
392390
);
393391
}
394392

395-
// note that we can't call `createMany` directly because it doesn't support
396-
// nested created, which is needed for creating base entities
393+
// `createMany` doesn't support nested create, which is needed for creating entities
394+
// inheriting a delegate base, so we need to convert it to a regular `create` here.
395+
// Note that the main difference is `create` doesn't support `skipDuplicates` as
396+
// `createMany` does.
397+
397398
return this.queryUtils.transaction(this.prisma, async (tx) => {
398399
const r = await Promise.all(
399400
enumerate(args.data).map(async (item) => {
@@ -425,17 +426,33 @@ export class DelegateProxyHandler extends DefaultPrismaProxyHandler {
425426
this.doProcessCreatePayload(model, args);
426427
},
427428

428-
createMany: (model, args, _context) => {
429-
if (args.skipDuplicates) {
430-
throw prismaClientValidationError(
431-
this.prisma,
432-
this.options.prismaModule,
433-
'`createMany` with `skipDuplicates` set to true is not supported for delegated models'
434-
);
435-
}
429+
createMany: (model, args, context) => {
430+
// `createMany` doesn't support nested create, which is needed for creating entities
431+
// inheriting a delegate base, so we need to convert it to a regular `create` here.
432+
// Note that the main difference is `create` doesn't support `skipDuplicates` as
433+
// `createMany` does.
436434

437-
for (const item of enumerate(args?.data)) {
438-
this.doProcessCreatePayload(model, item);
435+
if (this.isDelegateOrDescendantOfDelegate(model)) {
436+
if (args.skipDuplicates) {
437+
throw prismaClientValidationError(
438+
this.prisma,
439+
this.options.prismaModule,
440+
'`createMany` with `skipDuplicates` set to true is not supported for delegated models'
441+
);
442+
}
443+
444+
// convert to regular `create`
445+
let createPayload = context.parent.create ?? [];
446+
if (!Array.isArray(createPayload)) {
447+
createPayload = [createPayload];
448+
}
449+
450+
for (const item of enumerate(args.data)) {
451+
this.doProcessCreatePayload(model, item);
452+
createPayload.push(item);
453+
}
454+
context.parent.create = createPayload;
455+
delete context.parent['createMany'];
439456
}
440457
},
441458
});
@@ -460,8 +477,8 @@ export class DelegateProxyHandler extends DefaultPrismaProxyHandler {
460477
}
461478

462479
// ensure the full nested "create" structure is created for base types
463-
private ensureBaseCreateHierarchy(model: string, result: any) {
464-
let curr = result;
480+
private ensureBaseCreateHierarchy(model: string, args: any) {
481+
let curr = args;
465482
let base = this.getBaseModel(model);
466483
let sub = this.getModelInfo(model);
467484

@@ -478,6 +495,16 @@ export class DelegateProxyHandler extends DefaultPrismaProxyHandler {
478495
curr[baseRelationName].create[base.discriminator] = sub.name;
479496
}
480497
}
498+
499+
// Look for base id field assignments in the current level, and push
500+
// them down to the base level
501+
for (const idField of getIdFields(this.options.modelMeta, base.name)) {
502+
if (curr[idField.name] !== undefined) {
503+
curr[baseRelationName].create[idField.name] = curr[idField.name];
504+
delete curr[idField.name];
505+
}
506+
}
507+
481508
curr = curr[baseRelationName].create;
482509
sub = base;
483510
base = this.getBaseModel(base.name);

packages/schema/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"publisher": "zenstack",
44
"displayName": "ZenStack Language Tools",
55
"description": "Build scalable web apps with minimum code by defining authorization and validation rules inside the data schema that closer to the database",
6-
"version": "2.2.3",
6+
"version": "2.2.4",
77
"author": {
88
"name": "ZenStack Team"
99
},

packages/sdk/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@zenstackhq/sdk",
3-
"version": "2.2.3",
3+
"version": "2.2.4",
44
"description": "ZenStack plugin development SDK",
55
"main": "index.js",
66
"scripts": {

packages/server/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@zenstackhq/server",
3-
"version": "2.2.3",
3+
"version": "2.2.4",
44
"displayName": "ZenStack Server-side Adapters",
55
"description": "ZenStack server-side adapters",
66
"homepage": "https://zenstack.dev",

packages/testtools/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@zenstackhq/testtools",
3-
"version": "2.2.3",
3+
"version": "2.2.4",
44
"description": "ZenStack Test Tools",
55
"main": "index.js",
66
"private": true,

tests/integration/tests/enhancements/with-delegate/enhanced-client.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,22 @@ describe('Polymorphism Test', () => {
158158
).resolves.toMatchObject({ count: 2 });
159159
});
160160

161+
it('create concrete with explicit id', async () => {
162+
const { enhance } = await loadSchema(schema, { enhancements: ['delegate'] });
163+
const db = enhance();
164+
165+
await expect(
166+
db.ratedVideo.create({ data: { id: 1, duration: 100, url: 'xyz', rating: 5 } })
167+
).resolves.toMatchObject({
168+
id: 1,
169+
duration: 100,
170+
url: 'xyz',
171+
rating: 5,
172+
assetType: 'Video',
173+
videoType: 'RatedVideo',
174+
});
175+
});
176+
161177
it('read with concrete', async () => {
162178
const { db, user, video } = await setup();
163179

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { loadSchema } from '@zenstackhq/testtools';
2+
describe('issue 1518', () => {
3+
it('regression', async () => {
4+
const { enhance } = await loadSchema(
5+
`
6+
model Activity {
7+
id String @id @default(uuid())
8+
title String
9+
type String
10+
@@delegate(type)
11+
@@allow('all', true)
12+
}
13+
14+
model TaskActivity extends Activity {
15+
description String
16+
@@map("task_activity")
17+
@@allow('all', true)
18+
}
19+
`
20+
);
21+
22+
const db = enhance();
23+
await db.taskActivity.create({
24+
data: {
25+
id: '00000000-0000-0000-0000-111111111111',
26+
title: 'Test Activity',
27+
description: 'Description of task',
28+
},
29+
});
30+
});
31+
});
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { loadSchema } from '@zenstackhq/testtools';
2+
3+
describe('issue 1520', () => {
4+
it('regression', async () => {
5+
const { enhance } = await loadSchema(
6+
`
7+
model Course {
8+
id Int @id @default(autoincrement())
9+
title String
10+
addedToNotifications AddedToCourseNotification[]
11+
}
12+
13+
model Group {
14+
id Int @id @default(autoincrement())
15+
addedToNotifications AddedToGroupNotification[]
16+
}
17+
18+
model Notification {
19+
id Int @id @default(autoincrement())
20+
createdAt DateTime @default(now())
21+
type String
22+
senderId Int
23+
receiverId Int
24+
@@delegate (type)
25+
}
26+
27+
model AddedToGroupNotification extends Notification {
28+
groupId Int
29+
group Group @relation(fields: [groupId], references: [id], onDelete: Cascade)
30+
}
31+
32+
model AddedToCourseNotification extends Notification {
33+
courseId Int
34+
course Course @relation(fields: [courseId], references: [id], onDelete: Cascade)
35+
}
36+
`,
37+
{ enhancements: ['delegate'] }
38+
);
39+
40+
const db = enhance();
41+
const r = await db.course.create({
42+
data: {
43+
title: 'English classes',
44+
addedToNotifications: {
45+
createMany: {
46+
data: [
47+
{
48+
id: 1,
49+
receiverId: 1,
50+
senderId: 2,
51+
},
52+
],
53+
},
54+
},
55+
},
56+
include: { addedToNotifications: true },
57+
});
58+
59+
expect(r.addedToNotifications).toEqual(
60+
expect.arrayContaining([
61+
expect.objectContaining({
62+
id: 1,
63+
courseId: 1,
64+
receiverId: 1,
65+
senderId: 2,
66+
}),
67+
])
68+
);
69+
});
70+
});

0 commit comments

Comments
 (0)