prisma-generator-express 1.67.0 → 1.69.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.
Files changed (68) hide show
  1. package/README.md +223 -28
  2. package/dist/copy/operationDefinitions.d.ts +4 -1
  3. package/dist/copy/operationDefinitions.js +64 -3
  4. package/dist/copy/operationDefinitions.js.map +1 -1
  5. package/dist/generators/generateFastifyHandler.js +55 -9
  6. package/dist/generators/generateFastifyHandler.js.map +1 -1
  7. package/dist/generators/generateHonoHandler.js +44 -4
  8. package/dist/generators/generateHonoHandler.js.map +1 -1
  9. package/dist/generators/generateHonoOpenApi.d.ts +13 -0
  10. package/dist/generators/generateHonoOpenApi.js +70 -0
  11. package/dist/generators/generateHonoOpenApi.js.map +1 -0
  12. package/dist/generators/generateMcpApp.d.ts +10 -0
  13. package/dist/generators/generateMcpApp.js +113 -0
  14. package/dist/generators/generateMcpApp.js.map +1 -0
  15. package/dist/generators/generateModelMcp.d.ts +9 -0
  16. package/dist/generators/generateModelMcp.js +145 -0
  17. package/dist/generators/generateModelMcp.js.map +1 -0
  18. package/dist/generators/generateModelMetadata.js +9 -5
  19. package/dist/generators/generateModelMetadata.js.map +1 -1
  20. package/dist/generators/generateRouter.js +62 -56
  21. package/dist/generators/generateRouter.js.map +1 -1
  22. package/dist/generators/generateRouterFastify.js +56 -64
  23. package/dist/generators/generateRouterFastify.js.map +1 -1
  24. package/dist/generators/generateRouterHono.js +43 -411
  25. package/dist/generators/generateRouterHono.js.map +1 -1
  26. package/dist/generators/generateRouterPartsHono.d.ts +14 -0
  27. package/dist/generators/generateRouterPartsHono.js +180 -0
  28. package/dist/generators/generateRouterPartsHono.js.map +1 -0
  29. package/dist/generators/generateUnifiedHandler.js +36 -20
  30. package/dist/generators/generateUnifiedHandler.js.map +1 -1
  31. package/dist/index.d.ts +2 -0
  32. package/dist/index.js +101 -3
  33. package/dist/index.js.map +1 -1
  34. package/dist/utils/copyFiles.d.ts +1 -1
  35. package/dist/utils/copyFiles.js +20 -1
  36. package/dist/utils/copyFiles.js.map +1 -1
  37. package/dist/utils/mcpGate.d.ts +10 -0
  38. package/dist/utils/mcpGate.js +118 -0
  39. package/dist/utils/mcpGate.js.map +1 -0
  40. package/dist/utils/writeFileSafely.js +6 -0
  41. package/dist/utils/writeFileSafely.js.map +1 -1
  42. package/package.json +18 -3
  43. package/src/copy/buildModelOpenApi.ts +76 -126
  44. package/src/copy/docsRenderer.ts +14 -15
  45. package/src/copy/mcpRuntime.ts +1017 -0
  46. package/src/copy/operationDefinitions.ts +78 -4
  47. package/src/copy/operationPipeline.ts +267 -0
  48. package/src/copy/operationRuntime.ts +24 -14
  49. package/src/copy/operationSchemas.ts +2773 -0
  50. package/src/copy/pagination.ts +10 -2
  51. package/src/copy/routeConfig.hono.ts +34 -5
  52. package/src/copy/routeConfig.ts +1 -1
  53. package/src/copy/routerParts.ts +524 -0
  54. package/src/generators/generateFastifyHandler.ts +55 -9
  55. package/src/generators/generateHonoHandler.ts +44 -4
  56. package/src/generators/generateHonoOpenApi.ts +93 -0
  57. package/src/generators/generateMcpApp.ts +133 -0
  58. package/src/generators/generateModelMcp.ts +208 -0
  59. package/src/generators/generateModelMetadata.ts +16 -10
  60. package/src/generators/generateRouter.ts +62 -56
  61. package/src/generators/generateRouterFastify.ts +56 -64
  62. package/src/generators/generateRouterHono.ts +49 -459
  63. package/src/generators/generateRouterPartsHono.ts +220 -0
  64. package/src/generators/generateUnifiedHandler.ts +36 -21
  65. package/src/index.ts +116 -3
  66. package/src/utils/copyFiles.ts +36 -0
  67. package/src/utils/mcpGate.ts +157 -0
  68. package/src/utils/writeFileSafely.ts +6 -0
@@ -0,0 +1,157 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+
4
+ /**
5
+ * MCP is fail-closed at GENERATION time: a guard-dropped artifact must not
6
+ * carry MCP support, because every MCP tool enforces a guard shape and a
7
+ * dropped guard would turn reads and writes into unguarded operations.
8
+ *
9
+ * MCP tool schemas are built against prisma-guard 1.33 semantics (unique
10
+ * selectors, operator configs, forced-value merging). A consumer running an
11
+ * older guard would accept shapes the tool schemas misrepresent, so an
12
+ * mcp=true generation REFUSES to emit MCP support unless prisma-guard
13
+ * >= 1.33.0 is resolvable from the schema's project.
14
+ */
15
+ export function assertMcpGuardCompatibility(
16
+ mcp: boolean,
17
+ dropGuard: boolean,
18
+ ): void {
19
+ if (mcp && dropGuard) {
20
+ throw new Error(
21
+ 'Generator option mcp=true cannot be combined with dropGuard=true. ' +
22
+ 'MCP is fail-closed: every tool enforces a guard shape, so a ' +
23
+ 'guard-dropped generation refuses to emit MCP support.',
24
+ )
25
+ }
26
+ }
27
+
28
+ const MCP_MIN_GUARD = '1.33.0'
29
+
30
+ type Semver = {
31
+ core: [number, number, number]
32
+ pre: string[]
33
+ }
34
+
35
+ /** Semver 2.0.0 ordering, including prerelease precedence. */
36
+ export function parseSemver(v: string): Semver | null {
37
+ // strict semver 2.0.0: no leading-zero numeric identifiers, no empty
38
+ // dot-separated prerelease/build identifiers; build metadata is parsed
39
+ // and ignored for precedence
40
+ const numeric = '0|[1-9]' + '\\d*'
41
+ const ident = '[0-9A-Za-z-]+'
42
+ const dotted = ident + '(?:\\.' + ident + ')*'
43
+ const m = new RegExp(
44
+ `^(${numeric})\\.(${numeric})\\.(${numeric})(?:-(${dotted}))?(?:\\+(${dotted}))?$`,
45
+ ).exec(v.trim())
46
+ if (!m) return null
47
+ const pre = m[4] ? m[4].split('.') : []
48
+ // semver 2.0.0: numeric PRERELEASE identifiers must not carry leading
49
+ // zeros (build-metadata identifiers are exempt)
50
+ for (const ident of pre) {
51
+ if (/^[0-9]+$/.test(ident) && ident.length > 1 && ident.startsWith('0')) {
52
+ return null
53
+ }
54
+ }
55
+ return {
56
+ core: [Number(m[1]), Number(m[2]), Number(m[3])],
57
+ pre,
58
+ }
59
+ }
60
+
61
+ /** `a < b` returns negative, `a > b` positive, equal 0 (semver 2.0.0). */
62
+ export function compareSemver(a: string, b: string): number {
63
+ const va = parseSemver(a)
64
+ const vb = parseSemver(b)
65
+ if (!va || !vb) {
66
+ // unparsable strings sort last so they never satisfy a minimum
67
+ return va ? 1 : vb ? -1 : 0
68
+ }
69
+ for (let i = 0; i < 3; i++) {
70
+ if (va.core[i] !== vb.core[i]) return va.core[i] - vb.core[i]
71
+ }
72
+ // no prerelease > any prerelease
73
+ if (va.pre.length === 0 && vb.pre.length === 0) return 0
74
+ if (va.pre.length === 0) return 1
75
+ if (vb.pre.length === 0) return -1
76
+ const len = Math.max(va.pre.length, vb.pre.length)
77
+ for (let i = 0; i < len; i++) {
78
+ const x = va.pre[i]
79
+ const y = vb.pre[i]
80
+ if (x === undefined) return -1 // shorter set is lower
81
+ if (y === undefined) return 1
82
+ const xn = /^\d+$/.test(x)
83
+ const yn = /^\d+$/.test(y)
84
+ if (xn && yn) {
85
+ if (Number(x) !== Number(y)) return Number(x) - Number(y)
86
+ } else if (xn)
87
+ return -1 // numeric identifiers are lower
88
+ else if (yn) return 1
89
+ else if (x !== y) return x < y ? -1 : 1
90
+ }
91
+ return 0
92
+ }
93
+
94
+ /**
95
+ * Resolve prisma-guard's installed version the way Node resolves it for the
96
+ * generated artifact: walk UP from the schema's directory, checking
97
+ * `<ancestor>/node_modules/prisma-guard` at each level, and stop at the
98
+ * FIRST hit. Returns null when no ancestor carries an install.
99
+ */
100
+ export function resolveInstalledGuardVersion(
101
+ schemaPath: string,
102
+ ): string | null {
103
+ const schemaDir = path.dirname(path.resolve(schemaPath))
104
+ let dir: string | undefined = schemaDir
105
+ while (dir) {
106
+ const pkgPath = path.join(
107
+ dir,
108
+ 'node_modules',
109
+ 'prisma-guard',
110
+ 'package.json',
111
+ )
112
+ try {
113
+ const version = (
114
+ JSON.parse(fs.readFileSync(pkgPath, 'utf8')) as {
115
+ version?: string
116
+ }
117
+ ).version
118
+ if (typeof version === 'string') return version
119
+ } catch {
120
+ // not installed at this ancestor — keep walking
121
+ }
122
+ const parent = path.dirname(dir)
123
+ dir = parent !== dir ? parent : undefined
124
+ }
125
+ return null
126
+ }
127
+
128
+ export function assertMcpGuardVersion(
129
+ mcp: boolean,
130
+ schemaPath: string,
131
+ resolve: (schemaPath: string) => string | null = resolveInstalledGuardVersion,
132
+ ): void {
133
+ if (!mcp) return
134
+ const version = resolve(schemaPath)
135
+ if (version === null) {
136
+ throw new Error(
137
+ 'mcp=true requires prisma-guard >= ' +
138
+ MCP_MIN_GUARD +
139
+ ', but prisma-guard could not be resolved from the schema project. ' +
140
+ 'Install it (npm install prisma-guard@^' +
141
+ MCP_MIN_GUARD +
142
+ ') or turn mcp off.',
143
+ )
144
+ }
145
+ if (compareSemver(version, MCP_MIN_GUARD) < 0) {
146
+ throw new Error(
147
+ 'mcp=true requires prisma-guard >= ' +
148
+ MCP_MIN_GUARD +
149
+ ' (MCP tool schemas mirror 1.33 semantics: unique-selector where, ' +
150
+ 'operator configs, forced-value merging). Found prisma-guard ' +
151
+ version +
152
+ '. Upgrade it (npm install prisma-guard@^' +
153
+ MCP_MIN_GUARD +
154
+ ') or turn mcp off.',
155
+ )
156
+ }
157
+ }
@@ -39,6 +39,12 @@ export async function writeFileSafely({
39
39
  case 'relationModelsIndex':
40
40
  filePath = path.join(outputPath, 'relationModels.ts')
41
41
  break
42
+ case 'mcpApp':
43
+ filePath = path.join(outputPath, 'mcp.ts')
44
+ break
45
+ case 'mcpMount':
46
+ filePath = path.join(outputPath, 'mcpMount.ts')
47
+ break
42
48
  default:
43
49
  if (!model) throw new Error('Model required for operation: ' + operation)
44
50
  filePath = path.join(