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.
- package/README.md +223 -28
- package/dist/copy/operationDefinitions.d.ts +4 -1
- package/dist/copy/operationDefinitions.js +64 -3
- package/dist/copy/operationDefinitions.js.map +1 -1
- package/dist/generators/generateFastifyHandler.js +55 -9
- package/dist/generators/generateFastifyHandler.js.map +1 -1
- package/dist/generators/generateHonoHandler.js +44 -4
- package/dist/generators/generateHonoHandler.js.map +1 -1
- package/dist/generators/generateHonoOpenApi.d.ts +13 -0
- package/dist/generators/generateHonoOpenApi.js +70 -0
- package/dist/generators/generateHonoOpenApi.js.map +1 -0
- package/dist/generators/generateMcpApp.d.ts +10 -0
- package/dist/generators/generateMcpApp.js +113 -0
- package/dist/generators/generateMcpApp.js.map +1 -0
- package/dist/generators/generateModelMcp.d.ts +9 -0
- package/dist/generators/generateModelMcp.js +145 -0
- package/dist/generators/generateModelMcp.js.map +1 -0
- package/dist/generators/generateModelMetadata.js +9 -5
- package/dist/generators/generateModelMetadata.js.map +1 -1
- package/dist/generators/generateRouter.js +62 -56
- package/dist/generators/generateRouter.js.map +1 -1
- package/dist/generators/generateRouterFastify.js +56 -64
- package/dist/generators/generateRouterFastify.js.map +1 -1
- package/dist/generators/generateRouterHono.js +43 -411
- package/dist/generators/generateRouterHono.js.map +1 -1
- package/dist/generators/generateRouterPartsHono.d.ts +14 -0
- package/dist/generators/generateRouterPartsHono.js +180 -0
- package/dist/generators/generateRouterPartsHono.js.map +1 -0
- package/dist/generators/generateUnifiedHandler.js +36 -20
- package/dist/generators/generateUnifiedHandler.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +101 -3
- package/dist/index.js.map +1 -1
- package/dist/utils/copyFiles.d.ts +1 -1
- package/dist/utils/copyFiles.js +20 -1
- package/dist/utils/copyFiles.js.map +1 -1
- package/dist/utils/mcpGate.d.ts +10 -0
- package/dist/utils/mcpGate.js +118 -0
- package/dist/utils/mcpGate.js.map +1 -0
- package/dist/utils/writeFileSafely.js +6 -0
- package/dist/utils/writeFileSafely.js.map +1 -1
- package/package.json +18 -3
- package/src/copy/buildModelOpenApi.ts +76 -126
- package/src/copy/docsRenderer.ts +14 -15
- package/src/copy/mcpRuntime.ts +1017 -0
- package/src/copy/operationDefinitions.ts +78 -4
- package/src/copy/operationPipeline.ts +267 -0
- package/src/copy/operationRuntime.ts +24 -14
- package/src/copy/operationSchemas.ts +2773 -0
- package/src/copy/pagination.ts +10 -2
- package/src/copy/routeConfig.hono.ts +34 -5
- package/src/copy/routeConfig.ts +1 -1
- package/src/copy/routerParts.ts +524 -0
- package/src/generators/generateFastifyHandler.ts +55 -9
- package/src/generators/generateHonoHandler.ts +44 -4
- package/src/generators/generateHonoOpenApi.ts +93 -0
- package/src/generators/generateMcpApp.ts +133 -0
- package/src/generators/generateModelMcp.ts +208 -0
- package/src/generators/generateModelMetadata.ts +16 -10
- package/src/generators/generateRouter.ts +62 -56
- package/src/generators/generateRouterFastify.ts +56 -64
- package/src/generators/generateRouterHono.ts +49 -459
- package/src/generators/generateRouterPartsHono.ts +220 -0
- package/src/generators/generateUnifiedHandler.ts +36 -21
- package/src/index.ts +116 -3
- package/src/utils/copyFiles.ts +36 -0
- package/src/utils/mcpGate.ts +157 -0
- package/src/utils/writeFileSafely.ts +6 -0
|
@@ -16,8 +16,24 @@ export async function ${exportName}(
|
|
|
16
16
|
request: FastifyRequest,
|
|
17
17
|
_reply: FastifyReply,
|
|
18
18
|
): Promise<void> {
|
|
19
|
-
const
|
|
20
|
-
|
|
19
|
+
const fx = request as FastifyExtended
|
|
20
|
+
const data = await executeOperation(
|
|
21
|
+
{ variantKey: fx.guardVariantKey, caller: fx.guardCaller },
|
|
22
|
+
{ guardShape: fx.guardShape },
|
|
23
|
+
{
|
|
24
|
+
core: core.${meta.coreName},
|
|
25
|
+
args: queryChannel(request),
|
|
26
|
+
body: request.body,
|
|
27
|
+
prisma: requirePrisma(fx.prisma),
|
|
28
|
+
postgres: fx.postgres,
|
|
29
|
+
sqlite: fx.sqlite,
|
|
30
|
+
pagination: fx.routeConfig?.pagination,
|
|
31
|
+
override: fx.operationOverride,
|
|
32
|
+
getContext: fx.getContext,
|
|
33
|
+
findManyPaginatedMode: fx.findManyPaginatedMode,
|
|
34
|
+
},
|
|
35
|
+
)
|
|
36
|
+
fx.resultData = data
|
|
21
37
|
}`;
|
|
22
38
|
})
|
|
23
39
|
.join('\n');
|
|
@@ -29,10 +45,24 @@ export async function ${exportName}(
|
|
|
29
45
|
request: FastifyRequest,
|
|
30
46
|
_reply: FastifyReply,
|
|
31
47
|
): Promise<void> {
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
48
|
+
const fx = request as FastifyExtended
|
|
49
|
+
const data = await executeOperation(
|
|
50
|
+
{ variantKey: fx.guardVariantKey, caller: fx.guardCaller },
|
|
51
|
+
{ guardShape: fx.guardShape },
|
|
52
|
+
{
|
|
53
|
+
core: core.${meta.coreName},
|
|
54
|
+
args: queryChannel(request),
|
|
55
|
+
body: request.body,
|
|
56
|
+
prisma: requirePrisma(fx.prisma),
|
|
57
|
+
postgres: fx.postgres,
|
|
58
|
+
sqlite: fx.sqlite,
|
|
59
|
+
pagination: fx.routeConfig?.pagination,
|
|
60
|
+
override: fx.operationOverride,
|
|
61
|
+
getContext: fx.getContext,
|
|
62
|
+
},
|
|
63
|
+
)
|
|
64
|
+
fx.resultData = data
|
|
65
|
+
fx.resultStatus = ${meta.successStatus}
|
|
36
66
|
}`;
|
|
37
67
|
})
|
|
38
68
|
.join('\n');
|
|
@@ -49,28 +79,44 @@ export async function ${updateEachExportName}(
|
|
|
49
79
|
return `import type { FastifyRequest, FastifyReply } from 'fastify'
|
|
50
80
|
import * as core from './${modelName}Core${ext}'
|
|
51
81
|
import type { RuntimeOperationOverride, OperationContext, FindManyPaginatedMode } from '../operationRuntime${ext}'
|
|
82
|
+
import type { PaginationConfig } from '../routeConfig${ext}'
|
|
83
|
+
import {
|
|
84
|
+
executeOperation,
|
|
85
|
+
requirePrisma,
|
|
86
|
+
type ArgsChannel,
|
|
87
|
+
} from '../operationPipeline${ext}'
|
|
52
88
|
|
|
53
89
|
type FastifyExtended = FastifyRequest & {
|
|
54
90
|
prisma?: unknown
|
|
55
91
|
postgres?: unknown
|
|
56
92
|
sqlite?: unknown
|
|
57
93
|
parsedQuery?: Record<string, unknown>
|
|
58
|
-
routeConfig?: { pagination?:
|
|
94
|
+
routeConfig?: { pagination?: PaginationConfig }
|
|
59
95
|
guardShape?: Record<string, unknown>
|
|
60
96
|
guardCaller?: string
|
|
61
97
|
guardVariantKey?: string
|
|
62
98
|
operationOverride?: RuntimeOperationOverride
|
|
63
|
-
|
|
99
|
+
getContext?: () => Promise<unknown>
|
|
64
100
|
findManyPaginatedMode?: FindManyPaginatedMode
|
|
65
101
|
resultData?: unknown
|
|
66
102
|
resultStatus?: number
|
|
67
103
|
}
|
|
68
104
|
|
|
105
|
+
function queryChannel(request: FastifyRequest): ArgsChannel {
|
|
106
|
+
const fx = request as FastifyExtended
|
|
107
|
+
return {
|
|
108
|
+
read: () => fx.parsedQuery,
|
|
109
|
+
write: (next) => {
|
|
110
|
+
fx.parsedQuery = next
|
|
111
|
+
},
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
69
115
|
function buildContext(request: FastifyRequest): OperationContext {
|
|
70
116
|
const req = request as FastifyExtended
|
|
71
117
|
return {
|
|
72
118
|
operationOverride: req.operationOverride,
|
|
73
|
-
resolveOperationContext: req.
|
|
119
|
+
resolveOperationContext: req.getContext,
|
|
74
120
|
prisma: req.prisma,
|
|
75
121
|
postgres: req.postgres,
|
|
76
122
|
sqlite: req.sqlite,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateFastifyHandler.js","sourceRoot":"","sources":["../../src/generators/generateFastifyHandler.ts"],"names":[],"mappings":";;AAKA,
|
|
1
|
+
{"version":3,"file":"generateFastifyHandler.js","sourceRoot":"","sources":["../../src/generators/generateFastifyHandler.ts"],"names":[],"mappings":";;AAKA,wDA6IC;AAhJD,kDAA8C;AAC9C,uEAAiE;AAEjE,SAAgB,sBAAsB,CAAC,OAGtC;IACC,MAAM,GAAG,GAAG,IAAA,qBAAS,EAAC,OAAO,CAAC,WAAW,CAAC,CAAA;IAC1C,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAA;IAEpC,MAAM,OAAO,GAAG,yCAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAA;IACnE,MAAM,QAAQ,GAAG,yCAAkB,CAAC,MAAM,CACxC,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY,CACxE,CAAA;IAED,MAAM,YAAY,GAAG,OAAO;SACzB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACZ,MAAM,UAAU,GAAG,GAAG,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;QAC1F,OAAO;wBACW,UAAU;;;;;;;;;mBASf,IAAI,CAAC,QAAQ;;;;;;;;;;;;;EAa9B,CAAA;IACE,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAA;IAEb,MAAM,aAAa,GAAG,QAAQ;SAC3B,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACZ,MAAM,UAAU,GAAG,GAAG,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;QAC1F,OAAO;wBACW,UAAU;;;;;;;;;mBASf,IAAI,CAAC,QAAQ;;;;;;;;;;;;sBAYV,IAAI,CAAC,aAAa;EACtC,CAAA;IACE,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAA;IAEb,MAAM,oBAAoB,GAAG,GAAG,SAAS,YAAY,CAAA;IACrD,MAAM,iBAAiB,GAAG;wBACJ,oBAAoB;;;;;;;EAO1C,CAAA;IAEA,OAAO;2BACkB,SAAS,OAAO,GAAG;6GAC+D,GAAG;uDACzD,GAAG;;;;;8BAK5B,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6C/B,YAAY;EACZ,aAAa;EACb,iBAAiB;CAClB,CAAA;AACD,CAAC"}
|
|
@@ -13,7 +13,21 @@ function generateHonoHandler(options) {
|
|
|
13
13
|
const exportName = `${modelName}${meta.name.charAt(0).toUpperCase() + meta.name.slice(1)}`;
|
|
14
14
|
return `
|
|
15
15
|
export async function ${exportName}(c: HandlerContext): Promise<void> {
|
|
16
|
-
const data = await
|
|
16
|
+
const data = await executeOperation(
|
|
17
|
+
{ variantKey: c.get('guardVariantKey'), caller: c.get('guardCaller') },
|
|
18
|
+
{ guardShape: c.get('guardShape') },
|
|
19
|
+
{
|
|
20
|
+
core: core.${meta.coreName},
|
|
21
|
+
args: queryChannel(c),
|
|
22
|
+
body: c.get('body'),
|
|
23
|
+
prisma: requirePrisma(c.get('prisma')),
|
|
24
|
+
postgres: c.get('postgres'),
|
|
25
|
+
sqlite: c.get('sqlite'),
|
|
26
|
+
pagination: c.get('routeConfig')?.pagination,
|
|
27
|
+
override: c.get('operationOverride'),
|
|
28
|
+
getContext: c.get('getContext'),
|
|
29
|
+
},
|
|
30
|
+
)
|
|
17
31
|
c.set('resultData', data)
|
|
18
32
|
}`;
|
|
19
33
|
})
|
|
@@ -23,7 +37,21 @@ export async function ${exportName}(c: HandlerContext): Promise<void> {
|
|
|
23
37
|
const exportName = `${modelName}${meta.name.charAt(0).toUpperCase() + meta.name.slice(1)}`;
|
|
24
38
|
return `
|
|
25
39
|
export async function ${exportName}(c: HandlerContext): Promise<void> {
|
|
26
|
-
const data = await
|
|
40
|
+
const data = await executeOperation(
|
|
41
|
+
{ variantKey: c.get('guardVariantKey'), caller: c.get('guardCaller') },
|
|
42
|
+
{ guardShape: c.get('guardShape') },
|
|
43
|
+
{
|
|
44
|
+
core: core.${meta.coreName},
|
|
45
|
+
args: queryChannel(c),
|
|
46
|
+
body: c.get('body'),
|
|
47
|
+
prisma: requirePrisma(c.get('prisma')),
|
|
48
|
+
postgres: c.get('postgres'),
|
|
49
|
+
sqlite: c.get('sqlite'),
|
|
50
|
+
pagination: c.get('routeConfig')?.pagination,
|
|
51
|
+
override: c.get('operationOverride'),
|
|
52
|
+
getContext: c.get('getContext'),
|
|
53
|
+
},
|
|
54
|
+
)
|
|
27
55
|
c.set('resultData', data)
|
|
28
56
|
c.set('resultStatus', ${meta.successStatus})
|
|
29
57
|
}`;
|
|
@@ -38,15 +66,27 @@ export async function ${updateEachExportName}(c: HandlerContext): Promise<void>
|
|
|
38
66
|
}`;
|
|
39
67
|
return `import type { Context } from 'hono'
|
|
40
68
|
import * as core from './${modelName}Core${ext}'
|
|
41
|
-
import type {
|
|
69
|
+
import type { OperationContext } from '../operationRuntime${ext}'
|
|
70
|
+
import {
|
|
71
|
+
executeOperation,
|
|
72
|
+
requirePrisma,
|
|
73
|
+
type ArgsChannel,
|
|
74
|
+
} from '../operationPipeline${ext}'
|
|
42
75
|
import type { HonoInternalVariables } from '../routeConfig.target${ext}'
|
|
43
76
|
|
|
44
77
|
type HandlerContext = Context<{ Variables: HonoInternalVariables }>
|
|
45
78
|
|
|
79
|
+
function queryChannel(c: HandlerContext): ArgsChannel {
|
|
80
|
+
return {
|
|
81
|
+
read: () => c.get('parsedQuery'),
|
|
82
|
+
write: (next) => c.set('parsedQuery', next),
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
46
86
|
function buildContext(c: HandlerContext): OperationContext {
|
|
47
87
|
return {
|
|
48
88
|
operationOverride: c.get('operationOverride'),
|
|
49
|
-
resolveOperationContext: c.get('
|
|
89
|
+
resolveOperationContext: c.get('getContext'),
|
|
50
90
|
prisma: c.get('prisma'),
|
|
51
91
|
postgres: c.get('postgres'),
|
|
52
92
|
sqlite: c.get('sqlite'),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateHonoHandler.js","sourceRoot":"","sources":["../../src/generators/generateHonoHandler.ts"],"names":[],"mappings":";;AAKA,
|
|
1
|
+
{"version":3,"file":"generateHonoHandler.js","sourceRoot":"","sources":["../../src/generators/generateHonoHandler.ts"],"names":[],"mappings":";;AAKA,kDA8GC;AAjHD,kDAA8C;AAC9C,uEAAiE;AAEjE,SAAgB,mBAAmB,CAAC,OAGnC;IACC,MAAM,GAAG,GAAG,IAAA,qBAAS,EAAC,OAAO,CAAC,WAAW,CAAC,CAAA;IAC1C,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAA;IAEpC,MAAM,OAAO,GAAG,yCAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAA;IACnE,MAAM,QAAQ,GAAG,yCAAkB,CAAC,MAAM,CACxC,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY,CACxE,CAAA;IAED,MAAM,YAAY,GAAG,OAAO;SACzB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACZ,MAAM,UAAU,GAAG,GAAG,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;QAC1F,OAAO;wBACW,UAAU;;;;;mBAKf,IAAI,CAAC,QAAQ;;;;;;;;;;;;EAY9B,CAAA;IACE,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAA;IAEb,MAAM,aAAa,GAAG,QAAQ;SAC3B,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACZ,MAAM,UAAU,GAAG,GAAG,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;QAC1F,OAAO;wBACW,UAAU;;;;;mBAKf,IAAI,CAAC,QAAQ;;;;;;;;;;;;0BAYN,IAAI,CAAC,aAAa;EAC1C,CAAA;IACE,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAA;IAEb,MAAM,oBAAoB,GAAG,GAAG,SAAS,YAAY,CAAA;IACrD,MAAM,iBAAiB,GAAG;wBACJ,oBAAoB;;;;EAI1C,CAAA;IAEA,OAAO;2BACkB,SAAS,OAAO,GAAG;4DACc,GAAG;;;;;8BAKjC,GAAG;mEACkC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;EA0BpE,YAAY;EACZ,aAAa;EACb,iBAAiB;CAClB,CAAA;AACD,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DMMF } from '@prisma/generator-helper';
|
|
2
|
+
import type { ImportStyle } from '../utils/resolveImportStyle';
|
|
3
|
+
import type { WriteStrategy } from '../constants';
|
|
4
|
+
import { type PathCase } from '../utils/pathCasing';
|
|
5
|
+
export declare function generateHonoOpenApiRoutes({ model, enums, guardShapesImport, clientImport, importStyle, writeStrategy, pathCase, }: {
|
|
6
|
+
model: DMMF.Model;
|
|
7
|
+
enums: DMMF.DatamodelEnum[];
|
|
8
|
+
guardShapesImport: string | null;
|
|
9
|
+
clientImport?: string;
|
|
10
|
+
importStyle: ImportStyle;
|
|
11
|
+
writeStrategy: WriteStrategy;
|
|
12
|
+
pathCase: PathCase;
|
|
13
|
+
}): string;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateHonoOpenApiRoutes = generateHonoOpenApiRoutes;
|
|
4
|
+
const generateRouteConfigType_1 = require("./generateRouteConfigType");
|
|
5
|
+
const importExt_1 = require("../utils/importExt");
|
|
6
|
+
const pathCasing_1 = require("../utils/pathCasing");
|
|
7
|
+
function generateHonoOpenApiRoutes({ model, enums, guardShapesImport, clientImport, importStyle, writeStrategy, pathCase, }) {
|
|
8
|
+
const ext = (0, importExt_1.importExt)(importStyle);
|
|
9
|
+
const modelName = model.name;
|
|
10
|
+
const modelSegment = (0, pathCasing_1.modelPathSegment)(modelName, pathCase);
|
|
11
|
+
const lower = modelName.charAt(0).toLowerCase() + modelName.slice(1);
|
|
12
|
+
return `import { Hono } from 'hono'
|
|
13
|
+
import type {
|
|
14
|
+
RouteConfig,
|
|
15
|
+
HonoEnvBase,
|
|
16
|
+
GeneratedHonoEnv,
|
|
17
|
+
PrismaClientLike,
|
|
18
|
+
} from '../routeConfig.target${ext}'
|
|
19
|
+
import { normalizePrefix, getEnv } from '../misc${ext}'
|
|
20
|
+
import { registerOpenApiRoutes } from '../routerParts${ext}'
|
|
21
|
+
import { buildModelOpenApi } from '../buildModelOpenApi${ext}'
|
|
22
|
+
import { MODEL_FIELDS, MODEL_ENUMS } from './${modelName}Metadata${ext}'
|
|
23
|
+
|
|
24
|
+
${(0, generateRouteConfigType_1.generateRouteConfigType)(modelName, 'HonoBeforeHook', guardShapesImport, importStyle, 'hono', clientImport)}
|
|
25
|
+
|
|
26
|
+
export function ${lower}OpenApi<TCtx = unknown, TPrisma extends PrismaClientLike = PrismaClientLike, TEnv extends HonoEnvBase = HonoEnvBase>(config: ${modelName}RouteConfig<TCtx, TPrisma, TEnv> = {}): Hono<GeneratedHonoEnv<TEnv>> {
|
|
27
|
+
const _env = getEnv()
|
|
28
|
+
const customPrefix = normalizePrefix(config.customUrlPrefix || '')
|
|
29
|
+
const modelPrefix = config.addModelPrefix !== false ? '/${modelSegment}' : ''
|
|
30
|
+
const basePath = customPrefix + modelPrefix
|
|
31
|
+
|
|
32
|
+
const openApiDisabled = config.disableOpenApi === true
|
|
33
|
+
|| (config.disableOpenApi !== false && (
|
|
34
|
+
_env.NODE_ENV === 'production'
|
|
35
|
+
|| _env.DISABLE_OPENAPI === 'true'
|
|
36
|
+
))
|
|
37
|
+
|
|
38
|
+
const app = new Hono<GeneratedHonoEnv<TEnv>>()
|
|
39
|
+
if (!openApiDisabled) {
|
|
40
|
+
let jsonCache: unknown = undefined
|
|
41
|
+
let yamlCache: string | undefined = undefined
|
|
42
|
+
registerOpenApiRoutes(app, basePath, () => {
|
|
43
|
+
if (jsonCache === undefined) {
|
|
44
|
+
jsonCache = buildModelOpenApi(
|
|
45
|
+
'${modelName}',
|
|
46
|
+
MODEL_FIELDS as unknown as Parameters<typeof buildModelOpenApi>[1],
|
|
47
|
+
MODEL_ENUMS as unknown as Parameters<typeof buildModelOpenApi>[2],
|
|
48
|
+
config as unknown as Parameters<typeof buildModelOpenApi>[3],
|
|
49
|
+
{ format: 'json', writeStrategy: '${writeStrategy}', pathSegment: '${modelSegment}' },
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
return jsonCache
|
|
53
|
+
}, () => {
|
|
54
|
+
if (yamlCache === undefined) {
|
|
55
|
+
yamlCache = buildModelOpenApi(
|
|
56
|
+
'${modelName}',
|
|
57
|
+
MODEL_FIELDS as unknown as Parameters<typeof buildModelOpenApi>[1],
|
|
58
|
+
MODEL_ENUMS as unknown as Parameters<typeof buildModelOpenApi>[2],
|
|
59
|
+
config as unknown as Parameters<typeof buildModelOpenApi>[3],
|
|
60
|
+
{ format: 'yaml', writeStrategy: '${writeStrategy}', pathSegment: '${modelSegment}' },
|
|
61
|
+
) as string
|
|
62
|
+
}
|
|
63
|
+
return yamlCache
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
return app
|
|
67
|
+
}
|
|
68
|
+
`;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=generateHonoOpenApi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateHonoOpenApi.js","sourceRoot":"","sources":["../../src/generators/generateHonoOpenApi.ts"],"names":[],"mappings":";;AAaA,8DA+EC;AA3FD,uEAAmE;AAEnE,kDAA8C;AAE9C,oDAAqE;AAQrE,SAAgB,yBAAyB,CAAC,EACxC,KAAK,EACL,KAAK,EACL,iBAAiB,EACjB,YAAY,EACZ,WAAW,EACX,aAAa,EACb,QAAQ,GAST;IACC,MAAM,GAAG,GAAG,IAAA,qBAAS,EAAC,WAAW,CAAC,CAAA;IAClC,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAA;IAC5B,MAAM,YAAY,GAAG,IAAA,6BAAgB,EAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;IAC1D,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAEpE,OAAO;;;;;;+BAMsB,GAAG;kDACgB,GAAG;uDACE,GAAG;yDACD,GAAG;+CACb,SAAS,WAAW,GAAG;;EAEpE,IAAA,iDAAuB,EAAC,SAAS,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,CAAC;;kBAE1F,KAAK,gIAAgI,SAAS;;;4DAGpG,YAAY;;;;;;;;;;;;;;;;aAgB3D,SAAS;;;;8CAIwB,aAAa,oBAAoB,YAAY;;;;;;;aAO9E,SAAS;;;;8CAIwB,aAAa,oBAAoB,YAAY;;;;;;;;CAQ1F,CAAA;AACD,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ImportStyle } from '../utils/resolveImportStyle';
|
|
2
|
+
export declare function generateMcpApp({ serverName, serverVersion, importStyle, }: {
|
|
3
|
+
serverName: string;
|
|
4
|
+
serverVersion: string;
|
|
5
|
+
importStyle: ImportStyle;
|
|
6
|
+
}): string;
|
|
7
|
+
export declare function generateMcpMount({ target, importStyle, }: {
|
|
8
|
+
target: 'express' | 'fastify' | 'hono';
|
|
9
|
+
importStyle: ImportStyle;
|
|
10
|
+
}): string;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateMcpApp = generateMcpApp;
|
|
4
|
+
exports.generateMcpMount = generateMcpMount;
|
|
5
|
+
function generateMcpApp({ serverName, serverVersion, importStyle, }) {
|
|
6
|
+
return `import type { McpServer } from '@modelcontextprotocol/server'
|
|
7
|
+
import { registerMcpTools } from './mcpRuntime'
|
|
8
|
+
import type { McpSharedOptions, McpToolContribution } from './mcpRuntime'
|
|
9
|
+
|
|
10
|
+
export const MCP_SERVER_INFO = { name: ${JSON.stringify(serverName)}, version: ${JSON.stringify(serverVersion)} } as const
|
|
11
|
+
|
|
12
|
+
export type McpRegisterOptions = McpSharedOptions & {
|
|
13
|
+
/** Explicit allowlist: only these model-operation tools are registered. */
|
|
14
|
+
tools: readonly McpToolContribution[]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Register the allowed MCP tools on a server instance. Call from the
|
|
19
|
+
* per-request server factory so \`authInfo\` is the verified principal for THIS
|
|
20
|
+
* request. Throws before registering anything when required options are
|
|
21
|
+
* missing, limits are invalid, or the guard is dropped in this environment.
|
|
22
|
+
*/
|
|
23
|
+
export function registerMcpToolsOnServer(
|
|
24
|
+
server: McpServer,
|
|
25
|
+
options: McpRegisterOptions,
|
|
26
|
+
): void {
|
|
27
|
+
registerMcpTools(server, options)
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
}
|
|
31
|
+
function generateMcpMount({ target, importStyle, }) {
|
|
32
|
+
if (target === 'express') {
|
|
33
|
+
return `import type { RequestHandler } from 'express'
|
|
34
|
+
import type { McpServer, AuthInfo } from '@modelcontextprotocol/server'
|
|
35
|
+
import { createMcpHandler } from '@modelcontextprotocol/server'
|
|
36
|
+
import { toNodeHandler } from '@modelcontextprotocol/node'
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Build the /mcp handler for Express. Authentication is YOUR middleware: put a
|
|
40
|
+
* verified AuthInfo on req.auth (e.g. requireBearerAuth from
|
|
41
|
+
* @modelcontextprotocol/express) before this handler runs. Without req.auth
|
|
42
|
+
* the request fails closed — registration refuses to run without a verified
|
|
43
|
+
* principal.
|
|
44
|
+
*/
|
|
45
|
+
export function createMcpExpressHandler(
|
|
46
|
+
getServer: (authInfo: AuthInfo) => McpServer,
|
|
47
|
+
): RequestHandler {
|
|
48
|
+
const handler = createMcpHandler((ctx) => getServer(ctx.authInfo as AuthInfo))
|
|
49
|
+
const node = toNodeHandler(handler)
|
|
50
|
+
return (req, res) => void node(req, res, req.body)
|
|
51
|
+
}
|
|
52
|
+
`;
|
|
53
|
+
}
|
|
54
|
+
if (target === 'fastify') {
|
|
55
|
+
return `import type { FastifyRequest, FastifyReply } from 'fastify'
|
|
56
|
+
import type { McpServer, AuthInfo } from '@modelcontextprotocol/server'
|
|
57
|
+
import { createMcpHandler } from '@modelcontextprotocol/server'
|
|
58
|
+
import { toNodeHandler } from '@modelcontextprotocol/node'
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Build the /mcp handler for Fastify. Authentication is YOUR hook: attach the
|
|
62
|
+
* verified AuthInfo to request.raw.auth (onRequest) before this handler runs.
|
|
63
|
+
* Without it the request fails closed — registration refuses to run without a
|
|
64
|
+
* verified principal.
|
|
65
|
+
*/
|
|
66
|
+
export function createMcpFastifyHandler(
|
|
67
|
+
getServer: (authInfo: AuthInfo) => McpServer,
|
|
68
|
+
): (request: FastifyRequest, reply: FastifyReply) => Promise<void> {
|
|
69
|
+
const handler = createMcpHandler((ctx) => getServer(ctx.authInfo as AuthInfo))
|
|
70
|
+
const node = toNodeHandler(handler)
|
|
71
|
+
return async (request, reply) => {
|
|
72
|
+
// The Node handler writes the response itself; without hijacking,
|
|
73
|
+
// Fastify would continue its own reply lifecycle after we return.
|
|
74
|
+
reply.hijack()
|
|
75
|
+
await node(request.raw, reply.raw, request.body)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
`;
|
|
79
|
+
}
|
|
80
|
+
return `import type { Context, Next } from 'hono'
|
|
81
|
+
import type { McpServer, AuthInfo } from '@modelcontextprotocol/server'
|
|
82
|
+
import { createMcpHandler } from '@modelcontextprotocol/server'
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Build the /mcp handler for Hono (web-standard). Authentication is YOUR
|
|
86
|
+
* middleware: verify the request and set c.set('authInfo', verified) before
|
|
87
|
+
* this handler runs — or use the web-standard requireBearerAuth gate from
|
|
88
|
+
* @modelcontextprotocol/server and pass its AuthInfo to fetch explicitly.
|
|
89
|
+
*/
|
|
90
|
+
export function createMcpHonoHandler(
|
|
91
|
+
getServer: (authInfo: AuthInfo) => McpServer,
|
|
92
|
+
): (c: Context) => Promise<Response> {
|
|
93
|
+
const handler = createMcpHandler((ctx) => getServer(ctx.authInfo as AuthInfo))
|
|
94
|
+
return async (c: Context) => {
|
|
95
|
+
let parsedBody: unknown
|
|
96
|
+
try {
|
|
97
|
+
parsedBody = await c.req.json()
|
|
98
|
+
} catch {
|
|
99
|
+
parsedBody = undefined
|
|
100
|
+
}
|
|
101
|
+
const authInfo = c.get('authInfo') as AuthInfo | undefined
|
|
102
|
+
if (!authInfo) {
|
|
103
|
+
return Response.json(
|
|
104
|
+
{ message: 'unauthenticated: a verified principal is required' },
|
|
105
|
+
{ status: 401 },
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
return handler.fetch(c.req.raw, { parsedBody, authInfo })
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
`;
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=generateMcpApp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateMcpApp.js","sourceRoot":"","sources":["../../src/generators/generateMcpApp.ts"],"names":[],"mappings":";;AAMA,wCAiCC;AAMD,4CAuFC;AA9HD,SAAgB,cAAc,CAAC,EAC7B,UAAU,EACV,aAAa,EACb,WAAW,GAKZ;IACC,OAAO;;;;yCAIgC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,cAAc,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC;;;;;;;;;;;;;;;;;;;CAmB7G,CAAA;AACD,CAAC;AAMD,SAAgB,gBAAgB,CAAC,EAC/B,MAAM,EACN,WAAW,GAIZ;IACC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO;;;;;;;;;;;;;;;;;;;CAmBV,CAAA;IACC,CAAC;IACD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO;;;;;;;;;;;;;;;;;;;;;;;CAuBV,CAAA;IACC,CAAC;IACD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BR,CAAA;AACD,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DMMF } from '@prisma/generator-helper';
|
|
2
|
+
import type { ImportStyle } from '../utils/resolveImportStyle';
|
|
3
|
+
import type { WriteStrategy } from '../constants';
|
|
4
|
+
export declare function generateModelMcp({ model, allModels, importStyle, writeStrategy, }: {
|
|
5
|
+
model: DMMF.Model;
|
|
6
|
+
allModels: readonly DMMF.Model[];
|
|
7
|
+
importStyle: ImportStyle;
|
|
8
|
+
writeStrategy: WriteStrategy;
|
|
9
|
+
}): string;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateModelMcp = generateModelMcp;
|
|
4
|
+
const importExt_1 = require("../utils/importExt");
|
|
5
|
+
const operationDefinitions_1 = require("../copy/operationDefinitions");
|
|
6
|
+
const MCP_OPS = [
|
|
7
|
+
{ name: 'findMany', coreName: 'findMany' },
|
|
8
|
+
{ name: 'findUnique', coreName: 'findUnique' },
|
|
9
|
+
{ name: 'findFirst', coreName: 'findFirst' },
|
|
10
|
+
{ name: 'count', coreName: 'count' },
|
|
11
|
+
{ name: 'findManyPaginated', coreName: 'findManyPaginated' },
|
|
12
|
+
];
|
|
13
|
+
const MCP_WRITE_OPS = operationDefinitions_1.OPERATION_METADATA.filter((m) => (m.kind === 'write' || m.kind === 'batch') && m.name !== 'updateEach').map((m) => ({ name: m.name, coreName: m.coreName }));
|
|
14
|
+
const MAX_PROJECTION_DEPTH = 4;
|
|
15
|
+
function transitiveRelations(model, allModels) {
|
|
16
|
+
const byName = new Map(allModels.map((m) => [m.name, m]));
|
|
17
|
+
const involved = new Set([model.name]);
|
|
18
|
+
let frontier = [model.name];
|
|
19
|
+
for (let depth = 0; depth < MAX_PROJECTION_DEPTH; depth++) {
|
|
20
|
+
const next = [];
|
|
21
|
+
for (const name of frontier) {
|
|
22
|
+
const m = byName.get(name);
|
|
23
|
+
if (!m)
|
|
24
|
+
continue;
|
|
25
|
+
for (const field of m.fields) {
|
|
26
|
+
if (field.kind === 'object' &&
|
|
27
|
+
byName.has(field.type) &&
|
|
28
|
+
!involved.has(field.type)) {
|
|
29
|
+
involved.add(field.type);
|
|
30
|
+
next.push(field.type);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (next.length === 0)
|
|
35
|
+
break;
|
|
36
|
+
frontier = next;
|
|
37
|
+
}
|
|
38
|
+
return [...involved].filter((n) => n !== model.name);
|
|
39
|
+
}
|
|
40
|
+
function generateModelMcp({ model, allModels, importStyle, writeStrategy, }) {
|
|
41
|
+
const ext = (0, importExt_1.importExt)(importStyle);
|
|
42
|
+
const modelName = model.name;
|
|
43
|
+
const lower = modelName.charAt(0).toLowerCase() + modelName.slice(1);
|
|
44
|
+
const cap = (s) => s.charAt(0).toUpperCase() + s.slice(1);
|
|
45
|
+
const related = transitiveRelations(model, allModels);
|
|
46
|
+
const relatedImports = related
|
|
47
|
+
.map((t) => `import { MODEL_FIELDS as ${t}Fields, MODEL_ENUMS as ${t}Enums, COMPOUND_ID as ${t}CompoundId, COMPOUND_UNIQUES as ${t}CompoundUniques } from '../${t}/${t}Metadata${ext}'`)
|
|
48
|
+
.join('\n');
|
|
49
|
+
const enumSets = [modelName, ...related]
|
|
50
|
+
.map((t) => `for (const e of ${t === modelName ? 'MODEL_ENUMS' : t + 'Enums'}) {
|
|
51
|
+
enums.set(e.name, e.values.map((v) => v.name))
|
|
52
|
+
}`)
|
|
53
|
+
.join('\n');
|
|
54
|
+
const coreEntries = [modelName, ...related]
|
|
55
|
+
.map((t) => {
|
|
56
|
+
const fields = t === modelName ? 'MODEL_FIELDS' : t + 'Fields';
|
|
57
|
+
const compound = t === modelName
|
|
58
|
+
? 'compoundUniques'
|
|
59
|
+
: `(() => {
|
|
60
|
+
const list: Array<{ selector: string; fields: string[] }> = []
|
|
61
|
+
if (${t}CompoundId) {
|
|
62
|
+
list.push({ selector: ${t}CompoundId.selector, fields: [...${t}CompoundId.fields] })
|
|
63
|
+
}
|
|
64
|
+
for (const cu of ${t}CompoundUniques) {
|
|
65
|
+
list.push({ selector: cu.selector, fields: [...cu.fields] })
|
|
66
|
+
}
|
|
67
|
+
return list
|
|
68
|
+
})()`;
|
|
69
|
+
return ` ['${t}', {
|
|
70
|
+
name: '${t}',
|
|
71
|
+
fields: ${fields},
|
|
72
|
+
enums,
|
|
73
|
+
uniqueFields: ${fields}.filter((f) => f.isId || f.isUnique).map((f) => f.name),
|
|
74
|
+
compoundUniques: ${compound},
|
|
75
|
+
}]`;
|
|
76
|
+
})
|
|
77
|
+
.join(',\n');
|
|
78
|
+
const writeNames = new Set(MCP_WRITE_OPS.map((op) => op.name));
|
|
79
|
+
const factories = [...MCP_OPS, ...MCP_WRITE_OPS]
|
|
80
|
+
.map((op) => `
|
|
81
|
+
export function ${lower}${cap(op.name)}Tool<TCtx = unknown, TPrisma extends PrismaClientLike = PrismaClientLike>(options: {
|
|
82
|
+
config: ${modelName}RouteConfig<TCtx, TPrisma>
|
|
83
|
+
}): McpToolContribution {
|
|
84
|
+
return ${writeNames.has(op.name) ? 'createMcpWriteTool' : 'createMcpReadTool'}({
|
|
85
|
+
model: '${modelName}',
|
|
86
|
+
operation: '${op.name}',
|
|
87
|
+
config: options.config as unknown as Record<string, unknown>,
|
|
88
|
+
core: core.${op.coreName},
|
|
89
|
+
fields: MODEL_FIELDS,
|
|
90
|
+
enums: enums,
|
|
91
|
+
uniqueFields: MODEL_FIELDS.filter((f) => f.isId || f.isUnique).map(
|
|
92
|
+
(f) => f.name,
|
|
93
|
+
),
|
|
94
|
+
compoundUniques: compoundUniques,
|
|
95
|
+
modelIndex: modelIndex,${writeNames.has(op.name)
|
|
96
|
+
? `
|
|
97
|
+
writeStrategy: '${writeStrategy}',`
|
|
98
|
+
: ''}
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
`)
|
|
102
|
+
.join('\n');
|
|
103
|
+
return `import * as core from './${modelName}Core${ext}'
|
|
104
|
+
import type { ${modelName}RouteConfig } from './${modelName}Router${ext}'
|
|
105
|
+
import type { PrismaClientLike } from '../routeConfig.target${ext}'
|
|
106
|
+
import {
|
|
107
|
+
createMcpReadTool,
|
|
108
|
+
createMcpWriteTool,
|
|
109
|
+
type McpToolContribution,
|
|
110
|
+
type SchemaModelMeta,
|
|
111
|
+
} from '../mcpRuntime${ext}'
|
|
112
|
+
import {
|
|
113
|
+
MODEL_FIELDS,
|
|
114
|
+
MODEL_ENUMS,
|
|
115
|
+
COMPOUND_ID,
|
|
116
|
+
COMPOUND_UNIQUES,
|
|
117
|
+
} from './${modelName}Metadata${ext}'
|
|
118
|
+
${relatedImports ? '\n' + relatedImports + '\n' : ''}
|
|
119
|
+
// transitive relation metadata: narrowing recurses through these FULL model
|
|
120
|
+
// metas — compound unique constraints (@@id / @@unique) ride along so nested
|
|
121
|
+
// cursors and nested findUnique surfaces keep their unique selectors.
|
|
122
|
+
const compoundUniques: Array<{ selector: string; fields: string[] }> = []
|
|
123
|
+
if (COMPOUND_ID) {
|
|
124
|
+
compoundUniques.push({ selector: COMPOUND_ID.selector, fields: COMPOUND_ID.fields })
|
|
125
|
+
}
|
|
126
|
+
for (const cu of COMPOUND_UNIQUES) {
|
|
127
|
+
compoundUniques.push({ selector: cu.selector, fields: cu.fields })
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const enums = new Map<string, readonly string[]>()
|
|
131
|
+
${enumSets}
|
|
132
|
+
|
|
133
|
+
// one shared, self-referential metadata index: every related model keeps
|
|
134
|
+
// its full meta (compound uniques included) at every recursion depth
|
|
135
|
+
const modelIndex = new Map<string, SchemaModelMeta>()
|
|
136
|
+
const coreMetas: Array<[string, Omit<SchemaModelMeta, 'modelIndex'>]> = [
|
|
137
|
+
${coreEntries},
|
|
138
|
+
]
|
|
139
|
+
for (const [name, core] of coreMetas) {
|
|
140
|
+
modelIndex.set(name, { ...core, modelIndex })
|
|
141
|
+
}
|
|
142
|
+
${factories}
|
|
143
|
+
`;
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=generateModelMcp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateModelMcp.js","sourceRoot":"","sources":["../../src/generators/generateModelMcp.ts"],"names":[],"mappings":"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"}
|
|
@@ -63,13 +63,17 @@ function generateModelMetadata(options) {
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
const compoundId = model.primaryKey && model.primaryKey.fields.length > 1
|
|
66
|
-
? {
|
|
66
|
+
? {
|
|
67
|
+
selector: model.primaryKey.name || model.primaryKey.fields.join('_'),
|
|
68
|
+
fields: [...model.primaryKey.fields],
|
|
69
|
+
}
|
|
67
70
|
: null;
|
|
68
|
-
const compoundUniques = (model.uniqueIndexes
|
|
71
|
+
const compoundUniques = (model.uniqueIndexes ?? [])
|
|
69
72
|
.filter((idx) => idx.fields && idx.fields.length > 1)
|
|
70
73
|
.map((idx) => ({
|
|
71
74
|
name: idx.name || idx.fields.join('_'),
|
|
72
|
-
|
|
75
|
+
selector: idx.name || idx.fields.join('_'),
|
|
76
|
+
fields: [...idx.fields],
|
|
73
77
|
}));
|
|
74
78
|
return `import type { FieldMeta, EnumMeta } from '../docsRenderer${ext}'
|
|
75
79
|
|
|
@@ -77,9 +81,9 @@ export const MODEL_FIELDS: FieldMeta[] = ${JSON.stringify(fieldsMeta, null, 2)}
|
|
|
77
81
|
|
|
78
82
|
export const MODEL_ENUMS: EnumMeta[] = ${JSON.stringify(enumsMeta, null, 2)}
|
|
79
83
|
|
|
80
|
-
export const COMPOUND_ID: { fields: string[] } | null = ${JSON.stringify(compoundId)}
|
|
84
|
+
export const COMPOUND_ID: { selector: string; fields: string[] } | null = ${JSON.stringify(compoundId)}
|
|
81
85
|
|
|
82
|
-
export const COMPOUND_UNIQUES: { name: string; fields: string[] }[] = ${JSON.stringify(compoundUniques)}
|
|
86
|
+
export const COMPOUND_UNIQUES: { name: string; selector: string; fields: string[] }[] = ${JSON.stringify(compoundUniques)}
|
|
83
87
|
|
|
84
88
|
export const EXAMPLE_VALUES: Record<string, unknown> = ${JSON.stringify(exampleValues, null, 2)}
|
|
85
89
|
`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateModelMetadata.js","sourceRoot":"","sources":["../../src/generators/generateModelMetadata.ts"],"names":[],"mappings":";;AAmCA,
|
|
1
|
+
{"version":3,"file":"generateModelMetadata.js","sourceRoot":"","sources":["../../src/generators/generateModelMetadata.ts"],"names":[],"mappings":"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"}
|