Skip to content

Commit 9eaf235

Browse files
authored
fix: canonicalize plugin's output folder detection; don't generate aux field unnecessarily (#423)
1 parent a5848ea commit 9eaf235

File tree

27 files changed

+365
-187
lines changed

27 files changed

+365
-187
lines changed

packages/plugins/openapi/src/generator-base.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import { DMMF } from '@prisma/generator-helper';
22
import { PluginError, PluginOptions, getDataModels, hasAttribute } from '@zenstackhq/sdk';
33
import { Model } from '@zenstackhq/sdk/ast';
44
import type { OpenAPIV3_1 as OAPI } from 'openapi-types';
5-
import { SecuritySchemesSchema } from './schema';
65
import { fromZodError } from 'zod-validation-error';
6+
import { SecuritySchemesSchema } from './schema';
77

88
export abstract class OpenAPIGeneratorBase {
99
constructor(protected model: Model, protected options: PluginOptions, protected dmmf: DMMF.Document) {}
@@ -51,7 +51,10 @@ export abstract class OpenAPIGeneratorBase {
5151
if (securitySchemes) {
5252
const parsed = SecuritySchemesSchema.safeParse(securitySchemes);
5353
if (!parsed.success) {
54-
throw new PluginError(`"securitySchemes" option is invalid: ${fromZodError(parsed.error)}`);
54+
throw new PluginError(
55+
this.options.name,
56+
`"securitySchemes" option is invalid: ${fromZodError(parsed.error)}`
57+
);
5558
}
5659
return parsed.data;
5760
}

packages/plugins/openapi/src/rest-generator.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
import { DMMF } from '@prisma/generator-helper';
44
import {
55
AUXILIARY_FIELDS,
6-
PluginError,
76
analyzePolicies,
87
getDataModels,
98
isForeignKeyField,
109
isIdField,
1110
isRelationshipField,
11+
requireOption,
12+
resolvePath,
1213
} from '@zenstackhq/sdk';
1314
import { DataModel, DataModelField, DataModelFieldType, Enum, isDataModel, isEnum } from '@zenstackhq/sdk/ast';
1415
import * as fs from 'fs';
@@ -30,10 +31,8 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
3031
private warnings: string[] = [];
3132

3233
generate() {
33-
const output = this.getOption('output', '');
34-
if (!output) {
35-
throw new PluginError('"output" option is required');
36-
}
34+
let output = requireOption<string>(this.options, 'output');
35+
output = resolvePath(output, this.options);
3736

3837
const components = this.generateComponents();
3938
const paths = this.generatePaths();

packages/plugins/openapi/src/rpc-generator.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Inspired by: https://github.com/omar-dulaimi/prisma-trpc-generator
22

33
import { DMMF } from '@prisma/generator-helper';
4-
import { analyzePolicies, AUXILIARY_FIELDS, PluginError } from '@zenstackhq/sdk';
4+
import { analyzePolicies, AUXILIARY_FIELDS, PluginError, requireOption, resolvePath } from '@zenstackhq/sdk';
55
import { DataModel, isDataModel } from '@zenstackhq/sdk/ast';
66
import {
77
addMissingInputObjectTypesForAggregate,
@@ -31,10 +31,8 @@ export class RPCOpenAPIGenerator extends OpenAPIGeneratorBase {
3131
private warnings: string[] = [];
3232

3333
generate() {
34-
const output = this.getOption('output', '');
35-
if (!output) {
36-
throw new PluginError('"output" option is required');
37-
}
34+
let output = requireOption<string>(this.options, 'output');
35+
output = resolvePath(output, this.options);
3836

3937
// input types
4038
this.inputObjectTypes.push(...this.dmmf.schema.inputObjectTypes.prisma);
@@ -663,7 +661,7 @@ export class RPCOpenAPIGenerator extends OpenAPIGeneratorBase {
663661
return this.wrapArray(this.ref(def.type, false), def.isList);
664662

665663
default:
666-
throw new PluginError(`Unsupported field kind: ${def.kind}`);
664+
throw new PluginError(this.options.name, `Unsupported field kind: ${def.kind}`);
667665
}
668666
}
669667

packages/plugins/react/src/generator/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ export async function generate(model: Model, options: PluginOptions, dmmf: DMMF.
1212
case 'react-query':
1313
return reactQueryGenerate(model, options, dmmf);
1414
default:
15-
throw new PluginError(`Unknown "fetcher" option: ${fetcher}, use "swr" or "react-query"`);
15+
throw new PluginError(options.name, `Unknown "fetcher" option: ${fetcher}, use "swr" or "react-query"`);
1616
}
1717
}

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

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,16 @@
11
import { DMMF } from '@prisma/generator-helper';
2-
import { PluginError, PluginOptions, createProject, getDataModels, saveProject } from '@zenstackhq/sdk';
2+
import { PluginOptions, createProject, getDataModels, saveProject } from '@zenstackhq/sdk';
33
import { DataModel, Model } from '@zenstackhq/sdk/ast';
4+
import { requireOption, resolvePath } from '@zenstackhq/sdk/utils';
45
import { paramCase } from 'change-case';
56
import { lowerCaseFirst } from 'lower-case-first';
67
import * as path from 'path';
78
import { Project, SourceFile, VariableDeclarationKind } from 'ts-morph';
89
import { upperCaseFirst } from 'upper-case-first';
910

1011
export async function generate(model: Model, options: PluginOptions, dmmf: DMMF.Document) {
11-
let outDir = options.output as string;
12-
if (!outDir) {
13-
throw new PluginError('"output" option is required');
14-
}
15-
16-
if (!path.isAbsolute(outDir)) {
17-
// output dir is resolved relative to the schema file path
18-
outDir = path.join(path.dirname(options.schemaPath), outDir);
19-
}
12+
let outDir = requireOption<string>(options, 'output');
13+
outDir = resolvePath(outDir, options);
2014

2115
const project = createProject();
2216
const warnings: string[] = [];

packages/plugins/react/src/generator/swr.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { DMMF } from '@prisma/generator-helper';
22
import {
33
CrudFailureReason,
4-
PluginError,
54
PluginOptions,
65
createProject,
76
getDataModels,
7+
requireOption,
8+
resolvePath,
89
saveProject,
910
} from '@zenstackhq/sdk';
1011
import { DataModel, Model } from '@zenstackhq/sdk/ast';
@@ -14,15 +15,8 @@ import * as path from 'path';
1415
import { Project } from 'ts-morph';
1516

1617
export async function generate(model: Model, options: PluginOptions, dmmf: DMMF.Document) {
17-
let outDir = options.output as string;
18-
if (!outDir) {
19-
throw new PluginError('"output" option is required');
20-
}
21-
22-
if (!path.isAbsolute(outDir)) {
23-
// output dir is resolved relative to the schema file path
24-
outDir = path.join(path.dirname(options.schemaPath), outDir);
25-
}
18+
let outDir = requireOption<string>(options, 'output');
19+
outDir = resolvePath(outDir, options);
2620

2721
const project = createProject();
2822
const warnings: string[] = [];

packages/plugins/swr/src/generator.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { DMMF } from '@prisma/generator-helper';
22
import {
33
CrudFailureReason,
4-
PluginError,
54
PluginOptions,
65
createProject,
76
getDataModels,
7+
requireOption,
8+
resolvePath,
89
saveProject,
910
} from '@zenstackhq/sdk';
1011
import { DataModel, Model } from '@zenstackhq/sdk/ast';
@@ -15,15 +16,8 @@ import path from 'path';
1516
import { Project } from 'ts-morph';
1617

1718
export async function generate(model: Model, options: PluginOptions, dmmf: DMMF.Document) {
18-
let outDir = options.output as string;
19-
if (!outDir) {
20-
throw new PluginError('"output" option is required');
21-
}
22-
23-
if (!path.isAbsolute(outDir)) {
24-
// output dir is resolved relative to the schema file path
25-
outDir = path.join(path.dirname(options.schemaPath), outDir);
26-
}
19+
let outDir = requireOption<string>(options, 'output');
20+
outDir = resolvePath(outDir, options);
2721

2822
const project = createProject();
2923
const warnings: string[] = [];

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

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,39 @@
11
import { DMMF } from '@prisma/generator-helper';
2-
import { PluginError, PluginOptions, createProject, getDataModels, saveProject } from '@zenstackhq/sdk';
2+
import {
3+
PluginError,
4+
PluginOptions,
5+
createProject,
6+
getDataModels,
7+
requireOption,
8+
resolvePath,
9+
saveProject,
10+
} from '@zenstackhq/sdk';
311
import { DataModel, Model } from '@zenstackhq/sdk/ast';
412
import { paramCase } from 'change-case';
513
import fs from 'fs';
614
import { lowerCaseFirst } from 'lower-case-first';
715
import path from 'path';
816
import { Project, SourceFile, VariableDeclarationKind } from 'ts-morph';
917
import { upperCaseFirst } from 'upper-case-first';
18+
import { name } from '.';
1019

1120
const supportedTargets = ['react', 'svelte'];
1221
type TargetFramework = (typeof supportedTargets)[number];
1322

1423
export async function generate(model: Model, options: PluginOptions, dmmf: DMMF.Document) {
15-
let outDir = options.output as string;
16-
if (!outDir) {
17-
throw new PluginError('"output" option is required');
18-
}
19-
20-
if (!path.isAbsolute(outDir)) {
21-
// output dir is resolved relative to the schema file path
22-
outDir = path.join(path.dirname(options.schemaPath), outDir);
23-
}
24+
let outDir = requireOption<string>(options, 'output');
25+
outDir = resolvePath(outDir, options);
2426

2527
const project = createProject();
2628
const warnings: string[] = [];
2729
const models = getDataModels(model);
2830

29-
const target = options.target as string;
30-
if (!target) {
31-
throw new PluginError(`"target" option is required, supported values: ${supportedTargets.join(', ')}`);
32-
}
31+
const target = requireOption<string>(options, 'target');
3332
if (!supportedTargets.includes(target)) {
34-
throw new PluginError(`Unsupported target "${target}", supported values: ${supportedTargets.join(', ')}`);
33+
throw new PluginError(
34+
options.name,
35+
`Unsupported target "${target}", supported values: ${supportedTargets.join(', ')}`
36+
);
3537
}
3638

3739
generateIndex(project, outDir, models);
@@ -198,7 +200,7 @@ function generateMutationHook(
198200
break;
199201

200202
default:
201-
throw new PluginError(`Unsupported target "${target}"`);
203+
throw new PluginError(name, `Unsupported target "${target}"`);
202204
}
203205

204206
func.addStatements('return mutation;');
@@ -395,7 +397,7 @@ function generateHelper(target: TargetFramework, project: Project, outDir: strin
395397
srcFile = path.join(__dirname, './res/svelte/helper.ts');
396398
break;
397399
default:
398-
throw new PluginError(`Unsupported target: ${target}`);
400+
throw new PluginError(name, `Unsupported target: ${target}`);
399401
}
400402

401403
// merge content of `shared.ts`, `helper.ts` and `marshal-?.ts`
@@ -418,7 +420,7 @@ function makeGetContext(target: TargetFramework) {
418420
case 'svelte':
419421
return `const { endpoint } = getContext<RequestHandlerContext>(SvelteQueryContextKey);`;
420422
default:
421-
throw new PluginError(`Unsupported target "${target}"`);
423+
throw new PluginError(name, `Unsupported target "${target}"`);
422424
}
423425
}
424426

@@ -441,7 +443,7 @@ function makeBaseImports(target: TargetFramework) {
441443
...shared,
442444
];
443445
default:
444-
throw new PluginError(`Unsupported target: ${target}`);
446+
throw new PluginError(name, `Unsupported target: ${target}`);
445447
}
446448
}
447449

@@ -452,7 +454,7 @@ function makeQueryOptions(target: string, returnType: string) {
452454
case 'svelte':
453455
return `QueryOptions<${returnType}>`;
454456
default:
455-
throw new PluginError(`Unsupported target: ${target}`);
457+
throw new PluginError(name, `Unsupported target: ${target}`);
456458
}
457459
}
458460

@@ -463,6 +465,6 @@ function makeMutationOptions(target: string, returnType: string, argsType: strin
463465
case 'svelte':
464466
return `MutationOptions<${returnType}, unknown, ${argsType}>`;
465467
default:
466-
throw new PluginError(`Unsupported target: ${target}`);
468+
throw new PluginError(name, `Unsupported target: ${target}`);
467469
}
468470
}

packages/plugins/trpc/src/generator.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
import { DMMF } from '@prisma/generator-helper';
2-
import { CrudFailureReason, PluginError, PluginOptions, RUNTIME_PACKAGE, saveProject } from '@zenstackhq/sdk';
2+
import {
3+
CrudFailureReason,
4+
PluginOptions,
5+
RUNTIME_PACKAGE,
6+
requireOption,
7+
resolvePath,
8+
saveProject,
9+
} from '@zenstackhq/sdk';
310
import { Model } from '@zenstackhq/sdk/ast';
4-
import { lowerCaseFirst } from 'lower-case-first';
511
import { promises as fs } from 'fs';
12+
import { lowerCaseFirst } from 'lower-case-first';
613
import path from 'path';
714
import { Project } from 'ts-morph';
815
import {
@@ -17,15 +24,8 @@ import removeDir from './utils/removeDir';
1724
import { generate as PrismaZodGenerator } from './zod/generator';
1825

1926
export async function generate(model: Model, options: PluginOptions, dmmf: DMMF.Document) {
20-
let outDir = options.output as string;
21-
if (!outDir) {
22-
throw new PluginError('"output" option is required');
23-
}
24-
25-
if (!path.isAbsolute(outDir)) {
26-
// output dir is resolved relative to the schema file path
27-
outDir = path.join(path.dirname(options.schemaPath), outDir);
28-
}
27+
let outDir = requireOption<string>(options, 'output');
28+
outDir = resolvePath(outDir, options);
2929

3030
await fs.mkdir(outDir, { recursive: true });
3131
await removeDir(outDir, true);

packages/plugins/trpc/src/zod/generator.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ConnectorType, DMMF } from '@prisma/generator-helper';
22
import { Dictionary } from '@prisma/internals';
3-
import { PluginOptions, getLiteral } from '@zenstackhq/sdk';
3+
import { PluginOptions, getLiteral, resolvePath } from '@zenstackhq/sdk';
44
import { DataSource, Model, isDataSource } from '@zenstackhq/sdk/ast';
55
import {
66
AggregateOperationSupport,
@@ -14,7 +14,9 @@ import removeDir from './utils/removeDir';
1414
import { writeFileSafely } from './utils/writeFileSafely';
1515

1616
export async function generate(model: Model, options: PluginOptions, dmmf: DMMF.Document) {
17-
const output = (options.output as string) ?? './generated';
17+
let output = (options.output as string) ?? './generated';
18+
output = resolvePath(output, options);
19+
1820
await handleGeneratorOutputValue(output);
1921

2022
const prismaClientDmmf = dmmf;

0 commit comments

Comments
 (0)