@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,132 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { readdir } from 'node:fs/promises';
|
|
3
|
+
import { resolve, join } from 'node:path';
|
|
4
|
+
export function registerRuntimeDetectProject(server) {
|
|
5
|
+
server.registerTool('runtime_detect_project', {
|
|
6
|
+
title: 'Detect RESTForge Project Names',
|
|
7
|
+
description: `Detect RESTForge project names by scanning the conventional 'src/modules/' folder. Each .js file in that folder represents one RESTForge project; the filename without extension is the project name.
|
|
8
|
+
|
|
9
|
+
USE WHEN:
|
|
10
|
+
- The user asks "which projects are available?", "what RESTForge projects are in this folder?", "list project saya"
|
|
11
|
+
- Before generating a launcher script — to confirm the project name to pass as --project=<name>
|
|
12
|
+
- Before invoking 'runtime_generate_launcher' — to determine whether the user must specify a project name or one can be auto-detected
|
|
13
|
+
- The user requests to run the server but the project name is unknown or ambiguous
|
|
14
|
+
|
|
15
|
+
DO NOT USE FOR:
|
|
16
|
+
- Listing config files -> use 'runtime_detect_config'
|
|
17
|
+
- Listing payload spec files -> use generic Read or filesystem tools
|
|
18
|
+
- Listing database tables -> use 'codegen_list_tables'
|
|
19
|
+
- Validating runtime preflight -> use 'runtime_validate_preflight'
|
|
20
|
+
|
|
21
|
+
Preconditions:
|
|
22
|
+
- The 'src/modules/' folder must exist at <cwd>/src/modules/. If missing, the precondition response will say so.
|
|
23
|
+
|
|
24
|
+
PRESENTATION GUIDANCE:
|
|
25
|
+
- Match the user's language. If the user writes in Indonesian, respond in Indonesian.
|
|
26
|
+
- Never mention internal tool names in the reply to the user.
|
|
27
|
+
- When exactly one project is found, proceed without asking. When multiple are found, ask the user to pick one before generating the launcher.
|
|
28
|
+
- The project name comes from the filename in src/modules/ (without the .js extension); explain this in plain language if asked.
|
|
29
|
+
- When a precondition is not met (folder missing), frame it as a question or next-step suggestion rather than an error.`,
|
|
30
|
+
inputSchema: {
|
|
31
|
+
cwd: z
|
|
32
|
+
.string()
|
|
33
|
+
.min(1)
|
|
34
|
+
.describe('Absolute path of the project folder root (must contain src/modules/)'),
|
|
35
|
+
},
|
|
36
|
+
annotations: {
|
|
37
|
+
title: 'Detect Project Names',
|
|
38
|
+
readOnlyHint: true,
|
|
39
|
+
idempotentHint: true,
|
|
40
|
+
},
|
|
41
|
+
}, async ({ cwd }) => {
|
|
42
|
+
const projectCwd = resolve(cwd);
|
|
43
|
+
const modulesDir = join(projectCwd, 'src', 'modules');
|
|
44
|
+
let entries;
|
|
45
|
+
try {
|
|
46
|
+
entries = await readdir(modulesDir);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return {
|
|
50
|
+
content: [
|
|
51
|
+
{
|
|
52
|
+
type: 'text',
|
|
53
|
+
text: `Precondition not met: the modules folder does not exist.
|
|
54
|
+
|
|
55
|
+
Project path: ${projectCwd}
|
|
56
|
+
Expected folder: ${modulesDir}
|
|
57
|
+
|
|
58
|
+
For the assistant:
|
|
59
|
+
- The user is trying to detect RESTForge projects, but the conventional location 'src/modules/' is missing in this directory.
|
|
60
|
+
- Suggest verifying that the user is at the correct project root, or ask the user where the project files are located.
|
|
61
|
+
- Match the user's language. Do not mention internal tool names.`,
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
isError: false,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
const projects = entries
|
|
68
|
+
.filter((name) => name.endsWith('.js'))
|
|
69
|
+
.map((name) => name.replace(/\.js$/, ''));
|
|
70
|
+
const envelope = {
|
|
71
|
+
cwd: projectCwd,
|
|
72
|
+
modules_dir: modulesDir,
|
|
73
|
+
projects,
|
|
74
|
+
count: projects.length,
|
|
75
|
+
};
|
|
76
|
+
const prettyJson = JSON.stringify(envelope, null, 2);
|
|
77
|
+
if (projects.length === 0) {
|
|
78
|
+
return {
|
|
79
|
+
content: [
|
|
80
|
+
{
|
|
81
|
+
type: 'text',
|
|
82
|
+
text: `No RESTForge project files were found in src/modules/.
|
|
83
|
+
|
|
84
|
+
Project path: ${projectCwd}
|
|
85
|
+
Modules folder: ${modulesDir}
|
|
86
|
+
Count: 0
|
|
87
|
+
|
|
88
|
+
--- Detection Result (JSON) ---
|
|
89
|
+
${prettyJson}
|
|
90
|
+
--- end Detection Result (JSON) ---
|
|
91
|
+
|
|
92
|
+
For the assistant:
|
|
93
|
+
- The src/modules/ folder exists but contains no .js files.
|
|
94
|
+
- A RESTForge project is conventionally a single .js file inside src/modules/ (e.g. mini-inventory.js -> project name 'mini-inventory').
|
|
95
|
+
- Suggest the user creates a project file there first, or verify they are at the right project root.
|
|
96
|
+
- Match the user's language. Do not mention internal tool names.`,
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
isError: false,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
const isSingle = projects.length === 1;
|
|
103
|
+
const summary = isSingle
|
|
104
|
+
? `One RESTForge project detected: '${projects[0]}'.`
|
|
105
|
+
: `${projects.length} RESTForge projects detected: ${projects.map((p) => `'${p}'`).join(', ')}.`;
|
|
106
|
+
return {
|
|
107
|
+
content: [
|
|
108
|
+
{
|
|
109
|
+
type: 'text',
|
|
110
|
+
text: `${summary}
|
|
111
|
+
|
|
112
|
+
Project path: ${projectCwd}
|
|
113
|
+
Modules folder: ${modulesDir}
|
|
114
|
+
Count: ${projects.length}
|
|
115
|
+
|
|
116
|
+
--- Detection Result (JSON) ---
|
|
117
|
+
${prettyJson}
|
|
118
|
+
--- end Detection Result (JSON) ---
|
|
119
|
+
|
|
120
|
+
For the assistant:
|
|
121
|
+
- ${isSingle
|
|
122
|
+
? `Only one project was found, so the runtime can use '${projects[0]}' without further input.`
|
|
123
|
+
: `Multiple projects were found. Ask the user which one to launch before proceeding.`}
|
|
124
|
+
- The project name comes from the filename in src/modules/ (without the .js extension). It is the value passed as --project=<name> when invoking the RESTForge runtime.
|
|
125
|
+
- Match the user's language. Do not mention internal tool names.`,
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
isError: false,
|
|
129
|
+
};
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=detect-project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-project.js","sourceRoot":"","sources":["../../../src/tools/runtime/detect-project.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { access, writeFile, stat } from 'node:fs/promises';
|
|
3
|
+
import { resolve, join } from 'node:path';
|
|
4
|
+
const LAUNCHER_FILES = {
|
|
5
|
+
windows: {
|
|
6
|
+
start: 'server-start.bat',
|
|
7
|
+
stop: 'server-stop.bat',
|
|
8
|
+
},
|
|
9
|
+
linux: {
|
|
10
|
+
start: 'server-start.sh',
|
|
11
|
+
stop: 'server-stop.sh',
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
const ECOSYSTEM_FILE = 'ecosystem.config.js';
|
|
15
|
+
const TEMPLATE_WINDOWS_HOST_START = `@echo off
|
|
16
|
+
REM RESTForge Server Launcher
|
|
17
|
+
REM Generated by restforge-mcp
|
|
18
|
+
REM Project: {{PROJECT}}
|
|
19
|
+
REM Config: {{CONFIG}}
|
|
20
|
+
REM Port: {{PORT}}
|
|
21
|
+
|
|
22
|
+
echo Starting RESTForge Server...
|
|
23
|
+
echo Project: {{PROJECT}}
|
|
24
|
+
echo Config: {{CONFIG}}
|
|
25
|
+
echo Port: {{PORT}}
|
|
26
|
+
echo.
|
|
27
|
+
echo To stop: press Ctrl+C in this window, or run server-stop.bat in another terminal.
|
|
28
|
+
echo.
|
|
29
|
+
|
|
30
|
+
npx restforge --project={{PROJECT}} --port={{PORT}} --config={{CONFIG}}{{EXTRA_ARGS_SH}}
|
|
31
|
+
`;
|
|
32
|
+
const TEMPLATE_WINDOWS_HOST_STOP = `@echo off
|
|
33
|
+
REM RESTForge Server Stopper
|
|
34
|
+
REM Generated by restforge-mcp
|
|
35
|
+
|
|
36
|
+
set PORT={{PORT}}
|
|
37
|
+
echo Stopping RESTForge Server on port %PORT%...
|
|
38
|
+
|
|
39
|
+
set FOUND=0
|
|
40
|
+
for /f "tokens=5" %%a in ('netstat -ano ^| findstr :%PORT% ^| findstr LISTENING') do (
|
|
41
|
+
echo Killing PID %%a
|
|
42
|
+
taskkill /F /PID %%a /T
|
|
43
|
+
set FOUND=1
|
|
44
|
+
goto :done
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
:done
|
|
48
|
+
if "%FOUND%"=="0" (
|
|
49
|
+
echo No process found listening on port %PORT%.
|
|
50
|
+
exit /b 1
|
|
51
|
+
)
|
|
52
|
+
`;
|
|
53
|
+
const TEMPLATE_LINUX_HOST_START = `#!/bin/bash
|
|
54
|
+
# RESTForge Server Launcher
|
|
55
|
+
# Generated by restforge-mcp
|
|
56
|
+
# Project: {{PROJECT}}
|
|
57
|
+
# Config: {{CONFIG}}
|
|
58
|
+
# Port: {{PORT}}
|
|
59
|
+
|
|
60
|
+
echo "Starting RESTForge Server..."
|
|
61
|
+
echo "Project: {{PROJECT}}"
|
|
62
|
+
echo "Config: {{CONFIG}}"
|
|
63
|
+
echo "Port: {{PORT}}"
|
|
64
|
+
echo ""
|
|
65
|
+
echo "To stop: press Ctrl+C, or run ./server-stop.sh in another terminal."
|
|
66
|
+
echo ""
|
|
67
|
+
|
|
68
|
+
exec npx restforge --project={{PROJECT}} --port={{PORT}} --config={{CONFIG}}{{EXTRA_ARGS_SH}}
|
|
69
|
+
`;
|
|
70
|
+
const TEMPLATE_LINUX_HOST_STOP = `#!/bin/bash
|
|
71
|
+
# RESTForge Server Stopper
|
|
72
|
+
# Generated by restforge-mcp
|
|
73
|
+
|
|
74
|
+
PORT={{PORT}}
|
|
75
|
+
echo "Stopping RESTForge Server on port $PORT..."
|
|
76
|
+
|
|
77
|
+
PID=""
|
|
78
|
+
if command -v lsof >/dev/null 2>&1; then
|
|
79
|
+
PID=$(lsof -ti:$PORT 2>/dev/null | head -1)
|
|
80
|
+
fi
|
|
81
|
+
if [ -z "$PID" ] && command -v fuser >/dev/null 2>&1; then
|
|
82
|
+
PID=$(fuser \${PORT}/tcp 2>/dev/null | awk '{print $1}')
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
if [ -z "$PID" ]; then
|
|
86
|
+
echo "No process found listening on port $PORT."
|
|
87
|
+
exit 1
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
echo "Killing PID $PID..."
|
|
91
|
+
kill -TERM "$PID" 2>/dev/null
|
|
92
|
+
sleep 1
|
|
93
|
+
if kill -0 "$PID" 2>/dev/null; then
|
|
94
|
+
kill -KILL "$PID" 2>/dev/null
|
|
95
|
+
fi
|
|
96
|
+
echo "Done."
|
|
97
|
+
`;
|
|
98
|
+
const TEMPLATE_PM2_ECOSYSTEM = `// ============================================================
|
|
99
|
+
// PM2 Ecosystem Configuration — {{PROJECT}}
|
|
100
|
+
// Generated by restforge-mcp
|
|
101
|
+
// ============================================================
|
|
102
|
+
// Usage:
|
|
103
|
+
// pm2 start ecosystem.config.js
|
|
104
|
+
// pm2 restart {{PROJECT}}
|
|
105
|
+
// pm2 stop {{PROJECT}}
|
|
106
|
+
// pm2 delete {{PROJECT}}
|
|
107
|
+
// ============================================================
|
|
108
|
+
|
|
109
|
+
module.exports = {
|
|
110
|
+
apps: [
|
|
111
|
+
{
|
|
112
|
+
name: '{{PROJECT}}',
|
|
113
|
+
script: './node_modules/@restforgejs/platform/server.js',
|
|
114
|
+
args: '--project={{PROJECT}} --port={{PORT}} --config={{CONFIG}}{{EXTRA_ARGS_SH}}',
|
|
115
|
+
cwd: __dirname,
|
|
116
|
+
|
|
117
|
+
// Process
|
|
118
|
+
exec_mode: 'fork',
|
|
119
|
+
instances: 1,
|
|
120
|
+
autorestart: true,
|
|
121
|
+
watch: false,
|
|
122
|
+
kill_timeout: 5000,
|
|
123
|
+
|
|
124
|
+
// Memory
|
|
125
|
+
max_memory_restart: '512M',
|
|
126
|
+
exp_backoff_restart_delay: 100,
|
|
127
|
+
|
|
128
|
+
// Environment
|
|
129
|
+
env: {
|
|
130
|
+
NODE_ENV: 'production',
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
// Logging
|
|
134
|
+
log_date_format: 'YYYY-MM-DD HH:mm:ss',
|
|
135
|
+
error_file: './logs/pm2-error.log',
|
|
136
|
+
out_file: './logs/pm2-out.log',
|
|
137
|
+
merge_logs: true,
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
};
|
|
141
|
+
`;
|
|
142
|
+
const TEMPLATE_WINDOWS_PM2_START = `@echo off
|
|
143
|
+
REM RESTForge Server Launcher (PM2 Mode)
|
|
144
|
+
REM Generated by restforge-mcp
|
|
145
|
+
|
|
146
|
+
if not exist logs mkdir logs
|
|
147
|
+
|
|
148
|
+
pm2 start ecosystem.config.js
|
|
149
|
+
pm2 save
|
|
150
|
+
|
|
151
|
+
echo Server started under PM2. Run "pm2 logs {{PROJECT}}" to see logs.
|
|
152
|
+
echo To stop: run server-stop.bat
|
|
153
|
+
`;
|
|
154
|
+
const TEMPLATE_WINDOWS_PM2_STOP = `@echo off
|
|
155
|
+
REM RESTForge Server Stopper (PM2 Mode)
|
|
156
|
+
pm2 stop ecosystem.config.js
|
|
157
|
+
pm2 delete ecosystem.config.js
|
|
158
|
+
`;
|
|
159
|
+
const TEMPLATE_LINUX_PM2_START = `#!/bin/bash
|
|
160
|
+
# RESTForge Server Launcher (PM2 Mode)
|
|
161
|
+
# Generated by restforge-mcp
|
|
162
|
+
|
|
163
|
+
mkdir -p logs
|
|
164
|
+
|
|
165
|
+
pm2 start ecosystem.config.js
|
|
166
|
+
pm2 save
|
|
167
|
+
|
|
168
|
+
echo "Server started under PM2. Run 'pm2 logs {{PROJECT}}' to see logs."
|
|
169
|
+
echo "To stop: run ./server-stop.sh"
|
|
170
|
+
`;
|
|
171
|
+
const TEMPLATE_LINUX_PM2_STOP = `#!/bin/bash
|
|
172
|
+
# RESTForge Server Stopper (PM2 Mode)
|
|
173
|
+
pm2 stop ecosystem.config.js
|
|
174
|
+
pm2 delete ecosystem.config.js
|
|
175
|
+
`;
|
|
176
|
+
function buildExtraArgs(opts) {
|
|
177
|
+
const parts = [];
|
|
178
|
+
if (opts.cluster) {
|
|
179
|
+
parts.push('--cluster');
|
|
180
|
+
}
|
|
181
|
+
else if (opts.workers !== undefined) {
|
|
182
|
+
parts.push(`--workers=${opts.workers}`);
|
|
183
|
+
}
|
|
184
|
+
if (opts.watch) {
|
|
185
|
+
parts.push('--watch');
|
|
186
|
+
}
|
|
187
|
+
return parts.length > 0 ? ' ' + parts.join(' ') : '';
|
|
188
|
+
}
|
|
189
|
+
function applyTemplate(template, vars) {
|
|
190
|
+
return template.replace(/\{\{(\w+)\}\}/g, (_, key) => vars[key] ?? '');
|
|
191
|
+
}
|
|
192
|
+
export function registerRuntimeGenerateLauncher(server) {
|
|
193
|
+
server.registerTool('runtime_generate_launcher', {
|
|
194
|
+
title: 'Generate RESTForge Launcher Script',
|
|
195
|
+
description: `Generate a launcher script for the RESTForge Server in the project root. This tool does NOT run the server — it produces a .bat or .sh script that the user must execute themselves. This is intentional: a server launched by the AI session would terminate when the session ends; a script executed by the user lives in the user's terminal/session and persists independently.
|
|
196
|
+
|
|
197
|
+
Files produced (depending on os + mode) — file names are FIXED, not user-customisable:
|
|
198
|
+
- windows + host: server-start.bat, server-stop.bat
|
|
199
|
+
- windows + pm2: server-start.bat (calls 'pm2 start ecosystem.config.js'), server-stop.bat, ecosystem.config.js
|
|
200
|
+
- linux + host: server-start.sh, server-stop.sh
|
|
201
|
+
- linux + pm2: server-start.sh (calls 'pm2 start ecosystem.config.js'), server-stop.sh, ecosystem.config.js
|
|
202
|
+
|
|
203
|
+
For host mode the start script runs 'npx restforge ...' in the foreground (or 'exec' on Linux). The stop script kills the process by port via netstat/taskkill on Windows or lsof/fuser+kill on Linux — no PID file is required. For PM2 mode the ecosystem points 'script' directly at './node_modules/@restforgejs/platform/server.js' to bypass the npx shim and avoid PM2's default node interpreter mis-parsing a .cmd file.
|
|
204
|
+
|
|
205
|
+
USE WHEN:
|
|
206
|
+
- The user asks "run the server", "jalankan server", "start RESTForge"
|
|
207
|
+
- After confirming OS, mode, project, config, and port with the user (typically via 'runtime_detect_project', 'runtime_detect_config', and direct questions)
|
|
208
|
+
- After 'runtime_check_launcher_exists' returned no conflicts, OR the user confirmed overwrite
|
|
209
|
+
|
|
210
|
+
DO NOT USE FOR:
|
|
211
|
+
- Actually starting or stopping the server -> the user runs the generated script themselves
|
|
212
|
+
- Modifying database schema or payload files -> out of scope
|
|
213
|
+
- Running one-off commands -> out of scope; this tool is launcher-scaffolding only
|
|
214
|
+
|
|
215
|
+
Preconditions:
|
|
216
|
+
- The cwd must exist.
|
|
217
|
+
- 'cluster' and 'workers' are mutually exclusive.
|
|
218
|
+
- 'watch' is not allowed with mode=pm2.
|
|
219
|
+
|
|
220
|
+
PRESENTATION GUIDANCE:
|
|
221
|
+
- Match the user's language.
|
|
222
|
+
- Never mention internal tool names. Refer to the produced files by their visible names (e.g. 'server-start.bat').
|
|
223
|
+
- Tell the user clearly that the AI does NOT execute the script — they must run it themselves so the server keeps running after the AI session ends.
|
|
224
|
+
- For PM2 mode: warn the user that PM2 must be installed globally first (npm install -g pm2). Do not auto-install.
|
|
225
|
+
- After generation, summarise: location, files produced, how to start, how to stop. Do not paste the JSON envelope unless explicitly asked.
|
|
226
|
+
- If the user asks for a different mode (Windows Service, Docker, systemd) — those are out of scope V1; suggest using host or pm2 instead.`,
|
|
227
|
+
inputSchema: {
|
|
228
|
+
cwd: z
|
|
229
|
+
.string()
|
|
230
|
+
.min(1)
|
|
231
|
+
.describe('Absolute path of the project folder root (output goes here)'),
|
|
232
|
+
os: z
|
|
233
|
+
.enum(['windows', 'linux'])
|
|
234
|
+
.describe('Target OS: windows produces .bat, linux produces .sh'),
|
|
235
|
+
mode: z
|
|
236
|
+
.enum(['host', 'pm2'])
|
|
237
|
+
.describe('Runtime mode: host runs npx restforge directly; pm2 uses ecosystem.config.js'),
|
|
238
|
+
project: z
|
|
239
|
+
.string()
|
|
240
|
+
.min(1)
|
|
241
|
+
.describe('Project name (filename in src/modules/ without .js). Passed as --project=<name>'),
|
|
242
|
+
config: z
|
|
243
|
+
.string()
|
|
244
|
+
.min(1)
|
|
245
|
+
.describe('Config file name in config/ folder (e.g. db-connection.env). Passed as --config=<filename>'),
|
|
246
|
+
port: z.number().int().min(1).max(65535).describe('Server port'),
|
|
247
|
+
overwrite: z
|
|
248
|
+
.boolean()
|
|
249
|
+
.default(false)
|
|
250
|
+
.describe('If true, overwrite existing files. If false, skip existing.'),
|
|
251
|
+
cluster: z
|
|
252
|
+
.boolean()
|
|
253
|
+
.optional()
|
|
254
|
+
.describe('If true, append --cluster flag. Mutually exclusive with workers.'),
|
|
255
|
+
workers: z
|
|
256
|
+
.number()
|
|
257
|
+
.int()
|
|
258
|
+
.min(1)
|
|
259
|
+
.max(64)
|
|
260
|
+
.optional()
|
|
261
|
+
.describe('If set, append --workers=N flag. Mutually exclusive with cluster.'),
|
|
262
|
+
watch: z
|
|
263
|
+
.boolean()
|
|
264
|
+
.optional()
|
|
265
|
+
.describe('If true, append --watch flag. Not allowed with mode=pm2 (PM2 has its own watch via ecosystem).'),
|
|
266
|
+
},
|
|
267
|
+
annotations: {
|
|
268
|
+
title: 'Generate Launcher Script',
|
|
269
|
+
readOnlyHint: false,
|
|
270
|
+
idempotentHint: false,
|
|
271
|
+
destructiveHint: true,
|
|
272
|
+
},
|
|
273
|
+
}, async (input) => {
|
|
274
|
+
const { cwd, os, mode, project, config, port, overwrite, cluster, workers, watch } = input;
|
|
275
|
+
if (cluster && workers !== undefined) {
|
|
276
|
+
return {
|
|
277
|
+
content: [
|
|
278
|
+
{
|
|
279
|
+
type: 'text',
|
|
280
|
+
text: `Conflicting options: 'cluster' and 'workers' cannot both be set.
|
|
281
|
+
|
|
282
|
+
For the assistant:
|
|
283
|
+
- Ask the user to pick one. Cluster auto-detects CPU count; workers=N is explicit.`,
|
|
284
|
+
},
|
|
285
|
+
],
|
|
286
|
+
isError: false,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
if (mode === 'pm2' && watch) {
|
|
290
|
+
return {
|
|
291
|
+
content: [
|
|
292
|
+
{
|
|
293
|
+
type: 'text',
|
|
294
|
+
text: `Conflicting options: 'watch' is not allowed when mode=pm2 (PM2 manages watch internally via ecosystem.config.js).
|
|
295
|
+
|
|
296
|
+
For the assistant:
|
|
297
|
+
- Suggest setting watch only with mode=host.`,
|
|
298
|
+
},
|
|
299
|
+
],
|
|
300
|
+
isError: false,
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
const projectCwd = resolve(cwd);
|
|
304
|
+
try {
|
|
305
|
+
await access(projectCwd);
|
|
306
|
+
}
|
|
307
|
+
catch {
|
|
308
|
+
return {
|
|
309
|
+
content: [
|
|
310
|
+
{
|
|
311
|
+
type: 'text',
|
|
312
|
+
text: `Precondition not met: cwd does not exist: ${projectCwd}
|
|
313
|
+
|
|
314
|
+
For the assistant:
|
|
315
|
+
- The target folder is missing. Suggest creating it first or verifying the path.
|
|
316
|
+
- Match the user's language. Do not mention internal tool names.`,
|
|
317
|
+
},
|
|
318
|
+
],
|
|
319
|
+
isError: false,
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
const extra = buildExtraArgs({ cluster, workers, watch });
|
|
323
|
+
const vars = {
|
|
324
|
+
PROJECT: project,
|
|
325
|
+
CONFIG: config,
|
|
326
|
+
PORT: String(port),
|
|
327
|
+
EXTRA_ARGS_SH: extra,
|
|
328
|
+
};
|
|
329
|
+
const startFile = LAUNCHER_FILES[os].start;
|
|
330
|
+
const stopFile = LAUNCHER_FILES[os].stop;
|
|
331
|
+
const filesToWrite = [];
|
|
332
|
+
if (os === 'windows' && mode === 'host') {
|
|
333
|
+
filesToWrite.push({ fileName: startFile, content: applyTemplate(TEMPLATE_WINDOWS_HOST_START, vars) }, { fileName: stopFile, content: applyTemplate(TEMPLATE_WINDOWS_HOST_STOP, vars) });
|
|
334
|
+
}
|
|
335
|
+
else if (os === 'windows' && mode === 'pm2') {
|
|
336
|
+
filesToWrite.push({ fileName: startFile, content: applyTemplate(TEMPLATE_WINDOWS_PM2_START, vars) }, { fileName: stopFile, content: applyTemplate(TEMPLATE_WINDOWS_PM2_STOP, vars) }, { fileName: ECOSYSTEM_FILE, content: applyTemplate(TEMPLATE_PM2_ECOSYSTEM, vars) });
|
|
337
|
+
}
|
|
338
|
+
else if (os === 'linux' && mode === 'host') {
|
|
339
|
+
filesToWrite.push({ fileName: startFile, content: applyTemplate(TEMPLATE_LINUX_HOST_START, vars) }, { fileName: stopFile, content: applyTemplate(TEMPLATE_LINUX_HOST_STOP, vars) });
|
|
340
|
+
}
|
|
341
|
+
else if (os === 'linux' && mode === 'pm2') {
|
|
342
|
+
filesToWrite.push({ fileName: startFile, content: applyTemplate(TEMPLATE_LINUX_PM2_START, vars) }, { fileName: stopFile, content: applyTemplate(TEMPLATE_LINUX_PM2_STOP, vars) }, { fileName: ECOSYSTEM_FILE, content: applyTemplate(TEMPLATE_PM2_ECOSYSTEM, vars) });
|
|
343
|
+
}
|
|
344
|
+
const generated = [];
|
|
345
|
+
const skipped = [];
|
|
346
|
+
for (const f of filesToWrite) {
|
|
347
|
+
const fullPath = join(projectCwd, f.fileName);
|
|
348
|
+
let existed = false;
|
|
349
|
+
try {
|
|
350
|
+
await stat(fullPath);
|
|
351
|
+
existed = true;
|
|
352
|
+
}
|
|
353
|
+
catch {
|
|
354
|
+
existed = false;
|
|
355
|
+
}
|
|
356
|
+
if (existed && !overwrite) {
|
|
357
|
+
skipped.push({ path: fullPath, reason: 'already exists, overwrite=false' });
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
try {
|
|
361
|
+
await writeFile(fullPath, f.content, 'utf8');
|
|
362
|
+
generated.push({
|
|
363
|
+
path: fullPath,
|
|
364
|
+
size_bytes: Buffer.byteLength(f.content, 'utf8'),
|
|
365
|
+
overwritten: existed,
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
catch (err) {
|
|
369
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
370
|
+
return {
|
|
371
|
+
content: [
|
|
372
|
+
{ type: 'text', text: `Failed to write ${fullPath}: ${msg}` },
|
|
373
|
+
],
|
|
374
|
+
isError: true,
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
const pm2Warning = mode === 'pm2'
|
|
379
|
+
? 'PM2 must be installed globally on the user machine (npm install -g pm2). This tool does not auto-install. If PM2 is missing, the launcher will fail at runtime.'
|
|
380
|
+
: null;
|
|
381
|
+
const stopMethod = mode === 'pm2'
|
|
382
|
+
? `pm2 stop ecosystem.config.js (invoked by ${stopFile})`
|
|
383
|
+
: `kill the process listening on port ${port} (invoked by ${stopFile})`;
|
|
384
|
+
const envelope = {
|
|
385
|
+
cwd: projectCwd,
|
|
386
|
+
os,
|
|
387
|
+
mode,
|
|
388
|
+
project,
|
|
389
|
+
config,
|
|
390
|
+
port,
|
|
391
|
+
generated_files: generated,
|
|
392
|
+
skipped_files: skipped,
|
|
393
|
+
stop_method: stopMethod,
|
|
394
|
+
pm2_warning: pm2Warning,
|
|
395
|
+
};
|
|
396
|
+
const prettyJson = JSON.stringify(envelope, null, 2);
|
|
397
|
+
const summary = generated.length === filesToWrite.length
|
|
398
|
+
? `Generated ${generated.length} launcher file${generated.length === 1 ? '' : 's'}.`
|
|
399
|
+
: `Generated ${generated.length}; skipped ${skipped.length} (already exist, overwrite=false).`;
|
|
400
|
+
const startCommand = os === 'windows' ? `.\\${startFile}` : `./${startFile}`;
|
|
401
|
+
const stopCommand = os === 'windows' ? stopFile : `./${stopFile}`;
|
|
402
|
+
return {
|
|
403
|
+
content: [
|
|
404
|
+
{
|
|
405
|
+
type: 'text',
|
|
406
|
+
text: `${summary}
|
|
407
|
+
|
|
408
|
+
Project path: ${projectCwd}
|
|
409
|
+
OS: ${os}
|
|
410
|
+
Mode: ${mode}
|
|
411
|
+
Project: ${project}
|
|
412
|
+
Config: ${config}
|
|
413
|
+
Port: ${port}
|
|
414
|
+
Generated: ${generated.length}
|
|
415
|
+
Skipped: ${skipped.length}
|
|
416
|
+
PM2 warning: ${pm2Warning ?? 'n/a'}
|
|
417
|
+
|
|
418
|
+
--- Generation Result (JSON) ---
|
|
419
|
+
${prettyJson}
|
|
420
|
+
--- end Generation Result (JSON) ---
|
|
421
|
+
|
|
422
|
+
For the assistant:
|
|
423
|
+
- ${generated.length > 0
|
|
424
|
+
? `Tell the user the launcher was generated at the project root. To start: ${startCommand}. To stop: ${stopCommand}.`
|
|
425
|
+
: `Nothing was generated because all files already exist and overwrite=false. Ask the user whether to overwrite (call again with overwrite=true) or pick a different base name.`}
|
|
426
|
+
- ${pm2Warning
|
|
427
|
+
? `Warn the user that PM2 must be installed globally on their machine before running the launcher.`
|
|
428
|
+
: ``}
|
|
429
|
+
- The server will run in the user's terminal — when launched manually, the process belongs to the user's session, NOT to this AI session.
|
|
430
|
+
- For host mode the stop script kills the process listening on port ${port} (cross-platform port-based lookup). For PM2 mode the stop script delegates to pm2.
|
|
431
|
+
- Match the user's language. Do not mention internal tool names.`,
|
|
432
|
+
},
|
|
433
|
+
],
|
|
434
|
+
isError: false,
|
|
435
|
+
};
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
//# sourceMappingURL=generate-launcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-launcher.js","sourceRoot":"","sources":["../../../src/tools/runtime/generate-launcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAG1C,MAAM,cAAc,GAAG;IACrB,OAAO,EAAE;QACP,KAAK,EAAE,kBAAkB;QACzB,IAAI,EAAE,iBAAiB;KACxB;IACD,KAAK,EAAE;QACL,KAAK,EAAE,iBAAiB;QACxB,IAAI,EAAE,gBAAgB;KACvB;CACO,CAAC;AAEX,MAAM,cAAc,GAAG,qBAAqB,CAAC;AAE7C,MAAM,2BAA2B,GAAG;;;;;;;;;;;;;;;;CAgBnC,CAAC;AAEF,MAAM,0BAA0B,GAAG;;;;;;;;;;;;;;;;;;;;CAoBlC,CAAC;AAEF,MAAM,yBAAyB,GAAG;;;;;;;;;;;;;;;;CAgBjC,CAAC;AAEF,MAAM,wBAAwB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BhC,CAAC;AAEF,MAAM,sBAAsB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2C9B,CAAC;AAEF,MAAM,0BAA0B,GAAG;;;;;;;;;;;CAWlC,CAAC;AAEF,MAAM,yBAAyB,GAAG;;;;CAIjC,CAAC;AAEF,MAAM,wBAAwB,GAAG;;;;;;;;;;;CAWhC,CAAC;AAEF,MAAM,uBAAuB,GAAG;;;;CAI/B,CAAC;AAQF,SAAS,cAAc,CAAC,IAAsB;IAC5C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC1B,CAAC;SAAM,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAC1C,CAAC;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACvD,CAAC;AAED,SAAS,aAAa,CAAC,QAAgB,EAAE,IAA4B;IACnE,OAAO,QAAQ,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,+BAA+B,CAAC,MAAiB;IAC/D,MAAM,CAAC,YAAY,CACjB,2BAA2B,EAC3B;QACE,KAAK,EAAE,oCAAoC;QAC3C,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2IA+BwH;QACrI,WAAW,EAAE;YACX,GAAG,EAAE,CAAC;iBACH,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,CAAC;iBACN,QAAQ,CAAC,6DAA6D,CAAC;YAC1E,EAAE,EAAE,CAAC;iBACF,IAAI,CAAC,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;iBAC1B,QAAQ,CAAC,sDAAsD,CAAC;YACnE,IAAI,EAAE,CAAC;iBACJ,IAAI,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;iBACrB,QAAQ,CAAC,8EAA8E,CAAC;YAC3F,OAAO,EAAE,CAAC;iBACP,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,CAAC;iBACN,QAAQ,CACP,iFAAiF,CAClF;YACH,MAAM,EAAE,CAAC;iBACN,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,CAAC;iBACN,QAAQ,CACP,4FAA4F,CAC7F;YACH,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC;YAChE,SAAS,EAAE,CAAC;iBACT,OAAO,EAAE;iBACT,OAAO,CAAC,KAAK,CAAC;iBACd,QAAQ,CAAC,6DAA6D,CAAC;YAC1E,OAAO,EAAE,CAAC;iBACP,OAAO,EAAE;iBACT,QAAQ,EAAE;iBACV,QAAQ,CAAC,kEAAkE,CAAC;YAC/E,OAAO,EAAE,CAAC;iBACP,MAAM,EAAE;iBACR,GAAG,EAAE;iBACL,GAAG,CAAC,CAAC,CAAC;iBACN,GAAG,CAAC,EAAE,CAAC;iBACP,QAAQ,EAAE;iBACV,QAAQ,CAAC,mEAAmE,CAAC;YAChF,KAAK,EAAE,CAAC;iBACL,OAAO,EAAE;iBACT,QAAQ,EAAE;iBACV,QAAQ,CACP,gGAAgG,CACjG;SACJ;QACD,WAAW,EAAE;YACX,KAAK,EAAE,0BAA0B;YACjC,YAAY,EAAE,KAAK;YACnB,cAAc,EAAE,KAAK;YACrB,eAAe,EAAE,IAAI;SACtB;KACF,EACD,KAAK,EAAE,KAAK,EAAE,EAAE;QACd,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;QAE3F,IAAI,OAAO,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YACrC,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE;;;mFAG+D;qBACtE;iBACF;gBACD,OAAO,EAAE,KAAK;aACf,CAAC;QACJ,CAAC;QACD,IAAI,IAAI,KAAK,KAAK,IAAI,KAAK,EAAE,CAAC;YAC5B,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE;;;6CAGyB;qBAChC;iBACF;gBACD,OAAO,EAAE,KAAK;aACf,CAAC;QACJ,CAAC;QAED,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,6CAA6C,UAAU;;;;iEAIV;qBACpD;iBACF;gBACD,OAAO,EAAE,KAAK;aACf,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,GAAG,cAAc,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAE1D,MAAM,IAAI,GAA2B;YACnC,OAAO,EAAE,OAAO;YAChB,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC;YAClB,aAAa,EAAE,KAAK;SACrB,CAAC;QAEF,MAAM,SAAS,GAAG,cAAc,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC;QAC3C,MAAM,QAAQ,GAAG,cAAc,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC;QAGzC,MAAM,YAAY,GAAe,EAAE,CAAC;QAEpC,IAAI,EAAE,KAAK,SAAS,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACxC,YAAY,CAAC,IAAI,CACf,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,CAAC,2BAA2B,EAAE,IAAI,CAAC,EAAE,EAClF,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,CAAC,0BAA0B,EAAE,IAAI,CAAC,EAAE,CACjF,CAAC;QACJ,CAAC;aAAM,IAAI,EAAE,KAAK,SAAS,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;YAC9C,YAAY,CAAC,IAAI,CACf,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,CAAC,0BAA0B,EAAE,IAAI,CAAC,EAAE,EACjF,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,CAAC,yBAAyB,EAAE,IAAI,CAAC,EAAE,EAC/E,EAAE,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE,aAAa,CAAC,sBAAsB,EAAE,IAAI,CAAC,EAAE,CACnF,CAAC;QACJ,CAAC;aAAM,IAAI,EAAE,KAAK,OAAO,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YAC7C,YAAY,CAAC,IAAI,CACf,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,CAAC,yBAAyB,EAAE,IAAI,CAAC,EAAE,EAChF,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,CAAC,wBAAwB,EAAE,IAAI,CAAC,EAAE,CAC/E,CAAC;QACJ,CAAC;aAAM,IAAI,EAAE,KAAK,OAAO,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;YAC5C,YAAY,CAAC,IAAI,CACf,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,CAAC,wBAAwB,EAAE,IAAI,CAAC,EAAE,EAC/E,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,CAAC,uBAAuB,EAAE,IAAI,CAAC,EAAE,EAC7E,EAAE,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE,aAAa,CAAC,sBAAsB,EAAE,IAAI,CAAC,EAAE,CACnF,CAAC;QACJ,CAAC;QAED,MAAM,SAAS,GAAiE,EAAE,CAAC;QACnF,MAAM,OAAO,GAAuC,EAAE,CAAC;QAEvD,KAAK,MAAM,CAAC,IAAI,YAAY,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;YAC9C,IAAI,OAAO,GAAG,KAAK,CAAC;YACpB,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACrB,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,GAAG,KAAK,CAAC;YAClB,CAAC;YAED,IAAI,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC;gBAC1B,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,iCAAiC,EAAE,CAAC,CAAC;gBAC5E,SAAS;YACX,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBAC7C,SAAS,CAAC,IAAI,CAAC;oBACb,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC;oBAChD,WAAW,EAAE,OAAO;iBACrB,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAC7D,OAAO;oBACL,OAAO,EAAE;wBACP,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,QAAQ,KAAK,GAAG,EAAE,EAAE;qBAC9D;oBACD,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;QACH,CAAC;QAED,MAAM,UAAU,GACd,IAAI,KAAK,KAAK;YACZ,CAAC,CAAC,iKAAiK;YACnK,CAAC,CAAC,IAAI,CAAC;QACX,MAAM,UAAU,GACd,IAAI,KAAK,KAAK;YACZ,CAAC,CAAC,4CAA4C,QAAQ,GAAG;YACzD,CAAC,CAAC,sCAAsC,IAAI,gBAAgB,QAAQ,GAAG,CAAC;QAE5E,MAAM,QAAQ,GAAG;YACf,GAAG,EAAE,UAAU;YACf,EAAE;YACF,IAAI;YACJ,OAAO;YACP,MAAM;YACN,IAAI;YACJ,eAAe,EAAE,SAAS;YAC1B,aAAa,EAAE,OAAO;YACtB,WAAW,EAAE,UAAU;YACvB,WAAW,EAAE,UAAU;SACxB,CAAC;QACF,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAErD,MAAM,OAAO,GACX,SAAS,CAAC,MAAM,KAAK,YAAY,CAAC,MAAM;YACtC,CAAC,CAAC,aAAa,SAAS,CAAC,MAAM,iBAAiB,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG;YACpF,CAAC,CAAC,aAAa,SAAS,CAAC,MAAM,aAAa,OAAO,CAAC,MAAM,oCAAoC,CAAC;QAEnG,MAAM,YAAY,GAAG,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,SAAS,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;QAC7E,MAAM,WAAW,GAAG,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;QAElE,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,GAAG,OAAO;;gBAEZ,UAAU;MACpB,EAAE;QACA,IAAI;WACD,OAAO;UACR,MAAM;QACR,IAAI;aACC,SAAS,CAAC,MAAM;WAClB,OAAO,CAAC,MAAM;eACV,UAAU,IAAI,KAAK;;;EAGhC,UAAU;;;;IAKE,SAAS,CAAC,MAAM,GAAG,CAAC;wBAClB,CAAC,CAAC,2EAA2E,YAAY,cAAc,WAAW,GAAG;wBACrH,CAAC,CAAC,8KACN;IAEE,UAAU;wBACR,CAAC,CAAC,iGAAiG;wBACnG,CAAC,CAAC,EACN;;sEAE0D,IAAI;iEACT;iBACtD;aACF;YACD,OAAO,EAAE,KAAK;SACf,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { registerRuntimeDetectProject } from './detect-project.js';
|
|
2
|
+
import { registerRuntimeDetectConfig } from './detect-config.js';
|
|
3
|
+
import { registerRuntimeValidatePreflight } from './validate-preflight.js';
|
|
4
|
+
import { registerRuntimeCheckLauncherExists } from './check-launcher-exists.js';
|
|
5
|
+
import { registerRuntimeGenerateLauncher } from './generate-launcher.js';
|
|
6
|
+
import { registerRuntimeCheckStatus } from './check-status.js';
|
|
7
|
+
export function registerRuntimeTools(server) {
|
|
8
|
+
registerRuntimeDetectProject(server);
|
|
9
|
+
registerRuntimeDetectConfig(server);
|
|
10
|
+
registerRuntimeValidatePreflight(server);
|
|
11
|
+
registerRuntimeCheckLauncherExists(server);
|
|
12
|
+
registerRuntimeGenerateLauncher(server);
|
|
13
|
+
registerRuntimeCheckStatus(server);
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/runtime/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,4BAA4B,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,gCAAgC,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,kCAAkC,EAAE,MAAM,4BAA4B,CAAC;AAChF,OAAO,EAAE,+BAA+B,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AAE/D,MAAM,UAAU,oBAAoB,CAAC,MAAiB;IACpD,4BAA4B,CAAC,MAAM,CAAC,CAAC;IACrC,2BAA2B,CAAC,MAAM,CAAC,CAAC;IACpC,gCAAgC,CAAC,MAAM,CAAC,CAAC;IACzC,kCAAkC,CAAC,MAAM,CAAC,CAAC;IAC3C,+BAA+B,CAAC,MAAM,CAAC,CAAC;IACxC,0BAA0B,CAAC,MAAM,CAAC,CAAC;AACrC,CAAC"}
|