Skip to content

Commit b2e001c

Browse files
committed
fix: compatibility with Prisma's "omit" feature
1 parent 6a71742 commit b2e001c

File tree

19 files changed

+196
-62
lines changed

19 files changed

+196
-62
lines changed

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

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

3-
import { analyzePolicies, PluginError, requireOption, resolvePath } from '@zenstackhq/sdk';
3+
import { PluginError, analyzePolicies, requireOption, resolvePath, supportCreateMany } from '@zenstackhq/sdk';
44
import { DataModel, isDataModel } from '@zenstackhq/sdk/ast';
55
import {
6+
AggregateOperationSupport,
67
addMissingInputObjectTypesForAggregate,
78
addMissingInputObjectTypesForInclude,
89
addMissingInputObjectTypesForModelArgs,
910
addMissingInputObjectTypesForSelect,
10-
AggregateOperationSupport,
1111
resolveAggregateOperationSupport,
1212
} from '@zenstackhq/sdk/dmmf-helpers';
13-
import type { DMMF } from '@zenstackhq/sdk/prisma';
13+
import { type DMMF } from '@zenstackhq/sdk/prisma';
1414
import * as fs from 'fs';
1515
import { lowerCaseFirst } from 'lower-case-first';
1616
import type { OpenAPIV3_1 as OAPI } from 'openapi-types';
1717
import * as path from 'path';
1818
import invariant from 'tiny-invariant';
19-
import { match, P } from 'ts-pattern';
19+
import { P, match } from 'ts-pattern';
2020
import { upperCaseFirst } from 'upper-case-first';
2121
import YAML from 'yaml';
2222
import { name } from '.';
@@ -166,7 +166,7 @@ export class RPCOpenAPIGenerator extends OpenAPIGeneratorBase {
166166
});
167167
}
168168

169-
if (ops['createMany']) {
169+
if (ops['createMany'] && supportCreateMany(zmodel.$container)) {
170170
definitions.push({
171171
method: 'post',
172172
operation: 'createMany',
@@ -704,7 +704,7 @@ export class RPCOpenAPIGenerator extends OpenAPIGeneratorBase {
704704
private generateEnumComponent(_enum: DMMF.SchemaEnum): OAPI.SchemaObject {
705705
const schema: OAPI.SchemaObject = {
706706
type: 'string',
707-
enum: _enum.values,
707+
enum: _enum.values as string[],
708708
};
709709
return schema;
710710
}
@@ -793,17 +793,14 @@ export class RPCOpenAPIGenerator extends OpenAPIGeneratorBase {
793793
return result;
794794
}
795795

796-
private setInputRequired(fields: { name: string; isRequired: boolean }[], result: OAPI.NonArraySchemaObject) {
796+
private setInputRequired(fields: readonly DMMF.SchemaArg[], result: OAPI.NonArraySchemaObject) {
797797
const required = fields.filter((f) => f.isRequired).map((f) => f.name);
798798
if (required.length > 0) {
799799
result.required = required;
800800
}
801801
}
802802

803-
private setOutputRequired(
804-
fields: { name: string; isNullable?: boolean; outputType: DMMF.OutputTypeRef }[],
805-
result: OAPI.NonArraySchemaObject
806-
) {
803+
private setOutputRequired(fields: readonly DMMF.SchemaField[], result: OAPI.NonArraySchemaObject) {
807804
const required = fields.filter((f) => f.isNullable !== true).map((f) => f.name);
808805
if (required.length > 0) {
809806
result.required = required;

packages/plugins/swr/src/generator.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
requireOption,
99
resolvePath,
1010
saveProject,
11+
supportCreateMany,
1112
} from '@zenstackhq/sdk';
1213
import { DataModel, DataModelFieldType, Model, isEnum } from '@zenstackhq/sdk/ast';
1314
import { getPrismaClientImportSpec, type DMMF } from '@zenstackhq/sdk/prisma';
@@ -85,7 +86,7 @@ function generateModelHooks(
8586
}
8687

8788
// createMany
88-
if (mapping.createMany) {
89+
if (mapping.createMany && supportCreateMany(model.$container)) {
8990
const argsType = `Prisma.${model.name}CreateManyArgs`;
9091
mutationFuncs.push(generateMutation(sf, model, 'POST', 'createMany', argsType, true));
9192
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
requireOption,
1010
resolvePath,
1111
saveProject,
12+
supportCreateMany,
1213
} from '@zenstackhq/sdk';
1314
import { DataModel, DataModelFieldType, Model, isEnum } from '@zenstackhq/sdk/ast';
1415
import { getPrismaClientImportSpec, type DMMF } from '@zenstackhq/sdk/prisma';
@@ -348,7 +349,7 @@ function generateModelHooks(
348349
}
349350

350351
// createMany
351-
if (mapping.createMany) {
352+
if (mapping.createMany && supportCreateMany(model.$container)) {
352353
generateMutationHook(target, sf, model.name, 'createMany', 'post', false, 'Prisma.BatchPayload');
353354
}
354355

packages/plugins/trpc/src/generator.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
requireOption,
88
resolvePath,
99
saveProject,
10+
supportCreateMany,
1011
type PluginOptions,
1112
} from '@zenstackhq/sdk';
1213
import { Model } from '@zenstackhq/sdk/ast';
@@ -79,11 +80,11 @@ export async function generate(model: Model, options: PluginOptions, dmmf: DMMF.
7980

8081
function createAppRouter(
8182
outDir: string,
82-
modelOperations: DMMF.ModelMapping[],
83+
modelOperations: readonly DMMF.ModelMapping[],
8384
hiddenModels: string[],
8485
generateModelActions: string[] | undefined,
8586
generateClientHelpers: string[] | undefined,
86-
_zmodel: Model,
87+
zmodel: Model,
8788
zodSchemasImport: string,
8889
options: PluginOptions
8990
) {
@@ -171,7 +172,8 @@ function createAppRouter(
171172
generateModelActions,
172173
generateClientHelpers,
173174
zodSchemasImport,
174-
options
175+
options,
176+
zmodel
175177
);
176178

177179
appRouter.addImportDeclaration({
@@ -241,7 +243,8 @@ function generateModelCreateRouter(
241243
generateModelActions: string[] | undefined,
242244
generateClientHelpers: string[] | undefined,
243245
zodSchemasImport: string,
244-
options: PluginOptions
246+
options: PluginOptions,
247+
zmodel: Model
245248
) {
246249
const modelRouter = project.createSourceFile(path.resolve(outputDir, 'routers', `${model}.router.ts`), undefined, {
247250
overwrite: true,
@@ -298,6 +301,10 @@ function generateModelCreateRouter(
298301
inputType &&
299302
(!generateModelActions || generateModelActions.includes(generateOpName))
300303
) {
304+
if (generateOpName === 'createMany' && !supportCreateMany(zmodel)) {
305+
continue;
306+
}
307+
301308
generateProcedure(funcWriter, generateOpName, upperCaseFirst(inputType), model, baseOpType);
302309

303310
if (routerTypingStructure) {

packages/plugins/trpc/src/helpers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ export const getProcedureTypeByOpName = (opName: string) => {
327327
return procType;
328328
};
329329

330-
export function resolveModelsComments(models: DMMF.Model[], hiddenModels: string[]) {
330+
export function resolveModelsComments(models: readonly DMMF.Model[], hiddenModels: string[]) {
331331
const modelAttributeRegex = /(@@Gen\.)+([A-z])+(\()+(.+)+(\))+/;
332332
const attributeNameRegex = /(?:\.)+([A-Za-z])+(?:\()+/;
333333
const attributeArgsRegex = /(?:\()+([A-Za-z])+:+(.+)+(?:\))+/;

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,11 @@ export class PolicyUtil extends QueryUtils {
982982
}
983983

984984
private doInjectReadCheckSelect(model: string, args: any, input: any) {
985+
// omit should be ignored to avoid interfering with field selection
986+
if (args.omit) {
987+
delete args.omit;
988+
}
989+
985990
if (!input?.select) {
986991
return;
987992
}
@@ -1178,6 +1183,12 @@ export class PolicyUtil extends QueryUtils {
11781183
continue;
11791184
}
11801185

1186+
if (queryArgs?.omit?.[field] === true) {
1187+
// respect `{ omit: { [field]: true } }`
1188+
delete entityData[field];
1189+
continue;
1190+
}
1191+
11811192
if (hasFieldLevelPolicy) {
11821193
// 1. remove fields selected for checking field-level policies but not selected by the original query args
11831194
// 2. evaluate field-level policies and remove fields that are not readable

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export class EnhancerGenerator {
5656
private readonly outDir: string
5757
) {}
5858

59-
async generate() {
59+
async generate(): Promise<{ dmmf: DMMF.Document | undefined }> {
6060
let logicalPrismaClientDir: string | undefined;
6161
let dmmf: DMMF.Document | undefined;
6262

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ export class ZodSchemaGenerator {
107107
project: this.project,
108108
inputObjectTypes,
109109
});
110-
await transformer.generateInputSchemas(this.options);
110+
await transformer.generateInputSchemas(this.options, this.model);
111111
this.sourceFiles.push(...transformer.sourceFiles);
112112
}
113113

@@ -189,7 +189,10 @@ export class ZodSchemaGenerator {
189189
);
190190
}
191191

192-
private async generateEnumSchemas(prismaSchemaEnum: DMMF.SchemaEnum[], modelSchemaEnum: DMMF.SchemaEnum[]) {
192+
private async generateEnumSchemas(
193+
prismaSchemaEnum: readonly DMMF.SchemaEnum[],
194+
modelSchemaEnum: readonly DMMF.SchemaEnum[]
195+
) {
193196
const enumTypes = [...prismaSchemaEnum, ...modelSchemaEnum];
194197
const enumNames = enumTypes.map((enumItem) => upperCaseFirst(enumItem.name));
195198
Transformer.enumNames = enumNames ?? [];

packages/schema/src/plugins/zod/transformer.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/* eslint-disable @typescript-eslint/ban-ts-comment */
2-
import { indentString, type PluginOptions } from '@zenstackhq/sdk';
2+
import { indentString, supportCreateMany, type PluginOptions } from '@zenstackhq/sdk';
3+
import type { Model } from '@zenstackhq/sdk/ast';
34
import { checkModelHasModelRelation, findModelByName, isAggregateInputType } from '@zenstackhq/sdk/dmmf-helpers';
45
import { type DMMF as PrismaDMMF } from '@zenstackhq/sdk/prisma';
56
import path from 'path';
@@ -11,12 +12,12 @@ import { AggregateOperationSupport, TransformerParams } from './types';
1112
export default class Transformer {
1213
name: string;
1314
originalName: string;
14-
fields: PrismaDMMF.SchemaArg[];
15+
fields: readonly PrismaDMMF.SchemaArg[];
1516
schemaImports = new Set<string>();
16-
models: PrismaDMMF.Model[];
17+
models: readonly PrismaDMMF.Model[];
1718
modelOperations: PrismaDMMF.ModelMapping[];
1819
aggregateOperationSupport: AggregateOperationSupport;
19-
enumTypes: PrismaDMMF.SchemaEnum[];
20+
enumTypes: readonly PrismaDMMF.SchemaEnum[];
2021

2122
static enumNames: string[] = [];
2223
static rawOpsMap: { [name: string]: string } = {};
@@ -389,7 +390,7 @@ export const ${this.name}ObjectSchema: SchemaType = ${schema} as SchemaType;`;
389390
return wrapped;
390391
}
391392

392-
async generateInputSchemas(options: PluginOptions) {
393+
async generateInputSchemas(options: PluginOptions, zmodel: Model) {
393394
const globalExports: string[] = [];
394395

395396
// whether Prisma's Unchecked* series of input types should be generated
@@ -489,7 +490,7 @@ export const ${this.name}ObjectSchema: SchemaType = ${schema} as SchemaType;`;
489490
operations.push(['create', origModelName]);
490491
}
491492

492-
if (createMany) {
493+
if (createMany && supportCreateMany(zmodel)) {
493494
imports.push(
494495
`import { ${modelName}CreateManyInputObjectSchema } from '../objects/${modelName}CreateManyInput.schema'`
495496
);

packages/schema/src/plugins/zod/types.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ import type { DMMF as PrismaDMMF } from '@zenstackhq/sdk/prisma';
22
import { Project } from 'ts-morph';
33

44
export type TransformerParams = {
5-
enumTypes?: PrismaDMMF.SchemaEnum[];
6-
fields?: PrismaDMMF.SchemaArg[];
5+
enumTypes?: readonly PrismaDMMF.SchemaEnum[];
6+
fields?: readonly PrismaDMMF.SchemaArg[];
77
name?: string;
8-
models?: PrismaDMMF.Model[];
8+
models?: readonly PrismaDMMF.Model[];
99
modelOperations?: PrismaDMMF.ModelMapping[];
1010
aggregateOperationSupport?: AggregateOperationSupport;
1111
isDefaultPrismaClientOutput?: boolean;

0 commit comments

Comments
 (0)