fa-mcp-sdk 0.2.38 → 0.2.76
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/bin/fa-mcp.js +781 -0
- package/cli-template/.editorconfig +13 -0
- package/cli-template/.env.example +29 -0
- package/cli-template/.envrc +3 -0
- package/cli-template/.run/== START ==.run.xml +14 -0
- package/cli-template/.run/TEST HTTP.run.xml +5 -0
- package/cli-template/.run/TEST SSE.run.xml +5 -0
- package/cli-template/.run/TEST STDIO.run.xml +5 -0
- package/cli-template/.run/TEST search.run.xml +11 -0
- package/cli-template/.run/cb.run.xml +12 -0
- package/cli-template/.run/ci.run.xml +12 -0
- package/cli-template/.run/kill-port 3030.run.xml +5 -0
- package/cli-template/.run/lint.run.xml +12 -0
- package/cli-template/.run/lint_fix.run.xml +12 -0
- package/cli-template/.run/reinstall.run.xml +12 -0
- package/cli-template/.run/remove-nul.js.run.xml +5 -0
- package/cli-template/LICENSE +21 -0
- package/cli-template/config/_local.yaml +64 -0
- package/cli-template/config/custom-environment-variables.yaml +33 -0
- package/cli-template/config/default.yaml +101 -0
- package/cli-template/config/development.yaml +4 -0
- package/cli-template/config/production.yaml +4 -0
- package/cli-template/config/test.yaml +26 -0
- package/cli-template/deploy/.gitkeep +0 -0
- package/cli-template/deploy/config.example.yml +3 -0
- package/cli-template/deploy/mcp-template.com.conf +58 -0
- package/cli-template/deploy/pm2.config.js +30 -0
- package/cli-template/deploy/pm2reg.sh +49 -0
- package/cli-template/deploy/srv.sh +359 -0
- package/cli-template/deploy/srv.sh.readme.md +347 -0
- package/cli-template/eslint.config.js +139 -0
- package/cli-template/jest.config.js +30 -0
- package/cli-template/package.json +73 -0
- package/cli-template/scripts/kill-port.js +107 -0
- package/cli-template/scripts/npm/patch_node_modules.js +9 -0
- package/cli-template/scripts/npm/run.js +31 -0
- package/cli-template/scripts/npm/yarn-ci.ps1 +16 -0
- package/cli-template/scripts/npm/yarn-ci.sh +8 -0
- package/cli-template/scripts/npm/yarn-reinstall.ps1 +54 -0
- package/cli-template/scripts/npm/yarn-reinstall.sh +10 -0
- package/cli-template/scripts/pre-commit +58 -0
- package/cli-template/scripts/remove-nul.js +53 -0
- package/cli-template/src/_types_/common.d.ts +27 -0
- package/cli-template/src/api/router.ts +35 -0
- package/cli-template/src/api/swagger.ts +167 -0
- package/cli-template/src/asset/favicon.svg +4 -0
- package/cli-template/src/custom-resources.ts +11 -0
- package/cli-template/src/prompts/agent-brief.ts +8 -0
- package/cli-template/src/prompts/agent-prompt.ts +1 -0
- package/cli-template/src/prompts/custom-prompts.ts +12 -0
- package/cli-template/src/start.ts +84 -0
- package/cli-template/src/tools/handle-tool-call.ts +55 -0
- package/cli-template/src/tools/tools.ts +88 -0
- package/cli-template/tests/jest-simple-reporter.js +10 -0
- package/cli-template/tests/mcp/sse/mcp-sse-client-handling.md +111 -0
- package/cli-template/tests/mcp/sse/test-sse-npm-package.js +96 -0
- package/cli-template/tests/mcp/test-cases.js +143 -0
- package/cli-template/tests/mcp/test-http.js +63 -0
- package/cli-template/tests/mcp/test-sse.js +67 -0
- package/cli-template/tests/mcp/test-stdio.js +78 -0
- package/cli-template/tests/utils.ts +154 -0
- package/cli-template/tsconfig.json +48 -0
- package/cli-template/update.cjs +631 -0
- package/dist/core/_types_/active-directory-config.d.ts +24 -0
- package/dist/core/_types_/active-directory-config.d.ts.map +1 -0
- package/dist/core/_types_/active-directory-config.js +2 -0
- package/dist/core/_types_/active-directory-config.js.map +1 -0
- package/dist/core/bootstrap/init-config.d.ts.map +1 -1
- package/dist/core/bootstrap/init-config.js +14 -3
- package/dist/core/bootstrap/init-config.js.map +1 -1
- package/dist/core/bootstrap/startup-info.js +1 -1
- package/dist/core/bootstrap/startup-info.js.map +1 -1
- package/dist/core/index.d.ts +3 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +5 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/init-mcp-server.js +1 -1
- package/dist/core/init-mcp-server.js.map +1 -1
- package/dist/core/token/gen-token-app/gen-token-server.d.ts.map +1 -1
- package/dist/core/token/gen-token-app/gen-token-server.js +85 -9
- package/dist/core/token/gen-token-app/gen-token-server.js.map +1 -1
- package/dist/core/token/gen-token-app/html.d.ts +8 -1
- package/dist/core/token/gen-token-app/html.d.ts.map +1 -1
- package/dist/core/token/gen-token-app/html.js +98 -2
- package/dist/core/token/gen-token-app/html.js.map +1 -1
- package/dist/core/token/gen-token-app/ntlm-auth-options.d.ts +4 -0
- package/dist/core/token/gen-token-app/ntlm-auth-options.d.ts.map +1 -0
- package/dist/core/token/gen-token-app/ntlm-auth-options.js +85 -0
- package/dist/core/token/gen-token-app/ntlm-auth-options.js.map +1 -0
- package/dist/core/token/gen-token-app/ntlm-domain-config.d.ts +16 -0
- package/dist/core/token/gen-token-app/ntlm-domain-config.d.ts.map +1 -0
- package/dist/core/token/gen-token-app/ntlm-domain-config.js +71 -0
- package/dist/core/token/gen-token-app/ntlm-domain-config.js.map +1 -0
- package/dist/core/token/gen-token-app/ntlm-integration.d.ts +6 -0
- package/dist/core/token/gen-token-app/ntlm-integration.d.ts.map +1 -0
- package/dist/core/token/gen-token-app/ntlm-integration.js +73 -0
- package/dist/core/token/gen-token-app/ntlm-integration.js.map +1 -0
- package/dist/core/token/gen-token-app/ntlm-session-storage.d.ts +16 -0
- package/dist/core/token/gen-token-app/ntlm-session-storage.d.ts.map +1 -0
- package/dist/core/token/gen-token-app/ntlm-session-storage.js +74 -0
- package/dist/core/token/gen-token-app/ntlm-session-storage.js.map +1 -0
- package/dist/core/token/gen-token-app/ntlm-templates.d.ts +21 -0
- package/dist/core/token/gen-token-app/ntlm-templates.d.ts.map +1 -0
- package/dist/core/token/gen-token-app/ntlm-templates.js +211 -0
- package/dist/core/token/gen-token-app/ntlm-templates.js.map +1 -0
- package/dist/core/token/{token.d.ts → token-auth.d.ts} +1 -1
- package/dist/core/token/token-auth.d.ts.map +1 -0
- package/dist/core/token/{token.js → token-auth.js} +4 -6
- package/dist/core/token/token-auth.js.map +1 -0
- package/dist/core/token/token-core.d.ts +5 -1
- package/dist/core/token/token-core.d.ts.map +1 -1
- package/dist/core/token/token-core.js +13 -3
- package/dist/core/token/token-core.js.map +1 -1
- package/dist/core/web/about-page/render.js +1 -1
- package/dist/core/web/about-page/render.js.map +1 -1
- package/dist/core/web/server-http.js +1 -1
- package/dist/core/web/server-http.js.map +1 -1
- package/package.json +10 -3
- package/dist/core/token/token.d.ts.map +0 -1
- package/dist/core/token/token.js.map +0 -1
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
#!/usr/bin/bash
|
|
2
|
+
|
|
3
|
+
# srv.sh - Unified systemd service management script
|
|
4
|
+
# Consolidates functionality from deploy/systemd-service/ scripts
|
|
5
|
+
# Can be run from project root or from deploy/ directory
|
|
6
|
+
|
|
7
|
+
# Colors for output
|
|
8
|
+
c="\e[1;36m"; lc="\e[0;36m";
|
|
9
|
+
g="\e[1;32m"; lg="\e[0;32m";
|
|
10
|
+
m="\e[1;35m"; lm="\e[0;35m";
|
|
11
|
+
r="\e[1;31m"; lr="\e[0;31m";
|
|
12
|
+
y="\e[1;33m"; ly="\e[0;33m";
|
|
13
|
+
c0='\033[0;0m'
|
|
14
|
+
|
|
15
|
+
# Script configuration
|
|
16
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
17
|
+
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" # Parent directory (project root)
|
|
18
|
+
SERVICE_NAME=""
|
|
19
|
+
NODE_VERSION=""
|
|
20
|
+
PORT=""
|
|
21
|
+
COMMAND=""
|
|
22
|
+
|
|
23
|
+
# Function to show usage
|
|
24
|
+
show_usage() {
|
|
25
|
+
echo "Usage:"
|
|
26
|
+
echo " $0 i|install [-n <service_name>] [-v <node_version>]"
|
|
27
|
+
echo " $0 d|delete [-n <service_name>] [-p <port>]"
|
|
28
|
+
echo " $0 r|reinstall [-n <service_name>] [-p <port>] [-v <node_version>]"
|
|
29
|
+
echo ""
|
|
30
|
+
echo "Commands:"
|
|
31
|
+
echo " i, install - Install and start systemd service"
|
|
32
|
+
echo " d, delete - Stop and remove systemd service"
|
|
33
|
+
echo " r, reinstall - Reinstall service (delete + install)"
|
|
34
|
+
echo ""
|
|
35
|
+
echo "Options:"
|
|
36
|
+
echo " -n <name> - Alternative service name (default: from package.json)"
|
|
37
|
+
echo " -v <version> - Node.js version (default: auto-detected)"
|
|
38
|
+
echo " -p <port> - Port number for service cleanup (default: auto-detected)"
|
|
39
|
+
echo ""
|
|
40
|
+
echo "Working directories:"
|
|
41
|
+
echo " Script location: $SCRIPT_DIR"
|
|
42
|
+
echo " Project root: $PROJECT_ROOT"
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
# Function to check if service exists
|
|
46
|
+
service_exists() {
|
|
47
|
+
local n=$1
|
|
48
|
+
if [[ $(systemctl list-units --all -t service --full --no-legend "$n.service" | sed 's/●//g' | sed 's/^\s*//g' | cut -f1 -d' ') == $n.service ]]; then
|
|
49
|
+
return 0
|
|
50
|
+
else
|
|
51
|
+
return 1
|
|
52
|
+
fi
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
# Function to detect Node.js version
|
|
56
|
+
detect_node_version() {
|
|
57
|
+
local version=""
|
|
58
|
+
|
|
59
|
+
# 1. Use provided version parameter
|
|
60
|
+
if [ -n "$NODE_VERSION" ]; then
|
|
61
|
+
version="$NODE_VERSION"
|
|
62
|
+
echo -e "$c**** Using provided Node.js version: $g$version$c ****$c0" >&2
|
|
63
|
+
# 2. Try to find version in .envrc (in project root)
|
|
64
|
+
elif [ -f "$PROJECT_ROOT/.envrc" ]; then
|
|
65
|
+
version=$(grep -E "^\s*nvm\s+use\s+" "$PROJECT_ROOT/.envrc" | sed -E 's/^\s*nvm\s+use\s+([0-9]+\.[0-9]+\.[0-9]+).*/\1/' | head -n1)
|
|
66
|
+
if [ -n "$version" ]; then
|
|
67
|
+
echo -e "$c**** Found Node.js version in .envrc: $g$version$c ****$c0" >&2
|
|
68
|
+
fi
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
# 3. Fallback to current node version
|
|
72
|
+
if [ -z "$version" ]; then
|
|
73
|
+
version=$(node -v 2>/dev/null | sed 's/^v//')
|
|
74
|
+
if [ -n "$version" ]; then
|
|
75
|
+
echo -e "$c**** Using current Node.js version: $g$version$c ****$c0" >&2
|
|
76
|
+
else
|
|
77
|
+
echo -e "$r**** Error: Could not detect Node.js version ****$c0" >&2
|
|
78
|
+
exit 1
|
|
79
|
+
fi
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
echo "$version"
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
# Function to find Node.js binary path
|
|
86
|
+
find_node_path() {
|
|
87
|
+
local version="$1"
|
|
88
|
+
local node_path=""
|
|
89
|
+
|
|
90
|
+
# Try NVM path first
|
|
91
|
+
local nvm_path="$HOME/.nvm/versions/node/v$version/bin/node"
|
|
92
|
+
if [ -f "$nvm_path" ]; then
|
|
93
|
+
node_path="$nvm_path"
|
|
94
|
+
echo -e "$c**** Found Node.js at NVM path: $g$node_path$c ****$c0" >&2
|
|
95
|
+
else
|
|
96
|
+
# Try system node
|
|
97
|
+
node_path=$(which node 2>/dev/null)
|
|
98
|
+
if [ -n "$node_path" ]; then
|
|
99
|
+
local current_version=$(node -v 2>/dev/null | sed 's/^v//')
|
|
100
|
+
if [ "$current_version" = "$version" ]; then
|
|
101
|
+
echo -e "$c**** Found Node.js at system path: $g$node_path$c ****$c0" >&2
|
|
102
|
+
else
|
|
103
|
+
echo -e "$y**** Warning: System Node.js version ($current_version) differs from target ($version) ****$c0" >&2
|
|
104
|
+
echo -e "$c**** Using system path anyway: $g$node_path$c ****$c0" >&2
|
|
105
|
+
fi
|
|
106
|
+
else
|
|
107
|
+
echo -e "$r**** Error: Could not find Node.js binary ****$c0" >&2
|
|
108
|
+
exit 1
|
|
109
|
+
fi
|
|
110
|
+
fi
|
|
111
|
+
|
|
112
|
+
echo "$node_path"
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
# Function to parse package.json
|
|
116
|
+
parse_package_json() {
|
|
117
|
+
local field="$1"
|
|
118
|
+
local package_file="$PROJECT_ROOT/package.json"
|
|
119
|
+
|
|
120
|
+
if [ ! -f "$package_file" ]; then
|
|
121
|
+
echo -e "$r**** Error: package.json not found at $package_file ****$c0" >&2
|
|
122
|
+
exit 1
|
|
123
|
+
fi
|
|
124
|
+
|
|
125
|
+
# Simple JSON parsing using node (execute from project root for proper require resolution)
|
|
126
|
+
local value=$(cd "$PROJECT_ROOT" && node -e "
|
|
127
|
+
try {
|
|
128
|
+
const pkg = require('./package.json');
|
|
129
|
+
console.log(pkg.$field || '');
|
|
130
|
+
} catch(e) {
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
" 2>/dev/null)
|
|
134
|
+
|
|
135
|
+
if [ $? -ne 0 ] || [ -z "$value" ]; then
|
|
136
|
+
echo -e "$r**** Error: Could not parse $field from package.json ****$c0" >&2
|
|
137
|
+
exit 1
|
|
138
|
+
fi
|
|
139
|
+
|
|
140
|
+
echo "$value"
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
# Function to get service name
|
|
144
|
+
get_service_name() {
|
|
145
|
+
if [ -n "$SERVICE_NAME" ]; then
|
|
146
|
+
echo "$SERVICE_NAME"
|
|
147
|
+
else
|
|
148
|
+
parse_package_json "name"
|
|
149
|
+
fi
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
# Function to detect port from config
|
|
153
|
+
detect_port() {
|
|
154
|
+
local port=""
|
|
155
|
+
|
|
156
|
+
if [ -n "$PORT" ]; then
|
|
157
|
+
port="$PORT"
|
|
158
|
+
else
|
|
159
|
+
# Try to get port from config using node (execute from project root for proper require resolution)
|
|
160
|
+
port=$(cd "$PROJECT_ROOT" && node -e 'try{const c=require("config");console.log(c.webServer?.port);}catch(e){import("config").then(c=>console.log(c.webServer?.port)).catch(()=>{});}' 2>/dev/null | grep -oE "[0-9]{2,5}" | head -n1)
|
|
161
|
+
|
|
162
|
+
if [ -z "$port" ]; then
|
|
163
|
+
echo -e "$r**** Error: Could not detect port from config ****$c0" >&2
|
|
164
|
+
exit 1
|
|
165
|
+
fi
|
|
166
|
+
fi
|
|
167
|
+
|
|
168
|
+
echo "$port"
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
# Function to generate systemd unit file
|
|
172
|
+
generate_unit_file() {
|
|
173
|
+
local service_name="$1"
|
|
174
|
+
local node_path="$2"
|
|
175
|
+
local main_file="$3"
|
|
176
|
+
local working_dir="$PROJECT_ROOT" # Always use project root as working directory
|
|
177
|
+
local serviceFile="/etc/systemd/system/${service_name}.service"
|
|
178
|
+
cat > "$serviceFile" << EOF
|
|
179
|
+
[Unit]
|
|
180
|
+
Description=$service_name
|
|
181
|
+
After=network.target
|
|
182
|
+
# https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html#StartLimitIntervalSec=interval
|
|
183
|
+
StartLimitIntervalSec=0
|
|
184
|
+
|
|
185
|
+
[Service]
|
|
186
|
+
User=root
|
|
187
|
+
WorkingDirectory=$working_dir
|
|
188
|
+
EnvironmentFile=$working_dir/.env
|
|
189
|
+
ExecStart=$node_path $main_file
|
|
190
|
+
Restart=always
|
|
191
|
+
RestartSec=3
|
|
192
|
+
|
|
193
|
+
[Install]
|
|
194
|
+
WantedBy=multi-user.target
|
|
195
|
+
EOF
|
|
196
|
+
|
|
197
|
+
echo -e "$c**** Generated unit file for $g$service_name$c ****$c0" >&2
|
|
198
|
+
echo -e "$lc WorkingDirectory: $g$working_dir$c0" >&2
|
|
199
|
+
echo -e "$lc ExecStart: $g$node_path $main_file$c0" >&2
|
|
200
|
+
echo -e "$lc View Service file: ${g}cat $serviceFile$c0" >&2
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
# Function to install service
|
|
204
|
+
install_service() {
|
|
205
|
+
echo -e "$c**** Installing service ****$c0"
|
|
206
|
+
|
|
207
|
+
# Detect Node.js version and path
|
|
208
|
+
local node_version=$(detect_node_version)
|
|
209
|
+
local node_path=$(find_node_path "$node_version")
|
|
210
|
+
|
|
211
|
+
# Get main entry point and service name
|
|
212
|
+
local main_file=$(parse_package_json "main")
|
|
213
|
+
local service_name=$(get_service_name)
|
|
214
|
+
|
|
215
|
+
echo -e "$c**** Service configuration ****$c0"
|
|
216
|
+
echo -e "$lc Service name: $g$service_name$c0"
|
|
217
|
+
echo -e "$lc Node.js version: $g$node_version$c0"
|
|
218
|
+
echo -e "$lc Node.js path: $g$node_path$c0"
|
|
219
|
+
echo -e "$lc Main file: $g$main_file$c0"
|
|
220
|
+
echo -e "$lc Project root: $g$PROJECT_ROOT$c0"
|
|
221
|
+
|
|
222
|
+
# Check if service already exists
|
|
223
|
+
if service_exists "$service_name"; then
|
|
224
|
+
echo -e "$c**** Service $g$service_name$c already installed ****$c0"
|
|
225
|
+
return 0
|
|
226
|
+
fi
|
|
227
|
+
|
|
228
|
+
# Generate and install unit file
|
|
229
|
+
generate_unit_file "$service_name" "$node_path" "$main_file"
|
|
230
|
+
|
|
231
|
+
# Reload systemd and enable service
|
|
232
|
+
systemctl daemon-reload
|
|
233
|
+
systemctl enable --now "$service_name"
|
|
234
|
+
|
|
235
|
+
if [ $? -eq 0 ]; then
|
|
236
|
+
echo -e "$c**** Service $g$service_name$c installed and started ****$c0"
|
|
237
|
+
echo ""
|
|
238
|
+
echo -e "${m}View status: ${y}systemctl -l status $service_name$c0"
|
|
239
|
+
echo -e "${m}View logs: ${y}journalctl -o cat -xefu $service_name$c0"
|
|
240
|
+
else
|
|
241
|
+
echo -e "$r**** Error: Failed to install service $service_name ****$c0"
|
|
242
|
+
exit 1
|
|
243
|
+
fi
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
# Function to delete service
|
|
247
|
+
delete_service() {
|
|
248
|
+
local service_name=$(get_service_name)
|
|
249
|
+
local port=$(detect_port)
|
|
250
|
+
|
|
251
|
+
echo -e "$c**** Removing service $g$service_name$c listening on port $g$port$c ****$c0"
|
|
252
|
+
|
|
253
|
+
if ! service_exists "$service_name"; then
|
|
254
|
+
echo -e "$c**** Service $g$service_name$c not found ****$c0"
|
|
255
|
+
return 0
|
|
256
|
+
fi
|
|
257
|
+
|
|
258
|
+
# Stop and disable service
|
|
259
|
+
systemctl stop "$service_name"
|
|
260
|
+
systemctl disable "$service_name"
|
|
261
|
+
|
|
262
|
+
# Remove unit file
|
|
263
|
+
rm -f "/etc/systemd/system/$service_name.service"
|
|
264
|
+
|
|
265
|
+
# Kill any remaining process on the port
|
|
266
|
+
local pid=$(lsof -i tcp:$port 2>/dev/null | grep $port | awk '{print $2}' | head -1)
|
|
267
|
+
if [ -n "$pid" ]; then
|
|
268
|
+
echo -e "$c**** Killing process $g$pid$c on port $g$port$c ****$c0"
|
|
269
|
+
kill -9 "$pid"
|
|
270
|
+
fi
|
|
271
|
+
|
|
272
|
+
# Reload systemd
|
|
273
|
+
systemctl daemon-reload
|
|
274
|
+
|
|
275
|
+
echo -e "$c**** Service $g$service_name$c removed ****$c0"
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
# Function to reinstall service
|
|
279
|
+
reinstall_service() {
|
|
280
|
+
echo -e "$c**** Reinstalling service ****$c0"
|
|
281
|
+
|
|
282
|
+
# Delete existing service
|
|
283
|
+
delete_service
|
|
284
|
+
|
|
285
|
+
# Install service
|
|
286
|
+
install_service
|
|
287
|
+
|
|
288
|
+
local service_name=$(get_service_name)
|
|
289
|
+
echo -e "$c**** Service $g$service_name$c reinstalled ****$c0"
|
|
290
|
+
|
|
291
|
+
# Show status and logs
|
|
292
|
+
systemctl status "$service_name"
|
|
293
|
+
echo ""
|
|
294
|
+
echo -e "${m}Following logs (Ctrl+C to exit): ${y}journalctl -o cat -xefu $service_name$c0"
|
|
295
|
+
journalctl -o cat -xefu "$service_name"
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
# Parse command line arguments
|
|
299
|
+
if [ $# -eq 0 ]; then
|
|
300
|
+
show_usage
|
|
301
|
+
exit 1
|
|
302
|
+
fi
|
|
303
|
+
|
|
304
|
+
# Parse command
|
|
305
|
+
case "$1" in
|
|
306
|
+
i|install)
|
|
307
|
+
COMMAND="install"
|
|
308
|
+
shift
|
|
309
|
+
;;
|
|
310
|
+
d|delete)
|
|
311
|
+
COMMAND="delete"
|
|
312
|
+
shift
|
|
313
|
+
;;
|
|
314
|
+
r|reinstall)
|
|
315
|
+
COMMAND="reinstall"
|
|
316
|
+
shift
|
|
317
|
+
;;
|
|
318
|
+
*)
|
|
319
|
+
echo -e "$r**** Error: Unknown command '$1' ****$c0"
|
|
320
|
+
show_usage
|
|
321
|
+
exit 1
|
|
322
|
+
;;
|
|
323
|
+
esac
|
|
324
|
+
|
|
325
|
+
# Parse options
|
|
326
|
+
while [[ $# -gt 0 ]]; do
|
|
327
|
+
case $1 in
|
|
328
|
+
-n)
|
|
329
|
+
SERVICE_NAME="$2"
|
|
330
|
+
shift 2
|
|
331
|
+
;;
|
|
332
|
+
-v)
|
|
333
|
+
NODE_VERSION="$2"
|
|
334
|
+
shift 2
|
|
335
|
+
;;
|
|
336
|
+
-p)
|
|
337
|
+
PORT="$2"
|
|
338
|
+
shift 2
|
|
339
|
+
;;
|
|
340
|
+
*)
|
|
341
|
+
echo -e "$r**** Error: Unknown option '$1' ****$c0"
|
|
342
|
+
show_usage
|
|
343
|
+
exit 1
|
|
344
|
+
;;
|
|
345
|
+
esac
|
|
346
|
+
done
|
|
347
|
+
|
|
348
|
+
# Execute command
|
|
349
|
+
case "$COMMAND" in
|
|
350
|
+
install)
|
|
351
|
+
install_service
|
|
352
|
+
;;
|
|
353
|
+
delete)
|
|
354
|
+
delete_service
|
|
355
|
+
;;
|
|
356
|
+
reinstall)
|
|
357
|
+
reinstall_service
|
|
358
|
+
;;
|
|
359
|
+
esac
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
# srv.sh - Unified systemd Service Management Script
|
|
2
|
+
|
|
3
|
+
Universal script for managing systemd services for Node.js applications. Consolidates functionality from separate `deploy/systemd-service/` scripts into a single solution.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- ✅ **Universal execution**: Works the same when launched from project root or from `deploy/` folder
|
|
8
|
+
- ✅ **Auto-detection of Node.js version**: Priority: parameter → .envrc → current version
|
|
9
|
+
- ✅ **Smart Node.js search**: NVM paths → system paths
|
|
10
|
+
- ✅ **Automatic configuration reading**: package.json, config for port
|
|
11
|
+
- ✅ **systemd unit file generation**: Correct paths and settings
|
|
12
|
+
- ✅ **Process management**: Stops processes on ports when removing
|
|
13
|
+
|
|
14
|
+
## Operation Algorithm
|
|
15
|
+
|
|
16
|
+
### Working Directory Determination
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Script folder: /path/to/project/deploy/
|
|
20
|
+
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" # Project root: /path/to/project/
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Result**: Regardless of launch location, the script always uses the project root for:
|
|
24
|
+
- Reading `package.json`
|
|
25
|
+
- Reading `.envrc`
|
|
26
|
+
- Reading configuration
|
|
27
|
+
- Setting `WorkingDirectory` in systemd unit
|
|
28
|
+
|
|
29
|
+
### Node.js Version Detection Algorithm
|
|
30
|
+
|
|
31
|
+
1. **Parameter `-v <version>`** (highest priority)
|
|
32
|
+
```bash
|
|
33
|
+
./deploy/srv.sh install -v 20.10.0
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
2. **`.envrc` file in project root**
|
|
37
|
+
```bash
|
|
38
|
+
# Searches for line like:
|
|
39
|
+
nvm use 22.17.1
|
|
40
|
+
# Extracts: 22.17.1
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
3. **Current Node.js version** (fallback)
|
|
44
|
+
```bash
|
|
45
|
+
node -v # For example: v22.17.1 → 22.17.1
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Node.js Path Search Algorithm
|
|
49
|
+
|
|
50
|
+
1. **NVM path** (priority)
|
|
51
|
+
```bash
|
|
52
|
+
$HOME/.nvm/versions/node/v22.17.1/bin/node
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
2. **System path** (fallback)
|
|
56
|
+
```bash
|
|
57
|
+
which node # For example: /usr/bin/node
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Service Name Detection Algorithm
|
|
61
|
+
|
|
62
|
+
1. **Parameter `-n <name>`** (priority)
|
|
63
|
+
2. **`name` value from package.json** (default)
|
|
64
|
+
|
|
65
|
+
### Port Detection Algorithm
|
|
66
|
+
|
|
67
|
+
1. **Parameter `-p <port>`** (priority)
|
|
68
|
+
2. **`config.webServer.port` value** (automatic)
|
|
69
|
+
```javascript
|
|
70
|
+
// Executed from project root:
|
|
71
|
+
const config = require('config');
|
|
72
|
+
console.log(config.webServer?.port);
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Commands
|
|
76
|
+
|
|
77
|
+
### Service Installation
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# Basic installation (auto-detect all parameters)
|
|
81
|
+
./deploy/srv.sh install
|
|
82
|
+
./deploy/srv.sh i
|
|
83
|
+
|
|
84
|
+
# With custom service name
|
|
85
|
+
./deploy/srv.sh install -n my-custom-service
|
|
86
|
+
|
|
87
|
+
# With specific Node.js version
|
|
88
|
+
./deploy/srv.sh install -v 20.10.0
|
|
89
|
+
|
|
90
|
+
# Combined parameters
|
|
91
|
+
./deploy/srv.sh i -n custom-service -v 22.17.1
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**What happens:**
|
|
95
|
+
1. Node.js version and binary path are determined
|
|
96
|
+
2. `package.json` is read to get `main` and `name`
|
|
97
|
+
3. systemd unit file is generated in `/etc/systemd/system/<service_name>.service`
|
|
98
|
+
4. `systemctl daemon-reload` is executed
|
|
99
|
+
5. `systemctl enable --now <service_name>` is executed
|
|
100
|
+
|
|
101
|
+
### Service Removal
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# Auto-detect port from config
|
|
105
|
+
./deploy/srv.sh delete
|
|
106
|
+
./deploy/srv.sh d
|
|
107
|
+
|
|
108
|
+
# With custom service name
|
|
109
|
+
./deploy/srv.sh delete -n custom-service
|
|
110
|
+
|
|
111
|
+
# With specific port
|
|
112
|
+
./deploy/srv.sh delete -p 8080
|
|
113
|
+
|
|
114
|
+
# Combined parameters
|
|
115
|
+
./deploy/srv.sh d -n custom-service -p 9021
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**What happens:**
|
|
119
|
+
1. Port is determined from configuration or parameter
|
|
120
|
+
2. `systemctl stop <service_name>` is executed
|
|
121
|
+
3. `systemctl disable <service_name>` is executed
|
|
122
|
+
4. Unit file `/etc/systemd/system/<service_name>.service` is removed
|
|
123
|
+
5. Process on specified port is terminated (if exists)
|
|
124
|
+
6. `systemctl daemon-reload` is executed
|
|
125
|
+
|
|
126
|
+
### Service Reinstallation
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
# Complete reinstallation
|
|
130
|
+
./deploy/srv.sh reinstall
|
|
131
|
+
./deploy/srv.sh r
|
|
132
|
+
|
|
133
|
+
# With parameters
|
|
134
|
+
./deploy/srv.sh r -n custom-service -v 22.17.1 -p 9021
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**What happens:**
|
|
138
|
+
1. Complete service removal is performed (as in `delete`)
|
|
139
|
+
2. Complete service installation is performed (as in `install`)
|
|
140
|
+
3. Status is shown and log viewing is started
|
|
141
|
+
|
|
142
|
+
## Execution Examples
|
|
143
|
+
|
|
144
|
+
### From Project Root
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
# All commands work from root
|
|
148
|
+
./deploy/srv.sh install
|
|
149
|
+
./deploy/srv.sh delete -p 9021
|
|
150
|
+
./deploy/srv.sh reinstall -n mcp-fin-office-dev
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### From deploy Folder
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
cd deploy/
|
|
157
|
+
|
|
158
|
+
# All commands work from deploy folder
|
|
159
|
+
./srv.sh install
|
|
160
|
+
./srv.sh delete -p 9021
|
|
161
|
+
./srv.sh reinstall -n mcp-fin-office-dev
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Real-world Project Examples
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
# Development installation
|
|
168
|
+
./deploy/srv.sh install -n mcp-fin-office-dev -v 22.17.1
|
|
169
|
+
|
|
170
|
+
# Production installation with auto-detection
|
|
171
|
+
./deploy/srv.sh install
|
|
172
|
+
|
|
173
|
+
# Remove dev version
|
|
174
|
+
./deploy/srv.sh delete -n mcp-fin-office-dev
|
|
175
|
+
|
|
176
|
+
# Quick reinstall after changes
|
|
177
|
+
./deploy/srv.sh reinstall
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Generated systemd Unit File
|
|
181
|
+
|
|
182
|
+
```ini
|
|
183
|
+
[Unit]
|
|
184
|
+
Description=mcp-fin-office
|
|
185
|
+
After=network.target
|
|
186
|
+
StartLimitIntervalSec=0
|
|
187
|
+
|
|
188
|
+
[Service]
|
|
189
|
+
User=root
|
|
190
|
+
WorkingDirectory=/path/to/project/root
|
|
191
|
+
EnvironmentFile=/path/to/project/root/.env
|
|
192
|
+
ExecStart=/root/.nvm/versions/node/v22.17.1/bin/node dist/src/_core/index.js
|
|
193
|
+
Restart=always
|
|
194
|
+
RestartSec=3
|
|
195
|
+
StandardOutput=syslog
|
|
196
|
+
StandardError=syslog
|
|
197
|
+
|
|
198
|
+
[Install]
|
|
199
|
+
WantedBy=multi-user.target
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Debugging and Monitoring
|
|
203
|
+
|
|
204
|
+
### View Status
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
systemctl status mcp-fin-office
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### View Logs
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
# Recent logs
|
|
214
|
+
journalctl -u mcp-fin-office
|
|
215
|
+
|
|
216
|
+
# Follow logs in real-time
|
|
217
|
+
journalctl -u mcp-fin-office -f
|
|
218
|
+
|
|
219
|
+
# Logs from last hour
|
|
220
|
+
journalctl -u mcp-fin-office --since "1 hour ago"
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Manual Control
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
# Stop
|
|
227
|
+
sudo systemctl stop mcp-fin-office
|
|
228
|
+
|
|
229
|
+
# Start
|
|
230
|
+
sudo systemctl start mcp-fin-office
|
|
231
|
+
|
|
232
|
+
# Restart
|
|
233
|
+
sudo systemctl restart mcp-fin-office
|
|
234
|
+
|
|
235
|
+
# Disable autostart
|
|
236
|
+
sudo systemctl disable mcp-fin-office
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## Requirements
|
|
240
|
+
|
|
241
|
+
- **Operating System**: Linux with systemd
|
|
242
|
+
- **Permissions**: `sudo` privileges for managing systemd services
|
|
243
|
+
- **Node.js**: Installed Node.js (NVM or system installation)
|
|
244
|
+
- **Project Files**:
|
|
245
|
+
- `package.json` in project root
|
|
246
|
+
- Built application (file specified in `package.json` `main`)
|
|
247
|
+
- Optional: `.envrc` for Node.js version detection
|
|
248
|
+
- Optional: `config/` folder for port detection
|
|
249
|
+
|
|
250
|
+
## File Structure
|
|
251
|
+
|
|
252
|
+
```
|
|
253
|
+
project-root/
|
|
254
|
+
├── package.json # Source: name, main
|
|
255
|
+
├── .envrc # Optional: Node.js version
|
|
256
|
+
├── config/
|
|
257
|
+
│ └── default.yaml # Optional: webServer.port
|
|
258
|
+
├── deploy/
|
|
259
|
+
│ ├── srv.sh # ← This script
|
|
260
|
+
│ └── srv.sh.readme.md # ← This documentation
|
|
261
|
+
└── dist/
|
|
262
|
+
└── src/
|
|
263
|
+
└── _core/
|
|
264
|
+
└── index.js # Main application file
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## Troubleshooting
|
|
268
|
+
|
|
269
|
+
### Script Cannot Find Node.js
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
# Check Node.js availability
|
|
273
|
+
node -v
|
|
274
|
+
which node
|
|
275
|
+
|
|
276
|
+
# Check NVM installation
|
|
277
|
+
ls -la ~/.nvm/versions/node/
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### package.json Reading Error
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
# Check JSON syntax
|
|
284
|
+
cat package.json | jq .
|
|
285
|
+
|
|
286
|
+
# Check for name and main fields
|
|
287
|
+
node -e "const pkg = require('./package.json'); console.log('name:', pkg.name); console.log('main:', pkg.main);"
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Port Detection Error
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
# Check configuration
|
|
294
|
+
node -e "const c = require('config'); console.log('port:', c.webServer?.port);"
|
|
295
|
+
|
|
296
|
+
# Check configuration files
|
|
297
|
+
ls -la config/
|
|
298
|
+
cat config/default.yaml | grep -A5 webServer
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Access Permissions
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
# Check systemd management permissions
|
|
305
|
+
sudo systemctl --version
|
|
306
|
+
|
|
307
|
+
# Check write permissions for /etc/systemd/system/
|
|
308
|
+
sudo ls -la /etc/systemd/system/
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## CI/CD Integration
|
|
312
|
+
|
|
313
|
+
### Automated Deployment
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
#!/bin/bash
|
|
317
|
+
# deploy.sh
|
|
318
|
+
|
|
319
|
+
# Build project
|
|
320
|
+
npm ci
|
|
321
|
+
npm run build
|
|
322
|
+
|
|
323
|
+
# Install/reinstall service
|
|
324
|
+
./deploy/srv.sh reinstall
|
|
325
|
+
|
|
326
|
+
# Check successful startup
|
|
327
|
+
sleep 5
|
|
328
|
+
systemctl is-active --quiet mcp-fin-office && echo "Service started successfully"
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### Rollback Script
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
#!/bin/bash
|
|
335
|
+
# rollback.sh
|
|
336
|
+
|
|
337
|
+
# Stop current service
|
|
338
|
+
./deploy/srv.sh delete
|
|
339
|
+
|
|
340
|
+
# Restore previous version
|
|
341
|
+
git checkout HEAD~1
|
|
342
|
+
npm ci
|
|
343
|
+
npm run build
|
|
344
|
+
|
|
345
|
+
# Start previous version
|
|
346
|
+
./deploy/srv.sh install
|
|
347
|
+
```
|