Skip to content

Commit d6fba93

Browse files
authored
fix: zod plugin issue with lower-case model names (#396)
1 parent 9a18af6 commit d6fba93

File tree

19 files changed

+155
-59
lines changed

19 files changed

+155
-59
lines changed

packages/plugins/openapi/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"@zenstackhq/runtime": "workspace:*",
2929
"@zenstackhq/sdk": "workspace:*",
3030
"change-case": "^4.1.2",
31+
"lower-case-first": "^2.0.2",
3132
"openapi-types": "^12.1.0",
3233
"tiny-invariant": "^1.3.1",
3334
"yaml": "^2.2.1",
@@ -38,6 +39,7 @@
3839
"@prisma/internals": "^4.7.1",
3940
"@readme/openapi-parser": "^2.4.0",
4041
"@types/jest": "^29.5.0",
42+
"@types/lower-case-first": "^1.0.1",
4143
"@types/tmp": "^0.2.3",
4244
"@typescript-eslint/eslint-plugin": "^5.54.0",
4345
"@typescript-eslint/parser": "^5.54.0",

packages/plugins/openapi/src/generator.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
AggregateOperationSupport,
1919
resolveAggregateOperationSupport,
2020
} from '@zenstackhq/sdk/dmmf-helpers';
21-
import { camelCase } from 'change-case';
21+
import { lowerCaseFirst } from 'lower-case-first';
2222
import * as fs from 'fs';
2323
import type { OpenAPIV3_1 as OAPI } from 'openapi-types';
2424
import * as path from 'path';
@@ -84,7 +84,7 @@ export class OpenAPIGenerator {
8484
tags: this.includedModels.map((model) => {
8585
const meta = getModelResourceMeta(model);
8686
return {
87-
name: camelCase(model.name),
87+
name: lowerCaseFirst(model.name),
8888
description: meta?.tagDescription ?? `${model.name} operations`,
8989
};
9090
}),
@@ -533,7 +533,7 @@ export class OpenAPIGenerator {
533533
const def: OAPI.OperationObject = {
534534
operationId: `${operation}${model.name}`,
535535
description: meta?.description ?? description,
536-
tags: meta?.tags || [camelCase(model.name)],
536+
tags: meta?.tags || [lowerCaseFirst(model.name)],
537537
summary: meta?.summary,
538538
// security priority: operation-level > model-level > inferred
539539
security: meta?.security ?? resourceMeta?.security ?? security,
@@ -581,7 +581,7 @@ export class OpenAPIGenerator {
581581
}
582582
}
583583

584-
result[`${prefix}/${camelCase(model.name)}/${resolvedPath}`] = {
584+
result[`${prefix}/${lowerCaseFirst(model.name)}/${resolvedPath}`] = {
585585
[resolvedMethod]: def,
586586
};
587587
}

packages/plugins/react/package.json

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,26 +28,30 @@
2828
"@zenstackhq/sdk": "workspace:*",
2929
"change-case": "^4.1.2",
3030
"decimal.js": "^10.4.2",
31+
"lower-case-first": "^2.0.2",
3132
"superjson": "^1.11.0",
32-
"ts-morph": "^16.0.0"
33+
"ts-morph": "^16.0.0",
34+
"upper-case-first": "^2.0.2"
3335
},
3436
"peerDependencies": {
37+
"@tanstack/react-query": "4.x",
3538
"react": "^17.0.2 || ^18",
3639
"react-dom": "^17.0.2 || ^18",
37-
"swr": "2.x",
38-
"@tanstack/react-query": "4.x"
40+
"swr": "2.x"
3941
},
4042
"devDependencies": {
4143
"@tanstack/react-query": "^4.28.0",
4244
"@types/jest": "^29.5.0",
45+
"@types/lower-case-first": "^1.0.1",
4346
"@types/react": "^18.0.26",
4447
"@types/tmp": "^0.2.3",
48+
"@types/upper-case-first": "^1.1.2",
4549
"@zenstackhq/testtools": "workspace:*",
4650
"copyfiles": "^2.4.1",
4751
"jest": "^29.5.0",
48-
"rimraf": "^3.0.2",
4952
"react": "^17.0.2 || ^18",
5053
"react-dom": "^17.0.2 || ^18",
54+
"rimraf": "^3.0.2",
5155
"swr": "^2.0.3",
5256
"ts-jest": "^29.0.5",
5357
"typescript": "^4.9.4"

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

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { DMMF } from '@prisma/generator-helper';
22
import { PluginError, PluginOptions, createProject, getDataModels, saveProject } from '@zenstackhq/sdk';
33
import { DataModel, Model } from '@zenstackhq/sdk/ast';
4-
import { camelCase, paramCase, pascalCase } from 'change-case';
4+
import { paramCase } from 'change-case';
5+
import { lowerCaseFirst } from 'lower-case-first';
56
import * as path from 'path';
67
import { Project, SourceFile, VariableDeclarationKind } from 'ts-morph';
8+
import { upperCaseFirst } from 'upper-case-first';
79

810
export async function generate(model: Model, options: PluginOptions, dmmf: DMMF.Document) {
911
let outDir = options.output as string;
@@ -45,7 +47,7 @@ function generateQueryHook(
4547
overrideInputType?: string,
4648
overrideTypeParameters?: string[]
4749
) {
48-
const capOperation = pascalCase(operation);
50+
const capOperation = upperCaseFirst(operation);
4951

5052
const argsType = overrideInputType ?? `Prisma.${model}${capOperation}Args`;
5153
const inputType = `Prisma.SelectSubset<T, ${argsType}>`;
@@ -71,7 +73,7 @@ function generateQueryHook(
7173

7274
func.addStatements([
7375
'const { endpoint } = useContext(RequestHandlerContext);',
74-
`return request.query<${returnType}>('${model}', \`\${endpoint}/${camelCase(
76+
`return request.query<${returnType}>('${model}', \`\${endpoint}/${lowerCaseFirst(
7577
model
7678
)}/${operation}\`, args, options);`,
7779
]);
@@ -84,7 +86,7 @@ function generateMutationHook(
8486
httpVerb: 'post' | 'put' | 'delete',
8587
overrideReturnType?: string
8688
) {
87-
const capOperation = pascalCase(operation);
89+
const capOperation = upperCaseFirst(operation);
8890

8991
const argsType = `Prisma.${model}${capOperation}Args`;
9092
const inputType = `Prisma.SelectSubset<T, ${argsType}>`;
@@ -119,7 +121,7 @@ function generateMutationHook(
119121
initializer: `
120122
request.${httpVerb}Mutation<${argsType}, ${
121123
overrideReturnType ?? model
122-
}>('${model}', \`\${endpoint}/${camelCase(model)}/${operation}\`, options, invalidateQueries)
124+
}>('${model}', \`\${endpoint}/${lowerCaseFirst(model)}/${operation}\`, options, invalidateQueries)
123125
`,
124126
},
125127
],

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import {
88
saveProject,
99
} from '@zenstackhq/sdk';
1010
import { DataModel, Model } from '@zenstackhq/sdk/ast';
11-
import { camelCase, paramCase } from 'change-case';
11+
import { paramCase } from 'change-case';
12+
import { lowerCaseFirst } from 'lower-case-first';
1213
import * as path from 'path';
1314
import { Project } from 'ts-morph';
1415

@@ -79,7 +80,7 @@ function generateModelHooks(project: Project, outDir: string, model: DataModel,
7980
});
8081

8182
const prefixesToMutate = ['find', 'aggregate', 'count', 'groupBy'];
82-
const modelRouteName = camelCase(model.name);
83+
const modelRouteName = lowerCaseFirst(model.name);
8384

8485
useFunc.addStatements([
8586
'const { endpoint } = useContext(RequestHandlerContext);',

packages/plugins/trpc/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,15 @@
2828
"@prisma/internals": "^4.7.1",
2929
"@zenstackhq/sdk": "workspace:*",
3030
"change-case": "^4.1.2",
31+
"lower-case-first": "^2.0.2",
3132
"prettier": "^2.8.3",
3233
"ts-morph": "^16.0.0",
3334
"tslib": "^2.4.1",
3435
"zod": "3.21.1"
3536
},
3637
"devDependencies": {
3738
"@types/jest": "^29.5.0",
39+
"@types/lower-case-first": "^1.0.1",
3840
"@types/prettier": "^2.7.2",
3941
"@zenstackhq/testtools": "workspace:*",
4042
"copyfiles": "^2.4.1",

packages/plugins/trpc/src/generator.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { DMMF } from '@prisma/generator-helper';
22
import { CrudFailureReason, PluginError, PluginOptions, RUNTIME_PACKAGE, saveProject } from '@zenstackhq/sdk';
33
import { Model } from '@zenstackhq/sdk/ast';
4-
import { camelCase } from 'change-case';
4+
import { lowerCaseFirst } from 'lower-case-first';
55
import { promises as fs } from 'fs';
66
import path from 'path';
77
import { Project } from 'ts-morph';
@@ -116,7 +116,7 @@ function createAppRouter(outDir: string, modelOperations: DMMF.ModelMapping[], h
116116
moduleSpecifier: `./${model}.router`,
117117
});
118118

119-
writer.writeLine(`${camelCase(model)}: create${model}Router<Config>(router, procedure),`);
119+
writer.writeLine(`${lowerCaseFirst(model)}: create${model}Router<Config>(router, procedure),`);
120120
}
121121
});
122122
writer.write(');');

packages/runtime/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"colors": "1.4.0",
2929
"decimal.js": "^10.4.2",
3030
"deepcopy": "^2.1.0",
31+
"lower-case-first": "^2.0.2",
3132
"pluralize": "^8.0.0",
3233
"superjson": "^1.11.0",
3334
"tslib": "^2.4.1",
@@ -45,6 +46,7 @@
4546
"devDependencies": {
4647
"@types/bcryptjs": "^2.4.2",
4748
"@types/jest": "^29.5.0",
49+
"@types/lower-case-first": "^1.0.1",
4850
"@types/node": "^14.18.29",
4951
"@types/pluralize": "^0.0.29",
5052
"copyfiles": "^2.4.1",

packages/runtime/src/enhancements/model-meta.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { camelCase } from 'change-case';
1+
import { lowerCaseFirst } from 'lower-case-first';
22
import { ModelMeta } from './types';
33

44
/**
@@ -17,5 +17,5 @@ export function getDefaultModelMeta(): ModelMeta {
1717
* Resolves a model field to its metadata. Returns undefined if not found.
1818
*/
1919
export function resolveField(modelMeta: ModelMeta, model: string, field: string) {
20-
return modelMeta.fields[camelCase(model)][field];
20+
return modelMeta.fields[lowerCaseFirst(model)][field];
2121
}

packages/runtime/src/enhancements/policy/policy-utils.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { createId } from '@paralleldrive/cuid2';
44
import { PrismaClientKnownRequestError, PrismaClientUnknownRequestError } from '@prisma/client/runtime';
55
import { AUXILIARY_FIELDS, CrudFailureReason, GUARD_FIELD_NAME, TRANSACTION_FIELD_NAME } from '@zenstackhq/sdk';
6-
import { camelCase } from 'change-case';
6+
import { lowerCaseFirst } from 'lower-case-first';
77
import deepcopy from 'deepcopy';
88
import pluralize from 'pluralize';
99
import { fromZodError } from 'zod-validation-error';
@@ -97,7 +97,7 @@ export class PolicyUtil {
9797
* otherwise returns a guard object
9898
*/
9999
async getAuthGuard(model: string, operation: PolicyOperationKind, preValue?: any): Promise<boolean | object> {
100-
const guard = this.policy.guard[camelCase(model)];
100+
const guard = this.policy.guard[lowerCaseFirst(model)];
101101
if (!guard) {
102102
throw this.unknownError(`unable to load policy guard for ${model}`);
103103
}
@@ -114,15 +114,15 @@ export class PolicyUtil {
114114
}
115115

116116
private async getPreValueSelect(model: string): Promise<object | undefined> {
117-
const guard = this.policy.guard[camelCase(model)];
117+
const guard = this.policy.guard[lowerCaseFirst(model)];
118118
if (!guard) {
119119
throw this.unknownError(`unable to load policy guard for ${model}`);
120120
}
121121
return guard.preValueSelect;
122122
}
123123

124124
private async getModelSchema(model: string) {
125-
return this.policy.schema[camelCase(model)];
125+
return this.policy.schema[lowerCaseFirst(model)];
126126
}
127127

128128
/**
@@ -255,7 +255,7 @@ export class PolicyUtil {
255255
// flatten unique constraint filters
256256
async flattenGeneratedUniqueField(model: string, args: any) {
257257
// e.g.: { a_b: { a: '1', b: '1' } } => { a: '1', b: '1' }
258-
const uniqueConstraints = this.modelMeta.uniqueConstraints?.[camelCase(model)];
258+
const uniqueConstraints = this.modelMeta.uniqueConstraints?.[lowerCaseFirst(model)];
259259
let flattened = false;
260260
if (uniqueConstraints) {
261261
for (const [field, value] of Object.entries<any>(args)) {
@@ -856,7 +856,7 @@ export class PolicyUtil {
856856
* Gets "id" field for a given model.
857857
*/
858858
getIdFields(model: string) {
859-
const fields = this.modelMeta.fields[camelCase(model)];
859+
const fields = this.modelMeta.fields[lowerCaseFirst(model)];
860860
if (!fields) {
861861
throw this.unknownError(`Unable to load fields for ${model}`);
862862
}

0 commit comments

Comments
 (0)