@doriandev/devcc 0.1.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.
Files changed (284) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +659 -0
  3. package/bin/devcc.mjs +66 -0
  4. package/dist/devcc/app/App.d.ts +178 -0
  5. package/dist/devcc/app/App.d.ts.map +1 -0
  6. package/dist/devcc/app/App.js +1255 -0
  7. package/dist/devcc/app/App.js.map +1 -0
  8. package/dist/devcc/app/builtinCommands.d.ts +17 -0
  9. package/dist/devcc/app/builtinCommands.d.ts.map +1 -0
  10. package/dist/devcc/app/builtinCommands.js +389 -0
  11. package/dist/devcc/app/builtinCommands.js.map +1 -0
  12. package/dist/devcc/app/keymap.d.ts +21 -0
  13. package/dist/devcc/app/keymap.d.ts.map +1 -0
  14. package/dist/devcc/app/keymap.js +162 -0
  15. package/dist/devcc/app/keymap.js.map +1 -0
  16. package/dist/devcc/app/theme.d.ts +49 -0
  17. package/dist/devcc/app/theme.d.ts.map +1 -0
  18. package/dist/devcc/app/theme.js +68 -0
  19. package/dist/devcc/app/theme.js.map +1 -0
  20. package/dist/devcc/cli.d.ts +3 -0
  21. package/dist/devcc/cli.d.ts.map +1 -0
  22. package/dist/devcc/cli.js +113 -0
  23. package/dist/devcc/cli.js.map +1 -0
  24. package/dist/devcc/components/CommandPalette.d.ts +26 -0
  25. package/dist/devcc/components/CommandPalette.d.ts.map +1 -0
  26. package/dist/devcc/components/CommandPalette.js +113 -0
  27. package/dist/devcc/components/CommandPalette.js.map +1 -0
  28. package/dist/devcc/components/ConfirmDialog.d.ts +31 -0
  29. package/dist/devcc/components/ConfirmDialog.d.ts.map +1 -0
  30. package/dist/devcc/components/ConfirmDialog.js +147 -0
  31. package/dist/devcc/components/ConfirmDialog.js.map +1 -0
  32. package/dist/devcc/components/Footer.d.ts +22 -0
  33. package/dist/devcc/components/Footer.d.ts.map +1 -0
  34. package/dist/devcc/components/Footer.js +72 -0
  35. package/dist/devcc/components/Footer.js.map +1 -0
  36. package/dist/devcc/components/Header.d.ts +12 -0
  37. package/dist/devcc/components/Header.d.ts.map +1 -0
  38. package/dist/devcc/components/Header.js +84 -0
  39. package/dist/devcc/components/Header.js.map +1 -0
  40. package/dist/devcc/components/HelpOverlay.d.ts +18 -0
  41. package/dist/devcc/components/HelpOverlay.d.ts.map +1 -0
  42. package/dist/devcc/components/HelpOverlay.js +48 -0
  43. package/dist/devcc/components/HelpOverlay.js.map +1 -0
  44. package/dist/devcc/components/Overlay.d.ts +31 -0
  45. package/dist/devcc/components/Overlay.d.ts.map +1 -0
  46. package/dist/devcc/components/Overlay.js +60 -0
  47. package/dist/devcc/components/Overlay.js.map +1 -0
  48. package/dist/devcc/components/ProjectPicker.d.ts +26 -0
  49. package/dist/devcc/components/ProjectPicker.d.ts.map +1 -0
  50. package/dist/devcc/components/ProjectPicker.js +114 -0
  51. package/dist/devcc/components/ProjectPicker.js.map +1 -0
  52. package/dist/devcc/components/Sidebar.d.ts +42 -0
  53. package/dist/devcc/components/Sidebar.d.ts.map +1 -0
  54. package/dist/devcc/components/Sidebar.js +127 -0
  55. package/dist/devcc/components/Sidebar.js.map +1 -0
  56. package/dist/devcc/components/StatusBadge.d.ts +16 -0
  57. package/dist/devcc/components/StatusBadge.d.ts.map +1 -0
  58. package/dist/devcc/components/StatusBadge.js +30 -0
  59. package/dist/devcc/components/StatusBadge.js.map +1 -0
  60. package/dist/devcc/components/primitives.d.ts +62 -0
  61. package/dist/devcc/components/primitives.d.ts.map +1 -0
  62. package/dist/devcc/components/primitives.js +169 -0
  63. package/dist/devcc/components/primitives.js.map +1 -0
  64. package/dist/devcc/components/styled.d.ts +16 -0
  65. package/dist/devcc/components/styled.d.ts.map +1 -0
  66. package/dist/devcc/components/styled.js +35 -0
  67. package/dist/devcc/components/styled.js.map +1 -0
  68. package/dist/devcc/core/commands.d.ts +89 -0
  69. package/dist/devcc/core/commands.d.ts.map +1 -0
  70. package/dist/devcc/core/commands.js +68 -0
  71. package/dist/devcc/core/commands.js.map +1 -0
  72. package/dist/devcc/core/config.d.ts +81 -0
  73. package/dist/devcc/core/config.d.ts.map +1 -0
  74. package/dist/devcc/core/config.js +313 -0
  75. package/dist/devcc/core/config.js.map +1 -0
  76. package/dist/devcc/core/events.d.ts +21 -0
  77. package/dist/devcc/core/events.d.ts.map +1 -0
  78. package/dist/devcc/core/events.js +27 -0
  79. package/dist/devcc/core/events.js.map +1 -0
  80. package/dist/devcc/core/state.d.ts +104 -0
  81. package/dist/devcc/core/state.d.ts.map +1 -0
  82. package/dist/devcc/core/state.js +139 -0
  83. package/dist/devcc/core/state.js.map +1 -0
  84. package/dist/devcc/deps/DependencyService.d.ts +50 -0
  85. package/dist/devcc/deps/DependencyService.d.ts.map +1 -0
  86. package/dist/devcc/deps/DependencyService.js +109 -0
  87. package/dist/devcc/deps/DependencyService.js.map +1 -0
  88. package/dist/devcc/deps/parse.d.ts +49 -0
  89. package/dist/devcc/deps/parse.d.ts.map +1 -0
  90. package/dist/devcc/deps/parse.js +158 -0
  91. package/dist/devcc/deps/parse.js.map +1 -0
  92. package/dist/devcc/git/GitService.d.ts +60 -0
  93. package/dist/devcc/git/GitService.d.ts.map +1 -0
  94. package/dist/devcc/git/GitService.js +160 -0
  95. package/dist/devcc/git/GitService.js.map +1 -0
  96. package/dist/devcc/git/parse.d.ts +57 -0
  97. package/dist/devcc/git/parse.d.ts.map +1 -0
  98. package/dist/devcc/git/parse.js +174 -0
  99. package/dist/devcc/git/parse.js.map +1 -0
  100. package/dist/devcc/index.d.ts +37 -0
  101. package/dist/devcc/index.d.ts.map +1 -0
  102. package/dist/devcc/index.js +36 -0
  103. package/dist/devcc/index.js.map +1 -0
  104. package/dist/devcc/logs/LogBuffer.d.ts +86 -0
  105. package/dist/devcc/logs/LogBuffer.d.ts.map +1 -0
  106. package/dist/devcc/logs/LogBuffer.js +200 -0
  107. package/dist/devcc/logs/LogBuffer.js.map +1 -0
  108. package/dist/devcc/logs/merge.d.ts +36 -0
  109. package/dist/devcc/logs/merge.d.ts.map +1 -0
  110. package/dist/devcc/logs/merge.js +71 -0
  111. package/dist/devcc/logs/merge.js.map +1 -0
  112. package/dist/devcc/processes/ManagedProcess.d.ts +129 -0
  113. package/dist/devcc/processes/ManagedProcess.d.ts.map +1 -0
  114. package/dist/devcc/processes/ManagedProcess.js +80 -0
  115. package/dist/devcc/processes/ManagedProcess.js.map +1 -0
  116. package/dist/devcc/processes/ProcessManager.d.ts +112 -0
  117. package/dist/devcc/processes/ProcessManager.d.ts.map +1 -0
  118. package/dist/devcc/processes/ProcessManager.js +525 -0
  119. package/dist/devcc/processes/ProcessManager.js.map +1 -0
  120. package/dist/devcc/processes/graph.d.ts +35 -0
  121. package/dist/devcc/processes/graph.d.ts.map +1 -0
  122. package/dist/devcc/processes/graph.js +68 -0
  123. package/dist/devcc/processes/graph.js.map +1 -0
  124. package/dist/devcc/projects/ProjectRegistry.d.ts +52 -0
  125. package/dist/devcc/projects/ProjectRegistry.d.ts.map +1 -0
  126. package/dist/devcc/projects/ProjectRegistry.js +177 -0
  127. package/dist/devcc/projects/ProjectRegistry.js.map +1 -0
  128. package/dist/devcc/services/ServiceManager.d.ts +48 -0
  129. package/dist/devcc/services/ServiceManager.d.ts.map +1 -0
  130. package/dist/devcc/services/ServiceManager.js +146 -0
  131. package/dist/devcc/services/ServiceManager.js.map +1 -0
  132. package/dist/devcc/services/docker.d.ts +37 -0
  133. package/dist/devcc/services/docker.d.ts.map +1 -0
  134. package/dist/devcc/services/docker.js +179 -0
  135. package/dist/devcc/services/docker.js.map +1 -0
  136. package/dist/devcc/services/node.d.ts +40 -0
  137. package/dist/devcc/services/node.d.ts.map +1 -0
  138. package/dist/devcc/services/node.js +107 -0
  139. package/dist/devcc/services/node.js.map +1 -0
  140. package/dist/devcc/services/ollama.d.ts +27 -0
  141. package/dist/devcc/services/ollama.d.ts.map +1 -0
  142. package/dist/devcc/services/ollama.js +66 -0
  143. package/dist/devcc/services/ollama.js.map +1 -0
  144. package/dist/devcc/services/postgres.d.ts +30 -0
  145. package/dist/devcc/services/postgres.d.ts.map +1 -0
  146. package/dist/devcc/services/postgres.js +47 -0
  147. package/dist/devcc/services/postgres.js.map +1 -0
  148. package/dist/devcc/services/redis.d.ts +20 -0
  149. package/dist/devcc/services/redis.d.ts.map +1 -0
  150. package/dist/devcc/services/redis.js +39 -0
  151. package/dist/devcc/services/redis.js.map +1 -0
  152. package/dist/devcc/services/types.d.ts +51 -0
  153. package/dist/devcc/services/types.d.ts.map +1 -0
  154. package/dist/devcc/services/types.js +10 -0
  155. package/dist/devcc/services/types.js.map +1 -0
  156. package/dist/devcc/system/SystemMonitor.d.ts +87 -0
  157. package/dist/devcc/system/SystemMonitor.d.ts.map +1 -0
  158. package/dist/devcc/system/SystemMonitor.js +142 -0
  159. package/dist/devcc/system/SystemMonitor.js.map +1 -0
  160. package/dist/devcc/utils/errors.d.ts +31 -0
  161. package/dist/devcc/utils/errors.d.ts.map +1 -0
  162. package/dist/devcc/utils/errors.js +52 -0
  163. package/dist/devcc/utils/errors.js.map +1 -0
  164. package/dist/devcc/utils/exec.d.ts +41 -0
  165. package/dist/devcc/utils/exec.d.ts.map +1 -0
  166. package/dist/devcc/utils/exec.js +112 -0
  167. package/dist/devcc/utils/exec.js.map +1 -0
  168. package/dist/devcc/utils/format.d.ts +18 -0
  169. package/dist/devcc/utils/format.d.ts.map +1 -0
  170. package/dist/devcc/utils/format.js +85 -0
  171. package/dist/devcc/utils/format.js.map +1 -0
  172. package/dist/devcc/utils/fuzzy.d.ts +12 -0
  173. package/dist/devcc/utils/fuzzy.d.ts.map +1 -0
  174. package/dist/devcc/utils/fuzzy.js +20 -0
  175. package/dist/devcc/utils/fuzzy.js.map +1 -0
  176. package/dist/devcc/utils/logger.d.ts +41 -0
  177. package/dist/devcc/utils/logger.d.ts.map +1 -0
  178. package/dist/devcc/utils/logger.js +117 -0
  179. package/dist/devcc/utils/logger.js.map +1 -0
  180. package/dist/devcc/utils/packageManager.d.ts +39 -0
  181. package/dist/devcc/utils/packageManager.d.ts.map +1 -0
  182. package/dist/devcc/utils/packageManager.js +85 -0
  183. package/dist/devcc/utils/packageManager.js.map +1 -0
  184. package/dist/devcc/utils/paths.d.ts +12 -0
  185. package/dist/devcc/utils/paths.d.ts.map +1 -0
  186. package/dist/devcc/utils/paths.js +39 -0
  187. package/dist/devcc/utils/paths.js.map +1 -0
  188. package/dist/devcc/views/DependenciesView.d.ts +34 -0
  189. package/dist/devcc/views/DependenciesView.d.ts.map +1 -0
  190. package/dist/devcc/views/DependenciesView.js +170 -0
  191. package/dist/devcc/views/DependenciesView.js.map +1 -0
  192. package/dist/devcc/views/GitView.d.ts +29 -0
  193. package/dist/devcc/views/GitView.d.ts.map +1 -0
  194. package/dist/devcc/views/GitView.js +226 -0
  195. package/dist/devcc/views/GitView.js.map +1 -0
  196. package/dist/devcc/views/LogsView.d.ts +39 -0
  197. package/dist/devcc/views/LogsView.d.ts.map +1 -0
  198. package/dist/devcc/views/LogsView.js +249 -0
  199. package/dist/devcc/views/LogsView.js.map +1 -0
  200. package/dist/devcc/views/OverviewView.d.ts +16 -0
  201. package/dist/devcc/views/OverviewView.d.ts.map +1 -0
  202. package/dist/devcc/views/OverviewView.js +135 -0
  203. package/dist/devcc/views/OverviewView.js.map +1 -0
  204. package/dist/devcc/views/ProcessesView.d.ts +26 -0
  205. package/dist/devcc/views/ProcessesView.d.ts.map +1 -0
  206. package/dist/devcc/views/ProcessesView.js +161 -0
  207. package/dist/devcc/views/ProcessesView.js.map +1 -0
  208. package/dist/devcc/views/ScriptsView.d.ts +30 -0
  209. package/dist/devcc/views/ScriptsView.d.ts.map +1 -0
  210. package/dist/devcc/views/ScriptsView.js +168 -0
  211. package/dist/devcc/views/ScriptsView.js.map +1 -0
  212. package/dist/devcc/views/ServicesView.d.ts +28 -0
  213. package/dist/devcc/views/ServicesView.d.ts.map +1 -0
  214. package/dist/devcc/views/ServicesView.js +153 -0
  215. package/dist/devcc/views/ServicesView.js.map +1 -0
  216. package/dist/devcc/views/SettingsView.d.ts +20 -0
  217. package/dist/devcc/views/SettingsView.d.ts.map +1 -0
  218. package/dist/devcc/views/SettingsView.js +114 -0
  219. package/dist/devcc/views/SettingsView.js.map +1 -0
  220. package/dist/devcc/views/SystemView.d.ts +13 -0
  221. package/dist/devcc/views/SystemView.d.ts.map +1 -0
  222. package/dist/devcc/views/SystemView.js +82 -0
  223. package/dist/devcc/views/SystemView.js.map +1 -0
  224. package/dist/devcc/views/View.d.ts +35 -0
  225. package/dist/devcc/views/View.d.ts.map +1 -0
  226. package/dist/devcc/views/View.js +42 -0
  227. package/dist/devcc/views/View.js.map +1 -0
  228. package/package.json +79 -0
  229. package/src/devcc/app/App.ts +1463 -0
  230. package/src/devcc/app/builtinCommands.ts +429 -0
  231. package/src/devcc/app/keymap.ts +167 -0
  232. package/src/devcc/app/theme.ts +83 -0
  233. package/src/devcc/cli.ts +122 -0
  234. package/src/devcc/components/CommandPalette.ts +136 -0
  235. package/src/devcc/components/ConfirmDialog.ts +174 -0
  236. package/src/devcc/components/Footer.ts +85 -0
  237. package/src/devcc/components/Header.ts +93 -0
  238. package/src/devcc/components/HelpOverlay.ts +62 -0
  239. package/src/devcc/components/Overlay.ts +91 -0
  240. package/src/devcc/components/ProjectPicker.ts +138 -0
  241. package/src/devcc/components/Sidebar.ts +163 -0
  242. package/src/devcc/components/StatusBadge.ts +36 -0
  243. package/src/devcc/components/primitives.ts +213 -0
  244. package/src/devcc/components/styled.ts +44 -0
  245. package/src/devcc/core/commands.ts +140 -0
  246. package/src/devcc/core/config.ts +405 -0
  247. package/src/devcc/core/events.ts +41 -0
  248. package/src/devcc/core/state.ts +236 -0
  249. package/src/devcc/deps/DependencyService.ts +152 -0
  250. package/src/devcc/deps/parse.ts +210 -0
  251. package/src/devcc/git/GitService.ts +205 -0
  252. package/src/devcc/git/parse.ts +203 -0
  253. package/src/devcc/index.ts +115 -0
  254. package/src/devcc/logs/LogBuffer.ts +237 -0
  255. package/src/devcc/logs/merge.ts +87 -0
  256. package/src/devcc/processes/ManagedProcess.ts +195 -0
  257. package/src/devcc/processes/ProcessManager.ts +625 -0
  258. package/src/devcc/processes/graph.ts +98 -0
  259. package/src/devcc/projects/ProjectRegistry.ts +219 -0
  260. package/src/devcc/services/ServiceManager.ts +180 -0
  261. package/src/devcc/services/docker.ts +220 -0
  262. package/src/devcc/services/node.ts +137 -0
  263. package/src/devcc/services/ollama.ts +80 -0
  264. package/src/devcc/services/postgres.ts +57 -0
  265. package/src/devcc/services/redis.ts +47 -0
  266. package/src/devcc/services/types.ts +59 -0
  267. package/src/devcc/system/SystemMonitor.ts +207 -0
  268. package/src/devcc/utils/errors.ts +64 -0
  269. package/src/devcc/utils/exec.ts +165 -0
  270. package/src/devcc/utils/format.ts +83 -0
  271. package/src/devcc/utils/fuzzy.ts +44 -0
  272. package/src/devcc/utils/logger.ts +140 -0
  273. package/src/devcc/utils/packageManager.ts +112 -0
  274. package/src/devcc/utils/paths.ts +39 -0
  275. package/src/devcc/views/DependenciesView.ts +206 -0
  276. package/src/devcc/views/GitView.ts +259 -0
  277. package/src/devcc/views/LogsView.ts +300 -0
  278. package/src/devcc/views/OverviewView.ts +187 -0
  279. package/src/devcc/views/ProcessesView.ts +177 -0
  280. package/src/devcc/views/ScriptsView.ts +187 -0
  281. package/src/devcc/views/ServicesView.ts +188 -0
  282. package/src/devcc/views/SettingsView.ts +146 -0
  283. package/src/devcc/views/SystemView.ts +110 -0
  284. package/src/devcc/views/View.ts +63 -0
@@ -0,0 +1,525 @@
1
+ import { spawn } from "node:child_process";
2
+ import { isAbsolute, resolve } from "node:path";
3
+ import { TypedEmitter } from "../core/events.js";
4
+ import { DevccError, errorMessage } from "../utils/errors.js";
5
+ import { probeTcpPort } from "../utils/exec.js";
6
+ import { planStartOrder } from "./graph.js";
7
+ import { canTransition, crashBackoffDelay, createManagedProcess, DEFAULT_CRASH_POLICY, DEFAULT_READINESS, describeCommand, isActive, shouldAutoRestart, } from "./ManagedProcess.js";
8
+ export const DEFAULT_KILL_GRACE_MS = 5_000;
9
+ /**
10
+ * Owns every child process devcc launches.
11
+ *
12
+ * Design notes:
13
+ * - Commands are always `spawn(executable, args[])`; nothing is ever passed to a
14
+ * shell, so arguments containing spaces or quotes are safe by construction.
15
+ * - Children are spawned `detached`, which makes each one a process-group leader.
16
+ * Stopping signals the whole group (`kill(-pgid)`) so dev servers that fork
17
+ * workers do not leave orphans behind.
18
+ * - Stopping escalates SIGTERM -> SIGKILL after a grace period.
19
+ */
20
+ export class ProcessManager extends TypedEmitter {
21
+ definitions = new Map();
22
+ snapshots = new Map();
23
+ runtimes = new Map();
24
+ /** Pending automatic-restart timers, keyed by process id. */
25
+ retryTimers = new Map();
26
+ /** In-flight readiness checks, so a stop can cancel the probe loop. */
27
+ readiness = new Map();
28
+ logs;
29
+ logger;
30
+ rootDir;
31
+ baseEnv;
32
+ disposed = false;
33
+ constructor(options) {
34
+ super();
35
+ this.logs = options.logs;
36
+ this.logger = options.logger;
37
+ this.rootDir = options.rootDir;
38
+ this.baseEnv = options.env ?? process.env;
39
+ }
40
+ /** Register (or replace, while stopped) a process definition. */
41
+ register(definition) {
42
+ const existing = this.snapshots.get(definition.id);
43
+ if (existing && isActive(existing.status)) {
44
+ this.definitions.set(definition.id, definition);
45
+ return existing;
46
+ }
47
+ this.definitions.set(definition.id, definition);
48
+ const snapshot = createManagedProcess(definition);
49
+ this.snapshots.set(definition.id, snapshot);
50
+ this.logs.register(definition.id, definition.name);
51
+ this.emit("process:list", this.list());
52
+ return snapshot;
53
+ }
54
+ registerAll(definitions) {
55
+ for (const definition of definitions)
56
+ this.register(definition);
57
+ }
58
+ /** Remove a stopped process. Refuses while it is still running. */
59
+ unregister(id) {
60
+ const snapshot = this.snapshots.get(id);
61
+ if (snapshot && isActive(snapshot.status)) {
62
+ throw new DevccError({ scope: "process", message: `Cannot remove "${id}" while it is running` });
63
+ }
64
+ this.definitions.delete(id);
65
+ this.snapshots.delete(id);
66
+ this.logs.unregister(id);
67
+ this.emit("process:list", this.list());
68
+ }
69
+ list() {
70
+ return [...this.snapshots.values()];
71
+ }
72
+ get(id) {
73
+ return this.snapshots.get(id);
74
+ }
75
+ getDefinition(id) {
76
+ return this.definitions.get(id);
77
+ }
78
+ isRunning(id) {
79
+ const snapshot = this.snapshots.get(id);
80
+ return snapshot ? isActive(snapshot.status) : false;
81
+ }
82
+ /**
83
+ * Start a process.
84
+ *
85
+ * A start the user asked for clears the crash budget; the automatic restart
86
+ * path passes `auto` so a crash loop cannot refill its own budget.
87
+ */
88
+ async start(id, options = {}) {
89
+ const definition = this.definitions.get(id);
90
+ const snapshot = this.snapshots.get(id);
91
+ if (!definition || !snapshot) {
92
+ throw new DevccError({ scope: "process", message: `Unknown process "${id}"` });
93
+ }
94
+ this.cancelRetry(id);
95
+ if (isActive(snapshot.status))
96
+ return snapshot;
97
+ if (this.disposed) {
98
+ throw new DevccError({ scope: "process", message: "Shutting down; refusing to start new processes" });
99
+ }
100
+ this.update(id, {
101
+ status: "starting",
102
+ exitCode: undefined,
103
+ exitSignal: undefined,
104
+ lastError: undefined,
105
+ ...(options.auto ? {} : { crashRestarts: 0, crashRestartsExhausted: false }),
106
+ });
107
+ const cwd = definition.cwd ? resolveCwd(this.rootDir, definition.cwd) : this.rootDir;
108
+ const buffer = this.logs.register(id, definition.name);
109
+ buffer.push(`$ ${describeCommand({ command: definition.command, args: definition.args })}`, "system");
110
+ let child;
111
+ try {
112
+ child = spawn(definition.command, definition.args ? [...definition.args] : [], {
113
+ cwd,
114
+ env: { ...this.baseEnv, ...definition.env, FORCE_COLOR: definition.env?.FORCE_COLOR ?? "0" },
115
+ stdio: ["ignore", "pipe", "pipe"],
116
+ // Own process group so we can signal the whole tree on stop.
117
+ detached: process.platform !== "win32",
118
+ windowsHide: true,
119
+ });
120
+ }
121
+ catch (error) {
122
+ const message = `Failed to start ${definition.name}: ${errorMessage(error)}`;
123
+ this.update(id, { status: "failed", lastError: message });
124
+ const devccError = new DevccError({ scope: "process", message, cause: error });
125
+ this.emit("process:error", devccError);
126
+ throw devccError;
127
+ }
128
+ let resolveExit = () => { };
129
+ const exitPromise = new Promise((resolve) => {
130
+ resolveExit = resolve;
131
+ });
132
+ const runtime = {
133
+ child,
134
+ pgid: child.pid !== undefined && process.platform !== "win32" ? child.pid : null,
135
+ killTimer: null,
136
+ exitPromise,
137
+ resolveExit,
138
+ };
139
+ this.runtimes.set(id, runtime);
140
+ child.stdout?.setEncoding("utf8");
141
+ child.stdout?.on("data", (chunk) => this.logs.appendChunk(id, chunk, "stdout"));
142
+ child.stderr?.setEncoding("utf8");
143
+ child.stderr?.on("data", (chunk) => this.logs.appendChunk(id, chunk, "stderr"));
144
+ child.once("error", (error) => {
145
+ const message = `${definition.name}: ${error.message}`;
146
+ this.logs.append(id, message, "stderr");
147
+ this.update(id, { status: "failed", lastError: message, pid: undefined });
148
+ this.finishRuntime(id);
149
+ this.emit("process:error", new DevccError({ scope: "process", message, cause: error }));
150
+ });
151
+ child.once("exit", (code, signal) => {
152
+ this.handleExit(id, code, signal);
153
+ });
154
+ this.update(id, {
155
+ pid: child.pid,
156
+ startedAt: new Date(),
157
+ stoppedAt: undefined,
158
+ ready: false,
159
+ readinessTimedOut: false,
160
+ });
161
+ this.logger.info("process started", { id, pid: child.pid, cwd });
162
+ if (definition.readiness) {
163
+ // Stay in `starting` until the check passes; `running` means usable.
164
+ this.beginReadinessCheck(id, definition.readiness);
165
+ }
166
+ else {
167
+ this.markReady(id, false);
168
+ }
169
+ const started = this.snapshots.get(id);
170
+ if (started)
171
+ this.emit("process:started", started);
172
+ return started ?? snapshot;
173
+ }
174
+ /**
175
+ * Resolve once the process is ready (readiness passed or timed out), or
176
+ * immediately if it is not starting. Used to sequence dependent starts.
177
+ */
178
+ async waitForReady(id) {
179
+ const pending = this.readiness.get(id);
180
+ if (pending)
181
+ await pending.done;
182
+ return this.snapshots.get(id);
183
+ }
184
+ /**
185
+ * Start several processes honouring `dependsOn`: each wave waits for the
186
+ * previous one to become ready. Failures in one wave are reported and the
187
+ * next wave still starts, since an unrelated process should not be blocked.
188
+ */
189
+ async startAll(ids) {
190
+ const plan = planStartOrder([...this.definitions.values()], ids);
191
+ for (const edge of plan.missing) {
192
+ this.logs.append(edge.id, `dependsOn "${edge.dependsOn}" is not a known process; ignoring`, "stderr");
193
+ }
194
+ if (plan.cycle.length > 0) {
195
+ this.emit("process:error", new DevccError({
196
+ scope: "process",
197
+ message: `Dependency cycle between ${plan.cycle.join(", ")}; not starting them`,
198
+ }));
199
+ }
200
+ for (const wave of plan.waves) {
201
+ const targets = wave.filter((id) => {
202
+ const snapshot = this.snapshots.get(id);
203
+ return snapshot && !isActive(snapshot.status);
204
+ });
205
+ await Promise.all(targets.map(async (id) => {
206
+ try {
207
+ await this.start(id);
208
+ }
209
+ catch (error) {
210
+ this.logger.warn("start failed", { id, error: errorMessage(error) });
211
+ }
212
+ }));
213
+ // Wait for the whole wave (including ones already running) before moving on.
214
+ await Promise.all(wave.map((id) => this.waitForReady(id)));
215
+ }
216
+ return plan;
217
+ }
218
+ beginReadinessCheck(id, check) {
219
+ this.cancelReadiness(id);
220
+ const timeoutMs = check.timeoutMs ?? DEFAULT_READINESS.timeoutMs;
221
+ const intervalMs = check.intervalMs ?? DEFAULT_READINESS.intervalMs;
222
+ let cancelled = false;
223
+ let settle = () => { };
224
+ const done = new Promise((resolve) => {
225
+ settle = resolve;
226
+ });
227
+ const finish = (timedOut) => {
228
+ if (cancelled)
229
+ return;
230
+ cancelled = true;
231
+ this.readiness.delete(id);
232
+ if (logListener)
233
+ this.logs.off("log:append", logListener);
234
+ clearTimeout(timer);
235
+ if (this.isActiveRuntime(id))
236
+ this.markReady(id, timedOut);
237
+ settle();
238
+ };
239
+ // --- log pattern -------------------------------------------------------
240
+ let logListener = null;
241
+ if (check.logPattern) {
242
+ let pattern = null;
243
+ try {
244
+ pattern = new RegExp(check.logPattern, "iu");
245
+ }
246
+ catch {
247
+ this.logs.append(id, `readiness.logPattern is not a valid regex: ${check.logPattern}`, "stderr");
248
+ }
249
+ if (pattern) {
250
+ const matcher = pattern;
251
+ logListener = (sourceId, entries) => {
252
+ if (sourceId !== id)
253
+ return;
254
+ if (entries.some((entry) => matcher.test(entry.text)))
255
+ finish(false);
256
+ };
257
+ this.logs.on("log:append", logListener);
258
+ }
259
+ }
260
+ // --- port probe --------------------------------------------------------
261
+ const probe = async () => {
262
+ while (!cancelled) {
263
+ if (check.port &&
264
+ (await probeTcpPort(check.port, check.host ?? "127.0.0.1", Math.min(intervalMs, 700)))) {
265
+ finish(false);
266
+ return;
267
+ }
268
+ if (!check.port && !logListener) {
269
+ // Nothing to wait for after all.
270
+ finish(false);
271
+ return;
272
+ }
273
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
274
+ }
275
+ };
276
+ const timer = setTimeout(() => {
277
+ this.logs.append(id, `Readiness check timed out after ${timeoutMs}ms; reporting as running`, "stderr");
278
+ finish(true);
279
+ }, timeoutMs);
280
+ timer.unref?.();
281
+ this.readiness.set(id, { cancel: () => finish(false), done });
282
+ void probe();
283
+ }
284
+ cancelReadiness(id) {
285
+ const pending = this.readiness.get(id);
286
+ if (!pending)
287
+ return;
288
+ this.readiness.delete(id);
289
+ pending.cancel();
290
+ }
291
+ isActiveRuntime(id) {
292
+ const snapshot = this.snapshots.get(id);
293
+ return this.runtimes.has(id) && snapshot?.status === "starting";
294
+ }
295
+ markReady(id, timedOut) {
296
+ this.update(id, { status: "running", ready: true, readinessTimedOut: timedOut });
297
+ const snapshot = this.snapshots.get(id);
298
+ if (snapshot) {
299
+ if (!timedOut && this.definitions.get(id)?.readiness)
300
+ this.logs.append(id, "Ready", "system");
301
+ this.emit("process:ready", snapshot);
302
+ }
303
+ }
304
+ /**
305
+ * Stop a managed process and everything it spawned.
306
+ * Resolves once the child has actually exited (or the grace period elapsed).
307
+ */
308
+ async stop(id, graceMs) {
309
+ const snapshot = this.snapshots.get(id);
310
+ const runtime = this.runtimes.get(id);
311
+ if (!snapshot)
312
+ throw new DevccError({ scope: "process", message: `Unknown process "${id}"` });
313
+ if (snapshot.ownership !== "managed") {
314
+ throw new DevccError({
315
+ scope: "process",
316
+ message: `"${snapshot.name}" was detected, not launched by devcc - refusing to signal it`,
317
+ });
318
+ }
319
+ // A manual stop cancels any pending automatic restart and clears the
320
+ // crash budget: the user is now in charge of this process.
321
+ this.cancelRetry(id);
322
+ this.cancelReadiness(id);
323
+ this.update(id, { crashRestarts: 0, retryAt: undefined, crashRestartsExhausted: false });
324
+ if (!runtime || !isActive(snapshot.status))
325
+ return;
326
+ this.update(id, { status: "stopping" });
327
+ this.logs.append(id, "Stopping…", "system");
328
+ const grace = graceMs ?? this.definitions.get(id)?.killGraceMs ?? DEFAULT_KILL_GRACE_MS;
329
+ this.signal(runtime, "SIGTERM");
330
+ runtime.killTimer = setTimeout(() => {
331
+ if (this.runtimes.has(id)) {
332
+ this.logs.append(id, "Grace period elapsed, sending SIGKILL", "system");
333
+ this.signal(runtime, "SIGKILL");
334
+ }
335
+ }, grace);
336
+ runtime.killTimer.unref?.();
337
+ await runtime.exitPromise;
338
+ }
339
+ async restart(id) {
340
+ const snapshot = this.snapshots.get(id);
341
+ if (!snapshot)
342
+ throw new DevccError({ scope: "process", message: `Unknown process "${id}"` });
343
+ this.cancelRetry(id);
344
+ if (isActive(snapshot.status))
345
+ await this.stop(id);
346
+ const restarted = await this.start(id);
347
+ this.update(id, { restarts: (this.snapshots.get(id)?.restarts ?? 0) + 1 });
348
+ return this.snapshots.get(id) ?? restarted;
349
+ }
350
+ /** Start every definition marked `autoStart`. Failures are reported, not thrown. */
351
+ async startAutoStart() {
352
+ const targets = [...this.definitions.values()].filter((definition) => definition.autoStart);
353
+ if (targets.length === 0)
354
+ return;
355
+ await this.startAll(targets.map((definition) => definition.id));
356
+ }
357
+ /**
358
+ * Stop everything devcc launched. Called on shutdown; never touches processes
359
+ * that were only detected.
360
+ */
361
+ async stopAll(graceMs = DEFAULT_KILL_GRACE_MS) {
362
+ this.disposed = true;
363
+ for (const id of [...this.retryTimers.keys()])
364
+ this.cancelRetry(id);
365
+ const running = this.list().filter((snapshot) => isActive(snapshot.status));
366
+ await Promise.all(running.map(async (snapshot) => {
367
+ try {
368
+ await this.stop(snapshot.id, graceMs);
369
+ }
370
+ catch (error) {
371
+ this.logger.warn("stop failed during shutdown", { id: snapshot.id, error: errorMessage(error) });
372
+ }
373
+ }));
374
+ }
375
+ handleExit(id, code, signal) {
376
+ this.cancelReadiness(id);
377
+ this.logs.flush(id);
378
+ const snapshot = this.snapshots.get(id);
379
+ const wasStopping = snapshot?.status === "stopping";
380
+ const kind = snapshot?.kind ?? "service";
381
+ const failed = !wasStopping && code !== 0 && code !== null;
382
+ const nextStatus = failed ? "failed" : "stopped";
383
+ this.logs.append(id, signal ? `Exited via ${signal}` : `Exited with code ${code ?? "unknown"}`, failed ? "stderr" : "system");
384
+ // A run that lasted long enough counts as healthy and clears the budget.
385
+ const definition = this.definitions.get(id);
386
+ const ranFor = snapshot?.startedAt ? Date.now() - snapshot.startedAt.getTime() : 0;
387
+ const healthyAfter = definition?.healthyAfterMs ?? DEFAULT_CRASH_POLICY.healthyAfterMs;
388
+ const wasHealthy = ranFor >= healthyAfter;
389
+ const crashRestarts = failed ? (wasHealthy ? 0 : (snapshot?.crashRestarts ?? 0)) : 0;
390
+ this.update(id, {
391
+ status: nextStatus,
392
+ pid: undefined,
393
+ exitCode: code ?? undefined,
394
+ exitSignal: signal ?? undefined,
395
+ stoppedAt: new Date(),
396
+ crashRestarts,
397
+ retryAt: undefined,
398
+ ready: false,
399
+ lastError: failed ? `${snapshot?.name ?? id} exited with code ${code ?? "?"}` : undefined,
400
+ });
401
+ this.finishRuntime(id);
402
+ const updated = this.snapshots.get(id);
403
+ if (updated) {
404
+ this.logger.info("process exited", { id, code, signal, kind });
405
+ this.emit("process:exit", updated);
406
+ if (failed)
407
+ this.considerAutoRestart(id);
408
+ if (failed) {
409
+ this.emit("process:error", new DevccError({
410
+ scope: "process",
411
+ message: `${updated.name} exited with code ${code ?? "?"}`,
412
+ detail: `Command: ${describeCommand(updated)}`,
413
+ }));
414
+ }
415
+ }
416
+ }
417
+ /**
418
+ * Schedule an automatic restart for a crashed process, if its definition opted
419
+ * in and it still has budget left. Backoff doubles per consecutive crash, so a
420
+ * process that is broken rather than flaky stops thrashing quickly.
421
+ */
422
+ considerAutoRestart(id) {
423
+ if (this.disposed)
424
+ return;
425
+ const definition = this.definitions.get(id);
426
+ const snapshot = this.snapshots.get(id);
427
+ if (!definition || !snapshot)
428
+ return;
429
+ if (!definition.restartOnCrash)
430
+ return;
431
+ if (!shouldAutoRestart(definition, snapshot)) {
432
+ if (!snapshot.crashRestartsExhausted) {
433
+ this.update(id, { crashRestartsExhausted: true });
434
+ this.logs.append(id, `Giving up after ${snapshot.crashRestarts} automatic restarts`, "system");
435
+ this.emit("process:error", new DevccError({
436
+ scope: "process",
437
+ message: `${definition.name} keeps crashing; automatic restarts exhausted`,
438
+ detail: `Last exit code ${snapshot.exitCode ?? "?"}. Start it manually to try again.`,
439
+ }));
440
+ }
441
+ return;
442
+ }
443
+ const attempt = snapshot.crashRestarts + 1;
444
+ const delay = crashBackoffDelay(attempt, definition.crashBackoffMs, definition.maxCrashBackoffMs);
445
+ const retryAt = new Date(Date.now() + delay);
446
+ this.update(id, { crashRestarts: attempt, retryAt, crashRestartsExhausted: false });
447
+ this.logs.append(id, `Restarting automatically in ${Math.round(delay / 100) / 10}s (attempt ${attempt})`, "system");
448
+ const updated = this.snapshots.get(id);
449
+ if (updated)
450
+ this.emit("process:retry", updated, delay);
451
+ const timer = setTimeout(() => {
452
+ this.retryTimers.delete(id);
453
+ if (this.disposed)
454
+ return;
455
+ // The user may have started or removed it while we waited.
456
+ const current = this.snapshots.get(id);
457
+ if (!current || isActive(current.status))
458
+ return;
459
+ this.update(id, { retryAt: undefined });
460
+ void this.start(id, { auto: true }).catch((error) => {
461
+ this.logger.warn("automatic restart failed", { id, error: errorMessage(error) });
462
+ });
463
+ }, delay);
464
+ timer.unref?.();
465
+ this.retryTimers.set(id, timer);
466
+ }
467
+ cancelRetry(id) {
468
+ const timer = this.retryTimers.get(id);
469
+ if (!timer)
470
+ return;
471
+ clearTimeout(timer);
472
+ this.retryTimers.delete(id);
473
+ this.update(id, { retryAt: undefined });
474
+ }
475
+ finishRuntime(id) {
476
+ const runtime = this.runtimes.get(id);
477
+ if (!runtime)
478
+ return;
479
+ if (runtime.killTimer)
480
+ clearTimeout(runtime.killTimer);
481
+ this.runtimes.delete(id);
482
+ runtime.resolveExit();
483
+ }
484
+ /** Signal the child's process group when we have one, else the child alone. */
485
+ signal(runtime, signal) {
486
+ const { child, pgid } = runtime;
487
+ try {
488
+ if (pgid !== null) {
489
+ process.kill(-pgid, signal);
490
+ return;
491
+ }
492
+ }
493
+ catch (error) {
494
+ const code = error.code;
495
+ // ESRCH: the group is already gone. Anything else: fall back to the child.
496
+ if (code === "ESRCH")
497
+ return;
498
+ }
499
+ try {
500
+ child.kill(signal);
501
+ }
502
+ catch {
503
+ // The process is already gone.
504
+ }
505
+ }
506
+ update(id, patch) {
507
+ const current = this.snapshots.get(id);
508
+ if (!current)
509
+ return;
510
+ if (patch.status && patch.status !== current.status && !canTransition(current.status, patch.status)) {
511
+ this.logger.debug("ignored illegal status transition", { id, from: current.status, to: patch.status });
512
+ const { status: _ignored, ...rest } = patch;
513
+ if (Object.keys(rest).length === 0)
514
+ return;
515
+ patch = rest;
516
+ }
517
+ const next = { ...current, ...patch };
518
+ this.snapshots.set(id, next);
519
+ this.emit("process:changed", next);
520
+ }
521
+ }
522
+ function resolveCwd(rootDir, cwd) {
523
+ return isAbsolute(cwd) ? cwd : resolve(rootDir, cwd);
524
+ }
525
+ //# sourceMappingURL=ProcessManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProcessManager.js","sourceRoot":"","sources":["../../../src/devcc/processes/ProcessManager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import type { ProcessDefinition } from "./ManagedProcess.js";
2
+ /**
3
+ * Dependency ordering for `dependsOn`.
4
+ *
5
+ * Pure so the ordering rules can be tested without spawning anything: the
6
+ * manager only has to execute the waves this produces.
7
+ */
8
+ export interface StartPlan {
9
+ /**
10
+ * Processes to start, grouped into waves. Everything in a wave can start
11
+ * concurrently; wave N+1 waits for wave N to become ready.
12
+ */
13
+ waves: string[][];
14
+ /** Edges pointing at ids that were never defined. */
15
+ missing: {
16
+ id: string;
17
+ dependsOn: string;
18
+ }[];
19
+ /** Ids that form a dependency cycle, if any. Their waves are omitted. */
20
+ cycle: string[];
21
+ }
22
+ /**
23
+ * Group ids into dependency waves (Kahn's algorithm).
24
+ *
25
+ * Unknown dependencies are reported and then ignored, so one typo cannot stop
26
+ * the rest of the project from starting. A cycle is reported rather than
27
+ * guessed at - devcc refuses to pick an arbitrary order.
28
+ */
29
+ export declare function planStartOrder(definitions: readonly ProcessDefinition[], only?: readonly string[]): StartPlan;
30
+ /**
31
+ * Ids that must be stopped before `id` can be, i.e. everything depending on it,
32
+ * transitively. Used to stop a stack from the top down.
33
+ */
34
+ export declare function dependentsOf(definitions: readonly ProcessDefinition[], id: string): string[];
35
+ //# sourceMappingURL=graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../../src/devcc/processes/graph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAE5D;;;;;GAKG;AAEH,MAAM,WAAW,SAAS;IACxB;;;OAGG;IACH,KAAK,EAAE,MAAM,EAAE,EAAE,CAAA;IACjB,qDAAqD;IACrD,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAC5C,yEAAyE;IACzE,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,SAAS,iBAAiB,EAAE,EACzC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,GACvB,SAAS,CA2CX;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,SAAS,iBAAiB,EAAE,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,CAiB5F"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Group ids into dependency waves (Kahn's algorithm).
3
+ *
4
+ * Unknown dependencies are reported and then ignored, so one typo cannot stop
5
+ * the rest of the project from starting. A cycle is reported rather than
6
+ * guessed at - devcc refuses to pick an arbitrary order.
7
+ */
8
+ export function planStartOrder(definitions, only) {
9
+ const byId = new Map(definitions.map((definition) => [definition.id, definition]));
10
+ const selected = new Set(only ?? definitions.map((definition) => definition.id));
11
+ // Only consider selected ids that actually exist.
12
+ const ids = [...selected].filter((id) => byId.has(id));
13
+ const missing = [];
14
+ const dependencies = new Map();
15
+ for (const id of ids) {
16
+ const declared = byId.get(id)?.dependsOn ?? [];
17
+ const resolved = new Set();
18
+ for (const dependency of declared) {
19
+ if (!byId.has(dependency)) {
20
+ missing.push({ id, dependsOn: dependency });
21
+ continue;
22
+ }
23
+ // A dependency outside the selection is still a real edge, but it cannot
24
+ // gate a start we were not asked to perform.
25
+ if (ids.includes(dependency))
26
+ resolved.add(dependency);
27
+ }
28
+ dependencies.set(id, resolved);
29
+ }
30
+ const waves = [];
31
+ const placed = new Set();
32
+ while (placed.size < ids.length) {
33
+ const wave = ids
34
+ .filter((id) => !placed.has(id))
35
+ .filter((id) => [...(dependencies.get(id) ?? [])].every((dependency) => placed.has(dependency)));
36
+ if (wave.length === 0) {
37
+ // Everything left depends on something unplaced: that is a cycle.
38
+ return { waves, missing, cycle: ids.filter((id) => !placed.has(id)).sort() };
39
+ }
40
+ for (const id of wave)
41
+ placed.add(id);
42
+ waves.push(wave);
43
+ }
44
+ return { waves, missing, cycle: [] };
45
+ }
46
+ /**
47
+ * Ids that must be stopped before `id` can be, i.e. everything depending on it,
48
+ * transitively. Used to stop a stack from the top down.
49
+ */
50
+ export function dependentsOf(definitions, id) {
51
+ const direct = new Map();
52
+ for (const definition of definitions) {
53
+ for (const dependency of definition.dependsOn ?? []) {
54
+ direct.set(dependency, [...(direct.get(dependency) ?? []), definition.id]);
55
+ }
56
+ }
57
+ const found = new Set();
58
+ const queue = [...(direct.get(id) ?? [])];
59
+ while (queue.length > 0) {
60
+ const next = queue.shift();
61
+ if (!next || found.has(next))
62
+ continue;
63
+ found.add(next);
64
+ queue.push(...(direct.get(next) ?? []));
65
+ }
66
+ return [...found].sort();
67
+ }
68
+ //# sourceMappingURL=graph.js.map