prisma-generator-express 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # Prisma Generator Express
2
2
 
3
- [![npm version](https://badge.fury.io/js/prisma-generator-express.svg)](https://badge.fury.io/js/prisma-generator-express)
3
+ [![npm version](https://img.shields.io/npm/v/prisma-generator-express.svg)](https://www.npmjs.com/package/prisma-generator-express)
4
4
  [![npm](https://img.shields.io/npm/dt/prisma-generator-express.svg)](https://www.npmjs.com/package/prisma-generator-express)
5
+ [![npm](https://img.shields.io/npm/types/prisma-generator-express)](https://www.npmjs.com/package/prisma-generator-express)
5
6
  [![HitCount](https://hits.dwyl.com/multipliedtwice/prisma-generator-express.svg?style=flat)](http://hits.dwyl.com/multipliedtwice/prisma-generator-express)
6
7
  [![npm](https://img.shields.io/npm/l/prisma-generator-express.svg)](LICENSE)
7
8
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "prisma-generator-express",
3
3
  "description": "Prisma generator of Express CRUD API",
4
- "version": "1.1.0",
4
+ "version": "1.2.0",
5
5
  "main": "dist/generator.js",
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -15,7 +15,8 @@
15
15
  "dev": "npx tsc -w",
16
16
  "build": "npx tsc",
17
17
  "prepack": "yarn build",
18
- "test": "jest"
18
+ "test": "jest",
19
+ "prepublishOnly": "node copy.js "
19
20
  },
20
21
  "dependencies": {
21
22
  "@prisma/client": "5.14.0",
@@ -36,12 +37,13 @@
36
37
  "prisma": "5.14.0",
37
38
  "semantic-release": "^23.1.1",
38
39
  "ts-jest": "29.1.2",
40
+ "shx": "^0.3.4",
39
41
  "typescript": "5.4.5"
40
42
  },
41
43
  "homepage": "https://github.com/multipliedtwice/prisma-generator-express/blob/master/README.md",
42
44
  "repository": {
43
45
  "type": "git",
44
- "url": "https://github.com/multipliedtwice/prisma-generator-express"
46
+ "url": "git+https://github.com/multipliedtwice/prisma-generator-express.git"
45
47
  },
46
48
  "author": "multipliedtwice",
47
49
  "keywords": [
@@ -50,6 +52,12 @@
50
52
  "crud",
51
53
  "generator"
52
54
  ],
55
+ "files": [
56
+ "dist/**/*",
57
+ "src/**/*",
58
+ "../../README.md",
59
+ "../../LICENSE"
60
+ ],
53
61
  "release": {
54
62
  "branches": [
55
63
  "master"
package/src/bin.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import './generator'
@@ -0,0 +1 @@
1
+ export const GENERATOR_NAME = 'prisma-generator-express'
@@ -0,0 +1,174 @@
1
+ import { generatorHandler, GeneratorOptions } from '@prisma/generator-helper'
2
+ import { logger } from '@prisma/sdk'
3
+ import { GENERATOR_NAME } from './constants'
4
+ import { writeFileSafely } from './utils/writeFileSafely'
5
+ import { generateFindUniqueFunction } from './helpers/generateFindUnique'
6
+ import { generateImportPrismaStatement } from './helpers/generateImportPrismaStatement'
7
+ import { generateFindManyFunction } from './helpers/generateFindMany'
8
+ import { generateFindFirstFunction } from './helpers/generateFindFirst'
9
+ import { generateCreateFunction } from './helpers/generateCreate'
10
+ import { generateRouterFunction } from './helpers/generateRouteFile'
11
+ import { generateCreateManyFunction } from './helpers/generateCreateMany'
12
+ import { generateUpdateFunction } from './helpers/generateUpdate'
13
+ import { generateUpdateManyFunction } from './helpers/generateUpdateMany'
14
+ import { generateUpsertFunction } from './helpers/generateUpsert'
15
+ import { generateDeleteFunction } from './helpers/generateDelete'
16
+ import { generateDeleteManyFunction } from './helpers/generateDeleteMany'
17
+ import { generateAggregateFunction } from './helpers/generateAggregate'
18
+ import { generateCountFunction } from './helpers/generateCount'
19
+ import { generateGroupByFunction } from './helpers/generateGroupBy'
20
+
21
+ const { version } = require('../package.json')
22
+
23
+ generatorHandler({
24
+ onManifest() {
25
+ logger.info(`${GENERATOR_NAME}:Registered`)
26
+ return {
27
+ version,
28
+ defaultOutput: '../generated',
29
+ prettyName: GENERATOR_NAME,
30
+ }
31
+ },
32
+ onGenerate: async (options: GeneratorOptions) => {
33
+ const prismaImportStatement = generateImportPrismaStatement(options)
34
+
35
+ options.dmmf.datamodel.models.forEach(async (model) => {
36
+ await writeFileSafely({
37
+ content: generateFindUniqueFunction({
38
+ model,
39
+ prismaImportStatement,
40
+ }),
41
+ options,
42
+ model,
43
+ operation: 'FindUnique',
44
+ })
45
+
46
+ await writeFileSafely({
47
+ content: generateFindFirstFunction({
48
+ model,
49
+ prismaImportStatement,
50
+ }),
51
+ options,
52
+ model,
53
+ operation: 'FindFirst',
54
+ })
55
+
56
+ await writeFileSafely({
57
+ content: generateFindManyFunction({
58
+ model,
59
+ prismaImportStatement,
60
+ }),
61
+ options,
62
+ model,
63
+ operation: 'FindMany',
64
+ })
65
+
66
+ await writeFileSafely({
67
+ content: generateCreateFunction({
68
+ model,
69
+ prismaImportStatement,
70
+ }),
71
+ options,
72
+ model,
73
+ operation: 'Create',
74
+ })
75
+
76
+ await writeFileSafely({
77
+ content: generateCreateManyFunction({
78
+ model,
79
+ prismaImportStatement,
80
+ }),
81
+ options,
82
+ model,
83
+ operation: 'CreateMany',
84
+ })
85
+
86
+ await writeFileSafely({
87
+ content: generateUpdateFunction({
88
+ model,
89
+ prismaImportStatement,
90
+ }),
91
+ options,
92
+ model,
93
+ operation: 'Update',
94
+ })
95
+
96
+ await writeFileSafely({
97
+ content: generateUpdateManyFunction({
98
+ model,
99
+ prismaImportStatement,
100
+ }),
101
+ options,
102
+ model,
103
+ operation: 'UpdateMany',
104
+ })
105
+
106
+ await writeFileSafely({
107
+ content: generateUpsertFunction({
108
+ model,
109
+ prismaImportStatement,
110
+ }),
111
+ options,
112
+ model,
113
+ operation: 'Upsert',
114
+ })
115
+
116
+ await writeFileSafely({
117
+ content: generateDeleteFunction({
118
+ model,
119
+ prismaImportStatement,
120
+ }),
121
+ options,
122
+ model,
123
+ operation: 'Delete',
124
+ })
125
+
126
+ await writeFileSafely({
127
+ content: generateDeleteManyFunction({
128
+ model,
129
+ prismaImportStatement,
130
+ }),
131
+ options,
132
+ model,
133
+ operation: 'DeleteMany',
134
+ })
135
+
136
+ await writeFileSafely({
137
+ content: generateAggregateFunction({
138
+ model,
139
+ prismaImportStatement,
140
+ }),
141
+ options,
142
+ model,
143
+ operation: 'Aggregate',
144
+ })
145
+
146
+ await writeFileSafely({
147
+ content: generateCountFunction({
148
+ model,
149
+ prismaImportStatement,
150
+ }),
151
+ options,
152
+ model,
153
+ operation: 'Count',
154
+ })
155
+
156
+ await writeFileSafely({
157
+ content: generateGroupByFunction({
158
+ model,
159
+ prismaImportStatement,
160
+ }),
161
+ options,
162
+ model,
163
+ operation: 'GroupBy',
164
+ })
165
+
166
+ await writeFileSafely({
167
+ content: generateRouterFunction({ model }),
168
+ options,
169
+ model,
170
+ operation: 'index',
171
+ })
172
+ })
173
+ },
174
+ })
@@ -0,0 +1,58 @@
1
+ import { DMMF } from '@prisma/generator-helper'
2
+
3
+ /**
4
+ * Generates an Express middleware function that handles aggregation queries
5
+ * and includes conditional output validation with Zod.
6
+ * This version dynamically includes the correct type for the arguments based on the Prisma model.
7
+ * @param options - The options containing the model name and the import statement for Prisma types.
8
+ * @returns {string} - The generated middleware function as a string.
9
+ */
10
+ export const generateAggregateFunction = (options: {
11
+ model: DMMF.Model
12
+ prismaImportStatement: string
13
+ }): string => {
14
+ const { model, prismaImportStatement } = options
15
+ const modelName = model.name
16
+ const functionName = `${modelName}Aggregate`
17
+ const argsTypeName = `Prisma.${modelName}AggregateArgs`
18
+
19
+ return `
20
+ ${prismaImportStatement}
21
+ import { Request, Response, NextFunction } from 'express';
22
+ import { RequestHandler, ParamsDictionary } from 'express-serve-static-core'
23
+ import { ZodTypeAny } from 'zod';
24
+
25
+ interface AggregateRequest extends Request {
26
+ prisma: PrismaClient;
27
+ body: ${argsTypeName};
28
+ outputValidation?: ZodTypeAny;
29
+ omitOutputValidation?: boolean;
30
+ }
31
+
32
+ export type AggregateMiddleware = RequestHandler<ParamsDictionary, any, ${argsTypeName}, Record<string, any>>;
33
+
34
+ export async function ${functionName}(req: AggregateRequest, res: Response, next: NextFunction) {
35
+ try {
36
+ if (!req.outputValidation && !req.omitOutputValidation) {
37
+ throw new Error('Output validation schema or omission flag must be provided.');
38
+ }
39
+
40
+ const result = await req.prisma.${modelName.toLowerCase()}.aggregate(req.body);
41
+
42
+ if (!req.omitOutputValidation && req.outputValidation) {
43
+ const validationResult = req.outputValidation.safeParse(result);
44
+ if (validationResult.success) {
45
+ res.status(200).json(validationResult.data);
46
+ } else {
47
+ res.status(400).json({ error: 'Invalid data format', details: validationResult.error });
48
+ }
49
+ } else {
50
+ res.status(200).json(result);
51
+ }
52
+ } catch (error) {
53
+ console.error('Error in handling aggregation request:', error);
54
+ res.status(500).json({ error: error.message });
55
+ next(error);
56
+ }
57
+ }`
58
+ }
@@ -0,0 +1,58 @@
1
+ import { DMMF } from '@prisma/generator-helper'
2
+
3
+ /**
4
+ * Generates an Express middleware function that handles count queries
5
+ * and includes conditional output validation with Zod.
6
+ * This version dynamically includes the correct type for the arguments based on the Prisma model.
7
+ * @param options - The options containing the model name and the import statement for Prisma types.
8
+ * @returns {string} - The generated middleware function as a string.
9
+ */
10
+ export const generateCountFunction = (options: {
11
+ model: DMMF.Model
12
+ prismaImportStatement: string
13
+ }): string => {
14
+ const { model, prismaImportStatement } = options
15
+ const modelName = model.name
16
+ const functionName = `${modelName}Count`
17
+ const argsTypeName = `Prisma.${modelName}CountArgs`
18
+
19
+ return `
20
+ ${prismaImportStatement}
21
+ import { Request, Response, NextFunction } from 'express';
22
+ import { RequestHandler, ParamsDictionary } from 'express-serve-static-core'
23
+ import { ZodTypeAny } from 'zod';
24
+
25
+ interface CountRequest extends Request {
26
+ prisma: PrismaClient;
27
+ body: ${argsTypeName};
28
+ outputValidation?: ZodTypeAny;
29
+ omitOutputValidation?: boolean;
30
+ }
31
+
32
+ export type CountMiddleware = RequestHandler<ParamsDictionary, any, ${argsTypeName}, Record<string, any>>;
33
+
34
+ export async function ${functionName}(req: CountRequest, res: Response, next: NextFunction) {
35
+ try {
36
+ if (!req.outputValidation && !req.omitOutputValidation) {
37
+ throw new Error('Output validation schema or omission flag must be provided.');
38
+ }
39
+
40
+ const result = await req.prisma.${modelName.toLowerCase()}.count(req.body);
41
+
42
+ if (!req.omitOutputValidation && req.outputValidation) {
43
+ const validationResult = req.outputValidation.safeParse(result);
44
+ if (validationResult.success) {
45
+ res.status(200).json(validationResult.data);
46
+ } else {
47
+ res.status(400).json({ error: 'Invalid data format', details: validationResult.error });
48
+ }
49
+ } else {
50
+ res.status(200).json(result);
51
+ }
52
+ } catch (error) {
53
+ console.error('Error in handling count request:', error);
54
+ res.status(500).json({ error: error.message });
55
+ next(error);
56
+ }
57
+ }`
58
+ }
@@ -0,0 +1,58 @@
1
+ import { DMMF } from '@prisma/generator-helper'
2
+
3
+ /**
4
+ * Generates an Express middleware function that handles creation of records and includes conditional output validation with Zod.
5
+ * This version dynamically includes the correct type for the arguments based on the Prisma model.
6
+ * @param options - The options containing the model name and the import statement for Prisma types.
7
+ * @returns {string} - The generated middleware function as a string.
8
+ */
9
+ export const generateCreateFunction = (options: {
10
+ model: DMMF.Model
11
+ prismaImportStatement: string
12
+ }): string => {
13
+ const { model, prismaImportStatement } = options
14
+ const modelName = model.name
15
+ const functionName = `${modelName}Create`
16
+ const argsTypeName = `Prisma.${modelName}CreateArgs`
17
+
18
+ return `
19
+ ${prismaImportStatement}
20
+ import { Request, Response, NextFunction } from 'express';
21
+ import { RequestHandler, ParamsDictionary } from 'express-serve-static-core'
22
+ import { ZodTypeAny } from 'zod';
23
+
24
+ interface CreateRequest extends Request {
25
+ prisma: PrismaClient;
26
+ body: ${argsTypeName};
27
+ outputValidation?: ZodTypeAny;
28
+ omitOutputValidation?: boolean;
29
+ }
30
+
31
+ export type CreateMiddleware = RequestHandler<ParamsDictionary, any, ${argsTypeName}, Record<string, any>>
32
+
33
+ export async function ${functionName}(req: CreateRequest, res: Response, next: NextFunction) {
34
+ try {
35
+ if (!req.outputValidation && !req.omitOutputValidation) {
36
+ throw new Error('Output validation schema or omission flag must be provided.');
37
+ }
38
+
39
+ const data = await req.prisma.${modelName.toLowerCase()}.create(req.body);
40
+ if (!req.omitOutputValidation && req.outputValidation) {
41
+ const validationResult = req.outputValidation.safeParse(data);
42
+ if (validationResult.success) {
43
+ res.status(201).json(validationResult.data);
44
+ } else {
45
+ res.status(400).json({ error: 'Invalid data format', details: validationResult.error });
46
+ }
47
+ } else if (!req.omitOutputValidation) {
48
+ throw new Error('Output validation schema must be provided unless explicitly omitted.');
49
+ } else {
50
+ res.status(201).json(data);
51
+ }
52
+ } catch (error) {
53
+ console.error('Error in handling create request:', error);
54
+ res.status(500).json({ error: error.message });
55
+ next(error);
56
+ }
57
+ }`
58
+ }
@@ -0,0 +1,58 @@
1
+ import { DMMF } from '@prisma/generator-helper'
2
+
3
+ /**
4
+ * Generates an Express middleware function that handles the creation of multiple records and includes conditional output validation with Zod.
5
+ * This version dynamically includes the correct type for the arguments based on the Prisma model.
6
+ * @param options - The options containing the model name and the import statement for Prisma types.
7
+ * @returns {string} - The generated middleware function as a string.
8
+ */
9
+ export const generateCreateManyFunction = (options: {
10
+ model: DMMF.Model
11
+ prismaImportStatement: string
12
+ }): string => {
13
+ const { model, prismaImportStatement } = options
14
+ const modelName = model.name
15
+ const functionName = `${modelName}CreateMany`
16
+ const argsTypeName = `Prisma.${modelName}CreateManyArgs`
17
+
18
+ return `
19
+ ${prismaImportStatement}
20
+ import { Request, Response, NextFunction } from 'express';
21
+ import { RequestHandler, ParamsDictionary } from 'express-serve-static-core';
22
+ import { ZodTypeAny } from 'zod';
23
+
24
+ interface CreateManyRequest extends Request {
25
+ prisma: PrismaClient;
26
+ body: ${argsTypeName};
27
+ outputValidation?: ZodTypeAny;
28
+ omitOutputValidation?: boolean;
29
+ }
30
+
31
+ export type CreateManyMiddleware = RequestHandler<ParamsDictionary, any, ${argsTypeName}, Record<string, any>>
32
+
33
+ export async function ${functionName}(req: CreateManyRequest, res: Response, next: NextFunction) {
34
+ try {
35
+ if (!req.outputValidation && !req.omitOutputValidation) {
36
+ throw new Error('Output validation schema or omission flag must be provided.');
37
+ }
38
+
39
+ const data = await req.prisma.${modelName.toLowerCase()}.createMany(req.body);
40
+ if (!req.omitOutputValidation && req.outputValidation) {
41
+ const validationResult = req.outputValidation.safeParse(data);
42
+ if (validationResult.success) {
43
+ res.status(201).json(validationResult.data);
44
+ } else {
45
+ res.status(400).json({ error: 'Invalid data format', details: validationResult.error });
46
+ }
47
+ } else if (!req.omitOutputValidation) {
48
+ throw new Error('Output validation schema must be provided unless explicitly omitted.');
49
+ } else {
50
+ res.status(201).json(data);
51
+ }
52
+ } catch (error) {
53
+ console.error('Error in handling createMany request:', error);
54
+ res.status(500).json({ error: error.message });
55
+ next(error);
56
+ }
57
+ }`
58
+ }
@@ -0,0 +1,60 @@
1
+ import { DMMF } from '@prisma/generator-helper'
2
+
3
+ /**
4
+ * Generates an Express middleware function that handles deleting records
5
+ * and includes conditional output validation with Zod.
6
+ * This version dynamically includes the correct type for the arguments based on the Prisma model.
7
+ * @param options - The options containing the model name and the import statement for Prisma types.
8
+ * @returns {string} - The generated middleware function as a string.
9
+ */
10
+ export const generateDeleteFunction = (options: {
11
+ model: DMMF.Model
12
+ prismaImportStatement: string
13
+ }): string => {
14
+ const { model, prismaImportStatement } = options
15
+ const modelName = model.name
16
+ const functionName = `${modelName}Delete`
17
+ const argsTypeName = `Prisma.${modelName}DeleteArgs`
18
+
19
+ return `
20
+ ${prismaImportStatement}
21
+ import { Request, Response, NextFunction } from 'express';
22
+ import { RequestHandler, ParamsDictionary } from 'express-serve-static-core';
23
+ import { ZodTypeAny } from 'zod';
24
+
25
+ interface DeleteRequest extends Request {
26
+ prisma: PrismaClient;
27
+ body: ${argsTypeName};
28
+ outputValidation?: ZodTypeAny;
29
+ omitOutputValidation?: boolean;
30
+ }
31
+
32
+ export type DeleteMiddleware = RequestHandler<ParamsDictionary, any, ${argsTypeName}, Record<string, any>>
33
+
34
+ export async function ${functionName}(req: DeleteRequest, res: Response, next: NextFunction) {
35
+ try {
36
+ if (!req.outputValidation && !req.omitOutputValidation) {
37
+ throw new Error('Output validation schema or omission flag must be provided.');
38
+ }
39
+
40
+ const data = await req.prisma.${modelName.toLowerCase()}.delete(req.body);
41
+
42
+ if (!req.omitOutputValidation && req.outputValidation) {
43
+ const validationResult = req.outputValidation.safeParse(data);
44
+ if (validationResult.success) {
45
+ res.status(200).json(validationResult.data);
46
+ } else {
47
+ res.status(400).json({ error: 'Invalid data format', details: validationResult.error });
48
+ }
49
+ } else if (!req.omitOutputValidation) {
50
+ throw new Error('Output validation schema must be provided unless explicitly omitted.');
51
+ } else {
52
+ res.status(200).json(data);
53
+ }
54
+ } catch (error) {
55
+ console.error('Error in handling delete request:', error);
56
+ res.status(500).json({ error: error.message });
57
+ next(error);
58
+ }
59
+ }`
60
+ }
@@ -0,0 +1,58 @@
1
+ import { DMMF } from '@prisma/generator-helper'
2
+
3
+ /**
4
+ * Generates an Express middleware function that handles batch deleting records
5
+ * and includes conditional output validation with Zod.
6
+ * This version dynamically includes the correct type for the arguments based on the Prisma model.
7
+ * @param options - The options containing the model name and the import statement for Prisma types.
8
+ * @returns {string} - The generated middleware function as a string.
9
+ */
10
+ export const generateDeleteManyFunction = (options: {
11
+ model: DMMF.Model
12
+ prismaImportStatement: string
13
+ }): string => {
14
+ const { model, prismaImportStatement } = options
15
+ const modelName = model.name
16
+ const functionName = `${modelName}DeleteMany`
17
+ const argsTypeName = `Prisma.${modelName}DeleteManyArgs`
18
+
19
+ return `
20
+ ${prismaImportStatement}
21
+ import { Request, Response, NextFunction } from 'express';
22
+ import { RequestHandler, ParamsDictionary } from 'express-serve-static-core';
23
+ import { ZodTypeAny } from 'zod';
24
+
25
+ interface DeleteManyRequest extends Request {
26
+ prisma: PrismaClient;
27
+ body: ${argsTypeName};
28
+ outputValidation?: ZodTypeAny;
29
+ omitOutputValidation?: boolean;
30
+ }
31
+
32
+ export type DeleteManyMiddleware = RequestHandler<ParamsDictionary, any, Prisma.${modelName}DeleteManyArgs, Record<string, any>>;
33
+
34
+ export async function ${functionName}(req: DeleteManyRequest, res: Response, next: NextFunction) {
35
+ try {
36
+ if (!req.outputValidation && !req.omitOutputValidation) {
37
+ throw new Error('Output validation schema or omission flag must be provided.');
38
+ }
39
+
40
+ const result = await req.prisma.${modelName.toLowerCase()}.deleteMany(req.body);
41
+
42
+ if (!req.omitOutputValidation && req.outputValidation) {
43
+ const validationResult = req.outputValidation.safeParse(result);
44
+ if (validationResult.success) {
45
+ res.status(200).json(validationResult.data);
46
+ } else {
47
+ res.status(400).json({ error: 'Invalid data format', details: validationResult.error });
48
+ }
49
+ } else {
50
+ res.status(200).json(result);
51
+ }
52
+ } catch (error) {
53
+ console.error('Error in handling batch delete request:', error);
54
+ res.status(500).json({ error: error.message });
55
+ next(error);
56
+ }
57
+ }`
58
+ }
@@ -0,0 +1,68 @@
1
+ import { DMMF } from '@prisma/generator-helper'
2
+
3
+ /**
4
+ * Generates an Express middleware function that includes conditional output validation with Zod.
5
+ * This version dynamically includes the correct type for the query parameter based on the Prisma model.
6
+ * @param options - The options containing the model name and the import statement for Prisma types.
7
+ * @returns {string} - The generated middleware function as a string.
8
+ */
9
+ export const generateFindFirstFunction = (options: {
10
+ model: DMMF.Model
11
+ prismaImportStatement: string
12
+ }): string => {
13
+ const { model, prismaImportStatement } = options
14
+ const modelName = model.name
15
+ const functionName = `${modelName}FindFirst`
16
+ const queryTypeName = `Prisma.${modelName}FindFirstArgs`
17
+
18
+ return `
19
+ ${prismaImportStatement.replace('{ Prisma }', `{ Prisma, ${modelName} }`)}
20
+ import { Request, Response, NextFunction } from 'express'
21
+ import {
22
+ RequestHandler,
23
+ ParamsDictionary,
24
+ } from 'express-serve-static-core'
25
+ import { ParsedQs } from 'qs';
26
+ import { ZodTypeAny } from 'zod';
27
+
28
+ export interface FindFirstRequest extends Request {
29
+ prisma: PrismaClient;
30
+ query: ${queryTypeName} & ParsedQs;
31
+ outputValidation?: ZodTypeAny;
32
+ omitOutputValidation?: boolean;
33
+ passToNext?: boolean;
34
+ locals: {
35
+ data?: ${modelName} | null
36
+ }
37
+ }
38
+ export type FindFirstMiddleware = RequestHandler<ParamsDictionary, any, any, ${queryTypeName} & ParsedQs, Record<string, any>>
39
+
40
+ export async function ${functionName}(req: FindFirstRequest, res: Response, next: NextFunction) {
41
+ try {
42
+ if (!req.outputValidation && !req.omitOutputValidation) {
43
+ throw new Error('Output validation schema or omission flag must be provided.');
44
+ }
45
+
46
+ const data = await req.prisma.${modelName.toLowerCase()}.findFirst(req.query as ${queryTypeName});
47
+ if (req.passToNext) {
48
+ req.locals.data = data;
49
+ next();
50
+ } else if (!req.omitOutputValidation && req.outputValidation) {
51
+ const validationResult = req.outputValidation.safeParse(data);
52
+ if (validationResult.success) {
53
+ res.status(200).json(validationResult.data);
54
+ } else {
55
+ res.status(400).json({ error: 'Invalid data format', details: validationResult.error });
56
+ }
57
+ } else if (!req.omitOutputValidation) {
58
+ throw new Error('Output validation schema must be provided unless explicitly omitted. Attach omitOutputValidation = true to request to suppress this error.');
59
+ } else {
60
+ res.status(200).json(data);
61
+ }
62
+ } catch (error) {
63
+ console.error('Error in handling request:', error);
64
+ res.status(500).json({ error: error.message });
65
+ next(error);
66
+ }
67
+ }`
68
+ }
@@ -0,0 +1,68 @@
1
+ import { DMMF } from '@prisma/generator-helper'
2
+
3
+ /**
4
+ * Generates an Express middleware function that handles multiple record retrieval with optional output validation using Zod.
5
+ * This version dynamically includes the correct type for the query parameter based on the Prisma model.
6
+ * @param options - The options containing the model name and the import statement for Prisma types.
7
+ * @returns {string} - The generated middleware function as a string.
8
+ */
9
+ export const generateFindManyFunction = (options: {
10
+ model: DMMF.Model
11
+ prismaImportStatement: string
12
+ }): string => {
13
+ const { model, prismaImportStatement } = options
14
+ const modelName = model.name
15
+ const functionName = `${modelName}FindMany`
16
+ const queryTypeName = `Prisma.${modelName}FindManyArgs`
17
+
18
+ return `
19
+ ${prismaImportStatement.replace('{ Prisma }', `{ Prisma, ${modelName} }`)}
20
+ import { Request, Response, NextFunction } from 'express'
21
+ import {
22
+ RequestHandler,
23
+ ParamsDictionary,
24
+ } from 'express-serve-static-core'
25
+ import { ParsedQs } from 'qs';
26
+ import { ZodTypeAny } from 'zod';
27
+
28
+ export interface FindManyRequest extends Request {
29
+ prisma: PrismaClient;
30
+ query: ${queryTypeName} & ParsedQs;
31
+ outputValidation?: ZodTypeAny;
32
+ omitOutputValidation?: boolean;
33
+ passToNext?: boolean;
34
+ locals: {
35
+ data?: ${modelName}[]
36
+ }
37
+ }
38
+ export type FindManyMiddleware = RequestHandler<ParamsDictionary, any, any, ${queryTypeName} & ParsedQs, Record<string, any>>
39
+
40
+ export async function ${functionName}(req: FindManyRequest, res: Response, next: NextFunction) {
41
+ try {
42
+ if (!req.outputValidation && !req.omitOutputValidation) {
43
+ throw new Error('Output validation schema or omission flag must be provided.');
44
+ }
45
+
46
+ const data = await req.prisma.${modelName.toLowerCase()}.findMany(req.query as ${queryTypeName});
47
+ if (req.passToNext) {
48
+ req.locals.data = data;
49
+ next();
50
+ } else if (!req.omitOutputValidation && req.outputValidation) {
51
+ const validationResult = req.outputValidation.safeParse(data);
52
+ if (validationResult.success) {
53
+ res.status(200).json(validationResult.data);
54
+ } else {
55
+ res.status(400).json({ error: 'Invalid data format', details: validationResult.error });
56
+ }
57
+ } else if (!req.omitOutputValidation) {
58
+ throw new Error('Output validation schema must be provided unless explicitly omitted. Attach omitOutputValidation = true to request to suppress this error.');
59
+ } else {
60
+ res.status(200).json(data);
61
+ }
62
+ } catch (error) {
63
+ console.error('Error in handling request:', error);
64
+ res.status(500).json({ error: error.message });
65
+ next(error);
66
+ }
67
+ }`
68
+ }
@@ -0,0 +1,68 @@
1
+ import { DMMF } from '@prisma/generator-helper'
2
+
3
+ /**
4
+ * Generates an Express middleware function that includes conditional output validation with Zod.
5
+ * This version dynamically includes the correct type for the query parameter based on the Prisma model.
6
+ * @param options - The options containing the model name and the import statement for Prisma types.
7
+ * @returns {string} - The generated middleware function as a string.
8
+ */
9
+ export const generateFindUniqueFunction = (options: {
10
+ model: DMMF.Model
11
+ prismaImportStatement: string
12
+ }): string => {
13
+ const { model, prismaImportStatement } = options
14
+ const modelName = model.name
15
+ const functionName = `${modelName}FindUnique`
16
+ const queryTypeName = `Prisma.${modelName}FindUniqueArgs`
17
+
18
+ return `
19
+ ${prismaImportStatement.replace('{ Prisma }', `{ Prisma, ${modelName} }`)}
20
+ import { Request, Response, NextFunction } from 'express'
21
+ import {
22
+ RequestHandler,
23
+ ParamsDictionary,
24
+ } from 'express-serve-static-core'
25
+ import { ParsedQs } from 'qs';
26
+ import { ZodTypeAny } from 'zod';
27
+
28
+ export interface FindUniqueRequest extends Request {
29
+ prisma: PrismaClient;
30
+ query: ${queryTypeName} & ParsedQs;
31
+ outputValidation?: ZodTypeAny;
32
+ omitOutputValidation?: boolean;
33
+ passToNext?: boolean;
34
+ locals: {
35
+ data?: ${modelName} | null
36
+ }
37
+ }
38
+ export type FindUniqueMiddleware = RequestHandler<ParamsDictionary, any, any, ${queryTypeName} & ParsedQs, Record<string, any>>
39
+
40
+ export async function ${functionName}(req: FindUniqueRequest, res: Response, next: NextFunction) {
41
+ try {
42
+ if (!req.outputValidation && !req.omitOutputValidation) {
43
+ throw new Error('Output validation schema or omission flag must be provided.');
44
+ }
45
+
46
+ const data = await req.prisma.${modelName.toLowerCase()}.findUnique(req.query as ${queryTypeName});
47
+ if (req.passToNext) {
48
+ req.locals.data = data;
49
+ next();
50
+ } else if (!req.omitOutputValidation && req.outputValidation) {
51
+ const validationResult = req.outputValidation.safeParse(data);
52
+ if (validationResult.success) {
53
+ res.status(200).json(validationResult.data);
54
+ } else {
55
+ res.status(400).json({ error: 'Invalid data format', details: validationResult.error });
56
+ }
57
+ } else if (!req.omitOutputValidation) {
58
+ throw new Error('Output validation schema must be provided unless explicitly omitted. Attach omitOutputValidation = true to request to suppress this error.');
59
+ } else {
60
+ res.status(200).json(data);
61
+ }
62
+ } catch (error) {
63
+ console.error('Error in handling request:', error);
64
+ res.status(500).json({ error: error.message });
65
+ next(error);
66
+ }
67
+ }`
68
+ }
@@ -0,0 +1,58 @@
1
+ import { DMMF } from '@prisma/generator-helper'
2
+
3
+ /**
4
+ * Generates an Express middleware function that handles groupBy queries
5
+ * and includes conditional output validation with Zod.
6
+ * This version dynamically includes the correct type for the arguments based on the Prisma model.
7
+ * @param options - The options containing the model name and the import statement for Prisma types.
8
+ * @returns {string} - The generated middleware function as a string.
9
+ */
10
+ export const generateGroupByFunction = (options: {
11
+ model: DMMF.Model
12
+ prismaImportStatement: string
13
+ }): string => {
14
+ const { model, prismaImportStatement } = options
15
+ const modelName = model.name
16
+ const functionName = `${modelName}GroupBy`
17
+ const argsTypeName = `Prisma.${modelName}GroupByArgs`
18
+
19
+ return `
20
+ ${prismaImportStatement}
21
+ import { Request, Response, NextFunction } from 'express';
22
+ import { RequestHandler, ParamsDictionary } from 'express-serve-static-core'
23
+ import { ZodTypeAny } from 'zod';
24
+
25
+ interface GroupByRequest extends Request {
26
+ prisma: PrismaClient;
27
+ body: ${argsTypeName};
28
+ outputValidation?: ZodTypeAny;
29
+ omitOutputValidation?: boolean;
30
+ }
31
+
32
+ export type GroupByMiddleware = RequestHandler<ParamsDictionary, any, ${argsTypeName}, Record<string, any>>;
33
+
34
+ export async function ${functionName}(req: GroupByRequest, res: Response, next: NextFunction) {
35
+ try {
36
+ if (!req.outputValidation && !req.omitOutputValidation) {
37
+ throw new Error('Output validation schema or omission flag must be provided.');
38
+ }
39
+
40
+ const result = await req.prisma.${modelName.toLowerCase()}.groupBy(req.body);
41
+
42
+ if (!req.omitOutputValidation && req.outputValidation) {
43
+ const validationResult = req.outputValidation.safeParse(result);
44
+ if (validationResult.success) {
45
+ res.status(200).json(validationResult.data);
46
+ } else {
47
+ res.status(400).json({ error: 'Invalid data format', details: validationResult.error });
48
+ }
49
+ } else {
50
+ res.status(200).json(result);
51
+ }
52
+ } catch (error) {
53
+ console.error('Error in handling groupBy request:', error);
54
+ res.status(500).json({ error: error.message });
55
+ next(error);
56
+ }
57
+ }`
58
+ }
@@ -0,0 +1,38 @@
1
+ import { GeneratorOptions } from '@prisma/generator-helper'
2
+ import path from 'path'
3
+
4
+ interface ImportPrismaStatementOptions {
5
+ outputPath: string
6
+ }
7
+
8
+ function getImportGeneratorOptions(
9
+ options: GeneratorOptions,
10
+ ): ImportPrismaStatementOptions {
11
+ const clientGenerator = options.otherGenerators.find(
12
+ (gen) => gen.name === 'client',
13
+ )
14
+
15
+ if (!clientGenerator || !clientGenerator.output?.value) {
16
+ throw new Error('Prisma client generator not found.')
17
+ }
18
+
19
+ const modelDirPath = path.join(
20
+ options.generator.output?.value!,
21
+ 'modelFolder', // workaround for saving with /modelName/operation structure
22
+ )
23
+ const clientOutputPath = clientGenerator.output.value
24
+
25
+ const relativeImportPath = path.relative(modelDirPath, clientOutputPath)
26
+
27
+ return {
28
+ outputPath: relativeImportPath.split(path.sep).join(path.posix.sep),
29
+ }
30
+ }
31
+
32
+ export function generateImportPrismaStatement(
33
+ generatorOptions: GeneratorOptions,
34
+ ): string {
35
+ const options = getImportGeneratorOptions(generatorOptions)
36
+ // console.log('options.outputPath :>> ', options.outputPath)
37
+ return `import type { Prisma } from '${options.outputPath}';\nimport type { PrismaClient } from '${options.outputPath}';\n`
38
+ }
@@ -0,0 +1,183 @@
1
+ import { DMMF } from '@prisma/generator-helper'
2
+
3
+ export function generateRouterFunction({
4
+ model,
5
+ }: {
6
+ model: DMMF.Model
7
+ }): string {
8
+ const modelName = model.name
9
+ const routerFunctionName = `${modelName}Router`
10
+
11
+ return `
12
+ import express, { RequestHandler } from 'express';
13
+ import { ${modelName}FindFirst, type FindFirstMiddleware } from './${modelName}FindFirst';
14
+ import { ${modelName}FindMany, type FindManyMiddleware } from './${modelName}FindMany';
15
+ import { ${modelName}FindUnique, type FindUniqueMiddleware } from './${modelName}FindUnique';
16
+ import { ${modelName}Create, type CreateMiddleware } from './${modelName}Create';
17
+ import { ${modelName}CreateMany, type CreateManyMiddleware } from './${modelName}CreateMany';
18
+ import { ${modelName}Update, type UpdateMiddleware } from './${modelName}Update';
19
+ import { ${modelName}UpdateMany, type UpdateManyMiddleware } from './${modelName}UpdateMany';
20
+ import { ${modelName}Upsert, type UpsertMiddleware } from './${modelName}Upsert';
21
+ import { ${modelName}Delete, type DeleteMiddleware } from './${modelName}Delete';
22
+ import { ${modelName}DeleteMany, type DeleteManyMiddleware } from './${modelName}DeleteMany';
23
+ import { ${modelName}Aggregate, type AggregateMiddleware } from './${modelName}Aggregate';
24
+ import { ${modelName}Count, type CountMiddleware } from './${modelName}Count';
25
+ import { ${modelName}GroupBy, type GroupByMiddleware } from './${modelName}GroupBy';
26
+
27
+ interface RouteConfig {
28
+ findFirstMiddleware?: FindFirstMiddleware[]
29
+ findFirstNextMiddleware?: RequestHandler[]
30
+
31
+ findManyMiddleware?: FindManyMiddleware[]
32
+ findManyNextMiddleware?: RequestHandler[]
33
+
34
+ findUniqueMiddleware?: FindUniqueMiddleware[]
35
+ findUniqueNextMiddleware?: RequestHandler[]
36
+
37
+ createMiddleware?: CreateMiddleware[]
38
+ createNextMiddleware?: RequestHandler[]
39
+
40
+ createManyMiddleware?: CreateManyMiddleware[]
41
+ createManyNextMiddleware?: RequestHandler[]
42
+
43
+ updateMiddleware?: UpdateMiddleware[]
44
+ updateNextMiddleware?: RequestHandler[]
45
+
46
+ updateManyMiddleware?: UpdateManyMiddleware[]
47
+ updateManyNextMiddleware?: RequestHandler[]
48
+
49
+ upsertMiddleware?: UpsertMiddleware[]
50
+ upsertNextMiddleware?: RequestHandler[]
51
+
52
+ deleteMiddleware?: DeleteMiddleware[]
53
+ deleteNextMiddleware?: RequestHandler[]
54
+
55
+ deleteManyMiddleware?: DeleteManyMiddleware[]
56
+ deleteManyNextMiddleware?: RequestHandler[]
57
+
58
+ aggregateMiddleware?: AggregateMiddleware[]
59
+ aggregateNextMiddleware?: RequestHandler[]
60
+
61
+ countMiddleware?: CountMiddleware[]
62
+ countNextMiddleware?: RequestHandler[]
63
+
64
+ groupByMiddleware?: GroupByMiddleware[]
65
+ groupByNextMiddleware?: RequestHandler[]
66
+ }
67
+
68
+ /**
69
+ * Generates an Express router for ${modelName} model.
70
+ * @param config Contains optional middleware to enable routes.
71
+ * @returns {express.Router}
72
+ */
73
+ export function ${routerFunctionName}(config: RouteConfig) {
74
+ const router = express.Router();
75
+
76
+ if (config?.findFirstMiddleware && config?.findFirstMiddleware.length) {
77
+ const middlewares = [...config.findFirstMiddleware, ${modelName}FindFirst]
78
+ if (config.findFirstNextMiddleware) {
79
+ middlewares.push(...config.findFirstNextMiddleware);
80
+ }
81
+ router.get('/first', ...middlewares as FindFirstMiddleware[]);
82
+ }
83
+
84
+ if (config?.findManyMiddleware && config?.findManyMiddleware.length) {
85
+ const middlewares = [...config.findManyMiddleware, ${modelName}FindMany]
86
+ if (config.findManyNextMiddleware) {
87
+ middlewares.push(...config.findManyNextMiddleware);
88
+ }
89
+ router.get('/', ...middlewares as FindManyMiddleware[]);
90
+ }
91
+
92
+ if (config?.findUniqueMiddleware && config?.findUniqueMiddleware.length) {
93
+ const middlewares = [...config.findUniqueMiddleware, ${modelName}FindUnique]
94
+ if (config.findUniqueNextMiddleware) {
95
+ middlewares.push(...config.findUniqueNextMiddleware);
96
+ }
97
+ router.get('/:id', ...middlewares as FindUniqueMiddleware[]);
98
+ }
99
+
100
+ if (config?.createMiddleware && config?.createMiddleware.length) {
101
+ const middlewares = [...config.createMiddleware, ${modelName}Create]
102
+ if (config.createNextMiddleware) {
103
+ middlewares.push(...config.createNextMiddleware);
104
+ }
105
+ router.post('/', ...middlewares);
106
+ }
107
+
108
+ if (config?.createManyMiddleware && config?.createManyMiddleware.length) {
109
+ const middlewares = [...config.createManyMiddleware, ${modelName}CreateMany]
110
+ if (config.createManyNextMiddleware) {
111
+ middlewares.push(...config.createManyNextMiddleware);
112
+ }
113
+ router.post('/many', ...middlewares);
114
+ }
115
+
116
+ if (config?.updateMiddleware && config?.updateMiddleware.length) {
117
+ const middlewares = [...config.updateMiddleware, ${modelName}Update]
118
+ if (config.updateNextMiddleware) {
119
+ middlewares.push(...config.updateNextMiddleware);
120
+ }
121
+ router.put('/', ...middlewares);
122
+ }
123
+
124
+ if (config?.updateManyMiddleware && config?.updateManyMiddleware.length) {
125
+ const middlewares = [...config.updateManyMiddleware, ${modelName}UpdateMany]
126
+ if (config.updateManyNextMiddleware) {
127
+ middlewares.push(...config.updateManyNextMiddleware);
128
+ }
129
+ router.put('/many', ...middlewares);
130
+ }
131
+
132
+ if (config?.upsertMiddleware && config?.upsertMiddleware.length) {
133
+ const middlewares = [...config.upsertMiddleware, ${modelName}Upsert]
134
+ if (config.upsertNextMiddleware) {
135
+ middlewares.push(...config.upsertNextMiddleware);
136
+ }
137
+ router.patch('/', ...middlewares);
138
+ }
139
+
140
+ if (config?.deleteMiddleware && config?.deleteMiddleware.length) {
141
+ const middlewares = [...config.deleteMiddleware, ${modelName}Delete]
142
+ if (config.deleteNextMiddleware) {
143
+ middlewares.push(...config.deleteNextMiddleware);
144
+ }
145
+ router.delete('/', ...middlewares);
146
+ }
147
+
148
+ if (config?.deleteManyMiddleware && config?.deleteManyMiddleware.length) {
149
+ const middlewares = [...config.deleteManyMiddleware, ${modelName}DeleteMany]
150
+ if (config.deleteManyNextMiddleware) {
151
+ middlewares.push(...config.deleteManyNextMiddleware);
152
+ }
153
+ router.delete('/many', ...middlewares);
154
+ }
155
+
156
+ if (config?.aggregateMiddleware && config?.aggregateMiddleware.length) {
157
+ const middlewares = [...config.aggregateMiddleware, ${modelName}Aggregate]
158
+ if (config.aggregateNextMiddleware) {
159
+ middlewares.push(...config.aggregateNextMiddleware);
160
+ }
161
+ router.get('/aggregate', ...middlewares);
162
+ }
163
+
164
+ if (config?.countMiddleware && config?.countMiddleware.length) {
165
+ const middlewares = [...config.countMiddleware, ${modelName}Count]
166
+ if (config.countNextMiddleware) {
167
+ middlewares.push(...config.countNextMiddleware);
168
+ }
169
+ router.get('/count', ...middlewares);
170
+ }
171
+
172
+ if (config?.groupByMiddleware && config?.groupByMiddleware.length) {
173
+ const middlewares = [...config.groupByMiddleware, ${modelName}GroupBy]
174
+ if (config.groupByNextMiddleware) {
175
+ middlewares.push(...config.groupByNextMiddleware);
176
+ }
177
+ router.get('/groupby', ...middlewares);
178
+ }
179
+
180
+ return router;
181
+ }
182
+ `
183
+ }
@@ -0,0 +1,62 @@
1
+ import { DMMF } from '@prisma/generator-helper'
2
+
3
+ /**
4
+ * Generates an Express middleware function that handles updating records and includes conditional output validation with Zod.
5
+ * This version dynamically includes the correct type for the arguments based on the Prisma model.
6
+ * @param options - The options containing the model name and the import statement for Prisma types.
7
+ * @returns {string} - The generated middleware function as a string.
8
+ */
9
+ export const generateUpdateFunction = (options: {
10
+ model: DMMF.Model
11
+ prismaImportStatement: string
12
+ }): string => {
13
+ const { model, prismaImportStatement } = options
14
+ const modelName = model.name
15
+ const functionName = `${modelName}Update`
16
+ const argsTypeName = `Prisma.${modelName}UpdateArgs`
17
+
18
+ return `
19
+ ${prismaImportStatement}
20
+ import { Request, Response, NextFunction } from 'express';
21
+ import { RequestHandler, ParamsDictionary } from 'express-serve-static-core';
22
+ import { ZodTypeAny } from 'zod';
23
+
24
+ interface UpdateRequest extends Request {
25
+ prisma: PrismaClient;
26
+ body: ${argsTypeName};
27
+ outputValidation?: ZodTypeAny;
28
+ omitOutputValidation?: boolean;
29
+ }
30
+
31
+ export type UpdateMiddleware = RequestHandler<ParamsDictionary, any, ${argsTypeName}, Record<string, any>>
32
+
33
+ export async function ${functionName}(req: UpdateRequest, res: Response, next: NextFunction) {
34
+ try {
35
+ if (!req.outputValidation && !req.omitOutputValidation) {
36
+ throw new Error('Output validation schema or omission flag must be provided.');
37
+ }
38
+
39
+ const data = await req.prisma.${modelName.toLowerCase()}.update({
40
+ where: { id: parseInt(req.params.id) },
41
+ data: req.body
42
+ });
43
+
44
+ if (!req.omitOutputValidation && req.outputValidation) {
45
+ const validationResult = req.outputValidation.safeParse(data);
46
+ if (validationResult.success) {
47
+ res.status(200).json(validationResult.data);
48
+ } else {
49
+ res.status(400).json({ error: 'Invalid data format', details: validationResult.error });
50
+ }
51
+ } else if (!req.omitOutputValidation) {
52
+ throw new Error('Output validation schema must be provided unless explicitly omitted.');
53
+ } else {
54
+ res.status(200).json(data);
55
+ }
56
+ } catch (error) {
57
+ console.error('Error in handling update request:', error);
58
+ res.status(500).json({ error: error.message });
59
+ next(error);
60
+ }
61
+ }`
62
+ }
@@ -0,0 +1,59 @@
1
+ import { DMMF } from '@prisma/generator-helper'
2
+
3
+ /**
4
+ * Generates an Express middleware function that handles updating multiple records and includes conditional output validation with Zod.
5
+ * This version dynamically includes the correct type for the arguments based on the Prisma model.
6
+ * @param options - The options containing the model name and the import statement for Prisma types.
7
+ * @returns {string} - The generated middleware function as a string.
8
+ */
9
+ export const generateUpdateManyFunction = (options: {
10
+ model: DMMF.Model
11
+ prismaImportStatement: string
12
+ }): string => {
13
+ const { model, prismaImportStatement } = options
14
+ const modelName = model.name
15
+ const functionName = `${modelName}UpdateMany`
16
+ const argsTypeName = `Prisma.${modelName}UpdateManyArgs`
17
+
18
+ return `
19
+ ${prismaImportStatement}
20
+ import { Request, Response, NextFunction } from 'express';
21
+ import { RequestHandler, ParamsDictionary } from 'express-serve-static-core';
22
+ import { ZodTypeAny } from 'zod';
23
+
24
+ interface UpdateManyRequest extends Request {
25
+ prisma: PrismaClient;
26
+ body: ${argsTypeName};
27
+ outputValidation?: ZodTypeAny;
28
+ omitOutputValidation?: boolean;
29
+ }
30
+
31
+ export type UpdateManyMiddleware = RequestHandler<ParamsDictionary, any, ${argsTypeName}, Record<string, any>>
32
+
33
+ export async function ${functionName}(req: UpdateManyRequest, res: Response, next: NextFunction) {
34
+ try {
35
+ if (!req.outputValidation && !req.omitOutputValidation) {
36
+ throw new Error('Output validation schema or omission flag must be provided.');
37
+ }
38
+
39
+ const data = await req.prisma.${modelName.toLowerCase()}.updateMany(req.body);
40
+
41
+ if (!req.omitOutputValidation && req.outputValidation) {
42
+ const validationResult = req.outputValidation.safeParse(data);
43
+ if (validationResult.success) {
44
+ res.status(200).json({ count: validationResult.data.count });
45
+ } else {
46
+ res.status(400).json({ error: 'Invalid data format', details: validationResult.error });
47
+ }
48
+ } else if (!req.omitOutputValidation) {
49
+ throw new Error('Output validation schema must be provided unless explicitly omitted.');
50
+ } else {
51
+ res.status(200).json({ count: data.count });
52
+ }
53
+ } catch (error) {
54
+ console.error('Error in handling updateMany request:', error);
55
+ res.status(500).json({ error: error.message });
56
+ next(error);
57
+ }
58
+ }`
59
+ }
@@ -0,0 +1,60 @@
1
+ import { DMMF } from '@prisma/generator-helper'
2
+
3
+ /**
4
+ * Generates an Express middleware function that handles the upsert operation (create or update)
5
+ * and includes conditional output validation with Zod.
6
+ * This version dynamically includes the correct type for the arguments based on the Prisma model.
7
+ * @param options - The options containing the model name and the import statement for Prisma types.
8
+ * @returns {string} - The generated middleware function as a string.
9
+ */
10
+ export const generateUpsertFunction = (options: {
11
+ model: DMMF.Model
12
+ prismaImportStatement: string
13
+ }): string => {
14
+ const { model, prismaImportStatement } = options
15
+ const modelName = model.name
16
+ const functionName = `${modelName}Upsert`
17
+ const argsTypeName = `Prisma.${modelName}UpsertArgs`
18
+
19
+ return `
20
+ ${prismaImportStatement}
21
+ import { Request, Response, NextFunction } from 'express';
22
+ import { RequestHandler, ParamsDictionary } from 'express-serve-static-core';
23
+ import { ZodTypeAny } from 'zod';
24
+
25
+ interface UpsertRequest extends Request {
26
+ prisma: PrismaClient;
27
+ body: ${argsTypeName};
28
+ outputValidation?: ZodTypeAny;
29
+ omitOutputValidation?: boolean;
30
+ }
31
+
32
+ export type UpsertMiddleware = RequestHandler<ParamsDictionary, any, ${argsTypeName}, Record<string, any>>
33
+
34
+ export async function ${functionName}(req: UpsertRequest, res: Response, next: NextFunction) {
35
+ try {
36
+ if (!req.outputValidation && !req.omitOutputValidation) {
37
+ throw new Error('Output validation schema or omission flag must be provided.');
38
+ }
39
+
40
+ const data = await req.prisma.${modelName.toLowerCase()}.upsert(req.body);
41
+
42
+ if (!req.omitOutputValidation && req.outputValidation) {
43
+ const validationResult = req.outputValidation.safeParse(data);
44
+ if (validationResult.success) {
45
+ res.status(200).json(validationResult.data);
46
+ } else {
47
+ res.status(400).json({ error: 'Invalid data format', details: validationResult.error });
48
+ }
49
+ } else if (!req.omitOutputValidation) {
50
+ throw new Error('Output validation schema must be provided unless explicitly omitted.');
51
+ } else {
52
+ res.status(200).json(data);
53
+ }
54
+ } catch (error) {
55
+ console.error('Error in handling upsert request:', error);
56
+ res.status(500).json({ error: error.message });
57
+ next(error);
58
+ }
59
+ }`
60
+ }
@@ -0,0 +1,22 @@
1
+ import prettier from 'prettier'
2
+
3
+ export const formatFile = (content: string): Promise<string> => {
4
+ return new Promise((res, rej) =>
5
+ prettier.resolveConfig(process.cwd()).then((options) => {
6
+ if (!options) {
7
+ res(content) // no prettier config was found, no need to format
8
+ }
9
+
10
+ try {
11
+ const formatted = prettier.format(content, {
12
+ ...options,
13
+ parser: 'typescript',
14
+ })
15
+
16
+ res(formatted)
17
+ } catch (error) {
18
+ rej(error)
19
+ }
20
+ })
21
+ )
22
+ }
@@ -0,0 +1,28 @@
1
+ import fs from 'fs/promises'
2
+ import path from 'path'
3
+ import { formatFile } from './formatFile'
4
+ import { DMMF, GeneratorOptions } from '@prisma/generator-helper'
5
+
6
+ export const writeFileSafely = async ({
7
+ model,
8
+ operation,
9
+ options,
10
+ content,
11
+ }: {
12
+ model: DMMF.Model
13
+ operation: string
14
+ options: GeneratorOptions
15
+ content: string
16
+ }) => {
17
+ const fileName = operation === 'index' ? 'index' : `${model.name}${operation}`
18
+ const filePath = path.join(
19
+ options.generator.output?.value!,
20
+ `${model.name}/${fileName}.ts`,
21
+ )
22
+ console.log('filePath :>> ', filePath)
23
+ await fs.mkdir(path.dirname(filePath), {
24
+ recursive: true,
25
+ })
26
+
27
+ await fs.writeFile(filePath, await formatFile(content))
28
+ }
package/CHANGELOG.md DELETED
@@ -1,14 +0,0 @@
1
- # [1.1.0](https://github.com/multipliedtwice/prisma-generator-express/compare/v1.0.0...v1.1.0) (2024-05-15)
2
-
3
-
4
- ### Features
5
-
6
- * **generator:** add MIT License and README file for Prisma Generator Express ([6c99565](https://github.com/multipliedtwice/prisma-generator-express/commit/6c995652c53946e0f3f303f0495fcfe4e7b96e48))
7
- * **generator:** update package.json description to provide a more specific description of the Prisma generator for Express CRUD API ([7b99050](https://github.com/multipliedtwice/prisma-generator-express/commit/7b99050d2089490082b6c6b7f5174f8572172779))
8
-
9
- # 1.0.0 (2024-05-15)
10
-
11
-
12
- ### Bug Fixes
13
-
14
- * **generator:** update minimum required Node.js version to 20.0 in engines field ([1b4e7b2](https://github.com/multipliedtwice/prisma-generator-express/commit/1b4e7b2a8e29cc8a9710cc6393ada81b01631de3))