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
}

packages/schema/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
"commander": "^8.3.0",
9595
"get-latest-version": "^5.0.1",
9696
"langium": "1.1.0",
97+
"lower-case-first": "^2.0.2",
9798
"mixpanel": "^0.17.0",
9899
"node-machine-id": "^1.1.12",
99100
"ora": "^5.4.1",
@@ -102,6 +103,7 @@
102103
"semver": "^7.3.8",
103104
"sleep-promise": "^9.1.0",
104105
"ts-morph": "^16.0.0",
106+
"upper-case-first": "^2.0.2",
105107
"uuid": "^9.0.0",
106108
"vscode-jsonrpc": "^8.0.2",
107109
"vscode-languageclient": "^8.0.2",
@@ -114,10 +116,12 @@
114116
"devDependencies": {
115117
"@types/async-exit-hook": "^2.0.0",
116118
"@types/jest": "^29.5.0",
119+
"@types/lower-case-first": "^1.0.1",
117120
"@types/node": "^14.18.32",
118121
"@types/pluralize": "^0.0.29",
119122
"@types/semver": "^7.3.13",
120123
"@types/tmp": "^0.2.3",
124+
"@types/upper-case-first": "^1.1.2",
121125
"@types/uuid": "^8.3.4",
122126
"@types/vscode": "^1.56.0",
123127
"@typescript-eslint/eslint-plugin": "^5.42.0",

packages/schema/src/plugins/access-policy/policy-guard-generator.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import {
2828
RUNTIME_PACKAGE,
2929
saveProject,
3030
} from '@zenstackhq/sdk';
31-
import { camelCase } from 'change-case';
31+
import { lowerCaseFirst } from 'lower-case-first';
3232
import { streamAllContents } from 'langium';
3333
import path from 'path';
3434
import { FunctionDeclaration, SourceFile, VariableDeclarationKind } from 'ts-morph';
@@ -90,7 +90,7 @@ export default class PolicyGenerator {
9090
writer.write('guard:');
9191
writer.inlineBlock(() => {
9292
for (const [model, map] of Object.entries(policyMap)) {
93-
writer.write(`${camelCase(model)}:`);
93+
writer.write(`${lowerCaseFirst(model)}:`);
9494
writer.inlineBlock(() => {
9595
for (const [op, func] of Object.entries(map)) {
9696
if (typeof func === 'object') {

packages/schema/src/plugins/access-policy/zod-schema-generator.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { DataModel, DataModelField, DataModelFieldAttribute, isDataModelField } from '@zenstackhq/language/ast';
22
import { AUXILIARY_FIELDS, VALIDATION_ATTRIBUTES, getLiteral } from '@zenstackhq/sdk';
3-
import { camelCase } from 'change-case';
3+
import { lowerCaseFirst } from 'lower-case-first';
44
import { CodeBlockWriter } from 'ts-morph';
55

66
/**
@@ -24,7 +24,7 @@ export class ZodSchemaGenerator {
2424
}
2525

2626
generated = true;
27-
writer.write(`${camelCase(model.name)}: z.object(`);
27+
writer.write(`${lowerCaseFirst(model.name)}: z.object(`);
2828
writer.inlineBlock(() => {
2929
fields.forEach((field) => {
3030
writer.writeLine(`${field.name}: ${this.makeFieldValidator(field)},`);

packages/schema/src/plugins/model-meta/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
resolved,
2020
saveProject,
2121
} from '@zenstackhq/sdk';
22-
import { camelCase } from 'change-case';
22+
import { lowerCaseFirst } from 'lower-case-first';
2323
import path from 'path';
2424
import { CodeBlockWriter, VariableDeclarationKind } from 'ts-morph';
2525
import { getIdFields } from '../../language-server/utils';
@@ -65,7 +65,7 @@ function generateModelMetadata(dataModels: DataModel[], writer: CodeBlockWriter)
6565
writer.write('fields:');
6666
writer.block(() => {
6767
for (const model of dataModels) {
68-
writer.write(`${camelCase(model.name)}:`);
68+
writer.write(`${lowerCaseFirst(model.name)}:`);
6969
writer.block(() => {
7070
for (const f of model.fields) {
7171
const backlink = getBackLink(f);
@@ -95,7 +95,7 @@ function generateModelMetadata(dataModels: DataModel[], writer: CodeBlockWriter)
9595
writer.write('uniqueConstraints:');
9696
writer.block(() => {
9797
for (const model of dataModels) {
98-
writer.write(`${camelCase(model.name)}:`);
98+
writer.write(`${lowerCaseFirst(model.name)}:`);
9999
writer.block(() => {
100100
for (const constraint of getUniqueConstraints(model)) {
101101
writer.write(`${constraint.name}: {

0 commit comments

Comments
 (0)