Skip to content

Commit 8693852

Browse files
authored
feat: trpc plugin, add "generateModelActions" option to control what operations to generate (#482)
1 parent 21affec commit 8693852

File tree

4 files changed

+102
-15
lines changed

4 files changed

+102
-15
lines changed

packages/plugins/trpc/src/config.ts

Lines changed: 0 additions & 7 deletions
This file was deleted.

packages/plugins/trpc/src/generator.ts

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { DMMF } from '@prisma/generator-helper';
22
import {
33
CrudFailureReason,
4+
PluginError,
45
PluginOptions,
56
RUNTIME_PACKAGE,
67
requireOption,
@@ -12,6 +13,7 @@ import { promises as fs } from 'fs';
1213
import { lowerCaseFirst } from 'lower-case-first';
1314
import path from 'path';
1415
import { Project } from 'ts-morph';
16+
import { name } from '.';
1517
import {
1618
generateHelperImport,
1719
generateProcedure,
@@ -27,6 +29,29 @@ export async function generate(model: Model, options: PluginOptions, dmmf: DMMF.
2729
let outDir = requireOption<string>(options, 'output');
2830
outDir = resolvePath(outDir, options);
2931

32+
// resolve "generateModelActions" option
33+
let generateModelActions: string[] | undefined = undefined;
34+
if (options.generateModelActions) {
35+
if (typeof options.generateModelActions === 'string') {
36+
// comma separated string
37+
generateModelActions = options.generateModelActions
38+
.split(',')
39+
.filter((i) => !!i)
40+
.map((i) => i.trim());
41+
} else if (
42+
Array.isArray(options.generateModelActions) &&
43+
options.generateModelActions.every((i) => typeof i === 'string')
44+
) {
45+
// string array
46+
generateModelActions = options.generateModelActions as string[];
47+
} else {
48+
throw new PluginError(
49+
name,
50+
`Invalid "generateModelActions" option: must be a comma-separated string or an array of strings`
51+
);
52+
}
53+
}
54+
3055
await fs.mkdir(outDir, { recursive: true });
3156
await removeDir(outDir, true);
3257

@@ -39,13 +64,18 @@ export async function generate(model: Model, options: PluginOptions, dmmf: DMMF.
3964
const hiddenModels: string[] = [];
4065
resolveModelsComments(models, hiddenModels);
4166

42-
createAppRouter(outDir, modelOperations, hiddenModels);
67+
createAppRouter(outDir, modelOperations, hiddenModels, generateModelActions);
4368
createHelper(outDir);
4469

4570
await saveProject(project);
4671
}
4772

48-
function createAppRouter(outDir: string, modelOperations: DMMF.ModelMapping[], hiddenModels: string[]) {
73+
function createAppRouter(
74+
outDir: string,
75+
modelOperations: DMMF.ModelMapping[],
76+
hiddenModels: string[],
77+
generateModelActions: string[] | undefined
78+
) {
4979
const appRouter = project.createSourceFile(path.resolve(outDir, 'routers', `index.ts`), undefined, {
5080
overwrite: true,
5181
});
@@ -109,7 +139,10 @@ function createAppRouter(outDir: string, modelOperations: DMMF.ModelMapping[], h
109139
continue;
110140
}
111141

112-
generateModelCreateRouter(project, model, operations, outDir);
142+
// somehow dmmf doesn't contain "count" operation, we need to add it here
143+
operations.count = 'count';
144+
145+
generateModelCreateRouter(project, model, operations, outDir, generateModelActions);
113146

114147
appRouter.addImportDeclaration({
115148
defaultImport: `create${model}Router`,
@@ -129,7 +162,8 @@ function generateModelCreateRouter(
129162
project: Project,
130163
model: string,
131164
operations: Record<string, string | undefined | null>,
132-
outputDir: string
165+
outputDir: string,
166+
generateModelActions: string[] | undefined
133167
) {
134168
const modelRouter = project.createSourceFile(path.resolve(outputDir, 'routers', `${model}.router.ts`), undefined, {
135169
overwrite: true,
@@ -162,11 +196,15 @@ function generateModelCreateRouter(
162196
writer.block(() => {
163197
for (const [opType, opNameWithModel] of Object.entries(operations)) {
164198
const baseOpType = opType.replace('OrThrow', '');
165-
166199
const inputType = getInputTypeByOpName(baseOpType, model);
167-
168-
if (opNameWithModel && inputType) {
169-
generateProcedure(writer, opType.replace(/One$/, ''), inputType, model, baseOpType);
200+
const generateOpName = opType.replace(/One$/, '');
201+
202+
if (
203+
opNameWithModel &&
204+
inputType &&
205+
(!generateModelActions || generateModelActions.includes(generateOpName))
206+
) {
207+
generateProcedure(writer, generateOpName, inputType, model, baseOpType);
170208
}
171209
}
172210
});

packages/plugins/trpc/src/types.ts

Whitespace-only changes.

packages/plugins/trpc/tests/trpc.test.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,4 +124,60 @@ model Post {
124124
);
125125
expect(fs.existsSync(path.join(projectDir, 'zenstack/trpc'))).toBe(true);
126126
});
127+
128+
it('generateModelActions option string', async () => {
129+
const { projectDir } = await loadSchema(
130+
`
131+
plugin trpc {
132+
provider = '${process.cwd()}/dist'
133+
output = './trpc'
134+
generateModelActions = 'findMany,findUnique,update'
135+
}
136+
137+
model Post {
138+
id String @id
139+
title String
140+
}
141+
`,
142+
true,
143+
false,
144+
[`${origDir}/dist`, '@trpc/client', '@trpc/server'],
145+
true,
146+
'zenstack/schema.zmodel'
147+
);
148+
const content = fs.readFileSync(path.join(projectDir, 'zenstack/trpc/routers/Post.router.ts'), 'utf-8');
149+
expect(content).toContain('findMany:');
150+
expect(content).toContain('findUnique:');
151+
expect(content).toContain('update:');
152+
expect(content).not.toContain('create:');
153+
expect(content).not.toContain('aggregate:');
154+
});
155+
156+
it('generateModelActions option array', async () => {
157+
const { projectDir } = await loadSchema(
158+
`
159+
plugin trpc {
160+
provider = '${process.cwd()}/dist'
161+
output = './trpc'
162+
generateModelActions = ['findMany', 'findUnique', 'update']
163+
}
164+
165+
model Post {
166+
id String @id
167+
title String
168+
}
169+
`,
170+
true,
171+
false,
172+
[`${origDir}/dist`, '@trpc/client', '@trpc/server'],
173+
true,
174+
'zenstack/schema.zmodel'
175+
);
176+
const content = fs.readFileSync(path.join(projectDir, 'zenstack/trpc/routers/Post.router.ts'), 'utf-8');
177+
expect(content).toContain('findMany:');
178+
expect(content).toContain('findUnique:');
179+
expect(content).toContain('update:');
180+
expect(content).not.toContain('create:');
181+
expect(content).not.toContain('aggregate:');
182+
});
127183
});

0 commit comments

Comments
 (0)