Skip to content

Commit e290fa8

Browse files
authored
Merge branch 'dev' into dev
2 parents da2bd07 + 485be72 commit e290fa8

File tree

24 files changed

+413
-165
lines changed

24 files changed

+413
-165
lines changed

packages/plugins/tanstack-query/src/generator.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
ensureEmptyDir,
77
generateModelMeta,
88
getDataModels,
9+
getPrismaClientGenerator,
910
isDelegateModel,
1011
requireOption,
1112
resolvePath,
@@ -50,7 +51,6 @@ export async function generate(model: Model, options: PluginOptions, dmmf: DMMF.
5051
`Invalid value for "portable" option: ${options.portable}, a boolean value is expected`
5152
);
5253
}
53-
const portable = options.portable ?? false;
5454

5555
await generateModelMeta(project, models, typeDefs, {
5656
output: path.join(outDir, '__model_meta.ts'),
@@ -68,8 +68,13 @@ export async function generate(model: Model, options: PluginOptions, dmmf: DMMF.
6868
generateModelHooks(target, version, project, outDir, dataModel, mapping, options);
6969
});
7070

71-
if (portable) {
72-
generateBundledTypes(project, outDir, options);
71+
if (options.portable) {
72+
const gen = getPrismaClientGenerator(model);
73+
if (gen?.isNewGenerator) {
74+
warnings.push(`The "portable" option is not supported with the "prisma-client" generator and is ignored.`);
75+
} else {
76+
generateBundledTypes(project, outDir, options);
77+
}
7378
}
7479

7580
await saveProject(project);

packages/plugins/trpc/tests/projects/nuxt-trpc-v10/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"postinstall": "nuxt prepare"
1111
},
1212
"dependencies": {
13-
"@prisma/client": "6.8.x",
13+
"@prisma/client": "6.10.x",
1414
"@trpc/client": "^10.45.2",
1515
"@trpc/server": "^10.45.2",
1616
"nuxt": "^3.14.1592",
@@ -21,7 +21,7 @@
2121
},
2222
"devDependencies": {
2323
"esbuild": "^0.24.0",
24-
"prisma": "6.8.x",
24+
"prisma": "6.10.x",
2525
"typescript": "^5.6.2",
2626
"vue-tsc": "^2.1.10"
2727
}

packages/plugins/trpc/tests/projects/nuxt-trpc-v11/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"postinstall": "nuxt prepare"
1111
},
1212
"dependencies": {
13-
"@prisma/client": "6.8.x",
13+
"@prisma/client": "6.10.x",
1414
"@trpc/client": "^11.0.0-rc.563",
1515
"@trpc/server": "^11.0.0-rc.563",
1616
"nuxt": "^3.14.1592",
@@ -21,7 +21,7 @@
2121
},
2222
"devDependencies": {
2323
"esbuild": "^0.24.0",
24-
"prisma": "6.8.x",
24+
"prisma": "6.10.x",
2525
"typescript": "^5.6.2",
2626
"vue-tsc": "^2.1.10"
2727
}

packages/plugins/trpc/tests/projects/t3-trpc-v11/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"start": "next start"
1616
},
1717
"dependencies": {
18-
"@prisma/client": "6.8.x",
18+
"@prisma/client": "6.10.x",
1919
"@t3-oss/env-nextjs": "^0.10.1",
2020
"@tanstack/react-query": "^5.50.0",
2121
"@trpc/client": "^11.0.0-rc.446",
@@ -39,7 +39,7 @@
3939
"@typescript-eslint/parser": "^8.1.0",
4040
"eslint": "^8.57.0",
4141
"eslint-config-next": "^14.2.4",
42-
"prisma": "6.8.x",
42+
"prisma": "6.10.x",
4343
"typescript": "^5.5.3"
4444
},
4545
"ct3aMetadata": {

packages/runtime/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@
112112
"zod-validation-error": "^1.5.0"
113113
},
114114
"peerDependencies": {
115-
"@prisma/client": "5.0.0 - 6.8.x"
115+
"@prisma/client": "5.0.0 - 6.10.x"
116116
},
117117
"author": {
118118
"name": "ZenStack Team"

packages/schema/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,10 @@
118118
"zod-validation-error": "^1.5.0"
119119
},
120120
"peerDependencies": {
121-
"prisma": "5.0.0 - 6.8.x"
121+
"prisma": "5.0.0 - 6.10.x"
122122
},
123123
"devDependencies": {
124-
"@prisma/client": "6.8.x",
124+
"@prisma/client": "6.10.x",
125125
"@types/async-exit-hook": "^2.0.0",
126126
"@types/pluralize": "^0.0.29",
127127
"@types/semver": "^7.3.13",

packages/schema/src/cli/actions/generate.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { PluginError } from '@zenstackhq/sdk';
1+
import { getPrismaClientGenerator, PluginError } from '@zenstackhq/sdk';
22
import { isPlugin } from '@zenstackhq/sdk/ast';
33
import colors from 'colors';
44
import path from 'path';
@@ -70,6 +70,18 @@ async function runPlugins(options: Options) {
7070

7171
const model = await loadDocument(schema);
7272

73+
const gen = getPrismaClientGenerator(model);
74+
if (gen?.isNewGenerator && !options.output) {
75+
console.error(
76+
colors.red(
77+
'When using the "prisma-client" generator, you must provide an explicit output path with the "--output" CLI parameter.'
78+
)
79+
);
80+
throw new CliError(
81+
'When using with the "prisma-client" generator, you must provide an explicit output path with the "--output" CLI parameter.'
82+
);
83+
}
84+
7385
for (const name of [...(options.withPlugins ?? []), ...(options.withoutPlugins ?? [])]) {
7486
const pluginDecl = model.declarations.find((d) => isPlugin(d) && d.name === name);
7587
if (!pluginDecl) {

packages/schema/src/cli/plugin-runner.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,7 @@ export class PluginRunner {
112112
const otherPlugins = plugins.filter((p) => !p.options.preprocessor);
113113

114114
// calculate all plugins (including core plugins implicitly enabled)
115-
const { corePlugins, userPlugins } = this.calculateAllPlugins(
116-
runnerOptions,
117-
otherPlugins,
118-
);
115+
const { corePlugins, userPlugins } = this.calculateAllPlugins(runnerOptions, otherPlugins);
119116
const allPlugins = [...corePlugins, ...userPlugins];
120117

121118
// check dependencies
@@ -448,7 +445,7 @@ export class PluginRunner {
448445
}
449446

450447
async function compileProject(project: Project, runnerOptions: PluginRunnerOptions) {
451-
if (runnerOptions.compile !== false) {
448+
if (!runnerOptions.output && runnerOptions.compile !== false) {
452449
// emit
453450
await emitProject(project);
454451
} else {

packages/schema/src/language-server/zmodel-workspace-manager.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { isPlugin, Model } from '@zenstackhq/language/ast';
22
import { getLiteral } from '@zenstackhq/sdk';
33
import { DefaultWorkspaceManager, interruptAndCheck, LangiumDocument } from 'langium';
4+
import fs from 'fs';
45
import path from 'path';
56
import { CancellationToken, WorkspaceFolder } from 'vscode-languageserver';
67
import { URI, Utils } from 'vscode-uri';
@@ -17,7 +18,42 @@ export class ZModelWorkspaceManager extends DefaultWorkspaceManager {
1718
_collector: (document: LangiumDocument) => void
1819
): Promise<void> {
1920
await super.loadAdditionalDocuments(_folders, _collector);
20-
const stdLibUri = URI.file(path.join(__dirname, '../res', STD_LIB_MODULE_NAME));
21+
22+
let stdLibPath: string;
23+
// First, try to find the stdlib from an installed zenstack package
24+
// in the project's node_modules
25+
let installedStdlibPath: string | undefined;
26+
for (const folder of _folders) {
27+
const folderPath = this.getRootFolder(folder).fsPath;
28+
try {
29+
// Try to resolve zenstack from the workspace folder
30+
const languagePackagePath = require.resolve('zenstack/package.json', {
31+
paths: [folderPath]
32+
});
33+
const languagePackageDir = path.dirname(languagePackagePath);
34+
const candidateStdlibPath = path.join(languagePackageDir, 'res', STD_LIB_MODULE_NAME);
35+
36+
// Check if the stdlib file exists in the installed package
37+
if (fs.existsSync(candidateStdlibPath)) {
38+
installedStdlibPath = candidateStdlibPath;
39+
console.log(`Found installed zenstack package stdlib at ${installedStdlibPath}`);
40+
break;
41+
}
42+
} catch (error) {
43+
// Package not found or other error, continue to next folder
44+
continue;
45+
}
46+
}
47+
48+
if (installedStdlibPath) {
49+
stdLibPath = installedStdlibPath;
50+
} else {
51+
// Fallback to bundled stdlib
52+
stdLibPath = path.join(__dirname, '../res', STD_LIB_MODULE_NAME);
53+
console.log(`Using bundled stdlib in extension`);
54+
}
55+
56+
const stdLibUri = URI.file(stdLibPath);
2157
console.log(`Adding stdlib document from ${stdLibUri}`);
2258
const stdlib = this.langiumDocuments.getOrCreateDocument(stdLibUri);
2359
_collector(stdlib);

packages/schema/src/plugins/enhancer/enhance/index.ts

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
getDataModelAndTypeDefs,
88
getDataModels,
99
getForeignKeyFields,
10-
getLiteral,
10+
getPrismaClientGenerator,
1111
getRelationField,
1212
hasAttribute,
1313
isDelegateModel,
@@ -22,7 +22,6 @@ import {
2222
ReferenceExpr,
2323
isArrayExpr,
2424
isDataModel,
25-
isGeneratorDecl,
2625
isTypeDef,
2726
type Model,
2827
} from '@zenstackhq/sdk/ast';
@@ -56,7 +55,7 @@ import { generateTypeDefType } from './model-typedef-generator';
5655
// information of delegate models and their sub models
5756
type DelegateInfo = [DataModel, DataModel[]][];
5857

59-
const LOGICAL_CLIENT_GENERATION_PATH = './.logical-prisma-client';
58+
const LOGICAL_CLIENT_GENERATION_PATH = './logical-prisma-client';
6059

6160
export class EnhancerGenerator {
6261
// regex for matching "ModelCreateXXXInput" and "ModelUncheckedCreateXXXInput" type
@@ -114,6 +113,9 @@ export class EnhancerGenerator {
114113
if (this.needsLogicalClient) {
115114
prismaTypesFixed = true;
116115
resultPrismaTypeImport = LOGICAL_CLIENT_GENERATION_PATH;
116+
if (this.isNewPrismaClientGenerator) {
117+
resultPrismaTypeImport += '/client';
118+
}
117119
const result = await this.generateLogicalPrisma();
118120
dmmf = result.dmmf;
119121
}
@@ -440,23 +442,14 @@ export type Enhanced<Client> =
440442
}
441443

442444
private getPrismaClientGeneratorName(model: Model) {
443-
for (const generator of model.declarations.filter(isGeneratorDecl)) {
444-
if (
445-
generator.fields.some(
446-
(f) => f.name === 'provider' && getLiteral<string>(f.value) === 'prisma-client-js'
447-
)
448-
) {
449-
return generator.name;
450-
}
445+
const gen = getPrismaClientGenerator(model);
446+
if (!gen) {
447+
throw new PluginError(name, `Cannot find "prisma-client-js" or "prisma-client" generator in the schema`);
451448
}
452-
throw new PluginError(name, `Cannot find prisma-client-js generator in the schema`);
449+
return gen.name;
453450
}
454451

455452
private async processClientTypes(prismaClientDir: string) {
456-
// make necessary updates to the generated `index.d.ts` file and overwrite it
457-
const project = new Project();
458-
const sf = project.addSourceFileAtPath(path.join(prismaClientDir, 'index.d.ts'));
459-
460453
// build a map of delegate models and their sub models
461454
const delegateInfo: DelegateInfo = [];
462455
this.model.declarations
@@ -468,6 +461,16 @@ export type Enhanced<Client> =
468461
}
469462
});
470463

464+
if (this.isNewPrismaClientGenerator) {
465+
await this.processClientTypesNewPrismaGenerator(prismaClientDir, delegateInfo);
466+
} else {
467+
await this.processClientTypesLegacyPrismaGenerator(prismaClientDir, delegateInfo);
468+
}
469+
}
470+
private async processClientTypesLegacyPrismaGenerator(prismaClientDir: string, delegateInfo: DelegateInfo) {
471+
const project = new Project();
472+
const sf = project.addSourceFileAtPath(path.join(prismaClientDir, 'index.d.ts'));
473+
471474
// transform index.d.ts and write it into a new file (better perf than in-line editing)
472475
const sfNew = project.createSourceFile(path.join(prismaClientDir, 'index-fixed.d.ts'), undefined, {
473476
overwrite: true,
@@ -484,6 +487,36 @@ export type Enhanced<Client> =
484487
await sfNew.save();
485488
}
486489

490+
private async processClientTypesNewPrismaGenerator(prismaClientDir: string, delegateInfo: DelegateInfo) {
491+
const project = new Project();
492+
493+
for (const d of this.model.declarations.filter(isDataModel)) {
494+
const fileName = `${prismaClientDir}/models/${d.name}.ts`;
495+
const sf = project.addSourceFileAtPath(fileName);
496+
const sfNew = project.createSourceFile(`${prismaClientDir}/models/${d.name}-fixed.ts`, undefined, {
497+
overwrite: true,
498+
});
499+
500+
const syntaxList = sf.getChildren()[0];
501+
if (!Node.isSyntaxList(syntaxList)) {
502+
throw new PluginError(name, `Unexpected syntax list structure in ${fileName}`);
503+
}
504+
505+
syntaxList.getChildren().forEach((node) => {
506+
if (Node.isInterfaceDeclaration(node)) {
507+
sfNew.addInterface(this.transformInterface(node, delegateInfo));
508+
} else if (Node.isTypeAliasDeclaration(node)) {
509+
sfNew.addTypeAlias(this.transformTypeAlias(node, delegateInfo));
510+
} else {
511+
sfNew.addStatements(node.getText());
512+
}
513+
});
514+
515+
await sfNew.move(sf.getFilePath(), { overwrite: true });
516+
await sfNew.save();
517+
}
518+
}
519+
487520
private transformPrismaTypes(sf: SourceFile, sfNew: SourceFile, delegateInfo: DelegateInfo) {
488521
// copy toplevel imports
489522
sfNew.addImportDeclarations(sf.getImportDeclarations().map((n) => n.getStructure()));
@@ -639,7 +672,7 @@ export type Enhanced<Client> =
639672
source = `${payloadRecord[1]
640673
.map(
641674
(concrete) =>
642-
`($${concrete.name}Payload<ExtArgs> & { scalars: { ${discriminatorDecl.name}: '${concrete.name}' } })`
675+
`(Prisma.$${concrete.name}Payload<ExtArgs> & { scalars: { ${discriminatorDecl.name}: '${concrete.name}' } })`
643676
)
644677
.join(' | ')}`;
645678
}
@@ -916,4 +949,9 @@ export type Enhanced<Client> =
916949
private trimEmptyLines(source: string): string {
917950
return source.replace(/^\s*[\r\n]/gm, '');
918951
}
952+
953+
private get isNewPrismaClientGenerator() {
954+
const gen = getPrismaClientGenerator(this.model);
955+
return !!gen?.isNewGenerator;
956+
}
919957
}

0 commit comments

Comments
 (0)