@restforgejs/mcp-server 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/LICENSE.md +21 -0
- package/README.md +149 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/env-parser.d.ts +30 -0
- package/dist/lib/env-parser.js +150 -0
- package/dist/lib/env-parser.js.map +1 -0
- package/dist/lib/exec.d.ts +29 -0
- package/dist/lib/exec.js +38 -0
- package/dist/lib/exec.js.map +1 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +220 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/codegen/create-dashboard.d.ts +2 -0
- package/dist/tools/codegen/create-dashboard.js +256 -0
- package/dist/tools/codegen/create-dashboard.js.map +1 -0
- package/dist/tools/codegen/create-endpoint.d.ts +2 -0
- package/dist/tools/codegen/create-endpoint.js +263 -0
- package/dist/tools/codegen/create-endpoint.js.map +1 -0
- package/dist/tools/codegen/dbschema-generate-ddl.d.ts +2 -0
- package/dist/tools/codegen/dbschema-generate-ddl.js +187 -0
- package/dist/tools/codegen/dbschema-generate-ddl.js.map +1 -0
- package/dist/tools/codegen/dbschema-init.d.ts +2 -0
- package/dist/tools/codegen/dbschema-init.js +158 -0
- package/dist/tools/codegen/dbschema-init.js.map +1 -0
- package/dist/tools/codegen/dbschema-introspect.d.ts +2 -0
- package/dist/tools/codegen/dbschema-introspect.js +241 -0
- package/dist/tools/codegen/dbschema-introspect.js.map +1 -0
- package/dist/tools/codegen/dbschema-migrate.d.ts +2 -0
- package/dist/tools/codegen/dbschema-migrate.js +219 -0
- package/dist/tools/codegen/dbschema-migrate.js.map +1 -0
- package/dist/tools/codegen/dbschema-models.d.ts +2 -0
- package/dist/tools/codegen/dbschema-models.js +146 -0
- package/dist/tools/codegen/dbschema-models.js.map +1 -0
- package/dist/tools/codegen/dbschema-validate.d.ts +2 -0
- package/dist/tools/codegen/dbschema-validate.js +153 -0
- package/dist/tools/codegen/dbschema-validate.js.map +1 -0
- package/dist/tools/codegen/describe-table.d.ts +2 -0
- package/dist/tools/codegen/describe-table.js +259 -0
- package/dist/tools/codegen/describe-table.js.map +1 -0
- package/dist/tools/codegen/diff-payload.d.ts +2 -0
- package/dist/tools/codegen/diff-payload.js +165 -0
- package/dist/tools/codegen/diff-payload.js.map +1 -0
- package/dist/tools/codegen/generate-payload.d.ts +2 -0
- package/dist/tools/codegen/generate-payload.js +145 -0
- package/dist/tools/codegen/generate-payload.js.map +1 -0
- package/dist/tools/codegen/get-dashboard-catalog.d.ts +2 -0
- package/dist/tools/codegen/get-dashboard-catalog.js +213 -0
- package/dist/tools/codegen/get-dashboard-catalog.js.map +1 -0
- package/dist/tools/codegen/get-dbschema-catalog.d.ts +2 -0
- package/dist/tools/codegen/get-dbschema-catalog.js +244 -0
- package/dist/tools/codegen/get-dbschema-catalog.js.map +1 -0
- package/dist/tools/codegen/get-field-validation-catalog.d.ts +2 -0
- package/dist/tools/codegen/get-field-validation-catalog.js +186 -0
- package/dist/tools/codegen/get-field-validation-catalog.js.map +1 -0
- package/dist/tools/codegen/get-query-declarative-catalog.d.ts +2 -0
- package/dist/tools/codegen/get-query-declarative-catalog.js +200 -0
- package/dist/tools/codegen/get-query-declarative-catalog.js.map +1 -0
- package/dist/tools/codegen/index.d.ts +2 -0
- package/dist/tools/codegen/index.js +43 -0
- package/dist/tools/codegen/index.js.map +1 -0
- package/dist/tools/codegen/list-tables.d.ts +2 -0
- package/dist/tools/codegen/list-tables.js +220 -0
- package/dist/tools/codegen/list-tables.js.map +1 -0
- package/dist/tools/codegen/sync-payload.d.ts +2 -0
- package/dist/tools/codegen/sync-payload.js +177 -0
- package/dist/tools/codegen/sync-payload.js.map +1 -0
- package/dist/tools/codegen/validate-dashboard-payload.d.ts +2 -0
- package/dist/tools/codegen/validate-dashboard-payload.js +239 -0
- package/dist/tools/codegen/validate-dashboard-payload.js.map +1 -0
- package/dist/tools/codegen/validate-payload.d.ts +2 -0
- package/dist/tools/codegen/validate-payload.js +166 -0
- package/dist/tools/codegen/validate-payload.js.map +1 -0
- package/dist/tools/codegen/validate-sql.d.ts +2 -0
- package/dist/tools/codegen/validate-sql.js +270 -0
- package/dist/tools/codegen/validate-sql.js.map +1 -0
- package/dist/tools/health/index.d.ts +2 -0
- package/dist/tools/health/index.js +5 -0
- package/dist/tools/health/index.js.map +1 -0
- package/dist/tools/health/ping.d.ts +2 -0
- package/dist/tools/health/ping.js +68 -0
- package/dist/tools/health/ping.js.map +1 -0
- package/dist/tools/runtime/check-launcher-exists.d.ts +2 -0
- package/dist/tools/runtime/check-launcher-exists.js +111 -0
- package/dist/tools/runtime/check-launcher-exists.js.map +1 -0
- package/dist/tools/runtime/check-status.d.ts +2 -0
- package/dist/tools/runtime/check-status.js +417 -0
- package/dist/tools/runtime/check-status.js.map +1 -0
- package/dist/tools/runtime/detect-config.d.ts +2 -0
- package/dist/tools/runtime/detect-config.js +130 -0
- package/dist/tools/runtime/detect-config.js.map +1 -0
- package/dist/tools/runtime/detect-project.d.ts +2 -0
- package/dist/tools/runtime/detect-project.js +132 -0
- package/dist/tools/runtime/detect-project.js.map +1 -0
- package/dist/tools/runtime/generate-launcher.d.ts +2 -0
- package/dist/tools/runtime/generate-launcher.js +438 -0
- package/dist/tools/runtime/generate-launcher.js.map +1 -0
- package/dist/tools/runtime/index.d.ts +2 -0
- package/dist/tools/runtime/index.js +15 -0
- package/dist/tools/runtime/index.js.map +1 -0
- package/dist/tools/runtime/validate-preflight.d.ts +2 -0
- package/dist/tools/runtime/validate-preflight.js +209 -0
- package/dist/tools/runtime/validate-preflight.js.map +1 -0
- package/dist/tools/setup/create-folder.d.ts +2 -0
- package/dist/tools/setup/create-folder.js +138 -0
- package/dist/tools/setup/create-folder.js.map +1 -0
- package/dist/tools/setup/get-config-schema.d.ts +2 -0
- package/dist/tools/setup/get-config-schema.js +158 -0
- package/dist/tools/setup/get-config-schema.js.map +1 -0
- package/dist/tools/setup/get-init-template.d.ts +2 -0
- package/dist/tools/setup/get-init-template.js +130 -0
- package/dist/tools/setup/get-init-template.js.map +1 -0
- package/dist/tools/setup/index.d.ts +2 -0
- package/dist/tools/setup/index.js +21 -0
- package/dist/tools/setup/index.js.map +1 -0
- package/dist/tools/setup/init-config.d.ts +2 -0
- package/dist/tools/setup/init-config.js +120 -0
- package/dist/tools/setup/init-config.js.map +1 -0
- package/dist/tools/setup/install-package.d.ts +2 -0
- package/dist/tools/setup/install-package.js +133 -0
- package/dist/tools/setup/install-package.js.map +1 -0
- package/dist/tools/setup/read-env.d.ts +2 -0
- package/dist/tools/setup/read-env.js +138 -0
- package/dist/tools/setup/read-env.js.map +1 -0
- package/dist/tools/setup/update-env.d.ts +2 -0
- package/dist/tools/setup/update-env.js +176 -0
- package/dist/tools/setup/update-env.js.map +1 -0
- package/dist/tools/setup/validate-config.d.ts +2 -0
- package/dist/tools/setup/validate-config.js +138 -0
- package/dist/tools/setup/validate-config.js.map +1 -0
- package/dist/tools/setup/write-env.d.ts +2 -0
- package/dist/tools/setup/write-env.js +168 -0
- package/dist/tools/setup/write-env.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { access } from 'node:fs/promises';
|
|
3
|
+
import { resolve, join } from 'node:path';
|
|
4
|
+
import { execProcess } from '../../lib/exec.js';
|
|
5
|
+
async function pathExists(p) {
|
|
6
|
+
try {
|
|
7
|
+
await access(p);
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function registerCodegenCreateEndpoint(server) {
|
|
15
|
+
server.registerTool('codegen_create_endpoint', {
|
|
16
|
+
title: 'Create Endpoint Module',
|
|
17
|
+
description: `Generate a project + endpoint module (submodule, model, metadata, demo files, optional audit migration) from an existing payload spec by wrapping restforge create. URL pattern produced: /api/{project}/{endpoint}/{action}.
|
|
18
|
+
|
|
19
|
+
This tool is DESTRUCTIVE: it spawns the CLI which writes / overwrites files in 'src/modules/<project>/', 'src/models/<project>/', 'metadata/<project>/', 'examples/<project>/<endpoint>/', and updates '.restforge/projects.json'. Single-call semantics: the tool always executes; there is no preview mode. Internally the tool always passes '--force=true' to the CLI to bypass the CLI's interactive y/N readline prompt (which would deadlock in a no-TTY subprocess).
|
|
20
|
+
|
|
21
|
+
Safety net: when the CLI overwrites an existing module, model, or query directory, it FIRST renames the previous version to '<name>.archive.NNN' (NNN is a sequential generation number starting at 001) inside the same folder. Rollback by restoring the most recent archive is always possible.
|
|
22
|
+
|
|
23
|
+
AI responsibility — IMPORTANT: because this tool always executes and may overwrite generated files, you MUST confirm intent with the user in plain language BEFORE invoking the tool. You do NOT need to detect file conflicts programmatically — the CLI handles that and the archive mechanism keeps the previous version safe. Just confirm intent. Examples of good confirmation phrasing in user-facing chat:
|
|
24
|
+
- "Saya akan generate endpoint <endpoint> di project <project> ({database}). Kalau modul/model lama sudah ada, versi sebelumnya akan disimpan sebagai '.archive.NNN'. Lanjut?"
|
|
25
|
+
- "I will generate <endpoint> under project <project> using <database>. Existing files will be archived as .archive.NNN before being overwritten. Proceed?"
|
|
26
|
+
|
|
27
|
+
USE WHEN:
|
|
28
|
+
- The user asks to generate, create, or scaffold an endpoint, resource, or module from a payload (e.g. "buatkan endpoint untuk product", "generate resource users", "create endpoint dari payload X", "scaffold a new endpoint")
|
|
29
|
+
- The user mentions "endpoint", "resource", "module" or the URL pattern /api/{project}/{resource}/{action} and wants to register it as runnable code
|
|
30
|
+
- The user has authored a payload file (e.g. via 'codegen_generate_payload' or manually) and now wants to materialise it as runnable code in the project
|
|
31
|
+
- Pertanyaan dalam bentuk: "tambahkan endpoint X ke project Y", "buat module baru di project Z", "scaffold endpoint baru pakai payload ini", "generate kode dari payload ini"
|
|
32
|
+
- The user asks to add a new endpoint to an existing project (registry already has the project, just adding more endpoints)
|
|
33
|
+
- The user asks to bootstrap a brand-new project together with its first endpoint
|
|
34
|
+
- The user asks about regenerating an existing endpoint after the payload changed (this triggers overwrite + archive flow inside the CLI; previous versions become '.archive.NNN' in place)
|
|
35
|
+
- After 'codegen_validate_payload' confirmed the payload is valid — this is the natural follow-up that turns a verified payload into runnable code
|
|
36
|
+
|
|
37
|
+
DO NOT USE FOR:
|
|
38
|
+
- Generating the payload JSON itself from a database table -> use 'codegen_generate_payload'
|
|
39
|
+
- Validating a payload before generation -> use 'codegen_validate_payload'
|
|
40
|
+
- Inspecting per-column differences between payload and database -> use 'codegen_diff_payload'
|
|
41
|
+
- Syncing payload changes back into existing payload files after schema drift -> use 'codegen_sync_payload'
|
|
42
|
+
- Looking up the field validation catalog before authoring the payload -> use 'codegen_get_field_validation_catalog'
|
|
43
|
+
- Looking up the query declarative catalog before authoring the payload -> use 'codegen_get_query_declarative_catalog'
|
|
44
|
+
- Deleting a project or endpoint — out of scope; the user must run 'npx restforge drop' manually
|
|
45
|
+
- Generating a processor (Kafka consumer, etc.) — out of scope; the CLI has separate 'processor' and 'consumer-create' subcommands not covered by this MCP server yet
|
|
46
|
+
- Generating a dashboard endpoint — out of scope; the CLI has a separate 'dashboard' subcommand
|
|
47
|
+
- Listing all registered projects in the registry — out of scope here; use the CLI's 'list' subcommand directly
|
|
48
|
+
- Database DDL changes (CREATE TABLE, ALTER TABLE) — not in this tool's scope. The audit migration sub-step DOES create a single audit table when the payload uses the 'audit' fieldPolicy strategy, but that is the only DDL it touches.
|
|
49
|
+
|
|
50
|
+
Preconditions:
|
|
51
|
+
- The project must have @restforgejs/platform installed in node_modules.
|
|
52
|
+
- The payload file must exist at <cwd>/payload/<payload>.json before calling this tool.
|
|
53
|
+
- The CLI itself rejects reserved project names (src, lib, node_modules, config, utils, models, controllers, middleware, routes) and reserved endpoint names (health, status, admin, api, auth, login, logout, register, index, main, app, config, test, docs, swagger, graphql, websocket, socket). When in doubt, ask the user to pick a different name before invoking this tool.
|
|
54
|
+
|
|
55
|
+
PRESENTATION GUIDANCE:
|
|
56
|
+
- Match the user's language. If the user writes in Indonesian, respond in Indonesian.
|
|
57
|
+
- Never mention internal tool names in the reply to the user. Describe actions by what they do (e.g. "the endpoint generator", "the project generator", "generate the payload first", "validate the payload first").
|
|
58
|
+
- Speak in plain language. Summarise the result; do not paste raw CLI output unless the user explicitly asks.
|
|
59
|
+
- This tool is destructive: it can overwrite existing module / model / query files. BEFORE invoking this tool, ALWAYS confirm with the user in plain language. Example: "Saya akan generate endpoint <endpoint> di project <project>. Kalau file lama sudah ada, akan ditimpa (versi lama disimpan sebagai .archive.NNN). Lanjut?". Do not detect conflicts programmatically; the CLI handles that and creates the archive.
|
|
60
|
+
- After the tool runs, summarise the result. Read the CLI output and identify any archive activity (the CLI uses the '.archive.NNN' naming convention in the filesystem and reports archive activity in its output, but the exact wording may evolve). When archives are created, tell the user that previous versions are preserved in case rollback is needed.
|
|
61
|
+
- When a precondition is not met, frame it as a question or next-step suggestion rather than an error.`,
|
|
62
|
+
inputSchema: {
|
|
63
|
+
cwd: z
|
|
64
|
+
.string()
|
|
65
|
+
.min(1)
|
|
66
|
+
.describe('Absolute path of the project folder (must contain node_modules/@restforgejs/platform and a payload/ directory with the named payload file)'),
|
|
67
|
+
project: z
|
|
68
|
+
.string()
|
|
69
|
+
.min(1)
|
|
70
|
+
.max(50)
|
|
71
|
+
.regex(/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/, 'must start with a letter or number; only letters, numbers, dashes, underscores allowed')
|
|
72
|
+
.describe('Project name. Letters/numbers/dash/underscore, max 50 chars, cannot start or end with dash or underscore. Auto-lowercased by the CLI. Reserved names rejected by the CLI: src, lib, node_modules, config, utils, models, controllers, middleware, routes.'),
|
|
73
|
+
endpoint: z
|
|
74
|
+
.string()
|
|
75
|
+
.min(1)
|
|
76
|
+
.max(50)
|
|
77
|
+
.regex(/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/, 'must start with a letter or number; only letters, numbers, dashes, underscores allowed')
|
|
78
|
+
.describe('Endpoint name (also called "resource" — the URL pattern is /api/{project}/{endpoint}/{action}). Same shape as project. Auto-lowercased by the CLI. Reserved names rejected by the CLI: health, status, admin, api, auth, login, logout, register, index, main, app, config, test, docs, swagger, graphql, websocket, socket. Naming convention: kebab-case or snake-case recommended.'),
|
|
79
|
+
payload: z
|
|
80
|
+
.string()
|
|
81
|
+
.min(1)
|
|
82
|
+
.max(50)
|
|
83
|
+
.regex(/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/, 'must start with a letter or number; only letters, numbers, dashes, underscores allowed')
|
|
84
|
+
.describe('Payload file name without the .json extension. The file must exist at <cwd>/payload/<payload>.json. Same shape rules as project.'),
|
|
85
|
+
database: z
|
|
86
|
+
.enum(['postgres', 'oracle', 'mysql'])
|
|
87
|
+
.optional()
|
|
88
|
+
.describe('Database type for the generated code. Default postgres.'),
|
|
89
|
+
createDemo: z
|
|
90
|
+
.boolean()
|
|
91
|
+
.optional()
|
|
92
|
+
.describe('Default true (CLI default). When true, generate demo files (curl, postman, insomnia) for testing the endpoint.'),
|
|
93
|
+
skipSqlValidation: z
|
|
94
|
+
.boolean()
|
|
95
|
+
.optional()
|
|
96
|
+
.describe('Default false (CLI default). When true, skip SQL keyword validation in the payload. Useful when payload includes generated SQL fragments that the validator flags as suspicious.'),
|
|
97
|
+
noAuditMigration: z
|
|
98
|
+
.boolean()
|
|
99
|
+
.optional()
|
|
100
|
+
.describe('Default false (CLI default). When true, skip executing the audit table migration even if the payload has fieldPolicy.*.strategies containing "audit". The migration SQL file is still written to migrations/audit/ as documentation.'),
|
|
101
|
+
},
|
|
102
|
+
annotations: {
|
|
103
|
+
title: 'Create Endpoint Module',
|
|
104
|
+
readOnlyHint: false, // tool spawns CLI that writes module/model/metadata/demo files and updates the registry
|
|
105
|
+
destructiveHint: true, // can overwrite existing files (CLI archives them as .archive.NNN first)
|
|
106
|
+
idempotentHint: false, // re-running creates new archive files and may execute audit migration again
|
|
107
|
+
},
|
|
108
|
+
}, async ({ cwd, project, endpoint, payload, database, createDemo, skipSqlValidation, noAuditMigration }) => {
|
|
109
|
+
const projectCwd = resolve(cwd);
|
|
110
|
+
const dbType = database ?? 'postgres';
|
|
111
|
+
// Pre-flight 1: @restforgejs/platform must be installed. Treated as a non-error precondition per §3.4.
|
|
112
|
+
try {
|
|
113
|
+
await access(join(projectCwd, 'node_modules', '@restforgejs', 'platform'));
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return {
|
|
117
|
+
content: [
|
|
118
|
+
{
|
|
119
|
+
type: 'text',
|
|
120
|
+
text: `Precondition not met: the RESTForge package is not installed in this project.
|
|
121
|
+
|
|
122
|
+
Project path: ${projectCwd}
|
|
123
|
+
Expected location: node_modules/@restforgejs/platform
|
|
124
|
+
Requested project: ${project}
|
|
125
|
+
Requested endpoint: ${endpoint}
|
|
126
|
+
Requested payload: ${payload}
|
|
127
|
+
Requested database: ${dbType}
|
|
128
|
+
|
|
129
|
+
For the assistant:
|
|
130
|
+
- The endpoint generator can only run once the RESTForge package is installed locally.
|
|
131
|
+
- Suggest installing the package first, then retry generating the endpoint.
|
|
132
|
+
- When explaining to the user, say something like "the RESTForge package isn't installed yet — should I install it first?". Do not mention internal tool names.`,
|
|
133
|
+
},
|
|
134
|
+
],
|
|
135
|
+
isError: false, // per §3.4
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
// Pre-flight 2: payload file must exist. Treated as a non-error precondition per §3.4.
|
|
139
|
+
const payloadPath = join(projectCwd, 'payload', `${payload}.json`);
|
|
140
|
+
if (!(await pathExists(payloadPath))) {
|
|
141
|
+
return {
|
|
142
|
+
content: [
|
|
143
|
+
{
|
|
144
|
+
type: 'text',
|
|
145
|
+
text: `Precondition not met: payload file not found.
|
|
146
|
+
|
|
147
|
+
Project path: ${projectCwd}
|
|
148
|
+
Expected payload file: ${payloadPath}
|
|
149
|
+
Requested project: ${project}
|
|
150
|
+
Requested endpoint: ${endpoint}
|
|
151
|
+
Requested database: ${dbType}
|
|
152
|
+
|
|
153
|
+
For the assistant:
|
|
154
|
+
- The endpoint generator needs the payload file to exist before it can run.
|
|
155
|
+
- Suggest generating or creating the payload first. The payload generator tool can introspect a database table into a payload JSON, or the user can author it manually in the payload/ folder.
|
|
156
|
+
- When explaining to the user, say something like "the payload file '${payload}.json' isn't in the payload/ folder yet — should I generate it from a database table first, or do you have one to put there?". Do not mention internal tool names.`,
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
isError: false, // per §3.4
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
// Build CLI invocation. --force=true is hardcoded: it bypasses the interactive readline
|
|
163
|
+
// prompt that would otherwise deadlock the subprocess. Conflict detection and archive
|
|
164
|
+
// creation are delegated to the CLI (single source of truth — see conflict-checker.js).
|
|
165
|
+
const cliArgs = [
|
|
166
|
+
'restforge',
|
|
167
|
+
'endpoint',
|
|
168
|
+
'create',
|
|
169
|
+
`--project=${project}`,
|
|
170
|
+
`--name=${endpoint}`,
|
|
171
|
+
`--payload=${payload}`,
|
|
172
|
+
`--database=${dbType}`,
|
|
173
|
+
'--force=true',
|
|
174
|
+
];
|
|
175
|
+
if (createDemo !== undefined)
|
|
176
|
+
cliArgs.push(`--create-demo=${createDemo}`);
|
|
177
|
+
if (skipSqlValidation !== undefined)
|
|
178
|
+
cliArgs.push(`--skip-sql-validation=${skipSqlValidation}`);
|
|
179
|
+
if (noAuditMigration !== undefined)
|
|
180
|
+
cliArgs.push(`--no-audit-migration=${noAuditMigration}`);
|
|
181
|
+
const result = await execProcess('npx', cliArgs, {
|
|
182
|
+
cwd: projectCwd,
|
|
183
|
+
timeout: 120_000,
|
|
184
|
+
env: { NODE_ENV: 'production' }, // suppress legacy banner output
|
|
185
|
+
stripFinalNewline: true,
|
|
186
|
+
});
|
|
187
|
+
// Branch C: CLI failure — real error per §3.4; structured per §3.5.
|
|
188
|
+
if (!result.success) {
|
|
189
|
+
return {
|
|
190
|
+
content: [
|
|
191
|
+
{
|
|
192
|
+
type: 'text',
|
|
193
|
+
text: `Failed to create the endpoint module.
|
|
194
|
+
|
|
195
|
+
Project path: ${projectCwd}
|
|
196
|
+
Project: ${project}
|
|
197
|
+
Endpoint: ${endpoint}
|
|
198
|
+
Payload: payload/${payload}.json
|
|
199
|
+
Database: ${dbType}
|
|
200
|
+
Command: ${result.command}
|
|
201
|
+
Exit code: ${result.exitCode}
|
|
202
|
+
|
|
203
|
+
--- CLI output ---
|
|
204
|
+
stdout:
|
|
205
|
+
${result.stdout}
|
|
206
|
+
|
|
207
|
+
stderr:
|
|
208
|
+
${result.stderr}
|
|
209
|
+
--- end CLI output ---
|
|
210
|
+
|
|
211
|
+
For the assistant:
|
|
212
|
+
- Tell the user that creating the endpoint module did not complete successfully.
|
|
213
|
+
- Summarise the most likely cause from the CLI output in plain language. Common causes:
|
|
214
|
+
* Reserved name rejected by the validator (project or endpoint name is in the reserved list) — suggest picking a different name.
|
|
215
|
+
* Database mismatch with the existing project registry entry — the CLI refuses to switch the database for an existing project. Suggest sticking with the originally registered database, or confirm with the user that switching is really intended.
|
|
216
|
+
* Payload validation failed (e.g. SQL keywords flagged) — suggest validating the payload first to surface the specific issue, or rerunning with skipSqlValidation=true if the SQL fragments are intentional.
|
|
217
|
+
* Audit migration failed (e.g. cannot connect to the database) — suggest checking the database connection config, or rerunning with noAuditMigration=true to skip the live migration (the SQL file will still be written for manual execution).
|
|
218
|
+
- Do not paste the raw stdout/stderr unless the user explicitly asks. Do not mention internal tool names.
|
|
219
|
+
- Offer to retry once the underlying issue is resolved.`,
|
|
220
|
+
},
|
|
221
|
+
],
|
|
222
|
+
isError: true, // per §3.4
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
// Branch D: CLI success — one-line summary + labeled facts + fenced output per §3.5.
|
|
226
|
+
return {
|
|
227
|
+
content: [
|
|
228
|
+
{
|
|
229
|
+
type: 'text',
|
|
230
|
+
text: `Endpoint module created successfully.
|
|
231
|
+
|
|
232
|
+
Project path: ${projectCwd}
|
|
233
|
+
Project: ${project}
|
|
234
|
+
Endpoint: ${endpoint}
|
|
235
|
+
Payload: payload/${payload}.json
|
|
236
|
+
Database: ${dbType}
|
|
237
|
+
|
|
238
|
+
Generated artefacts (commonly produced by the CLI):
|
|
239
|
+
- src/modules/${project}/${endpoint}.js (submodule)
|
|
240
|
+
- src/models/${project}/${endpoint}.js (model)
|
|
241
|
+
- src/models/${project}/query/ (if payload uses file reference queries)
|
|
242
|
+
- metadata/${project}/${endpoint}.json (and related metadata)
|
|
243
|
+
- examples/${project}/${endpoint}/* (if createDemo=true)
|
|
244
|
+
- migrations/audit/<table>_audit.sql (if payload uses fieldPolicy 'audit' strategy)
|
|
245
|
+
- .restforge/projects.json (registry update)
|
|
246
|
+
|
|
247
|
+
--- CLI output ---
|
|
248
|
+
${result.stdout}
|
|
249
|
+
--- end CLI output ---
|
|
250
|
+
|
|
251
|
+
For the assistant:
|
|
252
|
+
- Confirm to the user in plain language that the project and endpoint were generated. Mention the project, endpoint, and database used.
|
|
253
|
+
- Do not paste the entire CLI output unless the user explicitly asks; summarise instead.
|
|
254
|
+
- Suggest natural follow-up actions appropriate to context: review the generated files, run the project to test the new endpoint, generate a processor or test, etc. Do not mention internal tool names.
|
|
255
|
+
- Read the CLI output to identify any archive activity. The CLI uses the '.archive.NNN' naming convention in the filesystem; it also reports archive activity in its output, though the exact phrasing may evolve. When archives are created, tell the user that the previous version of each overwritten file is preserved as an archive file in the same folder, and explain where to find them if rollback is needed.
|
|
256
|
+
- Read the CLI output to identify any audit migration activity (the CLI reports it when the payload uses a fieldPolicy 'audit' strategy). When present, summarise it briefly to the user (e.g. that the audit table for the related table was created or updated).
|
|
257
|
+
- Match the user's language.`,
|
|
258
|
+
},
|
|
259
|
+
],
|
|
260
|
+
};
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
//# sourceMappingURL=create-endpoint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-endpoint.js","sourceRoot":"","sources":["../../../src/tools/codegen/create-endpoint.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { access } from 'node:fs/promises';
|
|
3
|
+
import { resolve, join } from 'node:path';
|
|
4
|
+
import { execProcess } from '../../lib/exec.js';
|
|
5
|
+
export function registerCodegenDbschemaGenerateDdl(server) {
|
|
6
|
+
server.registerTool('codegen_dbschema_generate_ddl', {
|
|
7
|
+
title: 'Generate DDL from dbschema-kit Files',
|
|
8
|
+
description: `Generate dialect-specific DDL SQL (CREATE TABLE, CREATE INDEX, optional DROP TABLE) from dbschema-kit definition files in topological order, by wrapping restforge schema generate-ddl. Output goes to stdout (returned in the response) or to a file when 'out' is set. Tables are emitted in topological order so parent tables are created before children; DROP order is reversed.
|
|
9
|
+
|
|
10
|
+
USE WHEN:
|
|
11
|
+
- The user asks to generate DDL, "buatkan SQL DDL", "generate CREATE TABLE statements"
|
|
12
|
+
- Pertanyaan dalam bentuk: "convert schema ke postgres SQL", "generate DDL untuk MySQL", "buatkan migration script"
|
|
13
|
+
- Before applying schema to a database — for preview/review (safer than running migrate directly)
|
|
14
|
+
- The user wants a portable SQL file for sharing with a DBA or for git versioning
|
|
15
|
+
- The user asks for cross-dialect compatibility ("apakah schema bisa untuk postgres dan mysql")
|
|
16
|
+
- Migration script preparation
|
|
17
|
+
- After validating schema and the user wants to see the SQL output
|
|
18
|
+
|
|
19
|
+
DO NOT USE FOR:
|
|
20
|
+
- Applying DDL to a live database -> use 'codegen_dbschema_migrate'
|
|
21
|
+
- Generating CRUD payload SQL -> out of scope (different layer)
|
|
22
|
+
- Generating ad-hoc query SQL -> out of scope
|
|
23
|
+
- Generating DDL for tables not defined in schema files -> out of scope (only schema-as-code files are processed)
|
|
24
|
+
- Validating schema correctness -> use 'codegen_dbschema_validate'
|
|
25
|
+
|
|
26
|
+
This tool runs: npx restforge schema generate-ddl <path> --dialect=<X> [--out=<file>] [--drop=<bool>] in the given cwd.
|
|
27
|
+
|
|
28
|
+
Preconditions:
|
|
29
|
+
- The project must have @restforgejs/platform installed in node_modules.
|
|
30
|
+
- The schema path must exist and contain valid schema files. If the CLI fails, the failure response surfaces the underlying cause.
|
|
31
|
+
|
|
32
|
+
PRESENTATION GUIDANCE:
|
|
33
|
+
- Match the user's language. If the user writes in Indonesian, respond in Indonesian.
|
|
34
|
+
- Never mention internal tool names in the reply to the user. Describe actions by what they do (e.g. "generate the DDL", "preview the SQL", "apply the schema").
|
|
35
|
+
- Speak in plain language. Summarise the result (dialect, output target, drop mode); do not paste raw DDL unless the user explicitly asks.
|
|
36
|
+
- Output is dialect-aware: column types, FK syntax, default value translation, and identifier quoting all change per dialect. Do not assume cross-dialect equivalence.
|
|
37
|
+
- The order is topological — parent tables before child tables. DROP order is reversed.
|
|
38
|
+
- For preview before applying, this is the safe path. To actually apply, suggest the migrate action next.
|
|
39
|
+
- When 'out' is set, the file is written; if it exists, it is overwritten. Confirm with the user if a destructive overwrite is intended.
|
|
40
|
+
- If the user wants multi-dialect output, suggest invoking once per dialect.
|
|
41
|
+
- When a precondition is not met, frame it as a question or next-step suggestion rather than an error.`,
|
|
42
|
+
inputSchema: {
|
|
43
|
+
cwd: z
|
|
44
|
+
.string()
|
|
45
|
+
.min(1)
|
|
46
|
+
.describe('Absolute path of the project folder (must contain node_modules/@restforgejs/platform)'),
|
|
47
|
+
path: z
|
|
48
|
+
.string()
|
|
49
|
+
.min(1)
|
|
50
|
+
.describe('Path to schema file or folder relative to cwd (e.g. "schema", "schema/supplier.js").'),
|
|
51
|
+
dialect: z
|
|
52
|
+
.enum(['postgres', 'mysql', 'oracle', 'sqlite'])
|
|
53
|
+
.describe('Target SQL dialect.'),
|
|
54
|
+
out: z
|
|
55
|
+
.string()
|
|
56
|
+
.min(1)
|
|
57
|
+
.optional()
|
|
58
|
+
.describe('Output file path relative to cwd (e.g. "db/migrations/001-init.sql"). When omitted, the DDL is returned in the response (stdout). Existing files at this path are overwritten.'),
|
|
59
|
+
drop: z
|
|
60
|
+
.boolean()
|
|
61
|
+
.optional()
|
|
62
|
+
.describe('Default false. When true, prepend DROP TABLE statements (in reverse topological order) before the CREATE statements.'),
|
|
63
|
+
},
|
|
64
|
+
annotations: {
|
|
65
|
+
title: 'Generate DDL from dbschema-kit Files',
|
|
66
|
+
idempotentHint: true, // pure transformation; same input -> same output (file overwrite is in-place)
|
|
67
|
+
},
|
|
68
|
+
}, async ({ cwd, path, dialect, out, drop }) => {
|
|
69
|
+
const projectCwd = resolve(cwd);
|
|
70
|
+
// Precondition check: @restforgejs/platform must be present in node_modules. per §3.4
|
|
71
|
+
try {
|
|
72
|
+
await access(join(projectCwd, 'node_modules', '@restforgejs', 'platform'));
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return {
|
|
76
|
+
content: [
|
|
77
|
+
{
|
|
78
|
+
type: 'text',
|
|
79
|
+
text: `Precondition not met: the RESTForge package is not installed in this project.
|
|
80
|
+
|
|
81
|
+
Project path: ${projectCwd}
|
|
82
|
+
Expected location: node_modules/@restforgejs/platform
|
|
83
|
+
Requested schema path: ${path}
|
|
84
|
+
Requested dialect: ${dialect}
|
|
85
|
+
Requested out: ${out ?? '(stdout)'}
|
|
86
|
+
Requested drop: ${drop ?? false}
|
|
87
|
+
|
|
88
|
+
For the assistant:
|
|
89
|
+
- The user needs to install the RESTForge package before DDL can be generated.
|
|
90
|
+
- Suggest installing the package first, then retry generating the DDL.
|
|
91
|
+
- When explaining to the user, say something like "the RESTForge package isn't installed yet — should I install it first?". Do not mention internal tool names.`,
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
isError: false, // per §3.4
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
// Forward only the arguments the user supplied. CLI defaults remain in
|
|
98
|
+
// effect when the user does not specify them. per §3.5
|
|
99
|
+
const cliArgs = [
|
|
100
|
+
'restforge',
|
|
101
|
+
'schema',
|
|
102
|
+
'generate-ddl',
|
|
103
|
+
path,
|
|
104
|
+
`--dialect=${dialect}`,
|
|
105
|
+
];
|
|
106
|
+
if (out !== undefined)
|
|
107
|
+
cliArgs.push(`--out=${out}`);
|
|
108
|
+
if (drop !== undefined)
|
|
109
|
+
cliArgs.push(`--drop=${drop}`);
|
|
110
|
+
const result = await execProcess('npx', cliArgs, {
|
|
111
|
+
cwd: projectCwd,
|
|
112
|
+
timeout: 30_000,
|
|
113
|
+
env: { NODE_ENV: 'production' },
|
|
114
|
+
stripFinalNewline: true,
|
|
115
|
+
});
|
|
116
|
+
// Branch C: CLI failure — real error per §3.4. per §3.5
|
|
117
|
+
if (!result.success) {
|
|
118
|
+
return {
|
|
119
|
+
content: [
|
|
120
|
+
{
|
|
121
|
+
type: 'text',
|
|
122
|
+
text: `Failed to generate DDL.
|
|
123
|
+
|
|
124
|
+
Project path: ${projectCwd}
|
|
125
|
+
Schema path: ${path}
|
|
126
|
+
Dialect: ${dialect}
|
|
127
|
+
Output: ${out ?? '(stdout)'}
|
|
128
|
+
Drop tables: ${drop ?? false}
|
|
129
|
+
Command: ${result.command}
|
|
130
|
+
Exit code: ${result.exitCode}
|
|
131
|
+
|
|
132
|
+
--- CLI output ---
|
|
133
|
+
stdout:
|
|
134
|
+
${result.stdout}
|
|
135
|
+
|
|
136
|
+
stderr:
|
|
137
|
+
${result.stderr}
|
|
138
|
+
--- end CLI output ---
|
|
139
|
+
|
|
140
|
+
For the assistant:
|
|
141
|
+
- Tell the user that generating the DDL did not complete successfully.
|
|
142
|
+
- Summarise the most likely cause from the CLI output in plain language. Common causes:
|
|
143
|
+
* Schema validation failure — a file has invalid syntax or a broken FK reference. Suggest running the validate action first to surface the specific issue.
|
|
144
|
+
* Schema folder not found — the CLI cannot locate the path. Suggest verifying the folder name.
|
|
145
|
+
* Invalid dialect — only postgres, mysql, oracle, sqlite are supported.
|
|
146
|
+
* Output path issue (parent folder missing) — the CLI does not auto-create intermediate folders. Suggest creating them first.
|
|
147
|
+
* Unknown command 'schema generate-ddl' — the installed RESTForge version may be older than this CLI subcommand; suggest upgrading the package.
|
|
148
|
+
- Do not paste the raw stdout/stderr unless the user explicitly asks. Do not mention internal tool names.
|
|
149
|
+
- Offer to retry once the issue is resolved.`,
|
|
150
|
+
},
|
|
151
|
+
],
|
|
152
|
+
isError: true, // per §3.4
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
// Branch B: success — labeled facts + fenced raw output per §3.5.
|
|
156
|
+
// When 'out' is set, stdout contains a short status message; when not, stdout contains the full DDL.
|
|
157
|
+
return {
|
|
158
|
+
content: [
|
|
159
|
+
{
|
|
160
|
+
type: 'text',
|
|
161
|
+
text: `DDL generated successfully.
|
|
162
|
+
|
|
163
|
+
Project path: ${projectCwd}
|
|
164
|
+
Schema path: ${path}
|
|
165
|
+
Dialect: ${dialect}
|
|
166
|
+
Drop tables: ${drop ?? false}
|
|
167
|
+
Output: ${out ?? '(stdout)'}
|
|
168
|
+
|
|
169
|
+
--- CLI output ---
|
|
170
|
+
${result.stdout}
|
|
171
|
+
--- end CLI output ---
|
|
172
|
+
|
|
173
|
+
For the assistant:
|
|
174
|
+
- Confirm to the user that the DDL was generated. Mention the dialect and (if applicable) the output file path in plain language.
|
|
175
|
+
- DDL is dialect-specific — column types, FK syntax, identifier quoting, and default value translation differ across postgres/mysql/oracle/sqlite. Do not assume cross-dialect equivalence.
|
|
176
|
+
- The order is topological — parent tables before child tables. When drop=true, DROP statements are emitted in reverse order before the CREATE block.
|
|
177
|
+
- When 'out' was set, the file is written; existing files at that path are overwritten. Mention the file path so the user can review or commit it.
|
|
178
|
+
- For preview before applying, this is the safe path. To apply the schema to a live database, suggest the migrate action next.
|
|
179
|
+
- If the user wants multi-dialect output, mention that the action can be invoked once per dialect.
|
|
180
|
+
- Do not paste the full DDL unless the user explicitly asks.
|
|
181
|
+
- Match the user's language.`,
|
|
182
|
+
},
|
|
183
|
+
],
|
|
184
|
+
};
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=dbschema-generate-ddl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dbschema-generate-ddl.js","sourceRoot":"","sources":["../../../src/tools/codegen/dbschema-generate-ddl.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { access } from 'node:fs/promises';
|
|
3
|
+
import { resolve, join } from 'node:path';
|
|
4
|
+
import { execProcess } from '../../lib/exec.js';
|
|
5
|
+
export function registerCodegenDbschemaInit(server) {
|
|
6
|
+
server.registerTool('codegen_dbschema_init', {
|
|
7
|
+
title: 'Init dbschema-kit Skeleton File',
|
|
8
|
+
description: `Create a new schema definition skeleton file at the given path, by wrapping restforge schema init. The generated file uses the factory function pattern with a minimal starter (id, code, name, is_active fields). The user is expected to edit the file afterwards to add the real domain fields, indexes, uniques, and relations.
|
|
9
|
+
|
|
10
|
+
USE WHEN:
|
|
11
|
+
- The user asks to create a new schema file, schema skeleton, or defineModel template
|
|
12
|
+
- Pertanyaan dalam bentuk: "buatkan file schema untuk tabel X", "init schema definition", "create dbschema skeleton", "buat starter file schema"
|
|
13
|
+
- Before any schema-as-code workflow when no schema files exist yet
|
|
14
|
+
- The user wants to start declarative schema definition from scratch
|
|
15
|
+
- The user asks for a starter template they can edit
|
|
16
|
+
- After 'codegen_get_dbschema_catalog' grounding and the user is ready to author
|
|
17
|
+
- The user mentions a new domain entity (e.g. "I need a customer_invoice table") and wants a schema file as a starting point
|
|
18
|
+
|
|
19
|
+
DO NOT USE FOR:
|
|
20
|
+
- Editing an existing schema file -> use Edit/Write tools directly
|
|
21
|
+
- Generating schema files from a live database -> use 'codegen_dbschema_introspect'
|
|
22
|
+
- Creating a CRUD payload (different concept) -> use 'codegen_generate_payload'
|
|
23
|
+
- Validating the schema -> use 'codegen_dbschema_validate'
|
|
24
|
+
- Generating DDL -> use 'codegen_dbschema_generate_ddl'
|
|
25
|
+
|
|
26
|
+
This tool runs: npx restforge schema init <path> in the given cwd.
|
|
27
|
+
The CLI writes a JavaScript factory function file to the target path. The path must end with '.js' and the file must NOT already exist.
|
|
28
|
+
|
|
29
|
+
Preconditions:
|
|
30
|
+
- The project must have @restforgejs/platform installed in node_modules.
|
|
31
|
+
- The target file must NOT already exist (CLI fails otherwise — the user can pick a different name or remove the existing file first).
|
|
32
|
+
- The parent folder of the target path must exist (CLI does not create intermediate folders).
|
|
33
|
+
|
|
34
|
+
PRESENTATION GUIDANCE:
|
|
35
|
+
- Match the user's language. If the user writes in Indonesian, respond in Indonesian.
|
|
36
|
+
- Never mention internal tool names in the reply to the user. Describe actions by what they do (e.g. "create a starter schema file", "look up the schema catalog", "validate the schema").
|
|
37
|
+
- Speak in plain language. Confirm the file was created, mention the file path and the derived table name; do not paste the raw CLI output unless the user explicitly asks.
|
|
38
|
+
- The skeleton is intentionally minimal — only id, code, name, is_active fields. The user will need to edit it for their actual domain.
|
|
39
|
+
- If the user wants multiple files (e.g. category.js, supplier.js, customer.js), invoke this action once per file. Do not assume one call covers multiple files.
|
|
40
|
+
- When a precondition is not met (e.g. the package is not installed), frame it as a question or next-step suggestion rather than an error.`,
|
|
41
|
+
inputSchema: {
|
|
42
|
+
cwd: z
|
|
43
|
+
.string()
|
|
44
|
+
.min(1)
|
|
45
|
+
.describe('Absolute path of the project folder (must contain node_modules/@restforgejs/platform)'),
|
|
46
|
+
path: z
|
|
47
|
+
.string()
|
|
48
|
+
.min(1)
|
|
49
|
+
.describe('Target file path relative to cwd (must end with .js, file must NOT already exist). Examples: "schema/supplier.js", "db/models/inventory/products.js".'),
|
|
50
|
+
},
|
|
51
|
+
annotations: {
|
|
52
|
+
title: 'Init dbschema-kit Skeleton File',
|
|
53
|
+
destructiveHint: false, // creates a new file; CLI refuses to overwrite an existing one
|
|
54
|
+
idempotentHint: false, // each call attempts to create a new file; second call on the same path fails
|
|
55
|
+
},
|
|
56
|
+
}, async ({ cwd, path }) => {
|
|
57
|
+
const projectCwd = resolve(cwd);
|
|
58
|
+
// Precondition check: @restforgejs/platform must be present in node_modules. per §3.4
|
|
59
|
+
try {
|
|
60
|
+
await access(join(projectCwd, 'node_modules', '@restforgejs', 'platform'));
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return {
|
|
64
|
+
content: [
|
|
65
|
+
{
|
|
66
|
+
type: 'text',
|
|
67
|
+
text: `Precondition not met: the RESTForge package is not installed in this project.
|
|
68
|
+
|
|
69
|
+
Project path: ${projectCwd}
|
|
70
|
+
Expected location: node_modules/@restforgejs/platform
|
|
71
|
+
Requested path: ${path}
|
|
72
|
+
|
|
73
|
+
For the assistant:
|
|
74
|
+
- The user needs to install the RESTForge package before a schema skeleton file can be created.
|
|
75
|
+
- Suggest installing the package first, then retry creating the skeleton.
|
|
76
|
+
- When explaining to the user, say something like "the RESTForge package isn't installed yet — should I install it first?". Do not mention internal tool names.`,
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
isError: false, // per §3.4
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
// Subprocess call. The CLI handles all filesystem validation
|
|
83
|
+
// (extension, parent folder existence, target file non-existence). per §3.5
|
|
84
|
+
const cliArgs = ['restforge', 'schema', 'init', path];
|
|
85
|
+
const result = await execProcess('npx', cliArgs, {
|
|
86
|
+
cwd: projectCwd,
|
|
87
|
+
timeout: 10_000,
|
|
88
|
+
env: { NODE_ENV: 'production' },
|
|
89
|
+
stripFinalNewline: true,
|
|
90
|
+
});
|
|
91
|
+
// Branch C: CLI failure — real error per §3.4; structured per §3.5.
|
|
92
|
+
if (!result.success) {
|
|
93
|
+
return {
|
|
94
|
+
content: [
|
|
95
|
+
{
|
|
96
|
+
type: 'text',
|
|
97
|
+
text: `Failed to create the schema skeleton file.
|
|
98
|
+
|
|
99
|
+
Project path: ${projectCwd}
|
|
100
|
+
Target path: ${path}
|
|
101
|
+
Command: ${result.command}
|
|
102
|
+
Exit code: ${result.exitCode}
|
|
103
|
+
|
|
104
|
+
--- CLI output ---
|
|
105
|
+
stdout:
|
|
106
|
+
${result.stdout}
|
|
107
|
+
|
|
108
|
+
stderr:
|
|
109
|
+
${result.stderr}
|
|
110
|
+
--- end CLI output ---
|
|
111
|
+
|
|
112
|
+
For the assistant:
|
|
113
|
+
- Tell the user that creating the schema skeleton did not complete successfully.
|
|
114
|
+
- Summarise the most likely cause from the CLI output in plain language. Common causes:
|
|
115
|
+
* The target file already exists — suggest picking a different filename or removing the existing file first.
|
|
116
|
+
* The path does not end with '.js' — schema files use the JavaScript factory function pattern; suggest correcting the extension.
|
|
117
|
+
* The parent folder does not exist — the CLI does not auto-create intermediate folders. Suggest creating the folder first.
|
|
118
|
+
* Unknown command 'schema init' — the installed RESTForge version may be older than this CLI subcommand; suggest upgrading the package.
|
|
119
|
+
- Do not paste the raw stdout/stderr unless the user explicitly asks. Do not mention internal tool names.`,
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
isError: true, // per §3.4
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
// Derive the table name from filename (CLI applies the same rule).
|
|
126
|
+
// This is informational only — the labeled fact mirrors what the CLI will print to stdout.
|
|
127
|
+
const lastSegment = path.split(/[/\\]/).pop() ?? path;
|
|
128
|
+
const derivedTableName = lastSegment.endsWith('.js')
|
|
129
|
+
? lastSegment.slice(0, -3)
|
|
130
|
+
: lastSegment;
|
|
131
|
+
// Branch B: success — labeled facts + fenced raw output per §3.5.
|
|
132
|
+
return {
|
|
133
|
+
content: [
|
|
134
|
+
{
|
|
135
|
+
type: 'text',
|
|
136
|
+
text: `Schema skeleton file created successfully.
|
|
137
|
+
|
|
138
|
+
Project path: ${projectCwd}
|
|
139
|
+
Target file: ${path}
|
|
140
|
+
Table name (derived from filename): ${derivedTableName}
|
|
141
|
+
|
|
142
|
+
--- CLI output ---
|
|
143
|
+
${result.stdout}
|
|
144
|
+
--- end CLI output ---
|
|
145
|
+
|
|
146
|
+
For the assistant:
|
|
147
|
+
- Confirm to the user that the skeleton file was created. Mention the file path and the derived table name in plain language.
|
|
148
|
+
- The skeleton is a starting point only: it has minimal fields (id, code, name, is_active). Suggest opening the file and adding the actual fields, indexes, uniques, and relations that match the user's domain.
|
|
149
|
+
- Use the schema catalog as ground truth when helping the user fill in the model (field types, constraints, relations, shorthand syntax).
|
|
150
|
+
- After the user edits the file, suggest validating the schema next as a sanity check (without mentioning the internal tool name).
|
|
151
|
+
- If the user wants several entities, this action creates one file per call. For multiple entities, invoke once per file.
|
|
152
|
+
- Match the user's language.`,
|
|
153
|
+
},
|
|
154
|
+
],
|
|
155
|
+
};
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=dbschema-init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dbschema-init.js","sourceRoot":"","sources":["../../../src/tools/codegen/dbschema-init.ts"],"names":[],"mappings":"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"}
|