Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"name": "zenstack-monorepo",
"version": "2.21.1",
"version": "2.22.0",
"description": "",
"scripts": {
"build": "pnpm -r --filter=\"!./packages/ide/*\" build",
"build-ci": "pnpm -r build",
"lint": "pnpm -r lint",
"test": "pnpm -r --parallel run test --silent --forceExit",
"test-ci": "pnpm -r --parallel run --filter=\"./packages/**\" test --silent --forceExit",
"test-ci": "pnpm -r run --filter=\"./packages/**\" test --silent --forceExit",
"test-integration": "pnpm run --filter=integration test --silent --forceExit",
"test-regression": "pnpm run --filter=regression test --silent --forceExit",
"test-scaffold": "tsx script/test-scaffold.ts",
Expand Down
2 changes: 1 addition & 1 deletion packages/ide/jetbrains/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ plugins {
}

group = "dev.zenstack"
version = "2.21.1"
version = "2.22.0"

repositories {
mavenCentral()
Expand Down
2 changes: 1 addition & 1 deletion packages/ide/jetbrains/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "jetbrains",
"version": "2.21.1",
"version": "2.22.0",
"displayName": "ZenStack JetBrains IDE Plugin",
"description": "ZenStack JetBrains IDE plugin",
"homepage": "https://zenstack.dev",
Expand Down
2 changes: 1 addition & 1 deletion packages/language/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/language",
"version": "2.21.1",
"version": "2.22.0",
"displayName": "ZenStack modeling language compiler",
"description": "ZenStack modeling language compiler",
"homepage": "https://zenstack.dev",
Expand Down
2 changes: 1 addition & 1 deletion packages/misc/redwood/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@zenstackhq/redwood",
"displayName": "ZenStack RedwoodJS Integration",
"version": "2.21.1",
"version": "2.22.0",
"description": "CLI and runtime for integrating ZenStack with RedwoodJS projects.",
"repository": {
"type": "git",
Expand Down
2 changes: 1 addition & 1 deletion packages/plugins/openapi/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@zenstackhq/openapi",
"displayName": "ZenStack Plugin and Runtime for OpenAPI",
"version": "2.21.1",
"version": "2.22.0",
"description": "ZenStack plugin and runtime supporting OpenAPI",
"main": "index.js",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion packages/plugins/swr/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@zenstackhq/swr",
"displayName": "ZenStack plugin for generating SWR hooks",
"version": "2.21.1",
"version": "2.22.0",
"description": "ZenStack plugin for generating SWR hooks",
"main": "index.js",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion packages/plugins/tanstack-query/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@zenstackhq/tanstack-query",
"displayName": "ZenStack plugin for generating tanstack-query hooks",
"version": "2.21.1",
"version": "2.22.0",
"description": "ZenStack plugin for generating tanstack-query hooks",
"main": "index.js",
"exports": {
Expand Down
2 changes: 1 addition & 1 deletion packages/plugins/trpc/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@zenstackhq/trpc",
"displayName": "ZenStack plugin for tRPC",
"version": "2.21.1",
"version": "2.22.0",
"description": "ZenStack plugin for tRPC",
"main": "index.js",
"repository": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"postinstall": "nuxt prepare"
},
"dependencies": {
"@prisma/client": "6.17.x",
"@prisma/client": "6.19.x",
"@trpc/client": "^10.45.2",
"@trpc/server": "^10.45.2",
"nuxt": "^3.14.1592",
Expand All @@ -21,7 +21,7 @@
},
"devDependencies": {
"esbuild": "^0.24.0",
"prisma": "6.17.x",
"prisma": "6.19.x",
"typescript": "^5.6.2",
"vue-tsc": "^2.1.10"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"postinstall": "nuxt prepare"
},
"dependencies": {
"@prisma/client": "6.17.x",
"@prisma/client": "6.19.x",
"@trpc/client": "^11.0.0-rc.563",
"@trpc/server": "^11.0.0-rc.563",
"nuxt": "^3.14.1592",
Expand All @@ -21,7 +21,7 @@
},
"devDependencies": {
"esbuild": "^0.24.0",
"prisma": "6.17.x",
"prisma": "6.19.x",
"typescript": "^5.6.2",
"vue-tsc": "^2.1.10"
}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions packages/plugins/trpc/tests/projects/t3-trpc-v11/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"start": "next start"
},
"dependencies": {
"@prisma/client": "6.17.x",
"@prisma/client": "6.19.x",
"@t3-oss/env-nextjs": "^0.13.0",
"@tanstack/react-query": "^5.50.0",
"@trpc/client": "^11.0.0-rc.446",
Expand All @@ -39,7 +39,7 @@
"@typescript-eslint/parser": "^8.1.0",
"eslint": "^8.57.0",
"eslint-config-next": "^14.2.4",
"prisma": "6.17.x",
"prisma": "6.19.x",
"typescript": "^5.5.3"
},
"ct3aMetadata": {
Expand Down
6 changes: 3 additions & 3 deletions packages/runtime/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@zenstackhq/runtime",
"displayName": "ZenStack Runtime Library",
"version": "2.21.1",
"version": "2.22.0",
"description": "Runtime of ZenStack for both client-side and server-side environments.",
"repository": {
"type": "git",
Expand Down Expand Up @@ -122,10 +122,10 @@
"superjson": "^1.13.0",
"uuid": "^9.0.0",
"zod": "^3.25.0",
"@prisma/client": "6.17.x"
"@prisma/client": "6.19.x"
},
"peerDependencies": {
"@prisma/client": "5.0.0 - 6.18.x",
"@prisma/client": "5.0.0 - 6.19.x",
"zod": "catalog:"
},
"author": {
Expand Down
8 changes: 4 additions & 4 deletions packages/schema/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"publisher": "zenstack",
"displayName": "ZenStack Language Tools",
"description": "FullStack enhancement for Prisma ORM: seamless integration from database to UI",
"version": "2.21.1",
"version": "2.22.0",
"author": {
"name": "ZenStack Team"
},
Expand Down Expand Up @@ -187,13 +187,13 @@
"zod-validation-error": "catalog:"
},
"peerDependencies": {
"prisma": "5.0.0 - 6.18.x",
"prisma": "5.0.0 - 6.19.x",
"zod": "catalog:",
"@types/node": ">=18.0.0"
},
"devDependencies": {
"prisma": "6.17.x",
"@prisma/client": "6.17.x",
"prisma": "6.19.x",
"@prisma/client": "6.19.x",
"@types/async-exit-hook": "^2.0.0",
"@types/pluralize": "^0.0.29",
"@types/semver": "^7.3.13",
Expand Down
7 changes: 7 additions & 0 deletions packages/schema/src/cli/actions/generate.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { getPrismaClientGenerator, PluginError } from '@zenstackhq/sdk';
import { isPlugin } from '@zenstackhq/sdk/ast';
import { getPrismaVersion } from '@zenstackhq/sdk/prisma';
import colors from 'colors';
import path from 'path';
import semver from 'semver';
import { CliError } from '../cli-error';
import {
checkNewVersion,
Expand Down Expand Up @@ -48,6 +50,11 @@ export async function generate(projectPath: string, options: Options) {
}
}

const prismaVersion = getPrismaVersion();
if (prismaVersion && semver.gte(prismaVersion, '7.0.0')) {
console.warn(colors.yellow('Prisma 7 support is untested and not planned. Use with caution.'));
}

await runPlugins(options);

// note that we can't run online jobs concurrently with plugins because
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,8 @@ export default class DataSourceValidator implements AstValidator<DataSource> {
private validateUrl(ds: DataSource, accept: ValidationAcceptor) {
const url = ds.fields.find((f) => f.name === 'url');
if (!url) {
accept('error', 'datasource must include a "url" field', {
node: ds,
});
// url field is optional for new versions of Prisma
return;
}

for (const fieldName of ['url', 'shadowDatabaseUrl']) {
Expand Down
58 changes: 38 additions & 20 deletions packages/schema/src/plugins/enhancer/enhance/auth-type-generator.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { getIdFields, isAuthInvocation, isDataModelFieldReference } from '@zenstackhq/sdk';
import { getIdFields, getPrismaClientGenerator, isAuthInvocation, isDataModelFieldReference } from '@zenstackhq/sdk';
import {
DataModel,
DataModelField,
Expression,
isDataModel,
isMemberAccessExpr,
isTypeDef,
TypeDef,
type Model,
} from '@zenstackhq/sdk/ast';
Expand All @@ -19,27 +20,39 @@ export function generateAuthType(model: Model, authDecl: DataModel | TypeDef) {
const types = new Map<
string,
{
isTypeDef: boolean;
// relation fields to require
requiredRelations: { name: string; type: string }[];
}
>();

types.set(authDecl.name, { requiredRelations: [] });
types.set(authDecl.name, { isTypeDef: isTypeDef(authDecl), requiredRelations: [] });

const ensureType = (model: string) => {
if (!types.has(model)) {
types.set(model, { requiredRelations: [] });
const findType = (name: string) =>
model.declarations.find((d) => (isDataModel(d) || isTypeDef(d)) && d.name === name);

const ensureType = (name: string) => {
if (!types.has(name)) {
const decl = findType(name);
if (!decl) {
return;
}
types.set(name, { isTypeDef: isTypeDef(decl), requiredRelations: [] });
}
};

const addAddField = (model: string, name: string, type: string, array: boolean) => {
let fields = types.get(model);
if (!fields) {
fields = { requiredRelations: [] };
types.set(model, fields);
const addTypeField = (typeName: string, fieldName: string, fieldType: string, array: boolean) => {
let typeInfo = types.get(typeName);
if (!typeInfo) {
const decl = findType(typeName);
if (!decl) {
return;
}
typeInfo = { isTypeDef: isTypeDef(decl), requiredRelations: [] };
types.set(typeName, typeInfo);
}
if (!fields.requiredRelations.find((f) => f.name === name)) {
fields.requiredRelations.push({ name, type: array ? `${type}[]` : type });
if (!typeInfo.requiredRelations.find((f) => f.name === fieldName)) {
typeInfo.requiredRelations.push({ name: fieldName, type: array ? `${fieldType}[]` : fieldType });
}
};

Expand All @@ -57,7 +70,7 @@ export function generateAuthType(model: Model, authDecl: DataModel | TypeDef) {
// member is a relation
const fieldType = memberDecl.type.reference.ref.name;
ensureType(fieldType);
addAddField(exprType.name, memberDecl.name, fieldType, memberDecl.type.array);
addTypeField(exprType.name, memberDecl.name, fieldType, memberDecl.type.array);
}
}
}
Expand All @@ -69,12 +82,15 @@ export function generateAuthType(model: Model, authDecl: DataModel | TypeDef) {
if (isDataModel(fieldType)) {
// field is a relation
ensureType(fieldType.name);
addAddField(fieldDecl.$container.name, node.target.$refText, fieldType.name, fieldDecl.type.array);
addTypeField(fieldDecl.$container.name, node.target.$refText, fieldType.name, fieldDecl.type.array);
}
}
});
});

const prismaGenerator = getPrismaClientGenerator(model);
const isNewGenerator = !!prismaGenerator?.isNewGenerator;

// generate:
// `
// namespace auth {
Expand All @@ -86,25 +102,27 @@ export function generateAuthType(model: Model, authDecl: DataModel | TypeDef) {
return `export namespace auth {
type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };
${Array.from(types.entries())
.map(([model, fields]) => {
let result = `Partial<_P.${model}>`;
.map(([type, typeInfo]) => {
// TypeDef types are generated in "json-types.ts" for the new "prisma-client" generator
const typeRef = isNewGenerator && typeInfo.isTypeDef ? `$TypeDefs.${type}` : `_P.${type}`;
let result = `Partial<${typeRef}>`;

if (model === authDecl.name) {
if (type === authDecl.name) {
// auth model's id fields are always required
const idFields = getIdFields(authDecl).map((f) => f.name);
if (idFields.length > 0) {
result = `WithRequired<${result}, ${idFields.map((f) => `'${f}'`).join('|')}>`;
}
}

if (fields.requiredRelations.length > 0) {
if (typeInfo.requiredRelations.length > 0) {
// merge required relation fields
result = `${result} & { ${fields.requiredRelations.map((f) => `${f.name}: ${f.type}`).join('; ')} }`;
result = `${result} & { ${typeInfo.requiredRelations.map((f) => `${f.name}: ${f.type}`).join('; ')} }`;
}

result = `${result} & Record<string, unknown>`;

return ` export type ${model} = ${result};`;
return ` export type ${type} = ${result};`;
})
.join('\n')}
}`;
Expand Down
Loading
Loading