prisma-generator-express 1.16.7 → 1.19.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 +399 -194
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +1 -1
- package/dist/bin.js.map +1 -1
- package/dist/client/encodeQueryParams.d.ts +1 -0
- package/dist/client/encodeQueryParams.js +33 -0
- package/dist/client/encodeQueryParams.js.map +1 -0
- package/dist/constants.d.ts +1 -0
- package/dist/copy/misc.d.ts +5 -0
- package/dist/copy/misc.js +52 -0
- package/dist/copy/misc.js.map +1 -0
- package/dist/generators/generateImportPrismaStatement.d.ts +3 -0
- package/dist/generators/generateImportPrismaStatement.js +55 -0
- package/dist/generators/generateImportPrismaStatement.js.map +1 -0
- package/dist/generators/generateQueryBuilderHelper.d.ts +2 -0
- package/dist/generators/generateQueryBuilderHelper.js +139 -0
- package/dist/generators/generateQueryBuilderHelper.js.map +1 -0
- package/dist/generators/generateRouter.d.ts +6 -0
- package/dist/generators/generateRouter.js +340 -0
- package/dist/generators/generateRouter.js.map +1 -0
- package/dist/generators/generateUnifiedDocs.d.ts +1 -0
- package/dist/generators/generateUnifiedDocs.js +171 -0
- package/dist/generators/generateUnifiedDocs.js.map +1 -0
- package/dist/generators/generateUnifiedHandler.d.ts +6 -0
- package/dist/generators/generateUnifiedHandler.js +444 -0
- package/dist/generators/generateUnifiedHandler.js.map +1 -0
- package/dist/generators/generateUnifiedScalarUI.d.ts +5 -0
- package/dist/generators/generateUnifiedScalarUI.js +1390 -0
- package/dist/generators/generateUnifiedScalarUI.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +80 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/copyFiles.d.ts +6 -0
- package/dist/utils/copyFiles.js +123 -21
- package/dist/utils/copyFiles.js.map +1 -1
- package/dist/utils/strings.d.ts +2 -0
- package/dist/utils/writeFileSafely.d.ts +10 -0
- package/dist/utils/writeFileSafely.js +86 -14
- package/dist/utils/writeFileSafely.js.map +1 -1
- package/package.json +64 -31
- package/src/client/encodeQueryParams.ts +56 -0
- package/src/copy/buildModelOpenApi.ts +1569 -0
- package/src/copy/createOutputValidatorMiddleware.ts +1 -1
- package/src/copy/createValidatorMiddleware.ts +1 -1
- package/src/copy/misc.ts +22 -1
- package/src/copy/operationDefinitions.ts +96 -0
- package/src/copy/parseQueryParams.ts +36 -21
- package/src/copy/routeConfig.ts +69 -27
- package/src/copy/transformZod.ts +15 -16
- package/dist/generator.js +0 -168
- package/dist/generator.js.map +0 -1
- package/dist/helpers/generateAggregate.js +0 -51
- package/dist/helpers/generateAggregate.js.map +0 -1
- package/dist/helpers/generateCount.js +0 -50
- package/dist/helpers/generateCount.js.map +0 -1
- package/dist/helpers/generateCreate.js +0 -49
- package/dist/helpers/generateCreate.js.map +0 -1
- package/dist/helpers/generateCreateMany.js +0 -49
- package/dist/helpers/generateCreateMany.js.map +0 -1
- package/dist/helpers/generateDelete.js +0 -49
- package/dist/helpers/generateDelete.js.map +0 -1
- package/dist/helpers/generateDeleteMany.js +0 -49
- package/dist/helpers/generateDeleteMany.js.map +0 -1
- package/dist/helpers/generateFindFirst.js +0 -56
- package/dist/helpers/generateFindFirst.js.map +0 -1
- package/dist/helpers/generateFindMany.js +0 -56
- package/dist/helpers/generateFindMany.js.map +0 -1
- package/dist/helpers/generateFindUnique.js +0 -56
- package/dist/helpers/generateFindUnique.js.map +0 -1
- package/dist/helpers/generateGroupBy.js +0 -51
- package/dist/helpers/generateGroupBy.js.map +0 -1
- package/dist/helpers/generateImportPrismaStatement.js +0 -25
- package/dist/helpers/generateImportPrismaStatement.js.map +0 -1
- package/dist/helpers/generateRouteFile.js +0 -192
- package/dist/helpers/generateRouteFile.js.map +0 -1
- package/dist/helpers/generateUpdate.js +0 -49
- package/dist/helpers/generateUpdate.js.map +0 -1
- package/dist/helpers/generateUpdateMany.js +0 -49
- package/dist/helpers/generateUpdateMany.js.map +0 -1
- package/dist/helpers/generateUpsert.js +0 -49
- package/dist/helpers/generateUpsert.js.map +0 -1
- package/dist/utils/formatFile.js +0 -26
- package/dist/utils/formatFile.js.map +0 -1
- package/src/bin.ts +0 -2
- package/src/constants.ts +0 -1
- package/src/copy/encodeQueryParams.spec.ts +0 -303
- package/src/copy/encodeQueryParams.ts +0 -44
- package/src/copy/misc.spec.ts +0 -62
- package/src/copy/parseQueryParams.spec.ts +0 -187
- package/src/copy/transformZod.spec.ts +0 -763
- package/src/generator.ts +0 -188
- package/src/helpers/generateAggregate.ts +0 -59
- package/src/helpers/generateCount.ts +0 -58
- package/src/helpers/generateCreate.ts +0 -56
- package/src/helpers/generateCreateMany.ts +0 -55
- package/src/helpers/generateDelete.ts +0 -57
- package/src/helpers/generateDeleteMany.ts +0 -57
- package/src/helpers/generateFindFirst.ts +0 -62
- package/src/helpers/generateFindMany.ts +0 -62
- package/src/helpers/generateFindUnique.ts +0 -62
- package/src/helpers/generateGroupBy.ts +0 -60
- package/src/helpers/generateImportPrismaStatement.ts +0 -38
- package/src/helpers/generateRouteFile.ts +0 -195
- package/src/helpers/generateUpdate.ts +0 -56
- package/src/helpers/generateUpdateMany.ts +0 -56
- package/src/helpers/generateUpsert.ts +0 -57
- package/src/utils/copyFiles.ts +0 -27
- package/src/utils/formatFile.ts +0 -22
- package/src/utils/strings.ts +0 -7
- package/src/utils/writeFileSafely.ts +0 -29
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { DMMF } from '@prisma/generator-helper'
|
|
2
|
-
import { toPascalCase } from '../utils/strings'
|
|
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
|
-
passToNext?: boolean;
|
|
33
|
-
locals?: {
|
|
34
|
-
data?: ${modelName} | null
|
|
35
|
-
outputValidator?: ZodTypeAny;
|
|
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
|
-
const outputValidator = req.locals?.outputValidator || req.outputValidation;
|
|
43
|
-
|
|
44
|
-
const data = await req.prisma.${toPascalCase(modelName)}.findUnique(req.query as ${queryTypeName});
|
|
45
|
-
if (req.passToNext) {
|
|
46
|
-
if (req.locals) req.locals.data = data;
|
|
47
|
-
next();
|
|
48
|
-
} else if (outputValidator) {
|
|
49
|
-
const validationResult = outputValidator.safeParse(data);
|
|
50
|
-
if (validationResult.success) {
|
|
51
|
-
return res.status(200).json(validationResult.data);
|
|
52
|
-
} else {
|
|
53
|
-
return res.status(400).json({ error: 'Invalid data format', details: validationResult.error });
|
|
54
|
-
}
|
|
55
|
-
} else {
|
|
56
|
-
return res.status(200).json(data);
|
|
57
|
-
}
|
|
58
|
-
} catch(error: unknown) {
|
|
59
|
-
next(error)
|
|
60
|
-
}
|
|
61
|
-
}`
|
|
62
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { DMMF } from '@prisma/generator-helper'
|
|
2
|
-
import { toPascalCase } from '../utils/strings'
|
|
3
|
-
import { PrismaClient, Prisma } from '@prisma/client'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Generates an Express middleware function that handles groupBy queries
|
|
7
|
-
* and includes conditional output validation with Zod.
|
|
8
|
-
* This version dynamically includes the correct type for the arguments based on the Prisma model.
|
|
9
|
-
* @param options - The options containing the model name and the import statement for Prisma types.
|
|
10
|
-
* @returns {string} - The generated middleware function as a string.
|
|
11
|
-
*/
|
|
12
|
-
export const generateGroupByFunction = (options: {
|
|
13
|
-
model: DMMF.Model
|
|
14
|
-
prismaImportStatement: string
|
|
15
|
-
}): string => {
|
|
16
|
-
const { model, prismaImportStatement } = options
|
|
17
|
-
const modelName = model.name
|
|
18
|
-
const functionName = `${modelName}GroupBy`
|
|
19
|
-
const argsTypeName = `Prisma.${modelName}GroupByArgs`
|
|
20
|
-
|
|
21
|
-
return `
|
|
22
|
-
${prismaImportStatement}
|
|
23
|
-
import { Request, Response, NextFunction } from 'express';
|
|
24
|
-
import { RequestHandler, ParamsDictionary } from 'express-serve-static-core';
|
|
25
|
-
import { ParsedQs } from 'qs';
|
|
26
|
-
import { ZodTypeAny } from 'zod';
|
|
27
|
-
|
|
28
|
-
interface GroupByRequest extends Request {
|
|
29
|
-
prisma: PrismaClient;
|
|
30
|
-
query: Partial<${argsTypeName}> & ParsedQs;
|
|
31
|
-
outputValidation?: ZodTypeAny;
|
|
32
|
-
locals?: {
|
|
33
|
-
outputValidator?: ZodTypeAny;
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export type GroupByMiddleware = RequestHandler<ParamsDictionary, any, {}, ParsedQs>;
|
|
38
|
-
|
|
39
|
-
export async function ${functionName}(req: GroupByRequest, res: Response, next: NextFunction) {
|
|
40
|
-
try {
|
|
41
|
-
const outputValidator = req.locals?.outputValidator || req.outputValidation;
|
|
42
|
-
|
|
43
|
-
// @ts-ignore
|
|
44
|
-
const result = await req.prisma.${toPascalCase(modelName)}.groupBy(req.query);
|
|
45
|
-
|
|
46
|
-
if (outputValidator) {
|
|
47
|
-
const validationResult = outputValidator.safeParse(result);
|
|
48
|
-
if (validationResult.success) {
|
|
49
|
-
return res.status(200).json(validationResult.data);
|
|
50
|
-
} else {
|
|
51
|
-
return res.status(400).json({ error: 'Invalid data format', details: validationResult.error });
|
|
52
|
-
}
|
|
53
|
-
} else {
|
|
54
|
-
return res.status(200).json(result);
|
|
55
|
-
}
|
|
56
|
-
} catch(error: unknown) {
|
|
57
|
-
next(error)
|
|
58
|
-
}
|
|
59
|
-
}`
|
|
60
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,195 +0,0 @@
|
|
|
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 `import express, {
|
|
12
|
-
RequestHandler
|
|
13
|
-
} from 'express'
|
|
14
|
-
import { ParsedQs } from 'qs'
|
|
15
|
-
import { ${modelName}FindFirst } from './${modelName}FindFirst';
|
|
16
|
-
import { ${modelName}FindMany } from './${modelName}FindMany';
|
|
17
|
-
import { ${modelName}FindUnique } from './${modelName}FindUnique';
|
|
18
|
-
import { ${modelName}Create } from './${modelName}Create';
|
|
19
|
-
import { ${modelName}CreateMany } from './${modelName}CreateMany';
|
|
20
|
-
import { ${modelName}Update } from './${modelName}Update';
|
|
21
|
-
import { ${modelName}UpdateMany } from './${modelName}UpdateMany';
|
|
22
|
-
import { ${modelName}Upsert } from './${modelName}Upsert';
|
|
23
|
-
import { ${modelName}Delete } from './${modelName}Delete';
|
|
24
|
-
import { ${modelName}DeleteMany } from './${modelName}DeleteMany';
|
|
25
|
-
import { ${modelName}Aggregate } from './${modelName}Aggregate';
|
|
26
|
-
import { ${modelName}Count } from './${modelName}Count';
|
|
27
|
-
import { ${modelName}GroupBy } from './${modelName}GroupBy';
|
|
28
|
-
import { createValidatorMiddleware, removeTrailingSlash } from '../createValidatorMiddleware'
|
|
29
|
-
import { RouteConfig, ValidatorConfig } from '../routeConfig'
|
|
30
|
-
import { parseQueryParams } from "../parseQueryParams";
|
|
31
|
-
|
|
32
|
-
const defaultBeforeAfter = {
|
|
33
|
-
before: [] as RequestHandler[],
|
|
34
|
-
after: [] as RequestHandler[],
|
|
35
|
-
inputValidator: undefined,
|
|
36
|
-
outputValidator: undefined,
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Generates an Express router for ${modelName} model.
|
|
41
|
-
* @param config Contains optional middleware to enable routes.
|
|
42
|
-
* @param customUrlPrefix Optional custom URL prefix for the routes.
|
|
43
|
-
* @returns {express.Router}
|
|
44
|
-
*/
|
|
45
|
-
export function ${routerFunctionName}(config: RouteConfig<RequestHandler>) {
|
|
46
|
-
const router = express.Router();
|
|
47
|
-
const basePath = removeTrailingSlash(config.customUrlPrefix || '') +
|
|
48
|
-
removeTrailingSlash(config.addModelPrefix !== false ? '/${modelName.toLowerCase()}' : '');
|
|
49
|
-
|
|
50
|
-
const setupRoute = (
|
|
51
|
-
path: string,
|
|
52
|
-
method: "all" | "get" | "post" | "put" | "delete" | "patch" | "options" | "head",
|
|
53
|
-
middlewares: RequestHandler[],
|
|
54
|
-
handler: RequestHandler,
|
|
55
|
-
inputValidator?: ValidatorConfig,
|
|
56
|
-
outputValidator?: ValidatorConfig
|
|
57
|
-
) => {
|
|
58
|
-
const middlewaresWithValidators: RequestHandler[] = [
|
|
59
|
-
(req, res, next) => {
|
|
60
|
-
if (req.query) {
|
|
61
|
-
req.query = parseQueryParams(req.query as Record<string, string>) as ParsedQs;
|
|
62
|
-
}
|
|
63
|
-
next();
|
|
64
|
-
},
|
|
65
|
-
...middlewares
|
|
66
|
-
];
|
|
67
|
-
|
|
68
|
-
if (inputValidator) {
|
|
69
|
-
middlewaresWithValidators.push(createValidatorMiddleware({
|
|
70
|
-
schema: inputValidator.schema,
|
|
71
|
-
allowedPaths: inputValidator.allow,
|
|
72
|
-
forbiddenPaths: inputValidator.forbid,
|
|
73
|
-
target: method === 'get' ? 'query' : 'body',
|
|
74
|
-
}));
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
middlewaresWithValidators.push((req, res, next) => {
|
|
78
|
-
res.locals.outputValidator = outputValidator;
|
|
79
|
-
next();
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
middlewaresWithValidators.push(handler);
|
|
83
|
-
|
|
84
|
-
router[method](removeTrailingSlash(basePath + path), ...middlewaresWithValidators);
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (config.enableAll || config?.findFirst) {
|
|
89
|
-
const { before = [], after = [], inputValidator, outputValidator } = config.findFirst || defaultBeforeAfter;
|
|
90
|
-
setupRoute('/first', 'get', before, ${modelName}FindFirst as RequestHandler, inputValidator, outputValidator);
|
|
91
|
-
if (after.length) {
|
|
92
|
-
router.use(removeTrailingSlash(basePath) + '/first', ...after);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (config.enableAll || config?.findMany) {
|
|
97
|
-
const { before = [], after = [], inputValidator, outputValidator } = config.findMany || defaultBeforeAfter;
|
|
98
|
-
setupRoute('/', 'get', before, ${modelName}FindMany as RequestHandler, inputValidator, outputValidator);
|
|
99
|
-
if (after.length) {
|
|
100
|
-
router.use(removeTrailingSlash(basePath + '/'), ...after);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (config.enableAll || config?.findUnique) {
|
|
105
|
-
const { before = [], after = [], inputValidator, outputValidator } = config.findUnique || defaultBeforeAfter;
|
|
106
|
-
setupRoute('/:id', 'get', before, ${modelName}FindUnique as any, inputValidator, outputValidator);
|
|
107
|
-
if (after.length) {
|
|
108
|
-
router.use(removeTrailingSlash(basePath) + '/:id', ...after);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
if (config.enableAll || config?.create) {
|
|
113
|
-
const { before = [], after = [], inputValidator, outputValidator } = config.create || defaultBeforeAfter;
|
|
114
|
-
setupRoute('/', 'post', before, ${modelName}Create as RequestHandler, inputValidator, outputValidator);
|
|
115
|
-
if (after.length) {
|
|
116
|
-
router.use(removeTrailingSlash(basePath + '/'), ...after);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (config.enableAll || config?.createMany) {
|
|
121
|
-
const { before = [], after = [], inputValidator, outputValidator } = config.createMany || defaultBeforeAfter;
|
|
122
|
-
setupRoute('/many', 'post', before, ${modelName}CreateMany as RequestHandler, inputValidator, outputValidator);
|
|
123
|
-
if (after.length) {
|
|
124
|
-
router.use(removeTrailingSlash(basePath) + '/many', ...after);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (config.enableAll || config?.update) {
|
|
129
|
-
const { before = [], after = [], inputValidator, outputValidator } = config.update || defaultBeforeAfter;
|
|
130
|
-
setupRoute('/', 'put', before, ${modelName}Update as RequestHandler, inputValidator, outputValidator);
|
|
131
|
-
if (after.length) {
|
|
132
|
-
router.use(removeTrailingSlash(basePath + '/'), ...after);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (config.enableAll || config?.updateMany) {
|
|
137
|
-
const { before = [], after = [], inputValidator, outputValidator } = config.updateMany || defaultBeforeAfter;
|
|
138
|
-
setupRoute('/many', 'put', before, ${modelName}UpdateMany as RequestHandler, inputValidator, outputValidator);
|
|
139
|
-
if (after.length) {
|
|
140
|
-
router.use(removeTrailingSlash(basePath) + '/many', ...after);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
if (config.enableAll || config?.upsert) {
|
|
145
|
-
const { before = [], after = [], inputValidator, outputValidator } = config.upsert || defaultBeforeAfter;
|
|
146
|
-
setupRoute('/', 'patch', before, ${modelName}Upsert as RequestHandler, inputValidator, outputValidator);
|
|
147
|
-
if (after.length) {
|
|
148
|
-
router.use(removeTrailingSlash(basePath + '/'), ...after);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
if (config.enableAll || config?.delete) {
|
|
153
|
-
const { before = [], after = [], inputValidator, outputValidator } = config.delete || defaultBeforeAfter;
|
|
154
|
-
setupRoute('/', 'delete', before, ${modelName}Delete as RequestHandler, inputValidator, outputValidator);
|
|
155
|
-
if (after.length) {
|
|
156
|
-
router.use(removeTrailingSlash(basePath + '/'), ...after);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
if (config.enableAll || config?.deleteMany) {
|
|
161
|
-
const { before = [], after = [], inputValidator, outputValidator } = config.deleteMany || defaultBeforeAfter;
|
|
162
|
-
setupRoute('/many', 'delete', before, ${modelName}DeleteMany as RequestHandler, inputValidator, outputValidator);
|
|
163
|
-
if (after.length) {
|
|
164
|
-
router.use(removeTrailingSlash(basePath) + '/many', ...after);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
if (config.enableAll || config?.aggregate) {
|
|
169
|
-
const { before = [], after = [], inputValidator, outputValidator } = config.aggregate || defaultBeforeAfter;
|
|
170
|
-
setupRoute('/aggregate', 'get', before, ${modelName}Aggregate as RequestHandler, inputValidator, outputValidator);
|
|
171
|
-
if (after.length) {
|
|
172
|
-
router.use(removeTrailingSlash(basePath) + '/aggregate', ...after);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
if (config.enableAll || config?.count) {
|
|
177
|
-
const { before = [], after = [], inputValidator, outputValidator } = config.count || defaultBeforeAfter;
|
|
178
|
-
setupRoute('/count', 'get', before, ${modelName}Count as RequestHandler, inputValidator, outputValidator);
|
|
179
|
-
if (after.length) {
|
|
180
|
-
router.use(removeTrailingSlash(basePath) + '/count', ...after);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
if (config.enableAll || config?.groupBy) {
|
|
185
|
-
const { before = [], after = [], inputValidator, outputValidator } = config.groupBy || defaultBeforeAfter;
|
|
186
|
-
setupRoute('/groupby', 'get', before, ${modelName}GroupBy as RequestHandler, inputValidator, outputValidator);
|
|
187
|
-
if (after.length) {
|
|
188
|
-
router.use(removeTrailingSlash(basePath) + '/groupby', ...after);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
return router;
|
|
193
|
-
}
|
|
194
|
-
`
|
|
195
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { DMMF } from '@prisma/generator-helper'
|
|
2
|
-
import { toPascalCase } from '../utils/strings'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Generates an Express middleware function that handles updating records 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 generateUpdateFunction = (options: {
|
|
11
|
-
model: DMMF.Model
|
|
12
|
-
prismaImportStatement: string
|
|
13
|
-
}): string => {
|
|
14
|
-
const { model, prismaImportStatement } = options
|
|
15
|
-
const modelName = model.name
|
|
16
|
-
const functionName = `${modelName}Update`
|
|
17
|
-
const argsTypeName = `Prisma.${modelName}UpdateArgs`
|
|
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 UpdateRequest extends Request {
|
|
26
|
-
prisma: PrismaClient;
|
|
27
|
-
body: ${argsTypeName};
|
|
28
|
-
outputValidation?: ZodTypeAny;
|
|
29
|
-
locals?: {
|
|
30
|
-
outputValidator?: ZodTypeAny;
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export type UpdateMiddleware = RequestHandler<ParamsDictionary, any, ${argsTypeName}, Record<string, any>>
|
|
35
|
-
|
|
36
|
-
export async function ${functionName}(req: UpdateRequest, res: Response, next: NextFunction) {
|
|
37
|
-
try {
|
|
38
|
-
const outputValidator = req.locals?.outputValidator || req.outputValidation;
|
|
39
|
-
|
|
40
|
-
const data = await req.prisma.${toPascalCase(modelName)}.update(req.body);
|
|
41
|
-
|
|
42
|
-
if (outputValidator) {
|
|
43
|
-
const validationResult = outputValidator.safeParse(data);
|
|
44
|
-
if (validationResult.success) {
|
|
45
|
-
return res.status(200).json(validationResult.data);
|
|
46
|
-
} else {
|
|
47
|
-
return res.status(400).json({ error: 'Invalid data format', details: validationResult.error });
|
|
48
|
-
}
|
|
49
|
-
} else {
|
|
50
|
-
return res.status(200).json(data);
|
|
51
|
-
}
|
|
52
|
-
} catch(error: unknown) {
|
|
53
|
-
next(error)
|
|
54
|
-
}
|
|
55
|
-
}`
|
|
56
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { DMMF } from '@prisma/generator-helper'
|
|
2
|
-
import { toPascalCase } from '../utils/strings'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Generates an Express middleware function that handles updating multiple records 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 generateUpdateManyFunction = (options: {
|
|
11
|
-
model: DMMF.Model
|
|
12
|
-
prismaImportStatement: string
|
|
13
|
-
}): string => {
|
|
14
|
-
const { model, prismaImportStatement } = options
|
|
15
|
-
const modelName = model.name
|
|
16
|
-
const functionName = `${modelName}UpdateMany`
|
|
17
|
-
const argsTypeName = `Prisma.${modelName}UpdateManyArgs`
|
|
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 UpdateManyRequest extends Request {
|
|
26
|
-
prisma: PrismaClient;
|
|
27
|
-
body: ${argsTypeName};
|
|
28
|
-
outputValidation?: ZodTypeAny;
|
|
29
|
-
locals?: {
|
|
30
|
-
outputValidator?: ZodTypeAny;
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export type UpdateManyMiddleware = RequestHandler<ParamsDictionary, any, ${argsTypeName}, Record<string, any>>
|
|
35
|
-
|
|
36
|
-
export async function ${functionName}(req: UpdateManyRequest, res: Response, next: NextFunction) {
|
|
37
|
-
try {
|
|
38
|
-
const outputValidator = req.locals?.outputValidator || req.outputValidation;
|
|
39
|
-
|
|
40
|
-
const data = await req.prisma.${toPascalCase(modelName)}.updateMany(req.body);
|
|
41
|
-
|
|
42
|
-
if (outputValidator) {
|
|
43
|
-
const validationResult = outputValidator.safeParse(data);
|
|
44
|
-
if (validationResult.success) {
|
|
45
|
-
return res.status(200).json({ count: validationResult.data.count });
|
|
46
|
-
} else {
|
|
47
|
-
return res.status(400).json({ error: 'Invalid data format', details: validationResult.error });
|
|
48
|
-
}
|
|
49
|
-
} else {
|
|
50
|
-
return res.status(200).json({ count: data.count });
|
|
51
|
-
}
|
|
52
|
-
} catch(error: unknown) {
|
|
53
|
-
next(error)
|
|
54
|
-
}
|
|
55
|
-
}`
|
|
56
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { DMMF } from '@prisma/generator-helper'
|
|
2
|
-
import { toPascalCase } from '../utils/strings'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Generates an Express middleware function that handles the upsert operation (create or update)
|
|
6
|
-
* and includes conditional output validation with Zod.
|
|
7
|
-
* This version dynamically includes the correct type for the arguments based on the Prisma model.
|
|
8
|
-
* @param options - The options containing the model name and the import statement for Prisma types.
|
|
9
|
-
* @returns {string} - The generated middleware function as a string.
|
|
10
|
-
*/
|
|
11
|
-
export const generateUpsertFunction = (options: {
|
|
12
|
-
model: DMMF.Model
|
|
13
|
-
prismaImportStatement: string
|
|
14
|
-
}): string => {
|
|
15
|
-
const { model, prismaImportStatement } = options
|
|
16
|
-
const modelName = model.name
|
|
17
|
-
const functionName = `${modelName}Upsert`
|
|
18
|
-
const argsTypeName = `Prisma.${modelName}UpsertArgs`
|
|
19
|
-
|
|
20
|
-
return `
|
|
21
|
-
${prismaImportStatement}
|
|
22
|
-
import { Request, Response, NextFunction } from 'express';
|
|
23
|
-
import { RequestHandler, ParamsDictionary } from 'express-serve-static-core';
|
|
24
|
-
import { ZodTypeAny } from 'zod';
|
|
25
|
-
|
|
26
|
-
interface UpsertRequest extends Request {
|
|
27
|
-
prisma: PrismaClient;
|
|
28
|
-
body: ${argsTypeName};
|
|
29
|
-
outputValidation?: ZodTypeAny;
|
|
30
|
-
locals?: {
|
|
31
|
-
outputValidator?: ZodTypeAny;
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export type UpsertMiddleware = RequestHandler<ParamsDictionary, any, ${argsTypeName}, Record<string, any>>
|
|
36
|
-
|
|
37
|
-
export async function ${functionName}(req: UpsertRequest, res: Response, next: NextFunction) {
|
|
38
|
-
try {
|
|
39
|
-
const outputValidator = req.locals?.outputValidator || req.outputValidation;
|
|
40
|
-
|
|
41
|
-
const data = await req.prisma.${toPascalCase(modelName)}.upsert(req.body);
|
|
42
|
-
|
|
43
|
-
if (outputValidator) {
|
|
44
|
-
const validationResult = outputValidator.safeParse(data);
|
|
45
|
-
if (validationResult.success) {
|
|
46
|
-
return res.status(200).json(validationResult.data);
|
|
47
|
-
} else {
|
|
48
|
-
return res.status(400).json({ error: 'Invalid data format', details: validationResult.error });
|
|
49
|
-
}
|
|
50
|
-
} else {
|
|
51
|
-
return res.status(200).json(data);
|
|
52
|
-
}
|
|
53
|
-
} catch(error: unknown) {
|
|
54
|
-
next(error)
|
|
55
|
-
}
|
|
56
|
-
}`
|
|
57
|
-
}
|
package/src/utils/copyFiles.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { GeneratorOptions } from '@prisma/generator-helper'
|
|
2
|
-
import fs from 'fs/promises'
|
|
3
|
-
import path from 'path'
|
|
4
|
-
|
|
5
|
-
export const copyFiles = async (
|
|
6
|
-
options: GeneratorOptions,
|
|
7
|
-
destPath?: string,
|
|
8
|
-
) => {
|
|
9
|
-
const sourceDir = path.join(__dirname.replace('dist', 'src'), '..', 'copy')
|
|
10
|
-
const destinationDir = destPath || options.generator.output?.value!
|
|
11
|
-
|
|
12
|
-
const files = await fs.readdir(sourceDir)
|
|
13
|
-
|
|
14
|
-
for (const file of files) {
|
|
15
|
-
if (file.endsWith('.spec.ts')) {
|
|
16
|
-
continue
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const sourceFile = path.join(sourceDir, file)
|
|
20
|
-
const destinationFile = path.join(destinationDir, file)
|
|
21
|
-
|
|
22
|
-
await fs.mkdir(path.dirname(destinationFile), { recursive: true })
|
|
23
|
-
await fs.copyFile(sourceFile, destinationFile)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
console.log(`Files copied from ${sourceDir} to ${destinationDir}`)
|
|
27
|
-
}
|
package/src/utils/formatFile.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
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
|
-
}
|
package/src/utils/strings.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
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 =
|
|
18
|
-
operation === 'index' ? 'index' : `${model?.name || ''}${operation}`
|
|
19
|
-
const filePath = path.join(
|
|
20
|
-
options.generator.output?.value!,
|
|
21
|
-
model ? `${model?.name}/${fileName}.ts` : `/${fileName}.ts`,
|
|
22
|
-
)
|
|
23
|
-
console.log('filePath :>> ', filePath)
|
|
24
|
-
await fs.mkdir(path.dirname(filePath), {
|
|
25
|
-
recursive: true,
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
await fs.writeFile(filePath, await formatFile(content))
|
|
29
|
-
}
|