pidnap 0.0.0-dev.0 → 0.0.0-dev.2

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/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { _ as ProcessDefinitionSchema, a as TaskStateSchema, c as CronProcessStateSchema, h as RestartingProcessStateSchema, i as TaskList, m as RestartingProcessOptionsSchema, n as EnvManager, o as CronProcess, p as RestartingProcess, s as CronProcessOptionsSchema, t as logger } from "./logger-crc5neL8.mjs";
2
+ import { _ as ProcessDefinitionSchema, a as TaskStateSchema, c as CronProcessStateSchema, h as RestartingProcessStateSchema, i as TaskList, m as RestartingProcessOptionsSchema, n as EnvManager, o as CronProcess, p as RestartingProcess, s as CronProcessOptionsSchema, t as logger, y as treeKill } from "./logger-BF3KrCIK.mjs";
3
3
  import { createClient } from "./client.mjs";
4
4
  import { Command } from "commander";
5
5
  import { createServer } from "node:http";
@@ -9,8 +9,10 @@ import { RPCHandler } from "@orpc/server/node";
9
9
  import { implement, onError } from "@orpc/server";
10
10
  import * as v from "valibot";
11
11
  import { oc } from "@orpc/contract";
12
+ import { exec } from "node:child_process";
12
13
  import { cwd } from "node:process";
13
14
  import { mkdirSync } from "node:fs";
15
+ import { promisify } from "node:util";
14
16
  import { tsImport } from "tsx/esm/api";
15
17
  import Table from "cli-table3";
16
18
 
@@ -129,10 +131,10 @@ const listProcesses = os.processes.list.handler(async ({ context }) => {
129
131
  return Array.from(context.manager.getRestartingProcesses().values()).map(serializeProcess);
130
132
  });
131
133
  const addProcess = os.processes.add.handler(async ({ input, context }) => {
132
- return serializeProcess(context.manager.addProcess(input.name, input.definition));
134
+ return serializeProcess(await context.manager.addProcess(input.name, input.definition));
133
135
  });
134
136
  const startProcess = os.processes.start.handler(async ({ input, context }) => {
135
- return serializeProcess(context.manager.startProcessByTarget(input.target));
137
+ return serializeProcess(await context.manager.startProcessByTarget(input.target));
136
138
  });
137
139
  const stopProcess = os.processes.stop.handler(async ({ input, context }) => {
138
140
  return serializeProcess(await context.manager.stopProcessByTarget(input.target));
@@ -211,6 +213,26 @@ const router = os.router({
211
213
  }
212
214
  });
213
215
 
216
+ //#endregion
217
+ //#region src/port-utils.ts
218
+ const execAsync = promisify(exec);
219
+ /**
220
+ * Kill any process listening on the specified port, including all descendants.
221
+ */
222
+ async function killProcessOnPort(port) {
223
+ try {
224
+ const { stdout } = await execAsync(`lsof -ti tcp:${port}`);
225
+ const pids = stdout.trim().split("\n").filter(Boolean).map((p) => parseInt(p, 10)).filter((p) => !isNaN(p));
226
+ if (pids.length === 0) return false;
227
+ for (const pid of pids) try {
228
+ await treeKill(pid, "SIGKILL");
229
+ } catch {}
230
+ return true;
231
+ } catch {
232
+ return false;
233
+ }
234
+ }
235
+
214
236
  //#endregion
215
237
  //#region src/manager.ts
216
238
  const HttpServerConfigSchema = v.object({
@@ -234,7 +256,8 @@ const RestartingProcessEntrySchema = v.object({
234
256
  definition: ProcessDefinitionSchema,
235
257
  options: v.optional(RestartingProcessOptionsSchema),
236
258
  envFile: v.optional(v.string()),
237
- envReloadDelay: v.optional(EnvReloadDelaySchema)
259
+ envReloadDelay: v.optional(EnvReloadDelaySchema),
260
+ port: v.optional(v.number())
238
261
  });
239
262
  const TaskEntrySchema = v.object({
240
263
  name: v.string(),
@@ -268,6 +291,7 @@ var Manager = class {
268
291
  processEnvReloadConfig = /* @__PURE__ */ new Map();
269
292
  envReloadTimers = /* @__PURE__ */ new Map();
270
293
  envChangeUnsubscribe = null;
294
+ processPortConfig = /* @__PURE__ */ new Map();
271
295
  signalHandlers = /* @__PURE__ */ new Map();
272
296
  shutdownPromise = null;
273
297
  isShuttingDown = false;
@@ -322,6 +346,14 @@ var Manager = class {
322
346
  cronLogFile(name) {
323
347
  return join(this.logDir, "cron", `${name}.log`);
324
348
  }
349
+ /**
350
+ * Kill any process running on the configured port for a process
351
+ */
352
+ async killPortForProcess(processName) {
353
+ const port = this.processPortConfig.get(processName);
354
+ if (port === void 0) return;
355
+ if (await killProcessOnPort(port)) this.logger.info(`Killed process on port ${port} before starting "${processName}"`);
356
+ }
325
357
  ensureLogDirs() {
326
358
  mkdirSync(this.logDir, { recursive: true });
327
359
  mkdirSync(join(this.logDir, "process"), { recursive: true });
@@ -455,9 +487,10 @@ var Manager = class {
455
487
  /**
456
488
  * Start a restarting process by target
457
489
  */
458
- startProcessByTarget(target) {
490
+ async startProcessByTarget(target) {
459
491
  const proc = this.getProcessByTarget(target);
460
492
  if (!proc) throw new Error(`Process not found: ${target}`);
493
+ await this.killPortForProcess(proc.name);
461
494
  proc.start();
462
495
  return proc;
463
496
  }
@@ -476,6 +509,7 @@ var Manager = class {
476
509
  async restartProcessByTarget(target, force = false) {
477
510
  const proc = this.getProcessByTarget(target);
478
511
  if (!proc) throw new Error(`Process not found: ${target}`);
512
+ await this.killPortForProcess(proc.name);
479
513
  await proc.restart(force);
480
514
  return proc;
481
515
  }
@@ -533,11 +567,15 @@ var Manager = class {
533
567
  /**
534
568
  * Add a restarting process at runtime
535
569
  */
536
- addProcess(name, definition, options, envReloadDelay) {
570
+ async addProcess(name, definition, options, envReloadDelay, port) {
537
571
  if (this.restartingProcesses.has(name)) throw new Error(`Process "${name}" already exists`);
538
572
  const processLogger = this.logger.child(name, { logFile: this.processLogFile(name) });
539
573
  const restartingProcess = new RestartingProcess(name, this.applyDefaults(name, definition), options ?? DEFAULT_RESTART_OPTIONS, processLogger);
540
574
  this.restartingProcesses.set(name, restartingProcess);
575
+ if (port !== void 0) {
576
+ this.processPortConfig.set(name, port);
577
+ await this.killPortForProcess(name);
578
+ }
541
579
  restartingProcess.start();
542
580
  this.processEnvReloadConfig.set(name, envReloadDelay ?? 5e3);
543
581
  this.logger.info(`Added and started restarting process: ${name}`);
@@ -608,6 +646,10 @@ var Manager = class {
608
646
  const processLogger = this.logger.child(entry.name, { logFile: this.processLogFile(entry.name) });
609
647
  const restartingProcess = new RestartingProcess(entry.name, this.applyDefaults(entry.name, entry.definition, entry.envFile), entry.options ?? DEFAULT_RESTART_OPTIONS, processLogger);
610
648
  this.restartingProcesses.set(entry.name, restartingProcess);
649
+ if (entry.port !== void 0) {
650
+ this.processPortConfig.set(entry.name, entry.port);
651
+ await this.killPortForProcess(entry.name);
652
+ }
611
653
  restartingProcess.start();
612
654
  this.processEnvReloadConfig.set(entry.name, entry.envReloadDelay ?? 5e3);
613
655
  this.logger.info(`Started restarting process: ${entry.name}`);
package/dist/cli.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.mjs","names":["oc","ocBase","processes","tasks","crons","getCwd"],"sources":["../src/api/contract.ts","../src/api/server.ts","../src/manager.ts","../src/cli.ts"],"sourcesContent":["import { oc as ocBase } from \"@orpc/contract\";\nimport * as v from \"valibot\";\nimport { ProcessDefinitionSchema } from \"../lazy-process.ts\";\nimport { RestartingProcessStateSchema } from \"../restarting-process.ts\";\nimport { CronProcessStateSchema } from \"../cron-process.ts\";\nimport { TaskStateSchema } from \"../task-list.ts\";\n\n// Re-export schemas for use in other modules\nexport { ProcessDefinitionSchema } from \"../lazy-process.ts\";\nexport { RestartingProcessStateSchema } from \"../restarting-process.ts\";\nexport { CronProcessStateSchema } from \"../cron-process.ts\";\nexport { TaskStateSchema } from \"../task-list.ts\";\n\nconst oc = ocBase.$input(v.void());\n\n// Resource target (name or index)\nconst ResourceTarget = v.union([v.string(), v.number()]);\n\n// Manager state schema\nexport const ManagerStateSchema = v.picklist([\n \"idle\",\n \"initializing\",\n \"running\",\n \"stopping\",\n \"stopped\",\n]);\n\nexport type ManagerState = v.InferOutput<typeof ManagerStateSchema>;\n\n// Manager status response\nexport const ManagerStatusSchema = v.object({\n state: ManagerStateSchema,\n processCount: v.number(),\n cronCount: v.number(),\n taskCount: v.number(),\n});\n\nexport type ManagerStatus = v.InferOutput<typeof ManagerStatusSchema>;\n\n// API response schemas\nexport const RestartingProcessInfoSchema = v.object({\n name: v.string(),\n state: RestartingProcessStateSchema,\n restarts: v.number(),\n});\n\nexport type RestartingProcessInfo = v.InferOutput<typeof RestartingProcessInfoSchema>;\n\nexport const CronProcessInfoSchema = v.object({\n name: v.string(),\n state: CronProcessStateSchema,\n runCount: v.number(),\n failCount: v.number(),\n nextRun: v.nullable(v.string()), // ISO date string\n});\n\nexport type CronProcessInfo = v.InferOutput<typeof CronProcessInfoSchema>;\n\nexport const TaskEntryInfoSchema = v.object({\n id: v.string(),\n state: TaskStateSchema,\n processNames: v.array(v.string()),\n});\n\nexport type TaskEntryInfo = v.InferOutput<typeof TaskEntryInfoSchema>;\n\n// API contract\nexport const manager = {\n status: oc.output(ManagerStatusSchema),\n};\n\nexport const processes = {\n get: oc.input(v.object({ target: ResourceTarget })).output(RestartingProcessInfoSchema),\n list: oc.output(v.array(RestartingProcessInfoSchema)),\n add: oc\n .input(v.object({ name: v.string(), definition: ProcessDefinitionSchema }))\n .output(RestartingProcessInfoSchema),\n start: oc.input(v.object({ target: ResourceTarget })).output(RestartingProcessInfoSchema),\n stop: oc.input(v.object({ target: ResourceTarget })).output(RestartingProcessInfoSchema),\n restart: oc\n .input(v.object({ target: ResourceTarget, force: v.optional(v.boolean()) }))\n .output(RestartingProcessInfoSchema),\n reload: oc\n .input(\n v.object({\n target: ResourceTarget,\n definition: ProcessDefinitionSchema,\n restartImmediately: v.optional(v.boolean()),\n }),\n )\n .output(RestartingProcessInfoSchema),\n remove: oc.input(v.object({ target: ResourceTarget })).output(v.object({ success: v.boolean() })),\n};\n\nexport const tasks = {\n get: oc.input(v.object({ target: ResourceTarget })).output(TaskEntryInfoSchema),\n list: oc.output(v.array(TaskEntryInfoSchema)),\n add: oc\n .input(v.object({ name: v.string(), definition: ProcessDefinitionSchema }))\n .output(TaskEntryInfoSchema),\n remove: oc.input(v.object({ target: ResourceTarget })).output(TaskEntryInfoSchema),\n};\n\nexport const crons = {\n get: oc.input(v.object({ target: ResourceTarget })).output(CronProcessInfoSchema),\n list: oc.output(v.array(CronProcessInfoSchema)),\n trigger: oc.input(v.object({ target: ResourceTarget })).output(CronProcessInfoSchema),\n start: oc.input(v.object({ target: ResourceTarget })).output(CronProcessInfoSchema),\n stop: oc.input(v.object({ target: ResourceTarget })).output(CronProcessInfoSchema),\n};\n\nexport const api = {\n manager,\n processes,\n tasks,\n crons,\n};\n","import { implement } from \"@orpc/server\";\nimport {\n api,\n type RestartingProcessInfo,\n type CronProcessInfo,\n type TaskEntryInfo,\n type ManagerStatus,\n} from \"./contract.ts\";\nimport type { Manager } from \"../manager.ts\";\nimport type { RestartingProcess } from \"../restarting-process.ts\";\nimport type { CronProcess } from \"../cron-process.ts\";\n\nconst os = implement(api).$context<{ manager: Manager }>();\n\n// Helper to serialize a RestartingProcess to API response\nfunction serializeProcess(proc: RestartingProcess): RestartingProcessInfo {\n return {\n name: proc.name,\n state: proc.state,\n restarts: proc.restarts,\n };\n}\n\n// Helper to serialize a CronProcess to API response\nfunction serializeCron(cron: CronProcess): CronProcessInfo {\n return {\n name: cron.name,\n state: cron.state,\n runCount: cron.runCount,\n failCount: cron.failCount,\n nextRun: cron.nextRun?.toISOString() ?? null,\n };\n}\n\n// Manager handlers\nconst managerStatus = os.manager.status.handler(async ({ context }): Promise<ManagerStatus> => {\n const manager = context.manager;\n const taskList = manager.getTaskList();\n return {\n state: manager.state,\n processCount: manager.getRestartingProcesses().size,\n cronCount: manager.getCronProcesses().size,\n taskCount: taskList?.tasks.length ?? 0,\n };\n});\n\n// Processes handlers\nconst getProcess = os.processes.get.handler(async ({ input, context }) => {\n const proc = context.manager.getProcessByTarget(input.target);\n if (!proc) {\n throw new Error(`Process not found: ${input.target}`);\n }\n return serializeProcess(proc);\n});\n\nconst listProcesses = os.processes.list.handler(async ({ context }) => {\n const processes = Array.from(context.manager.getRestartingProcesses().values());\n return processes.map(serializeProcess);\n});\n\nconst addProcess = os.processes.add.handler(async ({ input, context }) => {\n const proc = context.manager.addProcess(input.name, input.definition);\n return serializeProcess(proc);\n});\n\nconst startProcess = os.processes.start.handler(async ({ input, context }) => {\n const proc = context.manager.startProcessByTarget(input.target);\n return serializeProcess(proc);\n});\n\nconst stopProcess = os.processes.stop.handler(async ({ input, context }) => {\n const proc = await context.manager.stopProcessByTarget(input.target);\n return serializeProcess(proc);\n});\n\nconst restartProcess = os.processes.restart.handler(async ({ input, context }) => {\n const proc = await context.manager.restartProcessByTarget(input.target, input.force);\n return serializeProcess(proc);\n});\n\nconst reloadProcess = os.processes.reload.handler(async ({ input, context }) => {\n const proc = await context.manager.reloadProcessByTarget(input.target, input.definition, {\n restartImmediately: input.restartImmediately,\n });\n return serializeProcess(proc);\n});\n\nconst removeProcess = os.processes.remove.handler(async ({ input, context }) => {\n await context.manager.removeProcessByTarget(input.target);\n return { success: true };\n});\n\n// Crons handlers\nconst getCron = os.crons.get.handler(async ({ input, context }) => {\n const cron = context.manager.getCronByTarget(input.target);\n if (!cron) {\n throw new Error(`Cron not found: ${input.target}`);\n }\n return serializeCron(cron);\n});\n\nconst listCrons = os.crons.list.handler(async ({ context }) => {\n const crons = Array.from(context.manager.getCronProcesses().values());\n return crons.map(serializeCron);\n});\n\nconst triggerCron = os.crons.trigger.handler(async ({ input, context }) => {\n const cron = await context.manager.triggerCronByTarget(input.target);\n return serializeCron(cron);\n});\n\nconst startCron = os.crons.start.handler(async ({ input, context }) => {\n const cron = context.manager.startCronByTarget(input.target);\n return serializeCron(cron);\n});\n\nconst stopCron = os.crons.stop.handler(async ({ input, context }) => {\n const cron = await context.manager.stopCronByTarget(input.target);\n return serializeCron(cron);\n});\n\n// Tasks handlers\nconst getTask = os.tasks.get.handler(async ({ input, context }) => {\n const task = context.manager.getTaskByTarget(input.target);\n if (!task) {\n throw new Error(`Task not found: ${input.target}`);\n }\n return task as TaskEntryInfo;\n});\n\nconst listTasks = os.tasks.list.handler(async ({ context }) => {\n const taskList = context.manager.getTaskList();\n if (!taskList) {\n return [];\n }\n return taskList.tasks.map((t) => ({\n id: t.id,\n state: t.state,\n processNames: t.processes.map((p) => p.name),\n })) as TaskEntryInfo[];\n});\n\nconst addTask = os.tasks.add.handler(async ({ input, context }) => {\n const task = context.manager.addTask(input.name, input.definition);\n return task as TaskEntryInfo;\n});\n\nconst removeTask = os.tasks.remove.handler(async ({ input, context }) => {\n const task = context.manager.removeTaskByTarget(input.target);\n return task as TaskEntryInfo;\n});\n\nexport const router = os.router({\n manager: {\n status: managerStatus,\n },\n processes: {\n add: addProcess,\n get: getProcess,\n list: listProcesses,\n start: startProcess,\n stop: stopProcess,\n restart: restartProcess,\n reload: reloadProcess,\n remove: removeProcess,\n },\n crons: {\n get: getCron,\n list: listCrons,\n trigger: triggerCron,\n start: startCron,\n stop: stopCron,\n },\n tasks: {\n get: getTask,\n list: listTasks,\n add: addTask,\n remove: removeTask,\n },\n});\n","import * as v from \"valibot\";\nimport { join } from \"node:path\";\nimport { cwd as getCwd } from \"node:process\";\nimport { mkdirSync } from \"node:fs\";\nimport { ProcessDefinitionSchema, type ProcessDefinition } from \"./lazy-process.ts\";\nimport type { Logger } from \"./logger.ts\";\nimport { TaskList, type NamedProcessDefinition } from \"./task-list.ts\";\nimport { CronProcess, CronProcessOptionsSchema } from \"./cron-process.ts\";\nimport {\n RestartingProcess,\n RestartingProcessOptionsSchema,\n type RestartingProcessOptions,\n} from \"./restarting-process.ts\";\nimport { EnvManager } from \"./env-manager.ts\";\n\n// Valibot schemas\n\n// HTTP server configuration schema\nexport const HttpServerConfigSchema = v.object({\n host: v.optional(v.string()),\n port: v.optional(v.number()),\n authToken: v.optional(v.string()),\n});\n\nexport type HttpServerConfig = v.InferOutput<typeof HttpServerConfigSchema>;\n\n// Cron process entry schema\nexport const CronProcessEntrySchema = v.object({\n name: v.string(),\n definition: ProcessDefinitionSchema,\n options: CronProcessOptionsSchema,\n envFile: v.optional(v.string()),\n});\n\nexport type CronProcessEntry = v.InferOutput<typeof CronProcessEntrySchema>;\n\n// Env reload delay schema - can be number (ms), \"immediately\"/true, or false for disabled\nexport const EnvReloadDelaySchema = v.union([v.number(), v.boolean(), v.literal(\"immediately\")]);\n\nexport type EnvReloadDelay = v.InferOutput<typeof EnvReloadDelaySchema>;\n\n// Restarting process entry schema\nexport const RestartingProcessEntrySchema = v.object({\n name: v.string(),\n definition: ProcessDefinitionSchema,\n options: v.optional(RestartingProcessOptionsSchema),\n envFile: v.optional(v.string()),\n envReloadDelay: v.optional(EnvReloadDelaySchema), // Default 5000ms\n});\n\nexport type RestartingProcessEntry = v.InferOutput<typeof RestartingProcessEntrySchema>;\n\n// Task entry schema with envFile\nexport const TaskEntrySchema = v.object({\n name: v.string(),\n definition: ProcessDefinitionSchema,\n envFile: v.optional(v.string()),\n});\n\nexport type TaskEntry = v.InferOutput<typeof TaskEntrySchema>;\n\n// Main manager configuration schema\nexport const ManagerConfigSchema = v.object({\n http: v.optional(HttpServerConfigSchema),\n cwd: v.optional(v.string()),\n logDir: v.optional(v.string()),\n env: v.optional(v.record(v.string(), v.string())),\n envFiles: v.optional(v.record(v.string(), v.string())),\n tasks: v.optional(v.array(TaskEntrySchema)),\n crons: v.optional(v.array(CronProcessEntrySchema)),\n processes: v.optional(v.array(RestartingProcessEntrySchema)),\n});\n\nexport type ManagerConfig = v.InferOutput<typeof ManagerConfigSchema>;\n\n// Default restart policy when not specified\nconst DEFAULT_RESTART_OPTIONS = {\n restartPolicy: \"always\" as const,\n};\n\n// Hardcoded shutdown configuration\nconst SHUTDOWN_TIMEOUT_MS = 15000;\nconst SHUTDOWN_SIGNALS: NodeJS.Signals[] = [\"SIGINT\", \"SIGTERM\"];\nconst SHUTDOWN_EXIT_CODE = 0;\n\n// Manager state\nexport type ManagerState =\n | \"idle\" // Not started\n | \"initializing\" // Running task list\n | \"running\" // All processes running\n | \"stopping\" // Stopping all processes\n | \"stopped\"; // Fully stopped\n\nexport class Manager {\n private config: ManagerConfig;\n private logger: Logger;\n private envManager: EnvManager;\n private envFileKeyByProcess: Map<string, string> = new Map();\n\n private _state: ManagerState = \"idle\";\n private taskList: TaskList | null = null;\n private cronProcesses: Map<string, CronProcess> = new Map();\n private restartingProcesses: Map<string, RestartingProcess> = new Map();\n private logDir: string;\n\n // Env reload tracking\n private processEnvReloadConfig: Map<string, EnvReloadDelay> = new Map();\n private envReloadTimers: Map<string, ReturnType<typeof setTimeout>> = new Map();\n private envChangeUnsubscribe: (() => void) | null = null;\n\n // Shutdown handling\n private signalHandlers: Map<NodeJS.Signals, () => void> = new Map();\n private shutdownPromise: Promise<void> | null = null;\n private isShuttingDown: boolean = false;\n\n constructor(config: ManagerConfig, logger: Logger) {\n this.config = config;\n this.logger = logger;\n this.logDir = config.logDir ?? join(getCwd(), \"logs\");\n this.ensureLogDirs();\n // Initialize EnvManager with watching enabled\n this.envManager = new EnvManager({\n cwd: config.cwd,\n files: config.envFiles,\n watch: true,\n });\n\n // Register env change handler\n this.envChangeUnsubscribe = this.envManager.onChange((changedKeys) => {\n this.handleEnvChange(changedKeys);\n });\n\n // Automatically register shutdown handlers\n this.registerShutdownHandlers();\n }\n\n /**\n * Merge global env with process-specific env and apply cwd inheritance\n * Merge order: .env (global), config.env (global), .env.<processName>, processEnvFile, definition.env\n */\n private applyDefaults(\n processName: string,\n definition: ProcessDefinition,\n envFile?: string,\n ): ProcessDefinition {\n // Start with env from .env file (global)\n const envFromFiles = this.envManager.getEnvVars(processName);\n\n // Build the env file map for this specific process if envFile is provided\n let envFromCustomFile: Record<string, string> = {};\n if (envFile) {\n let key = this.envFileKeyByProcess.get(processName);\n if (!key) {\n key = `custom:${processName}`;\n this.envFileKeyByProcess.set(processName, key);\n this.envManager.registerFile(key, envFile);\n }\n envFromCustomFile = this.envManager.getEnvForKey(key);\n }\n\n return {\n ...definition,\n cwd: definition.cwd ?? this.config.cwd,\n env: {\n ...envFromFiles, // .env (global) + .env.<processName>\n ...this.config.env, // Global env from config\n ...envFromCustomFile, // Custom env file if specified\n ...definition.env, // Process-specific env overrides\n },\n };\n }\n\n private processLogFile(name: string): string {\n return join(this.logDir, \"process\", `${name}.log`);\n }\n\n private taskLogFile(name: string): string {\n return join(this.logDir, \"tasks\", `${name}.log`);\n }\n\n private cronLogFile(name: string): string {\n return join(this.logDir, \"cron\", `${name}.log`);\n }\n\n private ensureLogDirs(): void {\n mkdirSync(this.logDir, { recursive: true });\n mkdirSync(join(this.logDir, \"process\"), { recursive: true });\n mkdirSync(join(this.logDir, \"tasks\"), { recursive: true });\n mkdirSync(join(this.logDir, \"cron\"), { recursive: true });\n }\n\n /**\n * Handle env file changes\n */\n private handleEnvChange(changedKeys: string[]): void {\n if (this._state !== \"running\") {\n return; // Only handle changes when manager is running\n }\n\n this.logger.info(`Env files changed for keys: ${changedKeys.join(\", \")}`);\n\n // Check which processes are affected\n const affectedProcesses = new Set<string>();\n\n for (const key of changedKeys) {\n // Global key affects all processes\n if (key === \"global\") {\n for (const processName of this.restartingProcesses.keys()) {\n affectedProcesses.add(processName);\n }\n } else {\n // Specific key affects matching process\n if (this.restartingProcesses.has(key)) {\n affectedProcesses.add(key);\n }\n\n for (const [processName, customKey] of this.envFileKeyByProcess.entries()) {\n if (customKey === key && this.restartingProcesses.has(processName)) {\n affectedProcesses.add(processName);\n }\n }\n }\n }\n\n // Schedule restarts for affected processes\n for (const processName of affectedProcesses) {\n const reloadDelay = this.processEnvReloadConfig.get(processName);\n\n // Skip if reload is disabled for this process\n if (reloadDelay === false) {\n continue;\n }\n\n this.scheduleProcessReload(processName, reloadDelay);\n }\n }\n\n /**\n * Schedule a process reload with debouncing\n */\n private scheduleProcessReload(processName: string, reloadDelay?: EnvReloadDelay): void {\n // Clear existing timer if any\n const existingTimer = this.envReloadTimers.get(processName);\n if (existingTimer) {\n clearTimeout(existingTimer);\n }\n\n // Determine delay in ms\n let delayMs: number;\n if (reloadDelay === false) {\n return; // Should not happen, but guard anyway\n } else if (reloadDelay === true || reloadDelay === \"immediately\") {\n delayMs = 0;\n } else if (typeof reloadDelay === \"number\") {\n delayMs = reloadDelay;\n } else {\n delayMs = 5000; // Default 5 seconds\n }\n\n this.logger.info(`Scheduling reload for process \"${processName}\" in ${delayMs}ms`);\n\n const timer = setTimeout(async () => {\n await this.reloadProcessEnv(processName);\n this.envReloadTimers.delete(processName);\n }, delayMs);\n\n this.envReloadTimers.set(processName, timer);\n }\n\n /**\n * Reload a process with updated env vars\n */\n private async reloadProcessEnv(processName: string): Promise<void> {\n const proc = this.restartingProcesses.get(processName);\n if (!proc) {\n this.logger.warn(`Process \"${processName}\" not found for env reload`);\n return;\n }\n\n this.logger.info(`Reloading process \"${processName}\" due to env change`);\n\n // Get the original config for this process\n const processConfig = this.config.processes?.find((p) => p.name === processName);\n if (!processConfig) {\n this.logger.warn(`Process config for \"${processName}\" not found`);\n return;\n }\n\n // Rebuild definition with updated env\n const updatedDefinition = this.applyDefaults(\n processName,\n processConfig.definition,\n processConfig.envFile,\n );\n\n // Reload the process (graceful restart)\n await proc.reload(updatedDefinition, true);\n }\n\n get state(): ManagerState {\n return this._state;\n }\n\n /**\n * Get all cron processes (read-only access)\n */\n getCronProcesses(): ReadonlyMap<string, CronProcess> {\n return this.cronProcesses;\n }\n\n /**\n * Get a specific cron process by name\n */\n getCronProcess(name: string): CronProcess | undefined {\n return this.cronProcesses.get(name);\n }\n\n /**\n * Get all restarting processes (read-only access)\n */\n getRestartingProcesses(): ReadonlyMap<string, RestartingProcess> {\n return this.restartingProcesses;\n }\n\n /**\n * Get a specific restarting process by name\n */\n getRestartingProcess(name: string): RestartingProcess | undefined {\n return this.restartingProcesses.get(name);\n }\n\n /**\n * Get the task list (read-only access)\n */\n getTaskList(): TaskList | null {\n return this.taskList;\n }\n\n /**\n * Get a restarting process by name or index\n */\n getProcessByTarget(target: string | number): RestartingProcess | undefined {\n if (typeof target === \"string\") {\n return this.restartingProcesses.get(target);\n }\n const entries = Array.from(this.restartingProcesses.values());\n return entries[target];\n }\n\n /**\n * Get a cron process by name or index\n */\n getCronByTarget(target: string | number): CronProcess | undefined {\n if (typeof target === \"string\") {\n return this.cronProcesses.get(target);\n }\n const entries = Array.from(this.cronProcesses.values());\n return entries[target];\n }\n\n /**\n * Get a task by id or index\n */\n getTaskByTarget(\n target: string | number,\n ): { id: string; state: string; processNames: string[] } | undefined {\n if (!this.taskList) return undefined;\n const tasks = this.taskList.tasks;\n\n if (typeof target === \"string\") {\n const task = tasks.find((t) => t.id === target);\n if (!task) return undefined;\n return {\n id: task.id,\n state: task.state,\n processNames: task.processes.map((p) => p.name),\n };\n }\n\n const task = tasks[target];\n if (!task) return undefined;\n return {\n id: task.id,\n state: task.state,\n processNames: task.processes.map((p) => p.name),\n };\n }\n\n /**\n * Start a restarting process by target\n */\n startProcessByTarget(target: string | number): RestartingProcess {\n const proc = this.getProcessByTarget(target);\n if (!proc) {\n throw new Error(`Process not found: ${target}`);\n }\n proc.start();\n return proc;\n }\n\n /**\n * Stop a restarting process by target\n */\n async stopProcessByTarget(target: string | number, timeout?: number): Promise<RestartingProcess> {\n const proc = this.getProcessByTarget(target);\n if (!proc) {\n throw new Error(`Process not found: ${target}`);\n }\n await proc.stop(timeout);\n return proc;\n }\n\n /**\n * Restart a restarting process by target\n */\n async restartProcessByTarget(\n target: string | number,\n force: boolean = false,\n ): Promise<RestartingProcess> {\n const proc = this.getProcessByTarget(target);\n if (!proc) {\n throw new Error(`Process not found: ${target}`);\n }\n await proc.restart(force);\n return proc;\n }\n\n /**\n * Reload a restarting process with new definition\n */\n async reloadProcessByTarget(\n target: string | number,\n newDefinition: ProcessDefinition,\n options?: {\n restartImmediately?: boolean;\n updateOptions?: Partial<RestartingProcessOptions>;\n },\n ): Promise<RestartingProcess> {\n const proc = this.getProcessByTarget(target);\n if (!proc) {\n throw new Error(`Process not found: ${target}`);\n }\n\n // Apply global defaults to new definition\n const definitionWithDefaults = this.applyDefaults(proc.name, newDefinition);\n\n // Update options if provided\n if (options?.updateOptions) {\n proc.updateOptions(options.updateOptions);\n }\n\n // Reload with new definition\n await proc.reload(definitionWithDefaults, options?.restartImmediately ?? true);\n this.logger.info(`Reloaded process: ${proc.name}`);\n return proc;\n }\n\n /**\n * Remove a restarting process by target\n */\n async removeProcessByTarget(target: string | number, timeout?: number): Promise<void> {\n const proc = this.getProcessByTarget(target);\n if (!proc) {\n throw new Error(`Process not found: ${target}`);\n }\n\n // Stop the process first\n await proc.stop(timeout);\n\n // Remove from the map\n this.restartingProcesses.delete(proc.name);\n this.logger.info(`Removed process: ${proc.name}`);\n }\n\n /**\n * Add a task to the task list\n * Creates the task list if it doesn't exist and starts it\n */\n addTask(\n name: string,\n definition: ProcessDefinition,\n ): { id: string; state: string; processNames: string[] } {\n if (!this.taskList) {\n const taskListLogger = this.logger.child(\"tasks\", {\n logFile: this.taskLogFile(\"tasks\"),\n });\n this.taskList = new TaskList(\"runtime\", taskListLogger, undefined, (processName) => {\n return this.taskLogFile(processName);\n });\n }\n\n const namedProcess: NamedProcessDefinition = {\n name,\n process: this.applyDefaults(name, definition),\n };\n const id = this.taskList.addTask(namedProcess);\n\n // Start the task list if it's idle so the task runs immediately\n if (this.taskList.state === \"idle\") {\n this.taskList.start();\n }\n\n return {\n id,\n state: \"pending\",\n processNames: [name],\n };\n }\n\n removeTaskByTarget(target: string | number): {\n id: string;\n state: string;\n processNames: string[];\n } {\n if (!this.taskList) {\n throw new Error(`Task list not initialized`);\n }\n\n const removed = this.taskList.removeTaskByTarget(target);\n return {\n id: removed.id,\n state: removed.state,\n processNames: removed.processes.map((p) => p.name),\n };\n }\n\n /**\n * Add a restarting process at runtime\n */\n addProcess(\n name: string,\n definition: ProcessDefinition,\n options?: RestartingProcessOptions,\n envReloadDelay?: EnvReloadDelay,\n ): RestartingProcess {\n if (this.restartingProcesses.has(name)) {\n throw new Error(`Process \"${name}\" already exists`);\n }\n\n const processLogger = this.logger.child(name, { logFile: this.processLogFile(name) });\n const restartingProcess = new RestartingProcess(\n name,\n this.applyDefaults(name, definition),\n options ?? DEFAULT_RESTART_OPTIONS,\n processLogger,\n );\n this.restartingProcesses.set(name, restartingProcess);\n restartingProcess.start();\n\n // Track env reload config for this process\n this.processEnvReloadConfig.set(name, envReloadDelay ?? 5000);\n\n this.logger.info(`Added and started restarting process: ${name}`);\n return restartingProcess;\n }\n\n /**\n * Trigger a cron process by target\n */\n async triggerCronByTarget(target: string | number): Promise<CronProcess> {\n const cron = this.getCronByTarget(target);\n if (!cron) {\n throw new Error(`Cron not found: ${target}`);\n }\n await cron.trigger();\n return cron;\n }\n\n /**\n * Start a cron process by target\n */\n startCronByTarget(target: string | number): CronProcess {\n const cron = this.getCronByTarget(target);\n if (!cron) {\n throw new Error(`Cron not found: ${target}`);\n }\n cron.start();\n return cron;\n }\n\n /**\n * Stop a cron process by target\n */\n async stopCronByTarget(target: string | number, timeout?: number): Promise<CronProcess> {\n const cron = this.getCronByTarget(target);\n if (!cron) {\n throw new Error(`Cron not found: ${target}`);\n }\n await cron.stop(timeout);\n return cron;\n }\n\n /**\n * Start the manager:\n * 1. Run task list (if configured) and wait for completion\n * 2. Create and start all cron/restarting processes\n */\n async start(): Promise<void> {\n if (this._state !== \"idle\" && this._state !== \"stopped\") {\n throw new Error(`Manager is already ${this._state}`);\n }\n\n this.logger.info(`Starting manager`);\n\n // Phase 1: Run initialization tasks\n if (this.config.tasks && this.config.tasks.length > 0) {\n this._state = \"initializing\";\n this.logger.info(`Running initialization tasks`);\n\n const taskListLogger = this.logger.child(\"tasks\");\n // Apply defaults to all tasks\n const tasksWithDefaults = this.config.tasks.map((task) => ({\n name: task.name,\n process: this.applyDefaults(task.name, task.definition, task.envFile),\n }));\n this.taskList = new TaskList(\"init\", taskListLogger, tasksWithDefaults, (processName) => {\n return this.taskLogFile(processName);\n });\n\n this.taskList.start();\n await this.taskList.waitUntilIdle();\n\n // Check if any tasks failed\n const failedTasks = this.taskList.tasks.filter((t) => t.state === \"failed\");\n if (failedTasks.length > 0) {\n this._state = \"stopped\";\n const failedNames = failedTasks.map((t) => t.id).join(\", \");\n throw new Error(`Initialization failed: tasks [${failedNames}] failed`);\n }\n\n this.logger.info(`Initialization tasks completed`);\n }\n\n // Phase 2: Create and start cron processes\n if (this.config.crons) {\n for (const entry of this.config.crons) {\n const processLogger = this.logger.child(entry.name, {\n logFile: this.cronLogFile(entry.name),\n });\n const cronProcess = new CronProcess(\n entry.name,\n this.applyDefaults(entry.name, entry.definition, entry.envFile),\n entry.options,\n processLogger,\n );\n this.cronProcesses.set(entry.name, cronProcess);\n cronProcess.start();\n this.logger.info(`Started cron process: ${entry.name}`);\n }\n }\n\n // Phase 3: Create and start restarting processes\n if (this.config.processes) {\n for (const entry of this.config.processes) {\n const processLogger = this.logger.child(entry.name, {\n logFile: this.processLogFile(entry.name),\n });\n const restartingProcess = new RestartingProcess(\n entry.name,\n this.applyDefaults(entry.name, entry.definition, entry.envFile),\n entry.options ?? DEFAULT_RESTART_OPTIONS,\n processLogger,\n );\n this.restartingProcesses.set(entry.name, restartingProcess);\n restartingProcess.start();\n\n // Track env reload config for this process\n this.processEnvReloadConfig.set(\n entry.name,\n entry.envReloadDelay ?? 5000, // Default to 5000ms\n );\n\n this.logger.info(`Started restarting process: ${entry.name}`);\n }\n }\n\n this._state = \"running\";\n this.logger.info(\n `Manager started with ${this.cronProcesses.size} cron process(es) and ${this.restartingProcesses.size} restarting process(es)`,\n );\n }\n\n /**\n * Stop all managed processes\n */\n async stop(timeout?: number): Promise<void> {\n if (this._state === \"idle\" || this._state === \"stopped\") {\n this._state = \"stopped\";\n this.unregisterShutdownHandlers();\n return;\n }\n\n this._state = \"stopping\";\n this.logger.info(`Stopping manager`);\n\n // Clear all env reload timers\n for (const timer of this.envReloadTimers.values()) {\n clearTimeout(timer);\n }\n this.envReloadTimers.clear();\n\n // Unsubscribe from env changes\n if (this.envChangeUnsubscribe) {\n this.envChangeUnsubscribe();\n this.envChangeUnsubscribe = null;\n }\n\n // Dispose env manager\n this.envManager.dispose();\n\n // Stop task list if still running\n if (this.taskList) {\n await this.taskList.stop(timeout);\n }\n\n // Stop all cron processes in parallel\n const cronStopPromises = Array.from(this.cronProcesses.values()).map((p) => p.stop(timeout));\n\n // Stop all restarting processes in parallel\n const restartingStopPromises = Array.from(this.restartingProcesses.values()).map((p) =>\n p.stop(timeout),\n );\n\n await Promise.all([...cronStopPromises, ...restartingStopPromises]);\n\n this._state = \"stopped\";\n this.logger.info(`Manager stopped`);\n\n this.unregisterShutdownHandlers();\n }\n\n /**\n * Register signal handlers for graceful shutdown\n * Called automatically by constructor\n */\n private registerShutdownHandlers(): void {\n if (this.signalHandlers.size > 0) {\n this.logger.warn(`Shutdown handlers already registered`);\n return;\n }\n\n for (const signal of SHUTDOWN_SIGNALS) {\n const handler = () => this.handleSignal(signal);\n this.signalHandlers.set(signal, handler);\n process.on(signal, handler);\n this.logger.debug(`Registered handler for ${signal}`);\n }\n\n this.logger.info(`Shutdown handlers registered for signals: ${SHUTDOWN_SIGNALS.join(\", \")}`);\n }\n\n /**\n * Unregister signal handlers for graceful shutdown\n */\n private unregisterShutdownHandlers(): void {\n if (this.signalHandlers.size === 0) {\n return;\n }\n\n for (const [signal, handler] of this.signalHandlers.entries()) {\n process.off(signal, handler);\n this.logger.debug(`Unregistered handler for ${signal}`);\n }\n\n this.signalHandlers.clear();\n }\n\n /**\n * Wait for shutdown to complete (useful for keeping process alive)\n * Resolves when the manager has fully stopped\n */\n async waitForShutdown(): Promise<void> {\n // If already stopped, return immediately\n if (this._state === \"stopped\") {\n return;\n }\n\n // If shutdown is in progress, wait for it\n if (this.shutdownPromise) {\n await this.shutdownPromise;\n return;\n }\n\n // Wait for state to become stopped\n return new Promise((resolve) => {\n const checkInterval = setInterval(() => {\n if (this._state === \"stopped\") {\n clearInterval(checkInterval);\n resolve();\n }\n }, 100);\n });\n }\n\n /**\n * Trigger graceful shutdown programmatically\n */\n async shutdown(): Promise<void> {\n if (this.isShuttingDown) {\n this.logger.warn(`Shutdown already in progress`);\n if (this.shutdownPromise) {\n await this.shutdownPromise;\n }\n return;\n }\n\n this.isShuttingDown = true;\n this.logger.info(`Initiating graceful shutdown (timeout: ${SHUTDOWN_TIMEOUT_MS}ms)`);\n\n this.shutdownPromise = this.performShutdown();\n await this.shutdownPromise;\n }\n\n private handleSignal(signal: NodeJS.Signals): void {\n this.logger.info(`Received ${signal}, initiating graceful shutdown...`);\n\n // Prevent handling multiple signals\n if (this.isShuttingDown) {\n this.logger.warn(`Shutdown already in progress, ignoring ${signal}`);\n return;\n }\n\n this.isShuttingDown = true;\n this.shutdownPromise = this.performShutdown();\n\n this.shutdownPromise\n .then(() => {\n this.logger.info(`Exiting with code ${SHUTDOWN_EXIT_CODE}`);\n process.exit(SHUTDOWN_EXIT_CODE);\n })\n .catch((err) => {\n this.logger.error(`Shutdown error:`, err);\n process.exit(1);\n });\n }\n\n private async performShutdown(): Promise<void> {\n // Create a timeout promise\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => {\n reject(new Error(`Shutdown timed out after ${SHUTDOWN_TIMEOUT_MS}ms`));\n }, SHUTDOWN_TIMEOUT_MS);\n });\n\n try {\n // Race between graceful stop and timeout\n await Promise.race([this.stop(SHUTDOWN_TIMEOUT_MS), timeoutPromise]);\n this.logger.info(`Graceful shutdown completed`);\n } catch (err) {\n this.logger.error(`Shutdown error:`, err);\n // Force stop on timeout\n this._state = \"stopped\";\n throw err;\n } finally {\n this.isShuttingDown = false;\n this.shutdownPromise = null;\n }\n }\n}\n","#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport { createServer } from \"node:http\";\nimport { pathToFileURL } from \"node:url\";\nimport { resolve } from \"node:path\";\nimport { RPCHandler } from \"@orpc/server/node\";\nimport { onError } from \"@orpc/server\";\nimport * as v from \"valibot\";\nimport { router } from \"./api/server.ts\";\nimport { Manager, ManagerConfigSchema } from \"./manager.ts\";\nimport { logger } from \"./logger.ts\";\nimport { tsImport } from \"tsx/esm/api\";\nimport Table from \"cli-table3\";\nimport { createClient } from \"./api/client.ts\";\nimport { ProcessDefinitionSchema } from \"./api/contract.ts\";\n\nconst program = new Command();\n\nprogram\n .name(\"pidnap\")\n .description(\"Process manager with init system capabilities\")\n .version(\"0.0.0-dev.1\");\n\nprogram\n .command(\"init\")\n .description(\"Initialize and run the process manager with config file\")\n .option(\"-c, --config <path>\", \"Path to config file\", \"pidnap.config.ts\")\n .action(async (options) => {\n const initLogger = logger({ name: \"pidnap\" });\n try {\n // Resolve config file path\n const configPath = resolve(process.cwd(), options.config);\n const configUrl = pathToFileURL(configPath).href;\n\n // Import the config file\n const configModule = await tsImport(configUrl, { parentURL: import.meta.url });\n const rawConfig =\n configModule.default.default || configModule.default || configModule.config || {};\n\n // Parse and validate the config with Valibot\n const config = v.parse(ManagerConfigSchema, rawConfig);\n\n // Extract HTTP config with defaults\n const host = config.http?.host ?? \"localhost\";\n const port = config.http?.port ?? 3000;\n const authToken = config.http?.authToken;\n\n // Create manager with config\n const logDir = config.logDir ?? resolve(process.cwd(), \"logs\");\n const managerLogger = logger({ name: \"pidnap\", logFile: resolve(logDir, \"pidnap.log\") });\n const manager = new Manager(config, managerLogger);\n\n // Setup ORPC server with optional auth token middleware\n const handler = new RPCHandler(router, {\n interceptors: [\n onError((error) => {\n managerLogger.error(error);\n }),\n ],\n });\n\n const server = createServer(async (req, res) => {\n // Check auth token if configured\n if (authToken) {\n const providedToken = req.headers[\"authorization\"]?.replace(\"Bearer \", \"\");\n if (providedToken !== authToken) {\n res.statusCode = 401;\n res.end(\"Unauthorized\");\n return;\n }\n }\n\n const { matched } = await handler.handle(req, res, {\n prefix: \"/rpc\",\n context: { manager },\n });\n if (matched) return;\n res.statusCode = 404;\n res.end(\"Not found\");\n });\n\n server.listen(port, host, async () => {\n managerLogger.info(`pidnap RPC server running on http://${host}:${port}`);\n if (authToken) {\n managerLogger.info(\"Auth token required for API access\");\n }\n\n try {\n await manager.start();\n } catch (err) {\n managerLogger.error(\"Failed to start manager:\", err);\n server.close();\n process.exit(1);\n }\n });\n\n // Wait for shutdown\n await manager.waitForShutdown();\n\n // Close server on shutdown\n server.close();\n } catch (error) {\n initLogger.error(\"Failed to start pidnap:\", error);\n process.exit(1);\n }\n });\n\nprogram\n .command(\"status\")\n .description(\"Show manager status\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (options) => {\n try {\n const client = createClient(options.url);\n const status = await client.manager.status();\n\n const table = new Table({ head: [\"State\", \"Processes\", \"Crons\", \"Tasks\"] });\n table.push([status.state, status.processCount, status.cronCount, status.taskCount]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to fetch status:\", error);\n process.exit(1);\n }\n });\n\nconst processes = program.command(\"processes\").description(\"Manage restarting processes\");\n\nprocesses\n .command(\"list\")\n .description(\"List restarting processes\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (options) => {\n try {\n const client = createClient(options.url);\n const processes = await client.processes.list();\n\n const table = new Table({ head: [\"Name\", \"State\", \"Restarts\"] });\n for (const proc of processes) {\n table.push([proc.name, proc.state, proc.restarts]);\n }\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to list processes:\", error);\n process.exit(1);\n }\n });\n\nprocesses\n .command(\"get\")\n .description(\"Get a restarting process by name or index\")\n .argument(\"<target>\", \"Process name or index\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (target, options) => {\n try {\n const client = createClient(options.url);\n const proc = await client.processes.get({ target: parseTarget(target) });\n\n const table = new Table({ head: [\"Name\", \"State\", \"Restarts\"] });\n table.push([proc.name, proc.state, proc.restarts]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to get process:\", error);\n process.exit(1);\n }\n });\n\nprocesses\n .command(\"add\")\n .description(\"Add a restarting process\")\n .requiredOption(\"-n, --name <name>\", \"Process name\")\n .requiredOption(\"-d, --definition <json>\", \"Process definition JSON\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (options) => {\n try {\n const client = createClient(options.url);\n const definition = parseDefinition(options.definition);\n const proc = await client.processes.add({ name: options.name, definition });\n\n const table = new Table({ head: [\"Name\", \"State\", \"Restarts\"] });\n table.push([proc.name, proc.state, proc.restarts]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to add process:\", error);\n process.exit(1);\n }\n });\n\nprocesses\n .command(\"start\")\n .description(\"Start a restarting process\")\n .argument(\"<target>\", \"Process name or index\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (target, options) => {\n try {\n const client = createClient(options.url);\n const proc = await client.processes.start({ target: parseTarget(target) });\n\n const table = new Table({ head: [\"Name\", \"State\", \"Restarts\"] });\n table.push([proc.name, proc.state, proc.restarts]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to start process:\", error);\n process.exit(1);\n }\n });\n\nprocesses\n .command(\"stop\")\n .description(\"Stop a restarting process\")\n .argument(\"<target>\", \"Process name or index\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (target, options) => {\n try {\n const client = createClient(options.url);\n const proc = await client.processes.stop({ target: parseTarget(target) });\n\n const table = new Table({ head: [\"Name\", \"State\", \"Restarts\"] });\n table.push([proc.name, proc.state, proc.restarts]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to stop process:\", error);\n process.exit(1);\n }\n });\n\nprocesses\n .command(\"restart\")\n .description(\"Restart a restarting process\")\n .argument(\"<target>\", \"Process name or index\")\n .option(\"-f, --force\", \"Force restart\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (target, options) => {\n try {\n const client = createClient(options.url);\n const proc = await client.processes.restart({\n target: parseTarget(target),\n force: options.force,\n });\n\n const table = new Table({ head: [\"Name\", \"State\", \"Restarts\"] });\n table.push([proc.name, proc.state, proc.restarts]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to restart process:\", error);\n process.exit(1);\n }\n });\n\nprocesses\n .command(\"remove\")\n .description(\"Remove a restarting process\")\n .argument(\"<target>\", \"Process name or index\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (target, options) => {\n try {\n const client = createClient(options.url);\n await client.processes.remove({ target: parseTarget(target) });\n console.log(\"Process removed\");\n } catch (error) {\n console.error(\"Failed to remove process:\", error);\n process.exit(1);\n }\n });\n\nconst crons = program.command(\"crons\").description(\"Manage cron processes\");\n\ncrons\n .command(\"list\")\n .description(\"List cron processes\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (options) => {\n try {\n const client = createClient(options.url);\n const crons = await client.crons.list();\n\n const table = new Table({ head: [\"Name\", \"State\", \"Runs\", \"Fails\", \"Next Run\"] });\n for (const cron of crons) {\n table.push([cron.name, cron.state, cron.runCount, cron.failCount, cron.nextRun ?? \"-\"]);\n }\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to list crons:\", error);\n process.exit(1);\n }\n });\n\ncrons\n .command(\"get\")\n .description(\"Get a cron process by name or index\")\n .argument(\"<target>\", \"Cron name or index\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (target, options) => {\n try {\n const client = createClient(options.url);\n const cron = await client.crons.get({ target: parseTarget(target) });\n\n const table = new Table({ head: [\"Name\", \"State\", \"Runs\", \"Fails\", \"Next Run\"] });\n table.push([cron.name, cron.state, cron.runCount, cron.failCount, cron.nextRun ?? \"-\"]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to get cron:\", error);\n process.exit(1);\n }\n });\n\ncrons\n .command(\"trigger\")\n .description(\"Trigger a cron process\")\n .argument(\"<target>\", \"Cron name or index\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (target, options) => {\n try {\n const client = createClient(options.url);\n const cron = await client.crons.trigger({ target: parseTarget(target) });\n\n const table = new Table({ head: [\"Name\", \"State\", \"Runs\", \"Fails\", \"Next Run\"] });\n table.push([cron.name, cron.state, cron.runCount, cron.failCount, cron.nextRun ?? \"-\"]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to trigger cron:\", error);\n process.exit(1);\n }\n });\n\ncrons\n .command(\"start\")\n .description(\"Start a cron process\")\n .argument(\"<target>\", \"Cron name or index\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (target, options) => {\n try {\n const client = createClient(options.url);\n const cron = await client.crons.start({ target: parseTarget(target) });\n\n const table = new Table({ head: [\"Name\", \"State\", \"Runs\", \"Fails\", \"Next Run\"] });\n table.push([cron.name, cron.state, cron.runCount, cron.failCount, cron.nextRun ?? \"-\"]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to start cron:\", error);\n process.exit(1);\n }\n });\n\ncrons\n .command(\"stop\")\n .description(\"Stop a cron process\")\n .argument(\"<target>\", \"Cron name or index\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (target, options) => {\n try {\n const client = createClient(options.url);\n const cron = await client.crons.stop({ target: parseTarget(target) });\n\n const table = new Table({ head: [\"Name\", \"State\", \"Runs\", \"Fails\", \"Next Run\"] });\n table.push([cron.name, cron.state, cron.runCount, cron.failCount, cron.nextRun ?? \"-\"]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to stop cron:\", error);\n process.exit(1);\n }\n });\n\nconst tasks = program.command(\"tasks\").description(\"Manage tasks\");\n\ntasks\n .command(\"list\")\n .description(\"List tasks\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (options) => {\n try {\n const client = createClient(options.url);\n const tasks = await client.tasks.list();\n\n const table = new Table({ head: [\"Id\", \"State\", \"Processes\"] });\n for (const task of tasks) {\n table.push([task.id, task.state, task.processNames.join(\", \")]);\n }\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to list tasks:\", error);\n process.exit(1);\n }\n });\n\ntasks\n .command(\"get\")\n .description(\"Get a task by id or index\")\n .argument(\"<target>\", \"Task id or index\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (target, options) => {\n try {\n const client = createClient(options.url);\n const task = await client.tasks.get({ target: parseTarget(target) });\n\n const table = new Table({ head: [\"Id\", \"State\", \"Processes\"] });\n table.push([task.id, task.state, task.processNames.join(\", \")]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to get task:\", error);\n process.exit(1);\n }\n });\n\ntasks\n .command(\"add\")\n .description(\"Add a task\")\n .requiredOption(\"-n, --name <name>\", \"Task name\")\n .requiredOption(\"-d, --definition <json>\", \"Process definition JSON\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (options) => {\n try {\n const client = createClient(options.url);\n const definition = parseDefinition(options.definition);\n const task = await client.tasks.add({ name: options.name, definition });\n\n const table = new Table({ head: [\"Id\", \"State\", \"Processes\"] });\n table.push([task.id, task.state, task.processNames.join(\", \")]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to add task:\", error);\n process.exit(1);\n }\n });\n\ntasks\n .command(\"remove\")\n .description(\"Remove a task by id or index\")\n .argument(\"<target>\", \"Task id or index\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (target, options) => {\n try {\n const client = createClient(options.url);\n const task = await client.tasks.remove({ target: parseTarget(target) });\n\n const table = new Table({ head: [\"Id\", \"State\", \"Processes\"] });\n table.push([task.id, task.state, task.processNames.join(\", \")]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to remove task:\", error);\n process.exit(1);\n }\n });\n\nconst TargetSchema = v.union([v.string(), v.number()]);\ntype ProcessDefinition = v.InferOutput<typeof ProcessDefinitionSchema>;\n\nfunction parseTarget(value: string): string | number {\n const asNumber = Number(value);\n return v.parse(TargetSchema, Number.isNaN(asNumber) ? value : asNumber);\n}\n\nfunction parseDefinition(raw: string): ProcessDefinition {\n try {\n const parsed = JSON.parse(raw);\n return v.parse(ProcessDefinitionSchema, parsed);\n } catch (error) {\n console.error(\"Invalid --definition JSON. Expected a ProcessDefinition.\");\n throw error;\n }\n}\n\nprogram.parse();\n"],"mappings":"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"}
1
+ {"version":3,"file":"cli.mjs","names":["oc","ocBase","processes","tasks","crons","getCwd"],"sources":["../src/api/contract.ts","../src/api/server.ts","../src/port-utils.ts","../src/manager.ts","../src/cli.ts"],"sourcesContent":["import { oc as ocBase } from \"@orpc/contract\";\nimport * as v from \"valibot\";\nimport { ProcessDefinitionSchema } from \"../lazy-process.ts\";\nimport { RestartingProcessStateSchema } from \"../restarting-process.ts\";\nimport { CronProcessStateSchema } from \"../cron-process.ts\";\nimport { TaskStateSchema } from \"../task-list.ts\";\n\n// Re-export schemas for use in other modules\nexport { ProcessDefinitionSchema } from \"../lazy-process.ts\";\nexport { RestartingProcessStateSchema } from \"../restarting-process.ts\";\nexport { CronProcessStateSchema } from \"../cron-process.ts\";\nexport { TaskStateSchema } from \"../task-list.ts\";\n\nconst oc = ocBase.$input(v.void());\n\n// Resource target (name or index)\nconst ResourceTarget = v.union([v.string(), v.number()]);\n\n// Manager state schema\nexport const ManagerStateSchema = v.picklist([\n \"idle\",\n \"initializing\",\n \"running\",\n \"stopping\",\n \"stopped\",\n]);\n\nexport type ManagerState = v.InferOutput<typeof ManagerStateSchema>;\n\n// Manager status response\nexport const ManagerStatusSchema = v.object({\n state: ManagerStateSchema,\n processCount: v.number(),\n cronCount: v.number(),\n taskCount: v.number(),\n});\n\nexport type ManagerStatus = v.InferOutput<typeof ManagerStatusSchema>;\n\n// API response schemas\nexport const RestartingProcessInfoSchema = v.object({\n name: v.string(),\n state: RestartingProcessStateSchema,\n restarts: v.number(),\n});\n\nexport type RestartingProcessInfo = v.InferOutput<typeof RestartingProcessInfoSchema>;\n\nexport const CronProcessInfoSchema = v.object({\n name: v.string(),\n state: CronProcessStateSchema,\n runCount: v.number(),\n failCount: v.number(),\n nextRun: v.nullable(v.string()), // ISO date string\n});\n\nexport type CronProcessInfo = v.InferOutput<typeof CronProcessInfoSchema>;\n\nexport const TaskEntryInfoSchema = v.object({\n id: v.string(),\n state: TaskStateSchema,\n processNames: v.array(v.string()),\n});\n\nexport type TaskEntryInfo = v.InferOutput<typeof TaskEntryInfoSchema>;\n\n// API contract\nexport const manager = {\n status: oc.output(ManagerStatusSchema),\n};\n\nexport const processes = {\n get: oc.input(v.object({ target: ResourceTarget })).output(RestartingProcessInfoSchema),\n list: oc.output(v.array(RestartingProcessInfoSchema)),\n add: oc\n .input(v.object({ name: v.string(), definition: ProcessDefinitionSchema }))\n .output(RestartingProcessInfoSchema),\n start: oc.input(v.object({ target: ResourceTarget })).output(RestartingProcessInfoSchema),\n stop: oc.input(v.object({ target: ResourceTarget })).output(RestartingProcessInfoSchema),\n restart: oc\n .input(v.object({ target: ResourceTarget, force: v.optional(v.boolean()) }))\n .output(RestartingProcessInfoSchema),\n reload: oc\n .input(\n v.object({\n target: ResourceTarget,\n definition: ProcessDefinitionSchema,\n restartImmediately: v.optional(v.boolean()),\n }),\n )\n .output(RestartingProcessInfoSchema),\n remove: oc.input(v.object({ target: ResourceTarget })).output(v.object({ success: v.boolean() })),\n};\n\nexport const tasks = {\n get: oc.input(v.object({ target: ResourceTarget })).output(TaskEntryInfoSchema),\n list: oc.output(v.array(TaskEntryInfoSchema)),\n add: oc\n .input(v.object({ name: v.string(), definition: ProcessDefinitionSchema }))\n .output(TaskEntryInfoSchema),\n remove: oc.input(v.object({ target: ResourceTarget })).output(TaskEntryInfoSchema),\n};\n\nexport const crons = {\n get: oc.input(v.object({ target: ResourceTarget })).output(CronProcessInfoSchema),\n list: oc.output(v.array(CronProcessInfoSchema)),\n trigger: oc.input(v.object({ target: ResourceTarget })).output(CronProcessInfoSchema),\n start: oc.input(v.object({ target: ResourceTarget })).output(CronProcessInfoSchema),\n stop: oc.input(v.object({ target: ResourceTarget })).output(CronProcessInfoSchema),\n};\n\nexport const api = {\n manager,\n processes,\n tasks,\n crons,\n};\n","import { implement } from \"@orpc/server\";\nimport {\n api,\n type RestartingProcessInfo,\n type CronProcessInfo,\n type TaskEntryInfo,\n type ManagerStatus,\n} from \"./contract.ts\";\nimport type { Manager } from \"../manager.ts\";\nimport type { RestartingProcess } from \"../restarting-process.ts\";\nimport type { CronProcess } from \"../cron-process.ts\";\n\nconst os = implement(api).$context<{ manager: Manager }>();\n\n// Helper to serialize a RestartingProcess to API response\nfunction serializeProcess(proc: RestartingProcess): RestartingProcessInfo {\n return {\n name: proc.name,\n state: proc.state,\n restarts: proc.restarts,\n };\n}\n\n// Helper to serialize a CronProcess to API response\nfunction serializeCron(cron: CronProcess): CronProcessInfo {\n return {\n name: cron.name,\n state: cron.state,\n runCount: cron.runCount,\n failCount: cron.failCount,\n nextRun: cron.nextRun?.toISOString() ?? null,\n };\n}\n\n// Manager handlers\nconst managerStatus = os.manager.status.handler(async ({ context }): Promise<ManagerStatus> => {\n const manager = context.manager;\n const taskList = manager.getTaskList();\n return {\n state: manager.state,\n processCount: manager.getRestartingProcesses().size,\n cronCount: manager.getCronProcesses().size,\n taskCount: taskList?.tasks.length ?? 0,\n };\n});\n\n// Processes handlers\nconst getProcess = os.processes.get.handler(async ({ input, context }) => {\n const proc = context.manager.getProcessByTarget(input.target);\n if (!proc) {\n throw new Error(`Process not found: ${input.target}`);\n }\n return serializeProcess(proc);\n});\n\nconst listProcesses = os.processes.list.handler(async ({ context }) => {\n const processes = Array.from(context.manager.getRestartingProcesses().values());\n return processes.map(serializeProcess);\n});\n\nconst addProcess = os.processes.add.handler(async ({ input, context }) => {\n const proc = await context.manager.addProcess(input.name, input.definition);\n return serializeProcess(proc);\n});\n\nconst startProcess = os.processes.start.handler(async ({ input, context }) => {\n const proc = await context.manager.startProcessByTarget(input.target);\n return serializeProcess(proc);\n});\n\nconst stopProcess = os.processes.stop.handler(async ({ input, context }) => {\n const proc = await context.manager.stopProcessByTarget(input.target);\n return serializeProcess(proc);\n});\n\nconst restartProcess = os.processes.restart.handler(async ({ input, context }) => {\n const proc = await context.manager.restartProcessByTarget(input.target, input.force);\n return serializeProcess(proc);\n});\n\nconst reloadProcess = os.processes.reload.handler(async ({ input, context }) => {\n const proc = await context.manager.reloadProcessByTarget(input.target, input.definition, {\n restartImmediately: input.restartImmediately,\n });\n return serializeProcess(proc);\n});\n\nconst removeProcess = os.processes.remove.handler(async ({ input, context }) => {\n await context.manager.removeProcessByTarget(input.target);\n return { success: true };\n});\n\n// Crons handlers\nconst getCron = os.crons.get.handler(async ({ input, context }) => {\n const cron = context.manager.getCronByTarget(input.target);\n if (!cron) {\n throw new Error(`Cron not found: ${input.target}`);\n }\n return serializeCron(cron);\n});\n\nconst listCrons = os.crons.list.handler(async ({ context }) => {\n const crons = Array.from(context.manager.getCronProcesses().values());\n return crons.map(serializeCron);\n});\n\nconst triggerCron = os.crons.trigger.handler(async ({ input, context }) => {\n const cron = await context.manager.triggerCronByTarget(input.target);\n return serializeCron(cron);\n});\n\nconst startCron = os.crons.start.handler(async ({ input, context }) => {\n const cron = context.manager.startCronByTarget(input.target);\n return serializeCron(cron);\n});\n\nconst stopCron = os.crons.stop.handler(async ({ input, context }) => {\n const cron = await context.manager.stopCronByTarget(input.target);\n return serializeCron(cron);\n});\n\n// Tasks handlers\nconst getTask = os.tasks.get.handler(async ({ input, context }) => {\n const task = context.manager.getTaskByTarget(input.target);\n if (!task) {\n throw new Error(`Task not found: ${input.target}`);\n }\n return task as TaskEntryInfo;\n});\n\nconst listTasks = os.tasks.list.handler(async ({ context }) => {\n const taskList = context.manager.getTaskList();\n if (!taskList) {\n return [];\n }\n return taskList.tasks.map((t) => ({\n id: t.id,\n state: t.state,\n processNames: t.processes.map((p) => p.name),\n })) as TaskEntryInfo[];\n});\n\nconst addTask = os.tasks.add.handler(async ({ input, context }) => {\n const task = context.manager.addTask(input.name, input.definition);\n return task as TaskEntryInfo;\n});\n\nconst removeTask = os.tasks.remove.handler(async ({ input, context }) => {\n const task = context.manager.removeTaskByTarget(input.target);\n return task as TaskEntryInfo;\n});\n\nexport const router = os.router({\n manager: {\n status: managerStatus,\n },\n processes: {\n add: addProcess,\n get: getProcess,\n list: listProcesses,\n start: startProcess,\n stop: stopProcess,\n restart: restartProcess,\n reload: reloadProcess,\n remove: removeProcess,\n },\n crons: {\n get: getCron,\n list: listCrons,\n trigger: triggerCron,\n start: startCron,\n stop: stopCron,\n },\n tasks: {\n get: getTask,\n list: listTasks,\n add: addTask,\n remove: removeTask,\n },\n});\n","import { exec } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { treeKill } from \"./tree-kill.ts\";\n\nconst execAsync = promisify(exec);\n\n/**\n * Kill any process listening on the specified port, including all descendants.\n */\nexport async function killProcessOnPort(port: number): Promise<boolean> {\n try {\n // Use lsof to find the process ID listening on the port\n const { stdout } = await execAsync(`lsof -ti tcp:${port}`);\n const pids = stdout\n .trim()\n .split(\"\\n\")\n .filter(Boolean)\n .map((p) => parseInt(p, 10))\n .filter((p) => !isNaN(p));\n\n if (pids.length === 0) {\n return false; // No process found on port\n }\n\n // Tree kill all processes found on the port (kills children/grandchildren too)\n for (const pid of pids) {\n try {\n await treeKill(pid, \"SIGKILL\");\n } catch {\n // Process may have already exited\n }\n }\n\n return true;\n } catch {\n // Command failed (e.g., no process on port)\n return false;\n }\n}\n","import * as v from \"valibot\";\nimport { join } from \"node:path\";\nimport { cwd as getCwd } from \"node:process\";\nimport { mkdirSync } from \"node:fs\";\nimport { ProcessDefinitionSchema, type ProcessDefinition } from \"./lazy-process.ts\";\nimport type { Logger } from \"./logger.ts\";\nimport { TaskList, type NamedProcessDefinition } from \"./task-list.ts\";\nimport { CronProcess, CronProcessOptionsSchema } from \"./cron-process.ts\";\nimport {\n RestartingProcess,\n RestartingProcessOptionsSchema,\n type RestartingProcessOptions,\n} from \"./restarting-process.ts\";\nimport { EnvManager } from \"./env-manager.ts\";\nimport { killProcessOnPort } from \"./port-utils.ts\";\n\n// Valibot schemas\n\n// HTTP server configuration schema\nexport const HttpServerConfigSchema = v.object({\n host: v.optional(v.string()),\n port: v.optional(v.number()),\n authToken: v.optional(v.string()),\n});\n\nexport type HttpServerConfig = v.InferOutput<typeof HttpServerConfigSchema>;\n\n// Cron process entry schema\nexport const CronProcessEntrySchema = v.object({\n name: v.string(),\n definition: ProcessDefinitionSchema,\n options: CronProcessOptionsSchema,\n envFile: v.optional(v.string()),\n});\n\nexport type CronProcessEntry = v.InferOutput<typeof CronProcessEntrySchema>;\n\n// Env reload delay schema - can be number (ms), \"immediately\"/true, or false for disabled\nexport const EnvReloadDelaySchema = v.union([v.number(), v.boolean(), v.literal(\"immediately\")]);\n\nexport type EnvReloadDelay = v.InferOutput<typeof EnvReloadDelaySchema>;\n\n// Restarting process entry schema\nexport const RestartingProcessEntrySchema = v.object({\n name: v.string(),\n definition: ProcessDefinitionSchema,\n options: v.optional(RestartingProcessOptionsSchema),\n envFile: v.optional(v.string()),\n envReloadDelay: v.optional(EnvReloadDelaySchema), // Default 5000ms\n port: v.optional(v.number()), // Kill any process on this port before spawning\n});\n\nexport type RestartingProcessEntry = v.InferOutput<typeof RestartingProcessEntrySchema>;\n\n// Task entry schema with envFile\nexport const TaskEntrySchema = v.object({\n name: v.string(),\n definition: ProcessDefinitionSchema,\n envFile: v.optional(v.string()),\n});\n\nexport type TaskEntry = v.InferOutput<typeof TaskEntrySchema>;\n\n// Main manager configuration schema\nexport const ManagerConfigSchema = v.object({\n http: v.optional(HttpServerConfigSchema),\n cwd: v.optional(v.string()),\n logDir: v.optional(v.string()),\n env: v.optional(v.record(v.string(), v.string())),\n envFiles: v.optional(v.record(v.string(), v.string())),\n tasks: v.optional(v.array(TaskEntrySchema)),\n crons: v.optional(v.array(CronProcessEntrySchema)),\n processes: v.optional(v.array(RestartingProcessEntrySchema)),\n});\n\nexport type ManagerConfig = v.InferOutput<typeof ManagerConfigSchema>;\n\n// Default restart policy when not specified\nconst DEFAULT_RESTART_OPTIONS = {\n restartPolicy: \"always\" as const,\n};\n\n// Hardcoded shutdown configuration\nconst SHUTDOWN_TIMEOUT_MS = 15000;\nconst SHUTDOWN_SIGNALS: NodeJS.Signals[] = [\"SIGINT\", \"SIGTERM\"];\nconst SHUTDOWN_EXIT_CODE = 0;\n\n// Manager state\nexport type ManagerState =\n | \"idle\" // Not started\n | \"initializing\" // Running task list\n | \"running\" // All processes running\n | \"stopping\" // Stopping all processes\n | \"stopped\"; // Fully stopped\n\nexport class Manager {\n private config: ManagerConfig;\n private logger: Logger;\n private envManager: EnvManager;\n private envFileKeyByProcess: Map<string, string> = new Map();\n\n private _state: ManagerState = \"idle\";\n private taskList: TaskList | null = null;\n private cronProcesses: Map<string, CronProcess> = new Map();\n private restartingProcesses: Map<string, RestartingProcess> = new Map();\n private logDir: string;\n\n // Env reload tracking\n private processEnvReloadConfig: Map<string, EnvReloadDelay> = new Map();\n private envReloadTimers: Map<string, ReturnType<typeof setTimeout>> = new Map();\n private envChangeUnsubscribe: (() => void) | null = null;\n\n // Port tracking for processes\n private processPortConfig: Map<string, number> = new Map();\n\n // Shutdown handling\n private signalHandlers: Map<NodeJS.Signals, () => void> = new Map();\n private shutdownPromise: Promise<void> | null = null;\n private isShuttingDown: boolean = false;\n\n constructor(config: ManagerConfig, logger: Logger) {\n this.config = config;\n this.logger = logger;\n this.logDir = config.logDir ?? join(getCwd(), \"logs\");\n this.ensureLogDirs();\n // Initialize EnvManager with watching enabled\n this.envManager = new EnvManager({\n cwd: config.cwd,\n files: config.envFiles,\n watch: true,\n });\n\n // Register env change handler\n this.envChangeUnsubscribe = this.envManager.onChange((changedKeys) => {\n this.handleEnvChange(changedKeys);\n });\n\n // Automatically register shutdown handlers\n this.registerShutdownHandlers();\n }\n\n /**\n * Merge global env with process-specific env and apply cwd inheritance\n * Merge order: .env (global), config.env (global), .env.<processName>, processEnvFile, definition.env\n */\n private applyDefaults(\n processName: string,\n definition: ProcessDefinition,\n envFile?: string,\n ): ProcessDefinition {\n // Start with env from .env file (global)\n const envFromFiles = this.envManager.getEnvVars(processName);\n\n // Build the env file map for this specific process if envFile is provided\n let envFromCustomFile: Record<string, string> = {};\n if (envFile) {\n let key = this.envFileKeyByProcess.get(processName);\n if (!key) {\n key = `custom:${processName}`;\n this.envFileKeyByProcess.set(processName, key);\n this.envManager.registerFile(key, envFile);\n }\n envFromCustomFile = this.envManager.getEnvForKey(key);\n }\n\n return {\n ...definition,\n cwd: definition.cwd ?? this.config.cwd,\n env: {\n ...envFromFiles, // .env (global) + .env.<processName>\n ...this.config.env, // Global env from config\n ...envFromCustomFile, // Custom env file if specified\n ...definition.env, // Process-specific env overrides\n },\n };\n }\n\n private processLogFile(name: string): string {\n return join(this.logDir, \"process\", `${name}.log`);\n }\n\n private taskLogFile(name: string): string {\n return join(this.logDir, \"tasks\", `${name}.log`);\n }\n\n private cronLogFile(name: string): string {\n return join(this.logDir, \"cron\", `${name}.log`);\n }\n\n /**\n * Kill any process running on the configured port for a process\n */\n private async killPortForProcess(processName: string): Promise<void> {\n const port = this.processPortConfig.get(processName);\n if (port === undefined) return;\n\n const killed = await killProcessOnPort(port);\n if (killed) {\n this.logger.info(`Killed process on port ${port} before starting \"${processName}\"`);\n }\n }\n\n private ensureLogDirs(): void {\n mkdirSync(this.logDir, { recursive: true });\n mkdirSync(join(this.logDir, \"process\"), { recursive: true });\n mkdirSync(join(this.logDir, \"tasks\"), { recursive: true });\n mkdirSync(join(this.logDir, \"cron\"), { recursive: true });\n }\n\n /**\n * Handle env file changes\n */\n private handleEnvChange(changedKeys: string[]): void {\n if (this._state !== \"running\") {\n return; // Only handle changes when manager is running\n }\n\n this.logger.info(`Env files changed for keys: ${changedKeys.join(\", \")}`);\n\n // Check which processes are affected\n const affectedProcesses = new Set<string>();\n\n for (const key of changedKeys) {\n // Global key affects all processes\n if (key === \"global\") {\n for (const processName of this.restartingProcesses.keys()) {\n affectedProcesses.add(processName);\n }\n } else {\n // Specific key affects matching process\n if (this.restartingProcesses.has(key)) {\n affectedProcesses.add(key);\n }\n\n for (const [processName, customKey] of this.envFileKeyByProcess.entries()) {\n if (customKey === key && this.restartingProcesses.has(processName)) {\n affectedProcesses.add(processName);\n }\n }\n }\n }\n\n // Schedule restarts for affected processes\n for (const processName of affectedProcesses) {\n const reloadDelay = this.processEnvReloadConfig.get(processName);\n\n // Skip if reload is disabled for this process\n if (reloadDelay === false) {\n continue;\n }\n\n this.scheduleProcessReload(processName, reloadDelay);\n }\n }\n\n /**\n * Schedule a process reload with debouncing\n */\n private scheduleProcessReload(processName: string, reloadDelay?: EnvReloadDelay): void {\n // Clear existing timer if any\n const existingTimer = this.envReloadTimers.get(processName);\n if (existingTimer) {\n clearTimeout(existingTimer);\n }\n\n // Determine delay in ms\n let delayMs: number;\n if (reloadDelay === false) {\n return; // Should not happen, but guard anyway\n } else if (reloadDelay === true || reloadDelay === \"immediately\") {\n delayMs = 0;\n } else if (typeof reloadDelay === \"number\") {\n delayMs = reloadDelay;\n } else {\n delayMs = 5000; // Default 5 seconds\n }\n\n this.logger.info(`Scheduling reload for process \"${processName}\" in ${delayMs}ms`);\n\n const timer = setTimeout(async () => {\n await this.reloadProcessEnv(processName);\n this.envReloadTimers.delete(processName);\n }, delayMs);\n\n this.envReloadTimers.set(processName, timer);\n }\n\n /**\n * Reload a process with updated env vars\n */\n private async reloadProcessEnv(processName: string): Promise<void> {\n const proc = this.restartingProcesses.get(processName);\n if (!proc) {\n this.logger.warn(`Process \"${processName}\" not found for env reload`);\n return;\n }\n\n this.logger.info(`Reloading process \"${processName}\" due to env change`);\n\n // Get the original config for this process\n const processConfig = this.config.processes?.find((p) => p.name === processName);\n if (!processConfig) {\n this.logger.warn(`Process config for \"${processName}\" not found`);\n return;\n }\n\n // Rebuild definition with updated env\n const updatedDefinition = this.applyDefaults(\n processName,\n processConfig.definition,\n processConfig.envFile,\n );\n\n // Reload the process (graceful restart)\n await proc.reload(updatedDefinition, true);\n }\n\n get state(): ManagerState {\n return this._state;\n }\n\n /**\n * Get all cron processes (read-only access)\n */\n getCronProcesses(): ReadonlyMap<string, CronProcess> {\n return this.cronProcesses;\n }\n\n /**\n * Get a specific cron process by name\n */\n getCronProcess(name: string): CronProcess | undefined {\n return this.cronProcesses.get(name);\n }\n\n /**\n * Get all restarting processes (read-only access)\n */\n getRestartingProcesses(): ReadonlyMap<string, RestartingProcess> {\n return this.restartingProcesses;\n }\n\n /**\n * Get a specific restarting process by name\n */\n getRestartingProcess(name: string): RestartingProcess | undefined {\n return this.restartingProcesses.get(name);\n }\n\n /**\n * Get the task list (read-only access)\n */\n getTaskList(): TaskList | null {\n return this.taskList;\n }\n\n /**\n * Get a restarting process by name or index\n */\n getProcessByTarget(target: string | number): RestartingProcess | undefined {\n if (typeof target === \"string\") {\n return this.restartingProcesses.get(target);\n }\n const entries = Array.from(this.restartingProcesses.values());\n return entries[target];\n }\n\n /**\n * Get a cron process by name or index\n */\n getCronByTarget(target: string | number): CronProcess | undefined {\n if (typeof target === \"string\") {\n return this.cronProcesses.get(target);\n }\n const entries = Array.from(this.cronProcesses.values());\n return entries[target];\n }\n\n /**\n * Get a task by id or index\n */\n getTaskByTarget(\n target: string | number,\n ): { id: string; state: string; processNames: string[] } | undefined {\n if (!this.taskList) return undefined;\n const tasks = this.taskList.tasks;\n\n if (typeof target === \"string\") {\n const task = tasks.find((t) => t.id === target);\n if (!task) return undefined;\n return {\n id: task.id,\n state: task.state,\n processNames: task.processes.map((p) => p.name),\n };\n }\n\n const task = tasks[target];\n if (!task) return undefined;\n return {\n id: task.id,\n state: task.state,\n processNames: task.processes.map((p) => p.name),\n };\n }\n\n /**\n * Start a restarting process by target\n */\n async startProcessByTarget(target: string | number): Promise<RestartingProcess> {\n const proc = this.getProcessByTarget(target);\n if (!proc) {\n throw new Error(`Process not found: ${target}`);\n }\n // Kill any process on the configured port before starting\n await this.killPortForProcess(proc.name);\n proc.start();\n return proc;\n }\n\n /**\n * Stop a restarting process by target\n */\n async stopProcessByTarget(target: string | number, timeout?: number): Promise<RestartingProcess> {\n const proc = this.getProcessByTarget(target);\n if (!proc) {\n throw new Error(`Process not found: ${target}`);\n }\n await proc.stop(timeout);\n return proc;\n }\n\n /**\n * Restart a restarting process by target\n */\n async restartProcessByTarget(\n target: string | number,\n force: boolean = false,\n ): Promise<RestartingProcess> {\n const proc = this.getProcessByTarget(target);\n if (!proc) {\n throw new Error(`Process not found: ${target}`);\n }\n // Kill any process on the configured port before restarting\n await this.killPortForProcess(proc.name);\n await proc.restart(force);\n return proc;\n }\n\n /**\n * Reload a restarting process with new definition\n */\n async reloadProcessByTarget(\n target: string | number,\n newDefinition: ProcessDefinition,\n options?: {\n restartImmediately?: boolean;\n updateOptions?: Partial<RestartingProcessOptions>;\n },\n ): Promise<RestartingProcess> {\n const proc = this.getProcessByTarget(target);\n if (!proc) {\n throw new Error(`Process not found: ${target}`);\n }\n\n // Apply global defaults to new definition\n const definitionWithDefaults = this.applyDefaults(proc.name, newDefinition);\n\n // Update options if provided\n if (options?.updateOptions) {\n proc.updateOptions(options.updateOptions);\n }\n\n // Reload with new definition\n await proc.reload(definitionWithDefaults, options?.restartImmediately ?? true);\n this.logger.info(`Reloaded process: ${proc.name}`);\n return proc;\n }\n\n /**\n * Remove a restarting process by target\n */\n async removeProcessByTarget(target: string | number, timeout?: number): Promise<void> {\n const proc = this.getProcessByTarget(target);\n if (!proc) {\n throw new Error(`Process not found: ${target}`);\n }\n\n // Stop the process first\n await proc.stop(timeout);\n\n // Remove from the map\n this.restartingProcesses.delete(proc.name);\n this.logger.info(`Removed process: ${proc.name}`);\n }\n\n /**\n * Add a task to the task list\n * Creates the task list if it doesn't exist and starts it\n */\n addTask(\n name: string,\n definition: ProcessDefinition,\n ): { id: string; state: string; processNames: string[] } {\n if (!this.taskList) {\n const taskListLogger = this.logger.child(\"tasks\", {\n logFile: this.taskLogFile(\"tasks\"),\n });\n this.taskList = new TaskList(\"runtime\", taskListLogger, undefined, (processName) => {\n return this.taskLogFile(processName);\n });\n }\n\n const namedProcess: NamedProcessDefinition = {\n name,\n process: this.applyDefaults(name, definition),\n };\n const id = this.taskList.addTask(namedProcess);\n\n // Start the task list if it's idle so the task runs immediately\n if (this.taskList.state === \"idle\") {\n this.taskList.start();\n }\n\n return {\n id,\n state: \"pending\",\n processNames: [name],\n };\n }\n\n removeTaskByTarget(target: string | number): {\n id: string;\n state: string;\n processNames: string[];\n } {\n if (!this.taskList) {\n throw new Error(`Task list not initialized`);\n }\n\n const removed = this.taskList.removeTaskByTarget(target);\n return {\n id: removed.id,\n state: removed.state,\n processNames: removed.processes.map((p) => p.name),\n };\n }\n\n /**\n * Add a restarting process at runtime\n */\n async addProcess(\n name: string,\n definition: ProcessDefinition,\n options?: RestartingProcessOptions,\n envReloadDelay?: EnvReloadDelay,\n port?: number,\n ): Promise<RestartingProcess> {\n if (this.restartingProcesses.has(name)) {\n throw new Error(`Process \"${name}\" already exists`);\n }\n\n const processLogger = this.logger.child(name, { logFile: this.processLogFile(name) });\n const restartingProcess = new RestartingProcess(\n name,\n this.applyDefaults(name, definition),\n options ?? DEFAULT_RESTART_OPTIONS,\n processLogger,\n );\n this.restartingProcesses.set(name, restartingProcess);\n\n // Track port config and kill any process on that port before starting\n if (port !== undefined) {\n this.processPortConfig.set(name, port);\n await this.killPortForProcess(name);\n }\n\n restartingProcess.start();\n\n // Track env reload config for this process\n this.processEnvReloadConfig.set(name, envReloadDelay ?? 5000);\n\n this.logger.info(`Added and started restarting process: ${name}`);\n return restartingProcess;\n }\n\n /**\n * Trigger a cron process by target\n */\n async triggerCronByTarget(target: string | number): Promise<CronProcess> {\n const cron = this.getCronByTarget(target);\n if (!cron) {\n throw new Error(`Cron not found: ${target}`);\n }\n await cron.trigger();\n return cron;\n }\n\n /**\n * Start a cron process by target\n */\n startCronByTarget(target: string | number): CronProcess {\n const cron = this.getCronByTarget(target);\n if (!cron) {\n throw new Error(`Cron not found: ${target}`);\n }\n cron.start();\n return cron;\n }\n\n /**\n * Stop a cron process by target\n */\n async stopCronByTarget(target: string | number, timeout?: number): Promise<CronProcess> {\n const cron = this.getCronByTarget(target);\n if (!cron) {\n throw new Error(`Cron not found: ${target}`);\n }\n await cron.stop(timeout);\n return cron;\n }\n\n /**\n * Start the manager:\n * 1. Run task list (if configured) and wait for completion\n * 2. Create and start all cron/restarting processes\n */\n async start(): Promise<void> {\n if (this._state !== \"idle\" && this._state !== \"stopped\") {\n throw new Error(`Manager is already ${this._state}`);\n }\n\n this.logger.info(`Starting manager`);\n\n // Phase 1: Run initialization tasks\n if (this.config.tasks && this.config.tasks.length > 0) {\n this._state = \"initializing\";\n this.logger.info(`Running initialization tasks`);\n\n const taskListLogger = this.logger.child(\"tasks\");\n // Apply defaults to all tasks\n const tasksWithDefaults = this.config.tasks.map((task) => ({\n name: task.name,\n process: this.applyDefaults(task.name, task.definition, task.envFile),\n }));\n this.taskList = new TaskList(\"init\", taskListLogger, tasksWithDefaults, (processName) => {\n return this.taskLogFile(processName);\n });\n\n this.taskList.start();\n await this.taskList.waitUntilIdle();\n\n // Check if any tasks failed\n const failedTasks = this.taskList.tasks.filter((t) => t.state === \"failed\");\n if (failedTasks.length > 0) {\n this._state = \"stopped\";\n const failedNames = failedTasks.map((t) => t.id).join(\", \");\n throw new Error(`Initialization failed: tasks [${failedNames}] failed`);\n }\n\n this.logger.info(`Initialization tasks completed`);\n }\n\n // Phase 2: Create and start cron processes\n if (this.config.crons) {\n for (const entry of this.config.crons) {\n const processLogger = this.logger.child(entry.name, {\n logFile: this.cronLogFile(entry.name),\n });\n const cronProcess = new CronProcess(\n entry.name,\n this.applyDefaults(entry.name, entry.definition, entry.envFile),\n entry.options,\n processLogger,\n );\n this.cronProcesses.set(entry.name, cronProcess);\n cronProcess.start();\n this.logger.info(`Started cron process: ${entry.name}`);\n }\n }\n\n // Phase 3: Create and start restarting processes\n if (this.config.processes) {\n for (const entry of this.config.processes) {\n const processLogger = this.logger.child(entry.name, {\n logFile: this.processLogFile(entry.name),\n });\n const restartingProcess = new RestartingProcess(\n entry.name,\n this.applyDefaults(entry.name, entry.definition, entry.envFile),\n entry.options ?? DEFAULT_RESTART_OPTIONS,\n processLogger,\n );\n this.restartingProcesses.set(entry.name, restartingProcess);\n\n // Track port config and kill any process on that port before starting\n if (entry.port !== undefined) {\n this.processPortConfig.set(entry.name, entry.port);\n await this.killPortForProcess(entry.name);\n }\n\n restartingProcess.start();\n\n // Track env reload config for this process\n this.processEnvReloadConfig.set(\n entry.name,\n entry.envReloadDelay ?? 5000, // Default to 5000ms\n );\n\n this.logger.info(`Started restarting process: ${entry.name}`);\n }\n }\n\n this._state = \"running\";\n this.logger.info(\n `Manager started with ${this.cronProcesses.size} cron process(es) and ${this.restartingProcesses.size} restarting process(es)`,\n );\n }\n\n /**\n * Stop all managed processes\n */\n async stop(timeout?: number): Promise<void> {\n if (this._state === \"idle\" || this._state === \"stopped\") {\n this._state = \"stopped\";\n this.unregisterShutdownHandlers();\n return;\n }\n\n this._state = \"stopping\";\n this.logger.info(`Stopping manager`);\n\n // Clear all env reload timers\n for (const timer of this.envReloadTimers.values()) {\n clearTimeout(timer);\n }\n this.envReloadTimers.clear();\n\n // Unsubscribe from env changes\n if (this.envChangeUnsubscribe) {\n this.envChangeUnsubscribe();\n this.envChangeUnsubscribe = null;\n }\n\n // Dispose env manager\n this.envManager.dispose();\n\n // Stop task list if still running\n if (this.taskList) {\n await this.taskList.stop(timeout);\n }\n\n // Stop all cron processes in parallel\n const cronStopPromises = Array.from(this.cronProcesses.values()).map((p) => p.stop(timeout));\n\n // Stop all restarting processes in parallel\n const restartingStopPromises = Array.from(this.restartingProcesses.values()).map((p) =>\n p.stop(timeout),\n );\n\n await Promise.all([...cronStopPromises, ...restartingStopPromises]);\n\n this._state = \"stopped\";\n this.logger.info(`Manager stopped`);\n\n this.unregisterShutdownHandlers();\n }\n\n /**\n * Register signal handlers for graceful shutdown\n * Called automatically by constructor\n */\n private registerShutdownHandlers(): void {\n if (this.signalHandlers.size > 0) {\n this.logger.warn(`Shutdown handlers already registered`);\n return;\n }\n\n for (const signal of SHUTDOWN_SIGNALS) {\n const handler = () => this.handleSignal(signal);\n this.signalHandlers.set(signal, handler);\n process.on(signal, handler);\n this.logger.debug(`Registered handler for ${signal}`);\n }\n\n this.logger.info(`Shutdown handlers registered for signals: ${SHUTDOWN_SIGNALS.join(\", \")}`);\n }\n\n /**\n * Unregister signal handlers for graceful shutdown\n */\n private unregisterShutdownHandlers(): void {\n if (this.signalHandlers.size === 0) {\n return;\n }\n\n for (const [signal, handler] of this.signalHandlers.entries()) {\n process.off(signal, handler);\n this.logger.debug(`Unregistered handler for ${signal}`);\n }\n\n this.signalHandlers.clear();\n }\n\n /**\n * Wait for shutdown to complete (useful for keeping process alive)\n * Resolves when the manager has fully stopped\n */\n async waitForShutdown(): Promise<void> {\n // If already stopped, return immediately\n if (this._state === \"stopped\") {\n return;\n }\n\n // If shutdown is in progress, wait for it\n if (this.shutdownPromise) {\n await this.shutdownPromise;\n return;\n }\n\n // Wait for state to become stopped\n return new Promise((resolve) => {\n const checkInterval = setInterval(() => {\n if (this._state === \"stopped\") {\n clearInterval(checkInterval);\n resolve();\n }\n }, 100);\n });\n }\n\n /**\n * Trigger graceful shutdown programmatically\n */\n async shutdown(): Promise<void> {\n if (this.isShuttingDown) {\n this.logger.warn(`Shutdown already in progress`);\n if (this.shutdownPromise) {\n await this.shutdownPromise;\n }\n return;\n }\n\n this.isShuttingDown = true;\n this.logger.info(`Initiating graceful shutdown (timeout: ${SHUTDOWN_TIMEOUT_MS}ms)`);\n\n this.shutdownPromise = this.performShutdown();\n await this.shutdownPromise;\n }\n\n private handleSignal(signal: NodeJS.Signals): void {\n this.logger.info(`Received ${signal}, initiating graceful shutdown...`);\n\n // Prevent handling multiple signals\n if (this.isShuttingDown) {\n this.logger.warn(`Shutdown already in progress, ignoring ${signal}`);\n return;\n }\n\n this.isShuttingDown = true;\n this.shutdownPromise = this.performShutdown();\n\n this.shutdownPromise\n .then(() => {\n this.logger.info(`Exiting with code ${SHUTDOWN_EXIT_CODE}`);\n process.exit(SHUTDOWN_EXIT_CODE);\n })\n .catch((err) => {\n this.logger.error(`Shutdown error:`, err);\n process.exit(1);\n });\n }\n\n private async performShutdown(): Promise<void> {\n // Create a timeout promise\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => {\n reject(new Error(`Shutdown timed out after ${SHUTDOWN_TIMEOUT_MS}ms`));\n }, SHUTDOWN_TIMEOUT_MS);\n });\n\n try {\n // Race between graceful stop and timeout\n await Promise.race([this.stop(SHUTDOWN_TIMEOUT_MS), timeoutPromise]);\n this.logger.info(`Graceful shutdown completed`);\n } catch (err) {\n this.logger.error(`Shutdown error:`, err);\n // Force stop on timeout\n this._state = \"stopped\";\n throw err;\n } finally {\n this.isShuttingDown = false;\n this.shutdownPromise = null;\n }\n }\n}\n","#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport { createServer } from \"node:http\";\nimport { pathToFileURL } from \"node:url\";\nimport { resolve } from \"node:path\";\nimport { RPCHandler } from \"@orpc/server/node\";\nimport { onError } from \"@orpc/server\";\nimport * as v from \"valibot\";\nimport { router } from \"./api/server.ts\";\nimport { Manager, ManagerConfigSchema } from \"./manager.ts\";\nimport { logger } from \"./logger.ts\";\nimport { tsImport } from \"tsx/esm/api\";\nimport Table from \"cli-table3\";\nimport { createClient } from \"./api/client.ts\";\nimport { ProcessDefinitionSchema } from \"./api/contract.ts\";\n\nconst program = new Command();\n\nprogram\n .name(\"pidnap\")\n .description(\"Process manager with init system capabilities\")\n .version(\"0.0.0-dev.1\");\n\nprogram\n .command(\"init\")\n .description(\"Initialize and run the process manager with config file\")\n .option(\"-c, --config <path>\", \"Path to config file\", \"pidnap.config.ts\")\n .action(async (options) => {\n const initLogger = logger({ name: \"pidnap\" });\n try {\n // Resolve config file path\n const configPath = resolve(process.cwd(), options.config);\n const configUrl = pathToFileURL(configPath).href;\n\n // Import the config file\n const configModule = await tsImport(configUrl, { parentURL: import.meta.url });\n const rawConfig =\n configModule.default.default || configModule.default || configModule.config || {};\n\n // Parse and validate the config with Valibot\n const config = v.parse(ManagerConfigSchema, rawConfig);\n\n // Extract HTTP config with defaults\n const host = config.http?.host ?? \"localhost\";\n const port = config.http?.port ?? 3000;\n const authToken = config.http?.authToken;\n\n // Create manager with config\n const logDir = config.logDir ?? resolve(process.cwd(), \"logs\");\n const managerLogger = logger({ name: \"pidnap\", logFile: resolve(logDir, \"pidnap.log\") });\n const manager = new Manager(config, managerLogger);\n\n // Setup ORPC server with optional auth token middleware\n const handler = new RPCHandler(router, {\n interceptors: [\n onError((error) => {\n managerLogger.error(error);\n }),\n ],\n });\n\n const server = createServer(async (req, res) => {\n // Check auth token if configured\n if (authToken) {\n const providedToken = req.headers[\"authorization\"]?.replace(\"Bearer \", \"\");\n if (providedToken !== authToken) {\n res.statusCode = 401;\n res.end(\"Unauthorized\");\n return;\n }\n }\n\n const { matched } = await handler.handle(req, res, {\n prefix: \"/rpc\",\n context: { manager },\n });\n if (matched) return;\n res.statusCode = 404;\n res.end(\"Not found\");\n });\n\n server.listen(port, host, async () => {\n managerLogger.info(`pidnap RPC server running on http://${host}:${port}`);\n if (authToken) {\n managerLogger.info(\"Auth token required for API access\");\n }\n\n try {\n await manager.start();\n } catch (err) {\n managerLogger.error(\"Failed to start manager:\", err);\n server.close();\n process.exit(1);\n }\n });\n\n // Wait for shutdown\n await manager.waitForShutdown();\n\n // Close server on shutdown\n server.close();\n } catch (error) {\n initLogger.error(\"Failed to start pidnap:\", error);\n process.exit(1);\n }\n });\n\nprogram\n .command(\"status\")\n .description(\"Show manager status\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (options) => {\n try {\n const client = createClient(options.url);\n const status = await client.manager.status();\n\n const table = new Table({ head: [\"State\", \"Processes\", \"Crons\", \"Tasks\"] });\n table.push([status.state, status.processCount, status.cronCount, status.taskCount]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to fetch status:\", error);\n process.exit(1);\n }\n });\n\nconst processes = program.command(\"processes\").description(\"Manage restarting processes\");\n\nprocesses\n .command(\"list\")\n .description(\"List restarting processes\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (options) => {\n try {\n const client = createClient(options.url);\n const processes = await client.processes.list();\n\n const table = new Table({ head: [\"Name\", \"State\", \"Restarts\"] });\n for (const proc of processes) {\n table.push([proc.name, proc.state, proc.restarts]);\n }\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to list processes:\", error);\n process.exit(1);\n }\n });\n\nprocesses\n .command(\"get\")\n .description(\"Get a restarting process by name or index\")\n .argument(\"<target>\", \"Process name or index\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (target, options) => {\n try {\n const client = createClient(options.url);\n const proc = await client.processes.get({ target: parseTarget(target) });\n\n const table = new Table({ head: [\"Name\", \"State\", \"Restarts\"] });\n table.push([proc.name, proc.state, proc.restarts]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to get process:\", error);\n process.exit(1);\n }\n });\n\nprocesses\n .command(\"add\")\n .description(\"Add a restarting process\")\n .requiredOption(\"-n, --name <name>\", \"Process name\")\n .requiredOption(\"-d, --definition <json>\", \"Process definition JSON\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (options) => {\n try {\n const client = createClient(options.url);\n const definition = parseDefinition(options.definition);\n const proc = await client.processes.add({ name: options.name, definition });\n\n const table = new Table({ head: [\"Name\", \"State\", \"Restarts\"] });\n table.push([proc.name, proc.state, proc.restarts]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to add process:\", error);\n process.exit(1);\n }\n });\n\nprocesses\n .command(\"start\")\n .description(\"Start a restarting process\")\n .argument(\"<target>\", \"Process name or index\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (target, options) => {\n try {\n const client = createClient(options.url);\n const proc = await client.processes.start({ target: parseTarget(target) });\n\n const table = new Table({ head: [\"Name\", \"State\", \"Restarts\"] });\n table.push([proc.name, proc.state, proc.restarts]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to start process:\", error);\n process.exit(1);\n }\n });\n\nprocesses\n .command(\"stop\")\n .description(\"Stop a restarting process\")\n .argument(\"<target>\", \"Process name or index\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (target, options) => {\n try {\n const client = createClient(options.url);\n const proc = await client.processes.stop({ target: parseTarget(target) });\n\n const table = new Table({ head: [\"Name\", \"State\", \"Restarts\"] });\n table.push([proc.name, proc.state, proc.restarts]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to stop process:\", error);\n process.exit(1);\n }\n });\n\nprocesses\n .command(\"restart\")\n .description(\"Restart a restarting process\")\n .argument(\"<target>\", \"Process name or index\")\n .option(\"-f, --force\", \"Force restart\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (target, options) => {\n try {\n const client = createClient(options.url);\n const proc = await client.processes.restart({\n target: parseTarget(target),\n force: options.force,\n });\n\n const table = new Table({ head: [\"Name\", \"State\", \"Restarts\"] });\n table.push([proc.name, proc.state, proc.restarts]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to restart process:\", error);\n process.exit(1);\n }\n });\n\nprocesses\n .command(\"remove\")\n .description(\"Remove a restarting process\")\n .argument(\"<target>\", \"Process name or index\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (target, options) => {\n try {\n const client = createClient(options.url);\n await client.processes.remove({ target: parseTarget(target) });\n console.log(\"Process removed\");\n } catch (error) {\n console.error(\"Failed to remove process:\", error);\n process.exit(1);\n }\n });\n\nconst crons = program.command(\"crons\").description(\"Manage cron processes\");\n\ncrons\n .command(\"list\")\n .description(\"List cron processes\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (options) => {\n try {\n const client = createClient(options.url);\n const crons = await client.crons.list();\n\n const table = new Table({ head: [\"Name\", \"State\", \"Runs\", \"Fails\", \"Next Run\"] });\n for (const cron of crons) {\n table.push([cron.name, cron.state, cron.runCount, cron.failCount, cron.nextRun ?? \"-\"]);\n }\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to list crons:\", error);\n process.exit(1);\n }\n });\n\ncrons\n .command(\"get\")\n .description(\"Get a cron process by name or index\")\n .argument(\"<target>\", \"Cron name or index\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (target, options) => {\n try {\n const client = createClient(options.url);\n const cron = await client.crons.get({ target: parseTarget(target) });\n\n const table = new Table({ head: [\"Name\", \"State\", \"Runs\", \"Fails\", \"Next Run\"] });\n table.push([cron.name, cron.state, cron.runCount, cron.failCount, cron.nextRun ?? \"-\"]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to get cron:\", error);\n process.exit(1);\n }\n });\n\ncrons\n .command(\"trigger\")\n .description(\"Trigger a cron process\")\n .argument(\"<target>\", \"Cron name or index\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (target, options) => {\n try {\n const client = createClient(options.url);\n const cron = await client.crons.trigger({ target: parseTarget(target) });\n\n const table = new Table({ head: [\"Name\", \"State\", \"Runs\", \"Fails\", \"Next Run\"] });\n table.push([cron.name, cron.state, cron.runCount, cron.failCount, cron.nextRun ?? \"-\"]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to trigger cron:\", error);\n process.exit(1);\n }\n });\n\ncrons\n .command(\"start\")\n .description(\"Start a cron process\")\n .argument(\"<target>\", \"Cron name or index\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (target, options) => {\n try {\n const client = createClient(options.url);\n const cron = await client.crons.start({ target: parseTarget(target) });\n\n const table = new Table({ head: [\"Name\", \"State\", \"Runs\", \"Fails\", \"Next Run\"] });\n table.push([cron.name, cron.state, cron.runCount, cron.failCount, cron.nextRun ?? \"-\"]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to start cron:\", error);\n process.exit(1);\n }\n });\n\ncrons\n .command(\"stop\")\n .description(\"Stop a cron process\")\n .argument(\"<target>\", \"Cron name or index\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (target, options) => {\n try {\n const client = createClient(options.url);\n const cron = await client.crons.stop({ target: parseTarget(target) });\n\n const table = new Table({ head: [\"Name\", \"State\", \"Runs\", \"Fails\", \"Next Run\"] });\n table.push([cron.name, cron.state, cron.runCount, cron.failCount, cron.nextRun ?? \"-\"]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to stop cron:\", error);\n process.exit(1);\n }\n });\n\nconst tasks = program.command(\"tasks\").description(\"Manage tasks\");\n\ntasks\n .command(\"list\")\n .description(\"List tasks\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (options) => {\n try {\n const client = createClient(options.url);\n const tasks = await client.tasks.list();\n\n const table = new Table({ head: [\"Id\", \"State\", \"Processes\"] });\n for (const task of tasks) {\n table.push([task.id, task.state, task.processNames.join(\", \")]);\n }\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to list tasks:\", error);\n process.exit(1);\n }\n });\n\ntasks\n .command(\"get\")\n .description(\"Get a task by id or index\")\n .argument(\"<target>\", \"Task id or index\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (target, options) => {\n try {\n const client = createClient(options.url);\n const task = await client.tasks.get({ target: parseTarget(target) });\n\n const table = new Table({ head: [\"Id\", \"State\", \"Processes\"] });\n table.push([task.id, task.state, task.processNames.join(\", \")]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to get task:\", error);\n process.exit(1);\n }\n });\n\ntasks\n .command(\"add\")\n .description(\"Add a task\")\n .requiredOption(\"-n, --name <name>\", \"Task name\")\n .requiredOption(\"-d, --definition <json>\", \"Process definition JSON\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (options) => {\n try {\n const client = createClient(options.url);\n const definition = parseDefinition(options.definition);\n const task = await client.tasks.add({ name: options.name, definition });\n\n const table = new Table({ head: [\"Id\", \"State\", \"Processes\"] });\n table.push([task.id, task.state, task.processNames.join(\", \")]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to add task:\", error);\n process.exit(1);\n }\n });\n\ntasks\n .command(\"remove\")\n .description(\"Remove a task by id or index\")\n .argument(\"<target>\", \"Task id or index\")\n .option(\"-u, --url <url>\", \"RPC server URL\", \"http://localhost:3000/rpc\")\n .action(async (target, options) => {\n try {\n const client = createClient(options.url);\n const task = await client.tasks.remove({ target: parseTarget(target) });\n\n const table = new Table({ head: [\"Id\", \"State\", \"Processes\"] });\n table.push([task.id, task.state, task.processNames.join(\", \")]);\n console.log(table.toString());\n } catch (error) {\n console.error(\"Failed to remove task:\", error);\n process.exit(1);\n }\n });\n\nconst TargetSchema = v.union([v.string(), v.number()]);\ntype ProcessDefinition = v.InferOutput<typeof ProcessDefinitionSchema>;\n\nfunction parseTarget(value: string): string | number {\n const asNumber = Number(value);\n return v.parse(TargetSchema, Number.isNaN(asNumber) ? value : asNumber);\n}\n\nfunction parseDefinition(raw: string): ProcessDefinition {\n try {\n const parsed = JSON.parse(raw);\n return v.parse(ProcessDefinitionSchema, parsed);\n } catch (error) {\n console.error(\"Invalid --definition JSON. Expected a ProcessDefinition.\");\n throw error;\n }\n}\n\nprogram.parse();\n"],"mappings":"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"}
package/dist/index.d.mts CHANGED
@@ -69,6 +69,7 @@ declare const ManagerConfigSchema: v.ObjectSchema<{
69
69
  }, undefined>, undefined>;
70
70
  readonly envFile: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
71
71
  readonly envReloadDelay: v.OptionalSchema<v.UnionSchema<[v.NumberSchema<undefined>, v.BooleanSchema<undefined>, v.LiteralSchema<"immediately", undefined>], undefined>, undefined>;
72
+ readonly port: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
72
73
  }, undefined>, undefined>, undefined>;
73
74
  }, undefined>;
74
75
  type ManagerConfig = v.InferOutput<typeof ManagerConfigSchema>;
@@ -145,6 +146,15 @@ declare class EnvManager {
145
146
  getAllEnv(): ReadonlyMap<string, Record<string, string>>;
146
147
  }
147
148
  //#endregion
149
+ //#region src/tree-kill.d.ts
150
+ /**
151
+ * Kill a process and all its descendants (children, grandchildren, etc.)
152
+ * @param pid - The process ID to kill
153
+ * @param signal - The signal to send (default: SIGTERM)
154
+ * @returns Promise that resolves when all processes have been signaled
155
+ */
156
+ declare function treeKill(pid: number, signal?: NodeJS.Signals): Promise<void>;
157
+ //#endregion
148
158
  //#region src/index.d.ts
149
159
  declare function defineConfig(config: ManagerConfig): {
150
160
  http?: {
@@ -223,8 +233,9 @@ declare function defineConfig(config: ManagerConfig): {
223
233
  } | undefined;
224
234
  envFile?: string | undefined;
225
235
  envReloadDelay?: number | boolean | "immediately" | undefined;
236
+ port?: number | undefined;
226
237
  }[] | undefined;
227
238
  };
228
239
  //#endregion
229
- export { BackoffStrategy, BackoffStrategySchema, CrashLoopConfig, CrashLoopConfigSchema, CronProcess, CronProcessOptions, CronProcessOptionsSchema, CronProcessState, CronProcessStateSchema, EnvChangeCallback, EnvManager, EnvManagerConfig, LazyProcess, Logger, NamedProcessDefinition, NamedProcessDefinitionSchema, ProcessDefinition, ProcessDefinitionSchema, ProcessState, ProcessStateSchema, RestartPolicy, RestartPolicySchema, RestartingProcess, RestartingProcessOptions, RestartingProcessOptionsSchema, RestartingProcessState, RestartingProcessStateSchema, RetryConfig, RetryConfigSchema, TaskEntry, TaskList, TaskListState, TaskState, TaskStateSchema, defineConfig, logger };
240
+ export { BackoffStrategy, BackoffStrategySchema, CrashLoopConfig, CrashLoopConfigSchema, CronProcess, CronProcessOptions, CronProcessOptionsSchema, CronProcessState, CronProcessStateSchema, EnvChangeCallback, EnvManager, EnvManagerConfig, LazyProcess, Logger, NamedProcessDefinition, NamedProcessDefinitionSchema, ProcessDefinition, ProcessDefinitionSchema, ProcessState, ProcessStateSchema, RestartPolicy, RestartPolicySchema, RestartingProcess, RestartingProcessOptions, RestartingProcessOptionsSchema, RestartingProcessState, RestartingProcessStateSchema, RetryConfig, RetryConfigSchema, TaskEntry, TaskList, TaskListState, TaskState, TaskStateSchema, defineConfig, logger, treeKill };
230
241
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/manager.ts","../src/env-manager.ts","../src/index.ts"],"mappings":";;;;cA8Da,mBAAA,EAAmB,CAAA,CAAA,YAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAWpB,aAAA,GAAgB,CAAA,CAAE,WAAA,QAAmB,mBAAA;;;KCpErC,iBAAA,IAAqB,WAAA;AAAA,UAEhB,gBAAA;;;ADuDjB;;EClDE,GAAA;;;;;;EAOA,KAAA,GAAQ,MAAA;;;;;EAMR,KAAA;AAAA;AAAA,cAGW,UAAA;EAAA,QACH,GAAA;EAAA,QACA,GAAA;EAAA,QACA,YAAA;EAAA,QACA,QAAA;EAAA,QACA,UAAA;EAAA,QACA,eAAA;EAAA,QACA,oBAAA;cAEI,MAAA,GAAQ,gBAAA;EAepB,YAAA,CAAa,GAAA,UAAa,QAAA;EAI1B,YAAA,CAAa,GAAA,WAAc,MAAA;;;;UAOnB,mBAAA;;;;UA6BA,WAAA;;;;UA8BA,SAAA;;;;UAiBA,gBAAA;;;;UAmBA,UAAA;;;;;EA6BR,QAAA,CAAS,QAAA,EAAU,iBAAA;;;;EAUnB,OAAA,CAAA;;;;;;EAsBA,UAAA,CAAW,UAAA,YAAsB,MAAA;;;;EAcjC,SAAA,CAAA,GAAa,WAAA,SAAoB,MAAA;AAAA;;;iBCvOnB,YAAA,CAAa,MAAA,EAAQ,aAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/manager.ts","../src/env-manager.ts","../src/tree-kill.ts","../src/index.ts"],"mappings":";;;;cAgEa,mBAAA,EAAmB,CAAA,CAAA,YAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAWpB,aAAA,GAAgB,CAAA,CAAE,WAAA,QAAmB,mBAAA;;;KCtErC,iBAAA,IAAqB,WAAA;AAAA,UAEhB,gBAAA;;;ADyDjB;;ECpDE,GAAA;;;;;;EAOA,KAAA,GAAQ,MAAA;;;;;EAMR,KAAA;AAAA;AAAA,cAGW,UAAA;EAAA,QACH,GAAA;EAAA,QACA,GAAA;EAAA,QACA,YAAA;EAAA,QACA,QAAA;EAAA,QACA,UAAA;EAAA,QACA,eAAA;EAAA,QACA,oBAAA;cAEI,MAAA,GAAQ,gBAAA;EAepB,YAAA,CAAa,GAAA,UAAa,QAAA;EAI1B,YAAA,CAAa,GAAA,WAAc,MAAA;;;;UAOnB,mBAAA;;;;UA6BA,WAAA;;;;UA8BA,SAAA;;;;UAiBA,gBAAA;;;;UAmBA,UAAA;;;;;EA6BR,QAAA,CAAS,QAAA,EAAU,iBAAA;;;;EAUnB,OAAA,CAAA;;;;;;EAsBA,UAAA,CAAW,UAAA,YAAsB,MAAA;;;;EAcjC,SAAA,CAAA,GAAa,WAAA,SAAoB,MAAA;AAAA;;;;;;;ADzKnC;;iBEtDsB,QAAA,CAAS,GAAA,UAAa,MAAA,GAAQ,MAAA,CAAO,OAAA,GAAsB,OAAA;;;iBCRjE,YAAA,CAAa,MAAA,EAAQ,aAAA"}
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { _ as ProcessDefinitionSchema, a as TaskStateSchema, c as CronProcessStateSchema, d as CrashLoopConfigSchema, f as RestartPolicySchema, g as LazyProcess, h as RestartingProcessStateSchema, i as TaskList, l as RetryConfigSchema, m as RestartingProcessOptionsSchema, n as EnvManager, o as CronProcess, p as RestartingProcess, r as NamedProcessDefinitionSchema, s as CronProcessOptionsSchema, t as logger, u as BackoffStrategySchema, v as ProcessStateSchema } from "./logger-crc5neL8.mjs";
1
+ import { _ as ProcessDefinitionSchema, a as TaskStateSchema, c as CronProcessStateSchema, d as CrashLoopConfigSchema, f as RestartPolicySchema, g as LazyProcess, h as RestartingProcessStateSchema, i as TaskList, l as RetryConfigSchema, m as RestartingProcessOptionsSchema, n as EnvManager, o as CronProcess, p as RestartingProcess, r as NamedProcessDefinitionSchema, s as CronProcessOptionsSchema, t as logger, u as BackoffStrategySchema, v as ProcessStateSchema, y as treeKill } from "./logger-BF3KrCIK.mjs";
2
2
 
3
3
  //#region src/index.ts
4
4
  function defineConfig(config) {
@@ -6,5 +6,5 @@ function defineConfig(config) {
6
6
  }
7
7
 
8
8
  //#endregion
9
- export { BackoffStrategySchema, CrashLoopConfigSchema, CronProcess, CronProcessOptionsSchema, CronProcessStateSchema, EnvManager, LazyProcess, NamedProcessDefinitionSchema, ProcessDefinitionSchema, ProcessStateSchema, RestartPolicySchema, RestartingProcess, RestartingProcessOptionsSchema, RestartingProcessStateSchema, RetryConfigSchema, TaskList, TaskStateSchema, defineConfig, logger };
9
+ export { BackoffStrategySchema, CrashLoopConfigSchema, CronProcess, CronProcessOptionsSchema, CronProcessStateSchema, EnvManager, LazyProcess, NamedProcessDefinitionSchema, ProcessDefinitionSchema, ProcessStateSchema, RestartPolicySchema, RestartingProcess, RestartingProcessOptionsSchema, RestartingProcessStateSchema, RetryConfigSchema, TaskList, TaskStateSchema, defineConfig, logger, treeKill };
10
10
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { ManagerConfig } from \"./manager.ts\";\n\nexport function defineConfig(config: ManagerConfig) {\n return config;\n}\n\nexport * from \"./restarting-process.ts\";\nexport * from \"./cron-process.ts\";\nexport * from \"./task-list.ts\";\nexport * from \"./lazy-process.ts\";\nexport * from \"./env-manager.ts\";\nexport * from \"./logger.ts\";\n"],"mappings":";;;AAEA,SAAgB,aAAa,QAAuB;AAClD,QAAO"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { ManagerConfig } from \"./manager.ts\";\n\nexport function defineConfig(config: ManagerConfig) {\n return config;\n}\n\nexport * from \"./restarting-process.ts\";\nexport * from \"./cron-process.ts\";\nexport * from \"./task-list.ts\";\nexport * from \"./lazy-process.ts\";\nexport * from \"./env-manager.ts\";\nexport * from \"./logger.ts\";\nexport * from \"./tree-kill.ts\";\n"],"mappings":";;;AAEA,SAAgB,aAAa,QAAuB;AAClD,QAAO"}