servherd 0.0.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/CONTRIBUTING.md +250 -0
  2. package/LICENSE +21 -0
  3. package/README.md +653 -29
  4. package/dist/cli/commands/config.d.ts +35 -0
  5. package/dist/cli/commands/config.js +336 -0
  6. package/dist/cli/commands/info.d.ts +37 -0
  7. package/dist/cli/commands/info.js +98 -0
  8. package/dist/cli/commands/list.d.ts +26 -0
  9. package/dist/cli/commands/list.js +86 -0
  10. package/dist/cli/commands/logs.d.ts +46 -0
  11. package/dist/cli/commands/logs.js +292 -0
  12. package/dist/cli/commands/mcp.d.ts +5 -0
  13. package/dist/cli/commands/mcp.js +17 -0
  14. package/dist/cli/commands/refresh.d.ts +20 -0
  15. package/dist/cli/commands/refresh.js +139 -0
  16. package/dist/cli/commands/remove.d.ts +20 -0
  17. package/dist/cli/commands/remove.js +144 -0
  18. package/dist/cli/commands/restart.d.ts +25 -0
  19. package/dist/cli/commands/restart.js +177 -0
  20. package/dist/cli/commands/start.d.ts +37 -0
  21. package/dist/cli/commands/start.js +293 -0
  22. package/dist/cli/commands/stop.d.ts +20 -0
  23. package/dist/cli/commands/stop.js +108 -0
  24. package/dist/cli/index.d.ts +9 -0
  25. package/dist/cli/index.js +160 -0
  26. package/dist/cli/output/formatters.d.ts +117 -0
  27. package/dist/cli/output/formatters.js +454 -0
  28. package/dist/cli/output/json-formatter.d.ts +22 -0
  29. package/dist/cli/output/json-formatter.js +40 -0
  30. package/dist/index.d.ts +15 -0
  31. package/dist/index.js +25 -0
  32. package/dist/mcp/index.d.ts +14 -0
  33. package/dist/mcp/index.js +352 -0
  34. package/dist/mcp/resources/servers.d.ts +14 -0
  35. package/dist/mcp/resources/servers.js +128 -0
  36. package/dist/mcp/tools/config.d.ts +33 -0
  37. package/dist/mcp/tools/config.js +88 -0
  38. package/dist/mcp/tools/info.d.ts +36 -0
  39. package/dist/mcp/tools/info.js +65 -0
  40. package/dist/mcp/tools/list.d.ts +36 -0
  41. package/dist/mcp/tools/list.js +49 -0
  42. package/dist/mcp/tools/logs.d.ts +44 -0
  43. package/dist/mcp/tools/logs.js +55 -0
  44. package/dist/mcp/tools/refresh.d.ts +33 -0
  45. package/dist/mcp/tools/refresh.js +54 -0
  46. package/dist/mcp/tools/remove.d.ts +23 -0
  47. package/dist/mcp/tools/remove.js +43 -0
  48. package/dist/mcp/tools/restart.d.ts +23 -0
  49. package/dist/mcp/tools/restart.js +42 -0
  50. package/dist/mcp/tools/start.d.ts +38 -0
  51. package/dist/mcp/tools/start.js +73 -0
  52. package/dist/mcp/tools/stop.d.ts +23 -0
  53. package/dist/mcp/tools/stop.js +40 -0
  54. package/dist/services/config.service.d.ts +80 -0
  55. package/dist/services/config.service.js +227 -0
  56. package/dist/services/port.service.d.ts +82 -0
  57. package/dist/services/port.service.js +151 -0
  58. package/dist/services/process.service.d.ts +61 -0
  59. package/dist/services/process.service.js +220 -0
  60. package/dist/services/registry.service.d.ts +50 -0
  61. package/dist/services/registry.service.js +157 -0
  62. package/dist/types/config.d.ts +107 -0
  63. package/dist/types/config.js +44 -0
  64. package/dist/types/errors.d.ts +102 -0
  65. package/dist/types/errors.js +197 -0
  66. package/dist/types/pm2.d.ts +50 -0
  67. package/dist/types/pm2.js +4 -0
  68. package/dist/types/registry.d.ts +230 -0
  69. package/dist/types/registry.js +33 -0
  70. package/dist/utils/ci-detector.d.ts +31 -0
  71. package/dist/utils/ci-detector.js +68 -0
  72. package/dist/utils/config-drift.d.ts +71 -0
  73. package/dist/utils/config-drift.js +128 -0
  74. package/dist/utils/error-handler.d.ts +21 -0
  75. package/dist/utils/error-handler.js +38 -0
  76. package/dist/utils/log-follower.d.ts +10 -0
  77. package/dist/utils/log-follower.js +98 -0
  78. package/dist/utils/logger.d.ts +11 -0
  79. package/dist/utils/logger.js +24 -0
  80. package/dist/utils/names.d.ts +7 -0
  81. package/dist/utils/names.js +20 -0
  82. package/dist/utils/template.d.ts +88 -0
  83. package/dist/utils/template.js +180 -0
  84. package/dist/utils/time-parser.d.ts +19 -0
  85. package/dist/utils/time-parser.js +54 -0
  86. package/docs/ci-cd.md +408 -0
  87. package/docs/configuration.md +325 -0
  88. package/docs/mcp-integration.md +411 -0
  89. package/examples/basic-usage/README.md +187 -0
  90. package/examples/ci-github-actions/workflow.yml +195 -0
  91. package/examples/mcp-claude-code/README.md +213 -0
  92. package/examples/multi-server/README.md +270 -0
  93. package/examples/storybook/README.md +187 -0
  94. package/examples/vite-project/README.md +251 -0
  95. package/package.json +123 -6
@@ -0,0 +1,54 @@
1
+ import { ServherdError, ServherdErrorCode } from "../types/errors.js";
2
+ /**
3
+ * Duration unit multipliers in milliseconds.
4
+ */
5
+ const DURATION_MULTIPLIERS = {
6
+ s: 1000,
7
+ m: 60 * 1000,
8
+ h: 60 * 60 * 1000,
9
+ d: 24 * 60 * 60 * 1000,
10
+ w: 7 * 24 * 60 * 60 * 1000,
11
+ };
12
+ /**
13
+ * Parse a time filter string into a Date object.
14
+ * Supports duration format (1h, 30m, 2d, 1w, 30s) or ISO date strings.
15
+ *
16
+ * @param input - Time filter string to parse
17
+ * @returns Date object representing the cutoff time
18
+ * @throws ServherdError if the format is invalid
19
+ */
20
+ export function parseTimeFilter(input) {
21
+ if (!input) {
22
+ throw new ServherdError(ServherdErrorCode.COMMAND_INVALID, "Invalid time format: empty string. Use duration (1h, 30m) or ISO date (2024-01-15)");
23
+ }
24
+ // Try duration format (e.g., 1h, 30m, 2d, 1w, 30s)
25
+ const durationMatch = input.match(/^(\d+)([smhdw])$/);
26
+ if (durationMatch) {
27
+ const value = parseInt(durationMatch[1], 10);
28
+ const unit = durationMatch[2];
29
+ const now = new Date();
30
+ return new Date(now.getTime() - value * DURATION_MULTIPLIERS[unit]);
31
+ }
32
+ // Try ISO date/datetime
33
+ const date = new Date(input);
34
+ if (!isNaN(date.getTime())) {
35
+ return date;
36
+ }
37
+ throw new ServherdError(ServherdErrorCode.COMMAND_INVALID, `Invalid time format: ${input}. Use duration (1h, 30m) or ISO date (2024-01-15)`);
38
+ }
39
+ /**
40
+ * Filter log lines by timestamp, keeping only those after the given date.
41
+ * Lines without timestamps (or where the parser returns null) are included.
42
+ *
43
+ * @param lines - Array of log lines to filter
44
+ * @param since - Only include logs from this date onward
45
+ * @param parseTimestamp - Function to extract a Date from a log line (returns null if no timestamp)
46
+ * @returns Filtered array of log lines
47
+ */
48
+ export function filterLogsByTime(lines, since, parseTimestamp) {
49
+ return lines.filter((line) => {
50
+ const timestamp = parseTimestamp(line);
51
+ // Include lines without timestamps, or lines >= since
52
+ return timestamp === null || timestamp >= since;
53
+ });
54
+ }
package/docs/ci-cd.md ADDED
@@ -0,0 +1,408 @@
1
+ # CI/CD Integration
2
+
3
+ servherd is designed to work seamlessly in CI/CD environments. This guide covers setup, configuration, and best practices for continuous integration.
4
+
5
+ ## CI Detection
6
+
7
+ servherd automatically detects CI environments and adjusts behavior:
8
+
9
+ - Disables interactive prompts
10
+ - Uses non-TTY safe output formatting
11
+ - Respects environment variable configuration
12
+
13
+ ### Supported CI Systems
14
+
15
+ | CI System | Detection Variable |
16
+ |-----------|-------------------|
17
+ | GitHub Actions | `GITHUB_ACTIONS=true` |
18
+ | GitLab CI | `GITLAB_CI=true` |
19
+ | Jenkins | `JENKINS_URL` set |
20
+ | CircleCI | `CIRCLECI=true` |
21
+ | Travis CI | `TRAVIS=true` |
22
+ | Azure Pipelines | `TF_BUILD=true` |
23
+ | Bitbucket Pipelines | `BITBUCKET_PIPELINE_UUID` set |
24
+ | Generic | `CI=true` |
25
+
26
+ ## GitHub Actions
27
+
28
+ ### Basic Workflow
29
+
30
+ ```yaml
31
+ name: E2E Tests
32
+
33
+ on: [push, pull_request]
34
+
35
+ jobs:
36
+ test:
37
+ runs-on: ubuntu-latest
38
+ steps:
39
+ - uses: actions/checkout@v4
40
+
41
+ - name: Setup Node.js
42
+ uses: actions/setup-node@v4
43
+ with:
44
+ node-version: 20
45
+ cache: 'npm'
46
+
47
+ - name: Install dependencies
48
+ run: npm ci
49
+
50
+ - name: Install servherd
51
+ run: npm install -g servherd
52
+
53
+ - name: Start development server
54
+ run: |
55
+ servherd start --name app-server -- npm run dev --port {{port}}
56
+ # Wait for server to be ready
57
+ sleep 5
58
+
59
+ - name: Run E2E tests
60
+ run: npm run test:e2e
61
+
62
+ - name: Stop server
63
+ if: always()
64
+ run: servherd stop --all
65
+ ```
66
+
67
+ ### With Custom Port Range
68
+
69
+ ```yaml
70
+ - name: Start server with custom ports
71
+ env:
72
+ SERVHERD_PORT_MIN: 8000
73
+ SERVHERD_PORT_MAX: 8100
74
+ run: servherd start --name test-server -- npm run dev --port {{port}}
75
+ ```
76
+
77
+ ### Matrix Testing
78
+
79
+ ```yaml
80
+ jobs:
81
+ test:
82
+ runs-on: ${{ matrix.os }}
83
+ strategy:
84
+ matrix:
85
+ os: [ubuntu-latest, macos-latest]
86
+ node: [18, 20]
87
+ steps:
88
+ - uses: actions/checkout@v4
89
+
90
+ - name: Setup Node.js
91
+ uses: actions/setup-node@v4
92
+ with:
93
+ node-version: ${{ matrix.node }}
94
+
95
+ - name: Install and test
96
+ run: |
97
+ npm ci
98
+ npm install -g servherd
99
+ servherd start -- npm run dev --port {{port}}
100
+ npm test
101
+ servherd stop --all
102
+ ```
103
+
104
+ ## GitLab CI
105
+
106
+ ### Basic Configuration
107
+
108
+ ```yaml
109
+ # .gitlab-ci.yml
110
+ stages:
111
+ - test
112
+
113
+ e2e-test:
114
+ stage: test
115
+ image: node:20
116
+ script:
117
+ - npm ci
118
+ - npm install -g servherd
119
+ - servherd start --name test-server -- npm run dev --port {{port}}
120
+ - npm run test:e2e
121
+ - servherd stop --all
122
+ variables:
123
+ CI: "true"
124
+ SERVHERD_PORT_MIN: "8000"
125
+ SERVHERD_PORT_MAX: "8100"
126
+ ```
127
+
128
+ ### With Services
129
+
130
+ ```yaml
131
+ e2e-test:
132
+ stage: test
133
+ image: node:20
134
+ services:
135
+ - name: redis:latest
136
+ alias: redis
137
+ script:
138
+ - npm ci
139
+ - npm install -g servherd
140
+ - servherd start --name api -- npm run dev --port {{port}}
141
+ - npm run test:e2e
142
+ variables:
143
+ REDIS_URL: redis://redis:6379
144
+ ```
145
+
146
+ ## Jenkins
147
+
148
+ ### Jenkinsfile
149
+
150
+ ```groovy
151
+ pipeline {
152
+ agent {
153
+ docker {
154
+ image 'node:20'
155
+ }
156
+ }
157
+
158
+ environment {
159
+ CI = 'true'
160
+ SERVHERD_PORT_MIN = '8000'
161
+ SERVHERD_PORT_MAX = '8100'
162
+ }
163
+
164
+ stages {
165
+ stage('Install') {
166
+ steps {
167
+ sh 'npm ci'
168
+ sh 'npm install -g servherd'
169
+ }
170
+ }
171
+
172
+ stage('Test') {
173
+ steps {
174
+ sh 'servherd start --name app -- npm run dev --port {{port}}'
175
+ sh 'npm run test:e2e'
176
+ }
177
+ post {
178
+ always {
179
+ sh 'servherd stop --all || true'
180
+ }
181
+ }
182
+ }
183
+ }
184
+ }
185
+ ```
186
+
187
+ ## CircleCI
188
+
189
+ ### Configuration
190
+
191
+ ```yaml
192
+ # .circleci/config.yml
193
+ version: 2.1
194
+
195
+ jobs:
196
+ test:
197
+ docker:
198
+ - image: cimg/node:20.0
199
+ environment:
200
+ CI: "true"
201
+ SERVHERD_PORT_MIN: "8000"
202
+ SERVHERD_PORT_MAX: "8100"
203
+ steps:
204
+ - checkout
205
+ - restore_cache:
206
+ keys:
207
+ - deps-{{ checksum "package-lock.json" }}
208
+ - run: npm ci
209
+ - save_cache:
210
+ key: deps-{{ checksum "package-lock.json" }}
211
+ paths:
212
+ - node_modules
213
+ - run: npm install -g servherd
214
+ - run:
215
+ name: Start server
216
+ command: servherd start --name app -- npm run dev --port {{port}}
217
+ - run:
218
+ name: Run tests
219
+ command: npm run test:e2e
220
+ - run:
221
+ name: Cleanup
222
+ command: servherd stop --all
223
+ when: always
224
+
225
+ workflows:
226
+ test:
227
+ jobs:
228
+ - test
229
+ ```
230
+
231
+ ## Docker
232
+
233
+ ### Development with Docker Compose
234
+
235
+ ```yaml
236
+ # docker-compose.yml
237
+ version: '3.8'
238
+
239
+ services:
240
+ app:
241
+ build: .
242
+ environment:
243
+ - CI=true
244
+ - SERVHERD_HOSTNAME=0.0.0.0
245
+ - SERVHERD_PORT_MIN=3000
246
+ - SERVHERD_PORT_MAX=3100
247
+ ports:
248
+ - "3000-3100:3000-3100"
249
+ command: |
250
+ sh -c "
251
+ npm ci &&
252
+ npm install -g servherd &&
253
+ servherd start --name app -- npm run dev --host 0.0.0.0 --port {{port}} &&
254
+ tail -f /dev/null
255
+ "
256
+ ```
257
+
258
+ ### Dockerfile
259
+
260
+ ```dockerfile
261
+ FROM node:20-slim
262
+
263
+ WORKDIR /app
264
+
265
+ # Install servherd globally
266
+ RUN npm install -g servherd
267
+
268
+ # Copy package files
269
+ COPY package*.json ./
270
+ RUN npm ci
271
+
272
+ # Copy source
273
+ COPY . .
274
+
275
+ # Set CI environment
276
+ ENV CI=true
277
+ ENV SERVHERD_PORT_MIN=3000
278
+ ENV SERVHERD_PORT_MAX=3100
279
+
280
+ # Start server
281
+ CMD ["servherd", "start", "--", "npm", "run", "dev", "--port", "{{port}}"]
282
+ ```
283
+
284
+ ## Best Practices
285
+
286
+ ### 1. Always Clean Up
287
+
288
+ Use `always()` or equivalent to ensure servers are stopped:
289
+
290
+ ```yaml
291
+ # GitHub Actions
292
+ - name: Stop servers
293
+ if: always()
294
+ run: servherd stop --all
295
+
296
+ # Jenkins
297
+ post {
298
+ always {
299
+ sh 'servherd stop --all || true'
300
+ }
301
+ }
302
+ ```
303
+
304
+ ### 2. Use Specific Port Ranges
305
+
306
+ Avoid port conflicts by using dedicated ranges per job:
307
+
308
+ ```yaml
309
+ env:
310
+ SERVHERD_PORT_MIN: 8000
311
+ SERVHERD_PORT_MAX: 8100
312
+ ```
313
+
314
+ ### 3. Wait for Server Ready
315
+
316
+ Add appropriate delays or health checks:
317
+
318
+ ```bash
319
+ # Simple delay
320
+ servherd start --name app -- npm run dev --port {{port}}
321
+ sleep 5
322
+
323
+ # With health check
324
+ servherd start --name app -- npm run dev --port {{port}}
325
+ until curl -s http://localhost:$(servherd info app --json | jq -r '.port') > /dev/null; do
326
+ sleep 1
327
+ done
328
+ ```
329
+
330
+ ### 4. Use Tags for Organization
331
+
332
+ ```bash
333
+ # Start with tags
334
+ servherd start --name frontend --tag e2e -- npm run dev --port {{port}}
335
+ servherd start --name backend --tag e2e -- npm run api --port {{port}}
336
+
337
+ # Stop by tag
338
+ servherd stop --tag e2e
339
+ ```
340
+
341
+ ### 5. Check Server Status
342
+
343
+ ```bash
344
+ # List running servers
345
+ servherd list --running
346
+
347
+ # Get specific server info
348
+ servherd info my-server
349
+ ```
350
+
351
+ ## Environment Variables Reference
352
+
353
+ | Variable | Description | Default |
354
+ |----------|-------------|---------|
355
+ | `CI` | Enable CI mode | `false` |
356
+ | `SERVHERD_HOSTNAME` | Server hostname | `localhost` |
357
+ | `SERVHERD_PROTOCOL` | Protocol (http/https) | `http` |
358
+ | `SERVHERD_PORT_MIN` | Minimum port | `3000` |
359
+ | `SERVHERD_PORT_MAX` | Maximum port | `9999` |
360
+ | `SERVHERD_CONFIG_DIR` | Config directory | `~/.servherd` |
361
+ | `LOG_LEVEL` | Log verbosity | `info` |
362
+ | `NO_COLOR` | Disable colors | `false` |
363
+
364
+ ## Troubleshooting
365
+
366
+ ### Port Already in Use
367
+
368
+ ```bash
369
+ # Check what's using a port
370
+ lsof -i :3000
371
+
372
+ # Use a different port range
373
+ export SERVHERD_PORT_MIN=9000
374
+ export SERVHERD_PORT_MAX=9100
375
+ ```
376
+
377
+ ### Server Not Starting
378
+
379
+ ```bash
380
+ # Check server logs
381
+ servherd logs my-server --error
382
+
383
+ # Try starting manually first
384
+ npm run dev --port 3000
385
+ ```
386
+
387
+ ### PM2 Not Available
388
+
389
+ ```bash
390
+ # Ensure PM2 is installed
391
+ npm install -g pm2
392
+
393
+ # Or use npx
394
+ npx pm2 list
395
+ ```
396
+
397
+ ### Cleanup Orphaned Processes
398
+
399
+ ```bash
400
+ # List all PM2 processes
401
+ pm2 list
402
+
403
+ # Delete servherd processes
404
+ pm2 delete $(pm2 list | grep servherd | awk '{print $4}')
405
+
406
+ # Or delete all
407
+ servherd remove --all --force
408
+ ```