diff --git a/package.json b/package.json index 39b0cea4c..8d38ad648 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "zenstack-monorepo", - "version": "2.13.0", + "version": "2.13.1", "description": "", "scripts": { "build": "pnpm -r --filter=\"!./packages/ide/*\" build", diff --git a/packages/ide/jetbrains/CHANGELOG.md b/packages/ide/jetbrains/CHANGELOG.md index 936e5e7bd..861a0da12 100644 --- a/packages/ide/jetbrains/CHANGELOG.md +++ b/packages/ide/jetbrains/CHANGELOG.md @@ -2,6 +2,12 @@ ## [Unreleased] +- Support `@default` for `@json` fields. + +### Fixed + +## 2.12.1 + ### Added - Validating regex patterns in ZModel. diff --git a/packages/ide/jetbrains/build.gradle.kts b/packages/ide/jetbrains/build.gradle.kts index 83c4b197c..6ab980b4c 100644 --- a/packages/ide/jetbrains/build.gradle.kts +++ b/packages/ide/jetbrains/build.gradle.kts @@ -9,7 +9,7 @@ plugins { } group = "dev.zenstack" -version = "2.13.0" +version = "2.13.1" repositories { mavenCentral() diff --git a/packages/ide/jetbrains/package.json b/packages/ide/jetbrains/package.json index 2be7eaad2..32e36bc9f 100644 --- a/packages/ide/jetbrains/package.json +++ b/packages/ide/jetbrains/package.json @@ -1,6 +1,6 @@ { "name": "jetbrains", - "version": "2.13.0", + "version": "2.13.1", "displayName": "ZenStack JetBrains IDE Plugin", "description": "ZenStack JetBrains IDE plugin", "homepage": "https://zenstack.dev", diff --git a/packages/language/package.json b/packages/language/package.json index a195b8a6b..bd4786008 100644 --- a/packages/language/package.json +++ b/packages/language/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/language", - "version": "2.13.0", + "version": "2.13.1", "displayName": "ZenStack modeling language compiler", "description": "ZenStack modeling language compiler", "homepage": "https://zenstack.dev", diff --git a/packages/misc/redwood/package.json b/packages/misc/redwood/package.json index 8b3c9a8ad..893067229 100644 --- a/packages/misc/redwood/package.json +++ b/packages/misc/redwood/package.json @@ -1,7 +1,7 @@ { "name": "@zenstackhq/redwood", "displayName": "ZenStack RedwoodJS Integration", - "version": "2.13.0", + "version": "2.13.1", "description": "CLI and runtime for integrating ZenStack with RedwoodJS projects.", "repository": { "type": "git", diff --git a/packages/plugins/openapi/package.json b/packages/plugins/openapi/package.json index a6d582069..9cabb92fb 100644 --- a/packages/plugins/openapi/package.json +++ b/packages/plugins/openapi/package.json @@ -1,7 +1,7 @@ { "name": "@zenstackhq/openapi", "displayName": "ZenStack Plugin and Runtime for OpenAPI", - "version": "2.13.0", + "version": "2.13.1", "description": "ZenStack plugin and runtime supporting OpenAPI", "main": "index.js", "repository": { diff --git a/packages/plugins/swr/package.json b/packages/plugins/swr/package.json index 008d43026..faa529bef 100644 --- a/packages/plugins/swr/package.json +++ b/packages/plugins/swr/package.json @@ -1,7 +1,7 @@ { "name": "@zenstackhq/swr", "displayName": "ZenStack plugin for generating SWR hooks", - "version": "2.13.0", + "version": "2.13.1", "description": "ZenStack plugin for generating SWR hooks", "main": "index.js", "repository": { diff --git a/packages/plugins/tanstack-query/package.json b/packages/plugins/tanstack-query/package.json index 502acdab5..b6b0ec3c6 100644 --- a/packages/plugins/tanstack-query/package.json +++ b/packages/plugins/tanstack-query/package.json @@ -1,7 +1,7 @@ { "name": "@zenstackhq/tanstack-query", "displayName": "ZenStack plugin for generating tanstack-query hooks", - "version": "2.13.0", + "version": "2.13.1", "description": "ZenStack plugin for generating tanstack-query hooks", "main": "index.js", "exports": { diff --git a/packages/plugins/trpc/package.json b/packages/plugins/trpc/package.json index cf1303e58..79ffae8c1 100644 --- a/packages/plugins/trpc/package.json +++ b/packages/plugins/trpc/package.json @@ -1,7 +1,7 @@ { "name": "@zenstackhq/trpc", "displayName": "ZenStack plugin for tRPC", - "version": "2.13.0", + "version": "2.13.1", "description": "ZenStack plugin for tRPC", "main": "index.js", "repository": { diff --git a/packages/runtime/package.json b/packages/runtime/package.json index 20ad561c9..bd67f8a40 100644 --- a/packages/runtime/package.json +++ b/packages/runtime/package.json @@ -1,7 +1,7 @@ { "name": "@zenstackhq/runtime", "displayName": "ZenStack Runtime Library", - "version": "2.13.0", + "version": "2.13.1", "description": "Runtime of ZenStack for both client-side and server-side environments.", "repository": { "type": "git", diff --git a/packages/schema/package.json b/packages/schema/package.json index 668ae0f96..58b0dfe58 100644 --- a/packages/schema/package.json +++ b/packages/schema/package.json @@ -3,7 +3,7 @@ "publisher": "zenstack", "displayName": "ZenStack Language Tools", "description": "FullStack enhancement for Prisma ORM: seamless integration from database to UI", - "version": "2.13.0", + "version": "2.13.1", "author": { "name": "ZenStack Team" }, diff --git a/packages/schema/src/plugins/enhancer/enhance/index.ts b/packages/schema/src/plugins/enhancer/enhance/index.ts index 695853838..8bc1c393d 100644 --- a/packages/schema/src/plugins/enhancer/enhance/index.ts +++ b/packages/schema/src/plugins/enhancer/enhance/index.ts @@ -151,8 +151,8 @@ ${ ${ prismaTypesFixed - ? this.createLogicalPrismaImports(prismaImport, resultPrismaImport) - : this.createSimplePrismaImports(prismaImport) + ? this.createLogicalPrismaImports(prismaImport, resultPrismaImport, target) + : this.createSimplePrismaImports(prismaImport, target) } ${authTypes} @@ -206,8 +206,10 @@ ${ return normalizedRelative(this.outDir, zodAbsPath); } - private createSimplePrismaImports(prismaImport: string) { - return `import { Prisma, type PrismaClient } from '${prismaImport}'; + private createSimplePrismaImports(prismaImport: string, target: string) { + const prismaTargetImport = target === 'edge' ? `${prismaImport}/edge` : prismaImport; + + return `import { Prisma, type PrismaClient } from '${prismaTargetImport}'; import type * as _P from '${prismaImport}'; export type { PrismaClient }; @@ -235,8 +237,9 @@ export function enhance(prisma: DbClient, context?: Enh `; } - private createLogicalPrismaImports(prismaImport: string, prismaClientImport: string) { - return `import { Prisma as _Prisma, PrismaClient as _PrismaClient } from '${prismaImport}'; + private createLogicalPrismaImports(prismaImport: string, prismaClientImport: string, target: string) { + const prismaTargetImport = target === 'edge' ? `${prismaImport}/edge` : prismaImport; + return `import { Prisma as _Prisma, PrismaClient as _PrismaClient } from '${prismaTargetImport}'; import type { InternalArgs, DynamicClientExtensionThis } from '${prismaImport}/runtime/library'; import type * as _P from '${prismaClientImport}'; import type { Prisma, PrismaClient } from '${prismaClientImport}'; @@ -824,12 +827,21 @@ export type Enhanced = }; const replacePrismaJson = (source: string, field: DataModelField) => { - return source.replace( - new RegExp(`(${field.name}\\??\\s*):[^\\n]+`), - `$1: ${field.type.reference!.$refText}${field.type.array ? '[]' : ''}${ - field.type.optional ? ' | null' : '' - }` - ); + let replaceValue = `$1: ${field.type.reference!.$refText}`; + if (field.type.array) { + replaceValue += '[]'; + } + if (field.type.optional) { + replaceValue += ' | null'; + } + + // Check if the field in the source is optional (has a `?`) + const isOptionalInSource = new RegExp(`(${field.name}\\?\\s*):`).test(source); + if (isOptionalInSource) { + replaceValue += ' | $Types.Skip'; + } + + return source.replace(new RegExp(`(${field.name}\\??\\s*):[^\\n]+`), replaceValue); }; // fix "$[Model]Payload" type diff --git a/packages/sdk/package.json b/packages/sdk/package.json index eb50c1d6c..1f4f88f94 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/sdk", - "version": "2.13.0", + "version": "2.13.1", "description": "ZenStack plugin development SDK", "main": "index.js", "scripts": { diff --git a/packages/server/package.json b/packages/server/package.json index 06fda5ad8..0f1614df6 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/server", - "version": "2.13.0", + "version": "2.13.1", "displayName": "ZenStack Server-side Adapters", "description": "ZenStack server-side adapters", "homepage": "https://zenstack.dev", diff --git a/packages/server/src/api/rest/index.ts b/packages/server/src/api/rest/index.ts index c50e5aa5b..ffb617245 100644 --- a/packages/server/src/api/rest/index.ts +++ b/packages/server/src/api/rest/index.ts @@ -1528,7 +1528,6 @@ class RequestHandler extends APIHandlerBase { } const items: any[] = []; - let currType = typeInfo; for (const [key, value] of Object.entries(query)) { if (!value) { @@ -1554,6 +1553,7 @@ class RequestHandler extends APIHandlerBase { const item: any = {}; let curr = item; + let currType = typeInfo; for (const filterValue of enumerate(value)) { for (let i = 0; i < filterKeys.length; i++) { diff --git a/packages/server/tests/api/rest.test.ts b/packages/server/tests/api/rest.test.ts index b36755055..fd2ddc262 100644 --- a/packages/server/tests/api/rest.test.ts +++ b/packages/server/tests/api/rest.test.ts @@ -633,6 +633,26 @@ describe('REST server tests', () => { prisma, }); expect(r.body.data).toHaveLength(0); + r = await handler({ + method: 'get', + path: '/post', + query: { + ['filter[author][email]']: 'user1@abc.com', + ['filter[title]']: 'Post1', + }, + prisma, + }); + expect(r.body.data).toHaveLength(1); + r = await handler({ + method: 'get', + path: '/post', + query: { + ['filter[author][email]']: 'user1@abc.com', + ['filter[title]']: 'Post2', + }, + prisma, + }); + expect(r.body.data).toHaveLength(0); // to-one relation filter r = await handler({ diff --git a/packages/testtools/package.json b/packages/testtools/package.json index 779b505c7..fab829fe2 100644 --- a/packages/testtools/package.json +++ b/packages/testtools/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/testtools", - "version": "2.13.0", + "version": "2.13.1", "description": "ZenStack Test Tools", "main": "index.js", "private": true, diff --git a/tests/integration/tests/enhancements/json/crud.test.ts b/tests/integration/tests/enhancements/json/crud.test.ts index 12c35ed09..f13b5727b 100644 --- a/tests/integration/tests/enhancements/json/crud.test.ts +++ b/tests/integration/tests/enhancements/json/crud.test.ts @@ -429,4 +429,66 @@ describe('Json field CRUD', () => { await expect(post.content.content[0].content[0].text).toBe('hello'); }); + + it('works with Prisma.skip', async () => { + const params = await loadSchema( + ` + type Profile { + foo Int + bar String + } + + model User { + id Int @id @default(autoincrement()) + name String + profile Profile @json + @@allow('all', true) + } + `, + { + provider: 'postgresql', + dbUrl, + compile: true, + extraSourceFiles: [ + { + name: 'main.ts', + content: ` +import { enhance } from '.zenstack/enhance'; +import { Prisma, PrismaClient } from '@prisma/client'; +const prisma = new PrismaClient(); +const db = enhance(prisma); + +async function main() { + // @ts-expect-error Non optional JSON fields should not be skippable in the create call + db.user.create({ data: { name: 'test', profile: Prisma.skip } }); + + const u = await db.user.create({ data: { name: 'test', profile: { foo: 18, bar: 'test' } } }); + await db.user.update({ where: { id: u.id }, data: { profile: Prisma.skip } }); +} + `, + }, + ], + } + ); + + prisma = params.prisma; + const skip = params.prismaModule.Prisma.skip; + const db = params.enhance(); + + const user = await db.user.create({ data: { name: 'test', profile: { foo: 18, bar: 'test' } } }); + + await expect( + db.user.update({ + where: { id: user.id }, + data: { profile: skip }, + }) + ).resolves.toMatchObject({ + id: user.id, + name: 'test', + profile: { + foo: 18, + bar: 'test', + }, + }); + }); });