prisma-generator-express 1.28.0 → 1.29.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 +244 -14
- package/dist/constants.d.ts +1 -0
- package/dist/generators/generateFastifyHandler.d.ts +4 -0
- package/dist/generators/generateFastifyHandler.js +78 -0
- package/dist/generators/generateFastifyHandler.js.map +1 -0
- package/dist/generators/generateOperationCore.d.ts +6 -0
- package/dist/generators/generateOperationCore.js +534 -0
- package/dist/generators/generateOperationCore.js.map +1 -0
- package/dist/generators/generateQueryBuilderHelper.js +85 -69
- package/dist/generators/generateQueryBuilderHelper.js.map +1 -1
- package/dist/generators/generateRouter.js +1 -25
- package/dist/generators/generateRouter.js.map +1 -1
- package/dist/generators/generateRouterFastify.d.ts +5 -0
- package/dist/generators/generateRouterFastify.js +512 -0
- package/dist/generators/generateRouterFastify.js.map +1 -0
- package/dist/generators/generateUnifiedDocs.d.ts +2 -1
- package/dist/generators/generateUnifiedDocs.js +147 -82
- package/dist/generators/generateUnifiedDocs.js.map +1 -1
- package/dist/generators/generateUnifiedHandler.d.ts +0 -1
- package/dist/generators/generateUnifiedHandler.js +47 -516
- package/dist/generators/generateUnifiedHandler.js.map +1 -1
- package/dist/generators/generateUnifiedScalarUI.d.ts +2 -0
- package/dist/generators/generateUnifiedScalarUI.js +127 -1324
- package/dist/generators/generateUnifiedScalarUI.js.map +1 -1
- package/dist/index.js +33 -8
- package/dist/index.js.map +1 -1
- package/dist/utils/copyFiles.d.ts +2 -1
- package/dist/utils/copyFiles.js +64 -38
- package/dist/utils/copyFiles.js.map +1 -1
- package/dist/utils/writeFileSafely.js +3 -0
- package/dist/utils/writeFileSafely.js.map +1 -1
- package/package.json +4 -1
- package/src/client/encodeQueryParams.ts +1 -1
- package/src/constants.ts +2 -0
- package/src/copy/createOutputValidatorMiddleware.ts +9 -12
- package/src/copy/docsRenderer.ts +1285 -0
- package/src/copy/parseQueryParams.ts +4 -8
- package/src/copy/routeConfig.ts +10 -4
- package/src/generators/generateFastifyHandler.ts +86 -0
- package/src/generators/generateOperationCore.ts +545 -0
- package/src/generators/generateQueryBuilderHelper.ts +86 -70
- package/src/generators/generateRouter.ts +1 -25
- package/src/generators/generateRouterFastify.ts +522 -0
- package/src/generators/generateUnifiedDocs.ts +164 -81
- package/src/generators/generateUnifiedHandler.ts +45 -533
- package/src/generators/generateUnifiedScalarUI.ts +134 -1323
- package/src/index.ts +45 -9
- package/src/utils/copyFiles.ts +79 -45
- package/src/utils/writeFileSafely.ts +4 -0
package/src/index.ts
CHANGED
|
@@ -4,17 +4,31 @@ import {
|
|
|
4
4
|
DMMF,
|
|
5
5
|
} from '@prisma/generator-helper'
|
|
6
6
|
import { generateUnifiedHandler } from './generators/generateUnifiedHandler.js'
|
|
7
|
+
import { generateFastifyHandler } from './generators/generateFastifyHandler.js'
|
|
7
8
|
import { generateRouterFunction } from './generators/generateRouter.js'
|
|
9
|
+
import { generateFastifyRouterFunction } from './generators/generateRouterFastify.js'
|
|
8
10
|
import { generateScalarUIHandler } from './generators/generateUnifiedScalarUI.js'
|
|
9
11
|
import { generateUnifiedDocs } from './generators/generateUnifiedDocs.js'
|
|
10
12
|
import { generateQueryBuilderHelper } from './generators/generateQueryBuilderHelper.js'
|
|
13
|
+
import {
|
|
14
|
+
generateOperationRuntime,
|
|
15
|
+
generateModelCore,
|
|
16
|
+
} from './generators/generateOperationCore.js'
|
|
11
17
|
import {
|
|
12
18
|
generateImportPrismaStatement,
|
|
13
19
|
getRelativeClientPath,
|
|
14
20
|
} from './generators/generateImportPrismaStatement.js'
|
|
15
21
|
import { writeFileSafely } from './utils/writeFileSafely.js'
|
|
16
22
|
import { copyFiles } from './utils/copyFiles.js'
|
|
17
|
-
import { GENERATOR_NAME } from './constants.js'
|
|
23
|
+
import { GENERATOR_NAME, Target } from './constants.js'
|
|
24
|
+
|
|
25
|
+
function getTarget(options: GeneratorOptions): Target {
|
|
26
|
+
const raw = String(
|
|
27
|
+
(options.generator.config as Record<string, unknown>).target ?? 'express',
|
|
28
|
+
).toLowerCase()
|
|
29
|
+
if (raw === 'express' || raw === 'fastify') return raw
|
|
30
|
+
throw new Error(`Invalid target "${raw}". Expected "express" or "fastify".`)
|
|
31
|
+
}
|
|
18
32
|
|
|
19
33
|
generatorHandler({
|
|
20
34
|
onManifest() {
|
|
@@ -26,14 +40,29 @@ generatorHandler({
|
|
|
26
40
|
},
|
|
27
41
|
|
|
28
42
|
async onGenerate(options: GeneratorOptions) {
|
|
29
|
-
const
|
|
43
|
+
const target = getTarget(options)
|
|
30
44
|
|
|
31
|
-
console.log(
|
|
45
|
+
console.log(`\n═══ Prisma Generator (${target.toUpperCase()}) ═══`)
|
|
46
|
+
console.log(` Target: ${target}`)
|
|
32
47
|
|
|
33
|
-
await copyFiles(options)
|
|
48
|
+
await copyFiles(options, target)
|
|
49
|
+
|
|
50
|
+
await writeFileSafely({
|
|
51
|
+
content: generateOperationRuntime(),
|
|
52
|
+
options,
|
|
53
|
+
operation: 'operationRuntime',
|
|
54
|
+
})
|
|
34
55
|
|
|
35
56
|
const modelNames: string[] = []
|
|
36
57
|
|
|
58
|
+
const generateHandler =
|
|
59
|
+
target === 'fastify' ? generateFastifyHandler : generateUnifiedHandler
|
|
60
|
+
|
|
61
|
+
const generateRouter =
|
|
62
|
+
target === 'fastify'
|
|
63
|
+
? generateFastifyRouterFunction
|
|
64
|
+
: generateRouterFunction
|
|
65
|
+
|
|
37
66
|
for (const model of options.dmmf.datamodel.models) {
|
|
38
67
|
if (
|
|
39
68
|
model.documentation &&
|
|
@@ -48,9 +77,15 @@ generatorHandler({
|
|
|
48
77
|
const relativeClientPath = getRelativeClientPath(options, model.name)
|
|
49
78
|
|
|
50
79
|
await writeFileSafely({
|
|
51
|
-
content:
|
|
80
|
+
content: generateModelCore({ model: model as DMMF.Model }),
|
|
81
|
+
options,
|
|
82
|
+
model: model as DMMF.Model,
|
|
83
|
+
operation: 'Core',
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
await writeFileSafely({
|
|
87
|
+
content: generateHandler({
|
|
52
88
|
model: model as DMMF.Model,
|
|
53
|
-
prismaImportStatement,
|
|
54
89
|
}),
|
|
55
90
|
options,
|
|
56
91
|
model: model as DMMF.Model,
|
|
@@ -58,7 +93,7 @@ generatorHandler({
|
|
|
58
93
|
})
|
|
59
94
|
|
|
60
95
|
await writeFileSafely({
|
|
61
|
-
content:
|
|
96
|
+
content: generateRouter({
|
|
62
97
|
model: model as DMMF.Model,
|
|
63
98
|
enums: options.dmmf.datamodel.enums as DMMF.DatamodelEnum[],
|
|
64
99
|
relativeClientPath,
|
|
@@ -72,6 +107,7 @@ generatorHandler({
|
|
|
72
107
|
content: generateScalarUIHandler({
|
|
73
108
|
model: model as DMMF.Model,
|
|
74
109
|
enums: options.dmmf.datamodel.enums as DMMF.DatamodelEnum[],
|
|
110
|
+
target,
|
|
75
111
|
}),
|
|
76
112
|
options,
|
|
77
113
|
model: model as DMMF.Model,
|
|
@@ -80,7 +116,7 @@ generatorHandler({
|
|
|
80
116
|
}
|
|
81
117
|
|
|
82
118
|
await writeFileSafely({
|
|
83
|
-
content: generateUnifiedDocs(modelNames),
|
|
119
|
+
content: generateUnifiedDocs(modelNames, target),
|
|
84
120
|
options,
|
|
85
121
|
operation: 'combinedDocs',
|
|
86
122
|
})
|
|
@@ -92,7 +128,7 @@ generatorHandler({
|
|
|
92
128
|
})
|
|
93
129
|
|
|
94
130
|
console.log('\n═══ Generation Complete ═══')
|
|
95
|
-
console.log(`✓ ${modelNames.length} models`)
|
|
131
|
+
console.log(`✓ ${modelNames.length} models (${target})`)
|
|
96
132
|
console.log(`✓ OpenAPI documentation generated`)
|
|
97
133
|
console.log(`✓ Query builder helper generated`)
|
|
98
134
|
console.log('')
|
package/src/utils/copyFiles.ts
CHANGED
|
@@ -1,54 +1,36 @@
|
|
|
1
1
|
import { GeneratorOptions } from '@prisma/generator-helper'
|
|
2
2
|
import * as fs from 'fs'
|
|
3
3
|
import * as path from 'path'
|
|
4
|
+
import { Target } from '../constants.js'
|
|
5
|
+
|
|
6
|
+
const SHARED_FILES = [
|
|
7
|
+
'parseQueryParams.ts',
|
|
8
|
+
'buildModelOpenApi.ts',
|
|
9
|
+
'operationDefinitions.ts',
|
|
10
|
+
'misc.ts',
|
|
11
|
+
'docsRenderer.ts',
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
const TARGET_FILES: Record<Target, string[]> = {
|
|
15
|
+
express: ['routeConfig.ts'],
|
|
16
|
+
fastify: ['routeConfig.ts'],
|
|
17
|
+
}
|
|
4
18
|
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
if (
|
|
8
|
-
|
|
9
|
-
const srcDir = path.join(__dirname, '..', '..', 'src', 'copy')
|
|
10
|
-
|
|
11
|
-
const baseFiles = [
|
|
12
|
-
'routeConfig.ts',
|
|
13
|
-
'parseQueryParams.ts',
|
|
14
|
-
'buildModelOpenApi.ts',
|
|
15
|
-
'operationDefinitions.ts',
|
|
16
|
-
'misc.ts',
|
|
17
|
-
]
|
|
18
|
-
|
|
19
|
-
let allCopied = true
|
|
20
|
-
|
|
21
|
-
console.log(`Copying utility files to: ${outputPath}`)
|
|
19
|
+
function resolveTemplateDir(subpath: string): string {
|
|
20
|
+
const fromSibling = path.join(__dirname, '..', subpath)
|
|
21
|
+
if (fs.existsSync(fromSibling)) return fromSibling
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (!ok) allCopied = false
|
|
26
|
-
}
|
|
23
|
+
const fromSrc = path.join(__dirname, '..', '..', 'src', subpath)
|
|
24
|
+
if (fs.existsSync(fromSrc)) return fromSrc
|
|
27
25
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
fs.mkdirSync(clientDir, { recursive: true })
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const clientSrcDir = path.join(__dirname, '..', '..', 'src', 'client')
|
|
34
|
-
const clientOk = await copyFile(
|
|
35
|
-
clientSrcDir,
|
|
36
|
-
clientDir,
|
|
37
|
-
'encodeQueryParams.ts',
|
|
38
|
-
{
|
|
39
|
-
required: true,
|
|
40
|
-
importRewrites: [{ from: '../copy/misc.js', to: '../misc.js' }],
|
|
41
|
-
},
|
|
26
|
+
throw new Error(
|
|
27
|
+
`Template directory "${subpath}" not found. Searched:\n ${fromSibling}\n ${fromSrc}\nEnsure template files are included in the published package.`,
|
|
42
28
|
)
|
|
43
|
-
|
|
29
|
+
}
|
|
44
30
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
throw new Error(
|
|
49
|
-
'One or more required utility files could not be copied. Generation aborted.',
|
|
50
|
-
)
|
|
51
|
-
}
|
|
31
|
+
function getTargetSourceDir(copyBase: string, target: Target): string {
|
|
32
|
+
if (target === 'express') return copyBase
|
|
33
|
+
return path.join(copyBase, target)
|
|
52
34
|
}
|
|
53
35
|
|
|
54
36
|
interface CopyFileOptions {
|
|
@@ -56,6 +38,10 @@ interface CopyFileOptions {
|
|
|
56
38
|
importRewrites?: Array<{ from: string; to: string }>
|
|
57
39
|
}
|
|
58
40
|
|
|
41
|
+
function escapeRegex(str: string): string {
|
|
42
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
43
|
+
}
|
|
44
|
+
|
|
59
45
|
async function copyFile(
|
|
60
46
|
srcDir: string,
|
|
61
47
|
destDir: string,
|
|
@@ -106,6 +92,54 @@ async function copyFile(
|
|
|
106
92
|
return true
|
|
107
93
|
}
|
|
108
94
|
|
|
109
|
-
function
|
|
110
|
-
|
|
95
|
+
export async function copyFiles(
|
|
96
|
+
options: GeneratorOptions,
|
|
97
|
+
target: Target,
|
|
98
|
+
): Promise<void> {
|
|
99
|
+
const outputPath = options.generator.output?.value
|
|
100
|
+
if (!outputPath) return
|
|
101
|
+
|
|
102
|
+
const copyBase = resolveTemplateDir('copy')
|
|
103
|
+
|
|
104
|
+
let allCopied = true
|
|
105
|
+
|
|
106
|
+
console.log(` Copying utility files to: ${outputPath} (target: ${target})`)
|
|
107
|
+
|
|
108
|
+
for (const file of SHARED_FILES) {
|
|
109
|
+
const ok = await copyFile(copyBase, outputPath, file, { required: true })
|
|
110
|
+
if (!ok) allCopied = false
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const targetSrcDir = getTargetSourceDir(copyBase, target)
|
|
114
|
+
for (const file of TARGET_FILES[target]) {
|
|
115
|
+
const ok = await copyFile(targetSrcDir, outputPath, file, {
|
|
116
|
+
required: true,
|
|
117
|
+
})
|
|
118
|
+
if (!ok) allCopied = false
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const clientDir = path.join(outputPath, 'client')
|
|
122
|
+
if (!fs.existsSync(clientDir)) {
|
|
123
|
+
fs.mkdirSync(clientDir, { recursive: true })
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const clientSrcDir = resolveTemplateDir('client')
|
|
127
|
+
const clientOk = await copyFile(
|
|
128
|
+
clientSrcDir,
|
|
129
|
+
clientDir,
|
|
130
|
+
'encodeQueryParams.ts',
|
|
131
|
+
{
|
|
132
|
+
required: true,
|
|
133
|
+
importRewrites: [{ from: '../copy/misc.js', to: '../misc.js' }],
|
|
134
|
+
},
|
|
135
|
+
)
|
|
136
|
+
if (!clientOk) allCopied = false
|
|
137
|
+
|
|
138
|
+
if (allCopied) {
|
|
139
|
+
console.log(` ✓ Utility files copied successfully`)
|
|
140
|
+
} else {
|
|
141
|
+
throw new Error(
|
|
142
|
+
'One or more required utility files could not be copied. Generation aborted.',
|
|
143
|
+
)
|
|
144
|
+
}
|
|
111
145
|
}
|
|
@@ -41,6 +41,10 @@ export async function writeFileSafely({
|
|
|
41
41
|
filePath = path.join(outputPath, 'queryBuilder.ts')
|
|
42
42
|
break
|
|
43
43
|
|
|
44
|
+
case 'operationRuntime':
|
|
45
|
+
filePath = path.join(outputPath, 'operationRuntime.ts')
|
|
46
|
+
break
|
|
47
|
+
|
|
44
48
|
default:
|
|
45
49
|
if (!model) {
|
|
46
50
|
throw new Error(`Model required for operation: ${operation}`)
|