@orkify/cli 1.0.0-beta.5
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 +191 -0
- package/README.md +1701 -0
- package/bin/orkify +3 -0
- package/boot/systemd/orkify@.service +30 -0
- package/dist/agent-name.d.ts +4 -0
- package/dist/agent-name.js +42 -0
- package/dist/alerts/AlertEvaluator.d.ts +14 -0
- package/dist/alerts/AlertEvaluator.js +135 -0
- package/dist/cli/commands/autostart.d.ts +3 -0
- package/dist/cli/commands/autostart.js +11 -0
- package/dist/cli/commands/crash-test.d.ts +3 -0
- package/dist/cli/commands/crash-test.js +17 -0
- package/dist/cli/commands/daemon-reload.d.ts +3 -0
- package/dist/cli/commands/daemon-reload.js +72 -0
- package/dist/cli/commands/delete.d.ts +3 -0
- package/dist/cli/commands/delete.js +37 -0
- package/dist/cli/commands/deploy.d.ts +6 -0
- package/dist/cli/commands/deploy.js +266 -0
- package/dist/cli/commands/down.d.ts +3 -0
- package/dist/cli/commands/down.js +36 -0
- package/dist/cli/commands/flush.d.ts +3 -0
- package/dist/cli/commands/flush.js +28 -0
- package/dist/cli/commands/kill.d.ts +3 -0
- package/dist/cli/commands/kill.js +35 -0
- package/dist/cli/commands/list.d.ts +14 -0
- package/dist/cli/commands/list.js +361 -0
- package/dist/cli/commands/logs.d.ts +3 -0
- package/dist/cli/commands/logs.js +107 -0
- package/dist/cli/commands/mcp.d.ts +3 -0
- package/dist/cli/commands/mcp.js +151 -0
- package/dist/cli/commands/reload.d.ts +3 -0
- package/dist/cli/commands/reload.js +54 -0
- package/dist/cli/commands/restart.d.ts +3 -0
- package/dist/cli/commands/restart.js +43 -0
- package/dist/cli/commands/restore.d.ts +3 -0
- package/dist/cli/commands/restore.js +88 -0
- package/dist/cli/commands/run.d.ts +8 -0
- package/dist/cli/commands/run.js +212 -0
- package/dist/cli/commands/snap.d.ts +3 -0
- package/dist/cli/commands/snap.js +30 -0
- package/dist/cli/commands/up.d.ts +3 -0
- package/dist/cli/commands/up.js +125 -0
- package/dist/cli/crash-recovery.d.ts +2 -0
- package/dist/cli/crash-recovery.js +67 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.js +46 -0
- package/dist/cli/parse.d.ts +28 -0
- package/dist/cli/parse.js +97 -0
- package/dist/cluster/ClusterWrapper.d.ts +18 -0
- package/dist/cluster/ClusterWrapper.js +602 -0
- package/dist/config/ConfigStore.d.ts +11 -0
- package/dist/config/ConfigStore.js +21 -0
- package/dist/config/schema.d.ts +103 -0
- package/dist/config/schema.js +49 -0
- package/dist/constants.d.ts +83 -0
- package/dist/constants.js +289 -0
- package/dist/cron/CronScheduler.d.ts +25 -0
- package/dist/cron/CronScheduler.js +149 -0
- package/dist/daemon/GracefulManager.d.ts +8 -0
- package/dist/daemon/GracefulManager.js +29 -0
- package/dist/daemon/ManagedProcess.d.ts +71 -0
- package/dist/daemon/ManagedProcess.js +1020 -0
- package/dist/daemon/Orchestrator.d.ts +51 -0
- package/dist/daemon/Orchestrator.js +416 -0
- package/dist/daemon/RotatingWriter.d.ts +27 -0
- package/dist/daemon/RotatingWriter.js +264 -0
- package/dist/daemon/index.d.ts +2 -0
- package/dist/daemon/index.js +106 -0
- package/dist/daemon/startDaemon.d.ts +30 -0
- package/dist/daemon/startDaemon.js +693 -0
- package/dist/deploy/CommandPoller.d.ts +13 -0
- package/dist/deploy/CommandPoller.js +53 -0
- package/dist/deploy/DeployExecutor.d.ts +33 -0
- package/dist/deploy/DeployExecutor.js +340 -0
- package/dist/deploy/config.d.ts +20 -0
- package/dist/deploy/config.js +161 -0
- package/dist/deploy/env.d.ts +2 -0
- package/dist/deploy/env.js +17 -0
- package/dist/deploy/tarball.d.ts +32 -0
- package/dist/deploy/tarball.js +243 -0
- package/dist/detect/framework.d.ts +2 -0
- package/dist/detect/framework.js +24 -0
- package/dist/ipc/DaemonClient.d.ts +31 -0
- package/dist/ipc/DaemonClient.js +248 -0
- package/dist/ipc/DaemonServer.d.ts +28 -0
- package/dist/ipc/DaemonServer.js +166 -0
- package/dist/ipc/MultiUserClient.d.ts +27 -0
- package/dist/ipc/MultiUserClient.js +203 -0
- package/dist/ipc/protocol.d.ts +7 -0
- package/dist/ipc/protocol.js +53 -0
- package/dist/ipc/restoreDaemon.d.ts +8 -0
- package/dist/ipc/restoreDaemon.js +19 -0
- package/dist/machine-id.d.ts +11 -0
- package/dist/machine-id.js +51 -0
- package/dist/mcp/auth.d.ts +118 -0
- package/dist/mcp/auth.js +245 -0
- package/dist/mcp/http.d.ts +20 -0
- package/dist/mcp/http.js +229 -0
- package/dist/mcp/index.d.ts +3 -0
- package/dist/mcp/index.js +8 -0
- package/dist/mcp/server.d.ts +37 -0
- package/dist/mcp/server.js +413 -0
- package/dist/probe/compute-fingerprint.d.ts +27 -0
- package/dist/probe/compute-fingerprint.js +65 -0
- package/dist/probe/parse-frames.d.ts +21 -0
- package/dist/probe/parse-frames.js +57 -0
- package/dist/probe/resolve-sourcemaps.d.ts +25 -0
- package/dist/probe/resolve-sourcemaps.js +281 -0
- package/dist/state/StateStore.d.ts +11 -0
- package/dist/state/StateStore.js +78 -0
- package/dist/telemetry/TelemetryReporter.d.ts +49 -0
- package/dist/telemetry/TelemetryReporter.js +451 -0
- package/dist/types/index.d.ts +373 -0
- package/dist/types/index.js +2 -0
- package/package.json +148 -0
- package/packages/cache/README.md +114 -0
- package/packages/cache/dist/CacheClient.d.ts +26 -0
- package/packages/cache/dist/CacheClient.d.ts.map +1 -0
- package/packages/cache/dist/CacheClient.js +174 -0
- package/packages/cache/dist/CacheClient.js.map +1 -0
- package/packages/cache/dist/CacheFileStore.d.ts +45 -0
- package/packages/cache/dist/CacheFileStore.d.ts.map +1 -0
- package/packages/cache/dist/CacheFileStore.js +446 -0
- package/packages/cache/dist/CacheFileStore.js.map +1 -0
- package/packages/cache/dist/CachePersistence.d.ts +9 -0
- package/packages/cache/dist/CachePersistence.d.ts.map +1 -0
- package/packages/cache/dist/CachePersistence.js +67 -0
- package/packages/cache/dist/CachePersistence.js.map +1 -0
- package/packages/cache/dist/CachePrimary.d.ts +25 -0
- package/packages/cache/dist/CachePrimary.d.ts.map +1 -0
- package/packages/cache/dist/CachePrimary.js +155 -0
- package/packages/cache/dist/CachePrimary.js.map +1 -0
- package/packages/cache/dist/CacheStore.d.ts +50 -0
- package/packages/cache/dist/CacheStore.d.ts.map +1 -0
- package/packages/cache/dist/CacheStore.js +271 -0
- package/packages/cache/dist/CacheStore.js.map +1 -0
- package/packages/cache/dist/constants.d.ts +6 -0
- package/packages/cache/dist/constants.d.ts.map +1 -0
- package/packages/cache/dist/constants.js +9 -0
- package/packages/cache/dist/constants.js.map +1 -0
- package/packages/cache/dist/index.d.ts +16 -0
- package/packages/cache/dist/index.d.ts.map +1 -0
- package/packages/cache/dist/index.js +86 -0
- package/packages/cache/dist/index.js.map +1 -0
- package/packages/cache/dist/serialize.d.ts +9 -0
- package/packages/cache/dist/serialize.d.ts.map +1 -0
- package/packages/cache/dist/serialize.js +40 -0
- package/packages/cache/dist/serialize.js.map +1 -0
- package/packages/cache/dist/types.d.ts +123 -0
- package/packages/cache/dist/types.d.ts.map +1 -0
- package/packages/cache/dist/types.js +2 -0
- package/packages/cache/dist/types.js.map +1 -0
- package/packages/cache/package.json +27 -0
- package/packages/cache/src/CacheClient.ts +227 -0
- package/packages/cache/src/CacheFileStore.ts +528 -0
- package/packages/cache/src/CachePersistence.ts +89 -0
- package/packages/cache/src/CachePrimary.ts +172 -0
- package/packages/cache/src/CacheStore.ts +308 -0
- package/packages/cache/src/constants.ts +10 -0
- package/packages/cache/src/index.ts +100 -0
- package/packages/cache/src/serialize.ts +49 -0
- package/packages/cache/src/types.ts +156 -0
- package/packages/cache/tsconfig.json +18 -0
- package/packages/cache/tsconfig.tsbuildinfo +1 -0
- package/packages/next/README.md +166 -0
- package/packages/next/dist/error-capture.d.ts +34 -0
- package/packages/next/dist/error-capture.d.ts.map +1 -0
- package/packages/next/dist/error-capture.js +130 -0
- package/packages/next/dist/error-capture.js.map +1 -0
- package/packages/next/dist/error-handler.d.ts +10 -0
- package/packages/next/dist/error-handler.d.ts.map +1 -0
- package/packages/next/dist/error-handler.js +186 -0
- package/packages/next/dist/error-handler.js.map +1 -0
- package/packages/next/dist/isr-cache.d.ts +9 -0
- package/packages/next/dist/isr-cache.d.ts.map +1 -0
- package/packages/next/dist/isr-cache.js +86 -0
- package/packages/next/dist/isr-cache.js.map +1 -0
- package/packages/next/dist/stream.d.ts +5 -0
- package/packages/next/dist/stream.d.ts.map +1 -0
- package/packages/next/dist/stream.js +22 -0
- package/packages/next/dist/stream.js.map +1 -0
- package/packages/next/dist/types.d.ts +33 -0
- package/packages/next/dist/types.d.ts.map +1 -0
- package/packages/next/dist/types.js +6 -0
- package/packages/next/dist/types.js.map +1 -0
- package/packages/next/dist/use-cache.d.ts +4 -0
- package/packages/next/dist/use-cache.d.ts.map +1 -0
- package/packages/next/dist/use-cache.js +86 -0
- package/packages/next/dist/use-cache.js.map +1 -0
- package/packages/next/dist/utils.d.ts +32 -0
- package/packages/next/dist/utils.d.ts.map +1 -0
- package/packages/next/dist/utils.js +88 -0
- package/packages/next/dist/utils.js.map +1 -0
- package/packages/next/package.json +52 -0
- package/packages/next/src/error-capture.ts +177 -0
- package/packages/next/src/error-handler.ts +221 -0
- package/packages/next/src/isr-cache.ts +100 -0
- package/packages/next/src/stream.ts +23 -0
- package/packages/next/src/types.ts +33 -0
- package/packages/next/src/use-cache.ts +99 -0
- package/packages/next/src/utils.ts +102 -0
- package/packages/next/tsconfig.json +19 -0
- package/packages/next/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
import { DEFAULT_LOG_MAX_AGE, DEFAULT_LOG_MAX_FILES, DEFAULT_LOG_MAX_SIZE, IPCMessageType, ProcessStatus, } from '../../constants.js';
|
|
5
|
+
import { daemonClient } from '../../ipc/DaemonClient.js';
|
|
6
|
+
import { parseCronSpecs, parseLogSize, parseMemorySize, parseWorkers, sleep } from '../parse.js';
|
|
7
|
+
import { formatProcessTable } from './list.js';
|
|
8
|
+
function isAllOnline(processes, name, expectedWorkers) {
|
|
9
|
+
const proc = processes.find((p) => p.name === name);
|
|
10
|
+
if (!proc)
|
|
11
|
+
return false;
|
|
12
|
+
if (proc.status === ProcessStatus.ERRORED)
|
|
13
|
+
return true; // Don't wait forever on errors
|
|
14
|
+
if (expectedWorkers <= 1) {
|
|
15
|
+
return proc.status === ProcessStatus.ONLINE;
|
|
16
|
+
}
|
|
17
|
+
const onlineWorkers = proc.workers.filter((w) => w.status === ProcessStatus.ONLINE).length;
|
|
18
|
+
return onlineWorkers >= expectedWorkers;
|
|
19
|
+
}
|
|
20
|
+
async function waitForReady(name, expectedWorkers) {
|
|
21
|
+
const isTTY = process.stdout.isTTY;
|
|
22
|
+
let prevLines = 0;
|
|
23
|
+
const maxWait = 30_000;
|
|
24
|
+
const start = Date.now();
|
|
25
|
+
while (Date.now() - start < maxWait) {
|
|
26
|
+
const listResponse = await daemonClient.request(IPCMessageType.LIST);
|
|
27
|
+
if (!listResponse.success)
|
|
28
|
+
break;
|
|
29
|
+
const processes = listResponse.data;
|
|
30
|
+
const tableStr = formatProcessTable(processes);
|
|
31
|
+
if (isTTY && prevLines > 0) {
|
|
32
|
+
process.stdout.write(`\x1B[${prevLines}A\x1B[J`);
|
|
33
|
+
}
|
|
34
|
+
process.stdout.write(tableStr + '\n');
|
|
35
|
+
prevLines = tableStr.split('\n').length;
|
|
36
|
+
if (isAllOnline(processes, name, expectedWorkers))
|
|
37
|
+
return;
|
|
38
|
+
// Non-TTY: print once and stop (can't overwrite)
|
|
39
|
+
if (!isTTY)
|
|
40
|
+
return;
|
|
41
|
+
await sleep(300);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export const upCommand = new Command('up')
|
|
45
|
+
.description('Start a process in daemon mode')
|
|
46
|
+
.argument('<script>', 'Script file to run')
|
|
47
|
+
.option('-n, --name <name>', 'Process name')
|
|
48
|
+
.option('-w, --workers <number>', 'Number of workers (0 = CPU cores, -1 = CPUs-1)', '1')
|
|
49
|
+
.option('--watch', 'Watch for file changes and reload')
|
|
50
|
+
.option('--watch-paths <paths...>', 'Specific paths to watch')
|
|
51
|
+
.option('--cwd <path>', 'Working directory')
|
|
52
|
+
.option('--node-args <args>', 'Node.js arguments (space-separated, quoted)')
|
|
53
|
+
.option('--args <args>', 'Script arguments (space-separated, quoted)')
|
|
54
|
+
.option('--kill-timeout <ms>', 'Kill timeout in milliseconds', '5000')
|
|
55
|
+
.option('--max-restarts <count>', 'Maximum restart attempts', '10')
|
|
56
|
+
.option('--min-uptime <ms>', 'Minimum uptime before restart counts', '1000')
|
|
57
|
+
.option('--restart-delay <ms>', 'Delay between restarts', '100')
|
|
58
|
+
.option('--sticky', 'Enable sticky sessions for Socket.IO')
|
|
59
|
+
.option('--port <port>', 'Port for sticky session routing (required with --sticky)')
|
|
60
|
+
.option('--reload-retries <count>', 'Retries per worker slot during reload (0-3)', '3')
|
|
61
|
+
.option('--health-check <path>', 'Health check endpoint path (e.g. /health)')
|
|
62
|
+
.option('--log-max-size <size>', 'Max log file size before rotation (e.g. 100M, 500K, 1G)', String(DEFAULT_LOG_MAX_SIZE))
|
|
63
|
+
.option('--log-max-files <count>', 'Rotated log files to keep (0 = no rotation)', String(DEFAULT_LOG_MAX_FILES))
|
|
64
|
+
.option('--log-max-age <days>', 'Delete rotated log files older than N days (0 = no age limit)', String(DEFAULT_LOG_MAX_AGE / (24 * 60 * 60 * 1000)))
|
|
65
|
+
.option('--restart-on-mem <size>', 'Restart when RSS exceeds threshold (e.g. 512M, 1G)')
|
|
66
|
+
.option('--restart-on-memory <size>', 'Alias for --restart-on-mem')
|
|
67
|
+
.option('--cron <spec...>', 'Cron job: "schedule path" (repeatable, e.g. "*/2 * * * * /api/cron/heartbeat-check")')
|
|
68
|
+
.action(async (script, options) => {
|
|
69
|
+
try {
|
|
70
|
+
// Validate script path
|
|
71
|
+
if (!script || script.trim() === '') {
|
|
72
|
+
console.error(chalk.red('✗ Error: Script path is required'));
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
const restartOnMemRaw = options.restartOnMem || options.restartOnMemory;
|
|
76
|
+
const cronJobs = options.cron ? parseCronSpecs(options.cron) : [];
|
|
77
|
+
const payload = {
|
|
78
|
+
script: resolve(options.cwd || process.cwd(), script),
|
|
79
|
+
name: options.name,
|
|
80
|
+
workers: parseWorkers(options.workers),
|
|
81
|
+
watch: options.watch || false,
|
|
82
|
+
watchPaths: options.watchPaths,
|
|
83
|
+
cwd: options.cwd || process.cwd(),
|
|
84
|
+
// Pass current process.env to daemon - includes vars from Node's --env-file
|
|
85
|
+
env: process.env,
|
|
86
|
+
nodeArgs: options.nodeArgs ? options.nodeArgs.split(/\s+/) : [],
|
|
87
|
+
args: options.args ? options.args.split(/\s+/) : [],
|
|
88
|
+
killTimeout: parseInt(options.killTimeout, 10),
|
|
89
|
+
maxRestarts: parseInt(options.maxRestarts, 10),
|
|
90
|
+
minUptime: parseInt(options.minUptime, 10),
|
|
91
|
+
restartDelay: parseInt(options.restartDelay, 10),
|
|
92
|
+
sticky: options.sticky || false,
|
|
93
|
+
port: options.port ? parseInt(options.port, 10) : undefined,
|
|
94
|
+
reloadRetries: parseInt(options.reloadRetries, 10),
|
|
95
|
+
healthCheck: options.healthCheck,
|
|
96
|
+
logMaxSize: parseLogSize(options.logMaxSize),
|
|
97
|
+
logMaxFiles: parseInt(options.logMaxFiles, 10),
|
|
98
|
+
logMaxAge: parseInt(options.logMaxAge, 10) * 24 * 60 * 60 * 1000,
|
|
99
|
+
restartOnMemory: restartOnMemRaw ? parseMemorySize(restartOnMemRaw) : undefined,
|
|
100
|
+
cron: cronJobs.length > 0 ? cronJobs : undefined,
|
|
101
|
+
};
|
|
102
|
+
const response = await daemonClient.request(IPCMessageType.UP, payload);
|
|
103
|
+
if (response.success) {
|
|
104
|
+
const info = response.data;
|
|
105
|
+
console.log(chalk.green(`✓ Process "${info.name}" started`));
|
|
106
|
+
console.log(` Mode: ${info.execMode} | Workers: ${info.workerCount}`);
|
|
107
|
+
if (info.sticky) {
|
|
108
|
+
console.log(` Sticky sessions: enabled`);
|
|
109
|
+
}
|
|
110
|
+
await waitForReady(info.name, info.workerCount);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
console.error(chalk.red(`✗ Failed to start: ${response.error}`));
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
console.error(chalk.red(`✗ Error: ${err.message}`));
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
finally {
|
|
122
|
+
daemonClient.disconnect();
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
//# sourceMappingURL=up.js.map
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { IPCMessageType } from '../constants.js';
|
|
2
|
+
import { DaemonClient } from '../ipc/DaemonClient.js';
|
|
3
|
+
import { restoreDaemon } from '../ipc/restoreDaemon.js';
|
|
4
|
+
/**
|
|
5
|
+
* Wait for a process to exit by polling kill(pid, 0).
|
|
6
|
+
*/
|
|
7
|
+
async function waitForPidDead(pid, maxWait) {
|
|
8
|
+
const deadline = Date.now() + maxWait;
|
|
9
|
+
while (Date.now() < deadline) {
|
|
10
|
+
try {
|
|
11
|
+
process.kill(pid, 0);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return; // Process is dead
|
|
15
|
+
}
|
|
16
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
async function main() {
|
|
20
|
+
const raw = process.env.ORKIFY_CRASH_RECOVERY;
|
|
21
|
+
if (!raw)
|
|
22
|
+
process.exit(0);
|
|
23
|
+
const { env, configs, mcpOptions, daemonPid } = JSON.parse(raw);
|
|
24
|
+
if (env.ORKIFY_API_KEY)
|
|
25
|
+
process.env.ORKIFY_API_KEY = env.ORKIFY_API_KEY;
|
|
26
|
+
if (env.ORKIFY_API_HOST)
|
|
27
|
+
process.env.ORKIFY_API_HOST = env.ORKIFY_API_HOST;
|
|
28
|
+
// Wait for the old daemon process to fully exit before starting a new one.
|
|
29
|
+
// The PID file is already removed by cleanup(), but on Windows the named pipe
|
|
30
|
+
// stays open until the process exits — causing the new daemon to fail to bind.
|
|
31
|
+
if (daemonPid) {
|
|
32
|
+
await waitForPidDead(daemonPid, 10_000);
|
|
33
|
+
}
|
|
34
|
+
const client = new DaemonClient();
|
|
35
|
+
try {
|
|
36
|
+
const response = await restoreDaemon(client, configs);
|
|
37
|
+
if (response.success) {
|
|
38
|
+
console.log('Crash recovery: processes restored');
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
console.error('Crash recovery: restore failed:', response.error);
|
|
42
|
+
}
|
|
43
|
+
// Restore MCP HTTP server if it was running
|
|
44
|
+
if (mcpOptions) {
|
|
45
|
+
try {
|
|
46
|
+
const mcpResponse = await client.request(IPCMessageType.MCP_START, mcpOptions);
|
|
47
|
+
if (mcpResponse.success) {
|
|
48
|
+
console.log('Crash recovery: MCP HTTP server restored');
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
console.error('Crash recovery: MCP restore failed:', mcpResponse.error);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
console.error('Crash recovery: MCP restore error:', err.message);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
client.disconnect();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
main().catch((err) => {
|
|
64
|
+
console.error('Crash recovery error:', err);
|
|
65
|
+
process.exit(1);
|
|
66
|
+
});
|
|
67
|
+
//# sourceMappingURL=crash-recovery.js.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { readFileSync } from 'node:fs';
|
|
4
|
+
import { dirname, join } from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { autostartCommand } from './commands/autostart.js';
|
|
7
|
+
import { crashTestCommand } from './commands/crash-test.js';
|
|
8
|
+
import { daemonReloadCommand } from './commands/daemon-reload.js';
|
|
9
|
+
import { deleteCommand } from './commands/delete.js';
|
|
10
|
+
import { deployCommand } from './commands/deploy.js';
|
|
11
|
+
import { downCommand } from './commands/down.js';
|
|
12
|
+
import { flushCommand } from './commands/flush.js';
|
|
13
|
+
import { killCommand } from './commands/kill.js';
|
|
14
|
+
import { listCommand } from './commands/list.js';
|
|
15
|
+
import { logsCommand } from './commands/logs.js';
|
|
16
|
+
import { mcpCommand } from './commands/mcp.js';
|
|
17
|
+
import { reloadCommand } from './commands/reload.js';
|
|
18
|
+
import { restartCommand } from './commands/restart.js';
|
|
19
|
+
import { restoreCommand } from './commands/restore.js';
|
|
20
|
+
import { runCommand } from './commands/run.js';
|
|
21
|
+
import { snapCommand } from './commands/snap.js';
|
|
22
|
+
import { upCommand } from './commands/up.js';
|
|
23
|
+
const program = new Command();
|
|
24
|
+
program
|
|
25
|
+
.name('orkify')
|
|
26
|
+
.description('Modern JS process orchestration and deployment for your own infrastructure')
|
|
27
|
+
.version(JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), '../../package.json'), 'utf-8')).version);
|
|
28
|
+
program.addCommand(upCommand);
|
|
29
|
+
program.addCommand(downCommand);
|
|
30
|
+
program.addCommand(runCommand);
|
|
31
|
+
program.addCommand(restartCommand);
|
|
32
|
+
program.addCommand(reloadCommand);
|
|
33
|
+
program.addCommand(listCommand);
|
|
34
|
+
program.addCommand(logsCommand);
|
|
35
|
+
program.addCommand(deleteCommand);
|
|
36
|
+
program.addCommand(flushCommand);
|
|
37
|
+
program.addCommand(snapCommand);
|
|
38
|
+
program.addCommand(restoreCommand);
|
|
39
|
+
program.addCommand(killCommand);
|
|
40
|
+
program.addCommand(daemonReloadCommand);
|
|
41
|
+
program.addCommand(deployCommand);
|
|
42
|
+
program.addCommand(mcpCommand);
|
|
43
|
+
program.addCommand(autostartCommand);
|
|
44
|
+
program.addCommand(crashTestCommand);
|
|
45
|
+
program.parse();
|
|
46
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { CronJob } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Parse human-readable size for log rotation config.
|
|
4
|
+
* Falls back to DEFAULT_LOG_MAX_SIZE on invalid input.
|
|
5
|
+
* Enforces MIN_LOG_MAX_SIZE minimum.
|
|
6
|
+
*/
|
|
7
|
+
export declare function parseLogSize(value: string): number;
|
|
8
|
+
/**
|
|
9
|
+
* Parse human-readable size for memory threshold.
|
|
10
|
+
* Exits process on invalid input (CLI validation).
|
|
11
|
+
*/
|
|
12
|
+
export declare function parseMemorySize(value: string): number;
|
|
13
|
+
/**
|
|
14
|
+
* Parse workers option:
|
|
15
|
+
* - "0" → CPU cores
|
|
16
|
+
* - negative number → CPU cores minus that value (-1 = CPUs - 1)
|
|
17
|
+
* - positive number → that many workers
|
|
18
|
+
*/
|
|
19
|
+
export declare function parseWorkers(value: string): number;
|
|
20
|
+
/**
|
|
21
|
+
* Parse --cron spec strings into CronJob objects.
|
|
22
|
+
* Each spec is "schedule path" where schedule is a 5-part cron expression
|
|
23
|
+
* and path is the last whitespace-separated token.
|
|
24
|
+
* Exits process on validation failure.
|
|
25
|
+
*/
|
|
26
|
+
export declare function parseCronSpecs(specs: string[]): CronJob[];
|
|
27
|
+
export declare function sleep(ms: number): Promise<void>;
|
|
28
|
+
//# sourceMappingURL=parse.d.ts.map
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { cpus } from 'node:os';
|
|
3
|
+
import { DEFAULT_LOG_MAX_SIZE, MIN_LOG_MAX_SIZE } from '../constants.js';
|
|
4
|
+
import { validateCronPath, validateCronSchedule } from '../cron/CronScheduler.js';
|
|
5
|
+
/**
|
|
6
|
+
* Core byte parser. Supports: 100M, 500K, 1G, 1.5G, or raw byte count.
|
|
7
|
+
* Returns null if the string is not a valid size.
|
|
8
|
+
*/
|
|
9
|
+
function parseSizeBytes(value) {
|
|
10
|
+
const match = value.match(/^(\d+(?:\.\d+)?)\s*([kmg]?)b?$/i);
|
|
11
|
+
if (!match) {
|
|
12
|
+
const num = parseInt(value, 10);
|
|
13
|
+
return isNaN(num) ? null : num;
|
|
14
|
+
}
|
|
15
|
+
const num = parseFloat(match[1]);
|
|
16
|
+
const unit = match[2].toLowerCase();
|
|
17
|
+
switch (unit) {
|
|
18
|
+
case 'k':
|
|
19
|
+
return Math.round(num * 1024);
|
|
20
|
+
case 'm':
|
|
21
|
+
return Math.round(num * 1024 * 1024);
|
|
22
|
+
case 'g':
|
|
23
|
+
return Math.round(num * 1024 * 1024 * 1024);
|
|
24
|
+
default:
|
|
25
|
+
return Math.round(num);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Parse human-readable size for log rotation config.
|
|
30
|
+
* Falls back to DEFAULT_LOG_MAX_SIZE on invalid input.
|
|
31
|
+
* Enforces MIN_LOG_MAX_SIZE minimum.
|
|
32
|
+
*/
|
|
33
|
+
export function parseLogSize(value) {
|
|
34
|
+
return Math.max(parseSizeBytes(value) ?? DEFAULT_LOG_MAX_SIZE, MIN_LOG_MAX_SIZE);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Parse human-readable size for memory threshold.
|
|
38
|
+
* Exits process on invalid input (CLI validation).
|
|
39
|
+
*/
|
|
40
|
+
export function parseMemorySize(value) {
|
|
41
|
+
const bytes = parseSizeBytes(value);
|
|
42
|
+
if (bytes === null || bytes <= 0) {
|
|
43
|
+
console.error(`Invalid memory size: ${value}`);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
return bytes;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Parse workers option:
|
|
50
|
+
* - "0" → CPU cores
|
|
51
|
+
* - negative number → CPU cores minus that value (-1 = CPUs - 1)
|
|
52
|
+
* - positive number → that many workers
|
|
53
|
+
*/
|
|
54
|
+
export function parseWorkers(value) {
|
|
55
|
+
const num = parseInt(value, 10);
|
|
56
|
+
if (isNaN(num))
|
|
57
|
+
return 1;
|
|
58
|
+
if (num === 0)
|
|
59
|
+
return cpus().length;
|
|
60
|
+
if (num < 0)
|
|
61
|
+
return Math.max(1, cpus().length + num);
|
|
62
|
+
return num;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Parse --cron spec strings into CronJob objects.
|
|
66
|
+
* Each spec is "schedule path" where schedule is a 5-part cron expression
|
|
67
|
+
* and path is the last whitespace-separated token.
|
|
68
|
+
* Exits process on validation failure.
|
|
69
|
+
*/
|
|
70
|
+
export function parseCronSpecs(specs) {
|
|
71
|
+
const cronJobs = [];
|
|
72
|
+
for (const spec of specs) {
|
|
73
|
+
const tokens = spec.trim().split(/\s+/);
|
|
74
|
+
if (tokens.length < 6) {
|
|
75
|
+
console.error(chalk.red(`✗ Invalid --cron spec: "${spec}" (need 5-part schedule + path)`));
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
const path = tokens[tokens.length - 1];
|
|
79
|
+
const schedule = tokens.slice(0, -1).join(' ');
|
|
80
|
+
const pathError = validateCronPath(path);
|
|
81
|
+
if (pathError) {
|
|
82
|
+
console.error(chalk.red(`✗ Invalid --cron: ${pathError}`));
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
const scheduleError = validateCronSchedule(schedule);
|
|
86
|
+
if (scheduleError) {
|
|
87
|
+
console.error(chalk.red(`✗ Invalid --cron: ${scheduleError}`));
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
cronJobs.push({ schedule, path });
|
|
91
|
+
}
|
|
92
|
+
return cronJobs;
|
|
93
|
+
}
|
|
94
|
+
export function sleep(ms) {
|
|
95
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=parse.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* ClusterWrapper - Primary process that manages worker lifecycle
|
|
4
|
+
*
|
|
5
|
+
* This script is spawned by ManagedProcess when running in cluster mode.
|
|
6
|
+
* It uses Node's cluster module to fork workers that share the same port.
|
|
7
|
+
*
|
|
8
|
+
* Environment variables expected:
|
|
9
|
+
* - ORKIFY_SCRIPT: Path to the user's script
|
|
10
|
+
* - ORKIFY_WORKERS: Number of workers to spawn
|
|
11
|
+
* - ORKIFY_PROCESS_NAME: Process name for logging
|
|
12
|
+
* - ORKIFY_PROCESS_ID: Process ID in ORKIFY
|
|
13
|
+
* - ORKIFY_KILL_TIMEOUT: Timeout for graceful shutdown
|
|
14
|
+
* - ORKIFY_STICKY: Whether to use sticky sessions
|
|
15
|
+
* - ORKIFY_ARGS: JSON-encoded array of arguments to pass to the user script
|
|
16
|
+
*/
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=ClusterWrapper.d.ts.map
|