@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,179 @@
1
+ import { existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { DevccError } from "../utils/errors.js";
4
+ import { exec } from "../utils/exec.js";
5
+ const COMPOSE_FILES = [
6
+ "docker-compose.yml",
7
+ "docker-compose.yaml",
8
+ "compose.yml",
9
+ "compose.yaml",
10
+ "docker/docker-compose.yml",
11
+ ];
12
+ export function findComposeFile(rootDir, exists = existsSync) {
13
+ for (const file of COMPOSE_FILES) {
14
+ if (exists(join(rootDir, file)))
15
+ return file;
16
+ }
17
+ return null;
18
+ }
19
+ /**
20
+ * `docker compose ps --format json` emits either a JSON array or one JSON
21
+ * object per line depending on the CLI version. Handle both.
22
+ */
23
+ export function parseComposePs(output) {
24
+ const trimmed = output.trim();
25
+ if (trimmed === "")
26
+ return [];
27
+ const entries = [];
28
+ if (trimmed.startsWith("[")) {
29
+ try {
30
+ const parsed = JSON.parse(trimmed);
31
+ if (Array.isArray(parsed))
32
+ entries.push(...parsed);
33
+ }
34
+ catch {
35
+ return [];
36
+ }
37
+ }
38
+ else {
39
+ for (const line of trimmed.split("\n")) {
40
+ if (line.trim() === "")
41
+ continue;
42
+ try {
43
+ entries.push(JSON.parse(line));
44
+ }
45
+ catch {
46
+ // Skip malformed lines rather than losing the whole listing.
47
+ }
48
+ }
49
+ }
50
+ return entries.map((entry) => {
51
+ const name = entry.Service ?? entry.Name ?? "container";
52
+ const ports = (entry.Publishers ?? [])
53
+ .map((publisher) => publisher.PublishedPort)
54
+ .filter((port) => typeof port === "number" && port > 0);
55
+ const detail = [entry.Status, ports.length > 0 ? `:${[...new Set(ports)].join(",")}` : null]
56
+ .filter(Boolean)
57
+ .join(" ");
58
+ return { name, state: composeState(entry), detail: detail || undefined };
59
+ });
60
+ }
61
+ function composeState(entry) {
62
+ const health = entry.Health?.toLowerCase();
63
+ if (health === "unhealthy" || health === "starting")
64
+ return "degraded";
65
+ switch (entry.State?.toLowerCase()) {
66
+ case "running":
67
+ return "running";
68
+ case "restarting":
69
+ case "paused":
70
+ return "degraded";
71
+ case "exited":
72
+ case "dead":
73
+ case "created":
74
+ return "stopped";
75
+ default:
76
+ return "unknown";
77
+ }
78
+ }
79
+ /**
80
+ * Docker / Docker Compose adapter.
81
+ *
82
+ * `stop` runs `docker compose stop` (not `down`): stopping must never remove
83
+ * containers, networks or volumes without an explicit confirmation.
84
+ */
85
+ export class DockerService {
86
+ options;
87
+ id = "docker";
88
+ name = "Docker Compose";
89
+ category = "container";
90
+ composeFile;
91
+ timeoutMs;
92
+ constructor(options) {
93
+ this.options = options;
94
+ this.composeFile = findComposeFile(options.rootDir);
95
+ this.timeoutMs = options.timeoutMs ?? 6_000;
96
+ }
97
+ get hasCompose() {
98
+ return this.composeFile !== null;
99
+ }
100
+ async detect() {
101
+ this.composeFile = findComposeFile(this.options.rootDir);
102
+ const result = await exec("docker", ["--version"], { timeoutMs: 3_000 });
103
+ return result.spawnError === undefined;
104
+ }
105
+ async getStatus() {
106
+ const checkedAt = new Date();
107
+ const info = await exec("docker", ["info", "--format", "{{.ServerVersion}}"], {
108
+ cwd: this.options.rootDir,
109
+ timeoutMs: this.timeoutMs,
110
+ });
111
+ if (!info.ok) {
112
+ return {
113
+ state: "unavailable",
114
+ detail: info.spawnError ? "docker not installed" : "daemon unreachable",
115
+ checkedAt,
116
+ };
117
+ }
118
+ const serverVersion = info.stdout.trim();
119
+ if (!this.composeFile) {
120
+ return { state: "running", detail: `daemon ${serverVersion}`, checkedAt };
121
+ }
122
+ const ps = await exec("docker", ["compose", "ps", "--all", "--format", "json"], {
123
+ cwd: this.options.rootDir,
124
+ timeoutMs: this.timeoutMs,
125
+ });
126
+ if (!ps.ok) {
127
+ return { state: "degraded", detail: `daemon ${serverVersion}, compose ps failed`, checkedAt };
128
+ }
129
+ const items = parseComposePs(ps.stdout);
130
+ const running = items.filter((item) => item.state === "running").length;
131
+ const state = items.length === 0 ? "stopped" : running === items.length ? "running" : "degraded";
132
+ return {
133
+ state,
134
+ detail: items.length === 0 ? `no containers (${this.composeFile})` : `${running}/${items.length} running`,
135
+ items,
136
+ checkedAt,
137
+ };
138
+ }
139
+ async start() {
140
+ this.requireCompose();
141
+ await this.compose(["up", "--detach"], 120_000);
142
+ }
143
+ async stop() {
144
+ this.requireCompose();
145
+ // `stop`, never `down` - see the class comment.
146
+ await this.compose(["stop"], 60_000);
147
+ }
148
+ async restart() {
149
+ this.requireCompose();
150
+ await this.compose(["restart"], 120_000);
151
+ }
152
+ /** `docker compose down` removes containers and networks, so it must be confirmed. */
153
+ async down(context, removeVolumes = false) {
154
+ this.requireCompose();
155
+ const message = removeVolumes
156
+ ? "This removes containers, networks AND named volumes. Data will be lost."
157
+ : "This removes containers and networks created by compose.";
158
+ const confirmed = await context.confirm(removeVolumes ? "docker compose down --volumes" : "docker compose down", message);
159
+ if (!confirmed)
160
+ return;
161
+ await this.compose(removeVolumes ? ["down", "--volumes"] : ["down"], 120_000);
162
+ }
163
+ requireCompose() {
164
+ if (!this.composeFile) {
165
+ throw new DevccError({ scope: "docker", message: "No docker compose file found in this project" });
166
+ }
167
+ }
168
+ async compose(args, timeoutMs) {
169
+ const result = await exec("docker", ["compose", ...args], { cwd: this.options.rootDir, timeoutMs });
170
+ if (!result.ok) {
171
+ throw new DevccError({
172
+ scope: "docker",
173
+ message: `docker compose ${args.join(" ")} failed`,
174
+ detail: result.stderr.trim() || result.stdout.trim() || (result.timedOut ? "timed out" : undefined),
175
+ });
176
+ }
177
+ }
178
+ }
179
+ //# sourceMappingURL=docker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker.js","sourceRoot":"","sources":["../../../src/devcc/services/docker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import type { ServiceAdapter, ServiceStatus } from "./types.js";
2
+ export interface PortServiceOptions {
3
+ id: string;
4
+ name: string;
5
+ port: number;
6
+ host?: string;
7
+ category?: ServiceAdapter["category"];
8
+ /** When set, a successful HTTP request to this path upgrades the detail line. */
9
+ healthPath?: string;
10
+ /** Auto-detected services hide themselves when nothing is listening. */
11
+ onlyWhenListening?: boolean;
12
+ timeoutMs?: number;
13
+ }
14
+ /**
15
+ * A generic "is something serving on this port?" adapter.
16
+ *
17
+ * This is how Next.js, Vite, Payload, Typesense and any user-declared HTTP
18
+ * service are represented - devcc observes them, it does not own them, so it
19
+ * deliberately exposes no start/stop actions here. Use a managed process for
20
+ * something devcc should control.
21
+ */
22
+ export declare class PortService implements ServiceAdapter {
23
+ readonly id: string;
24
+ readonly name: string;
25
+ readonly category: ServiceAdapter["category"];
26
+ private readonly host;
27
+ private readonly port;
28
+ private readonly healthPath;
29
+ private readonly onlyWhenListening;
30
+ private readonly timeoutMs;
31
+ constructor(options: PortServiceOptions);
32
+ detect(): Promise<boolean>;
33
+ getStatus(): Promise<ServiceStatus>;
34
+ }
35
+ /**
36
+ * Build port adapters for frameworks this project actually depends on.
37
+ * Nothing is assumed: a project with none of these gets no adapters.
38
+ */
39
+ export declare function detectNodeServices(packageJson: Record<string, unknown> | null): PortService[];
40
+ //# sourceMappingURL=node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../../src/devcc/services/node.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/D,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAA;IACrC,iFAAiF;IACjF,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,wEAAwE;IACxE,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;GAOG;AACH,qBAAa,WAAY,YAAW,cAAc;IAChD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,CAAA;IAE7C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAQ;IAC7B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAQ;IAC7B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;IAC/C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;gBAEtB,OAAO,EAAE,kBAAkB;IAWjC,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAK1B,SAAS,IAAI,OAAO,CAAC,aAAa,CAAC;CAsB1C;AAqCD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,WAAW,EAAE,CAsB7F"}
@@ -0,0 +1,107 @@
1
+ import { probeTcpPort } from "../utils/exec.js";
2
+ /**
3
+ * A generic "is something serving on this port?" adapter.
4
+ *
5
+ * This is how Next.js, Vite, Payload, Typesense and any user-declared HTTP
6
+ * service are represented - devcc observes them, it does not own them, so it
7
+ * deliberately exposes no start/stop actions here. Use a managed process for
8
+ * something devcc should control.
9
+ */
10
+ export class PortService {
11
+ id;
12
+ name;
13
+ category;
14
+ host;
15
+ port;
16
+ healthPath;
17
+ onlyWhenListening;
18
+ timeoutMs;
19
+ constructor(options) {
20
+ this.id = options.id;
21
+ this.name = options.name;
22
+ this.category = options.category ?? "web";
23
+ this.host = options.host ?? "127.0.0.1";
24
+ this.port = options.port;
25
+ this.healthPath = options.healthPath;
26
+ this.onlyWhenListening = options.onlyWhenListening ?? false;
27
+ this.timeoutMs = options.timeoutMs ?? 1_000;
28
+ }
29
+ async detect() {
30
+ if (!this.onlyWhenListening)
31
+ return true;
32
+ return probeTcpPort(this.port, this.host, this.timeoutMs);
33
+ }
34
+ async getStatus() {
35
+ const checkedAt = new Date();
36
+ const endpoint = `${this.host}:${this.port}`;
37
+ const listening = await probeTcpPort(this.port, this.host, this.timeoutMs);
38
+ if (!listening)
39
+ return { state: "stopped", endpoint, detail: "not listening", checkedAt };
40
+ if (!this.healthPath)
41
+ return { state: "running", endpoint, detail: "listening", checkedAt };
42
+ try {
43
+ const response = await fetch(`http://${endpoint}${this.healthPath}`, {
44
+ signal: AbortSignal.timeout(this.timeoutMs),
45
+ });
46
+ return {
47
+ state: response.ok ? "running" : "degraded",
48
+ endpoint,
49
+ detail: `HTTP ${response.status}`,
50
+ checkedAt,
51
+ };
52
+ }
53
+ catch {
54
+ return { state: "degraded", endpoint, detail: "listening, health check failed", checkedAt };
55
+ }
56
+ }
57
+ }
58
+ /** Well-known local dev servers and their conventional ports. */
59
+ const FRAMEWORK_HINTS = [
60
+ { dependency: "next", id: "next", name: "Next.js", port: 3000 },
61
+ { dependency: "vite", id: "vite", name: "Vite", port: 5173 },
62
+ { dependency: "@remix-run/dev", id: "remix", name: "Remix", port: 3000 },
63
+ { dependency: "nuxt", id: "nuxt", name: "Nuxt", port: 3000 },
64
+ { dependency: "astro", id: "astro", name: "Astro", port: 4321 },
65
+ { dependency: "payload", id: "payload", name: "Payload CMS", port: 3000, healthPath: "/admin" },
66
+ { dependency: "typesense", id: "typesense", name: "Typesense", port: 8108, category: "database" },
67
+ { dependency: "express", id: "express", name: "Express API", port: 3001, category: "runtime" },
68
+ { dependency: "fastify", id: "fastify", name: "Fastify API", port: 3001, category: "runtime" },
69
+ { dependency: "@nestjs/core", id: "nest", name: "NestJS API", port: 3000, category: "runtime" },
70
+ ];
71
+ function dependencyNames(packageJson) {
72
+ const names = new Set();
73
+ for (const field of ["dependencies", "devDependencies", "peerDependencies"]) {
74
+ const value = packageJson?.[field];
75
+ if (typeof value === "object" && value !== null) {
76
+ for (const name of Object.keys(value))
77
+ names.add(name);
78
+ }
79
+ }
80
+ return names;
81
+ }
82
+ /**
83
+ * Build port adapters for frameworks this project actually depends on.
84
+ * Nothing is assumed: a project with none of these gets no adapters.
85
+ */
86
+ export function detectNodeServices(packageJson) {
87
+ const dependencies = dependencyNames(packageJson);
88
+ const seenPorts = new Set();
89
+ const adapters = [];
90
+ for (const hint of FRAMEWORK_HINTS) {
91
+ if (!dependencies.has(hint.dependency))
92
+ continue;
93
+ if (seenPorts.has(hint.port))
94
+ continue;
95
+ seenPorts.add(hint.port);
96
+ adapters.push(new PortService({
97
+ id: hint.id,
98
+ name: hint.name,
99
+ port: hint.port,
100
+ category: hint.category ?? "web",
101
+ healthPath: hint.healthPath,
102
+ onlyWhenListening: true,
103
+ }));
104
+ }
105
+ return adapters;
106
+ }
107
+ //# sourceMappingURL=node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../../../src/devcc/services/node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { ServiceAdapter, ServiceStatus } from "./types.js";
2
+ export interface OllamaServiceOptions {
3
+ host?: string;
4
+ port?: number;
5
+ timeoutMs?: number;
6
+ }
7
+ /**
8
+ * Ollama adapter. Uses the HTTP API for a model count when the port is open;
9
+ * falls back to a plain port probe if the API call fails.
10
+ */
11
+ export declare class OllamaService implements ServiceAdapter {
12
+ readonly id = "ollama";
13
+ readonly name = "Ollama";
14
+ readonly category: "ai";
15
+ private readonly host;
16
+ private readonly port;
17
+ private readonly timeoutMs;
18
+ constructor(options?: OllamaServiceOptions);
19
+ detect(): Promise<boolean>;
20
+ getStatus(): Promise<ServiceStatus>;
21
+ private listModels;
22
+ }
23
+ export declare function parseHostPort(value: string | undefined): {
24
+ host: string;
25
+ port: number;
26
+ } | null;
27
+ //# sourceMappingURL=ollama.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ollama.d.ts","sourceRoot":"","sources":["../../../src/devcc/services/ollama.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAS/D,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;GAGG;AACH,qBAAa,aAAc,YAAW,cAAc;IAClD,QAAQ,CAAC,EAAE,YAAW;IACtB,QAAQ,CAAC,IAAI,YAAW;IACxB,QAAQ,CAAC,QAAQ,EAAG,IAAI,CAAS;IAEjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAQ;IAC7B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAQ;IAC7B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;gBAEtB,OAAO,GAAE,oBAAyB;IAOxC,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAI1B,SAAS,IAAI,OAAO,CAAC,aAAa,CAAC;YAgB3B,UAAU;CAYzB;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAS9F"}
@@ -0,0 +1,66 @@
1
+ import { probeTcpPort } from "../utils/exec.js";
2
+ const DEFAULT_HOST = "127.0.0.1";
3
+ const DEFAULT_PORT = 11434;
4
+ /**
5
+ * Ollama adapter. Uses the HTTP API for a model count when the port is open;
6
+ * falls back to a plain port probe if the API call fails.
7
+ */
8
+ export class OllamaService {
9
+ id = "ollama";
10
+ name = "Ollama";
11
+ category = "ai";
12
+ host;
13
+ port;
14
+ timeoutMs;
15
+ constructor(options = {}) {
16
+ const fromEnv = parseHostPort(process.env.OLLAMA_HOST);
17
+ this.host = options.host ?? fromEnv?.host ?? DEFAULT_HOST;
18
+ this.port = options.port ?? fromEnv?.port ?? DEFAULT_PORT;
19
+ this.timeoutMs = options.timeoutMs ?? 1_500;
20
+ }
21
+ async detect() {
22
+ return probeTcpPort(this.port, this.host);
23
+ }
24
+ async getStatus() {
25
+ const checkedAt = new Date();
26
+ const endpoint = `${this.host}:${this.port}`;
27
+ const listening = await probeTcpPort(this.port, this.host);
28
+ if (!listening)
29
+ return { state: "stopped", endpoint, detail: "not listening", checkedAt };
30
+ const models = await this.listModels();
31
+ return {
32
+ state: "running",
33
+ endpoint,
34
+ detail: models === null ? "listening" : `${models.length} model${models.length === 1 ? "" : "s"}`,
35
+ items: models?.slice(0, 6).map((name) => ({ name, state: "running" })),
36
+ checkedAt,
37
+ };
38
+ }
39
+ async listModels() {
40
+ try {
41
+ const response = await fetch(`http://${this.host}:${this.port}/api/tags`, {
42
+ signal: AbortSignal.timeout(this.timeoutMs),
43
+ });
44
+ if (!response.ok)
45
+ return null;
46
+ const body = (await response.json());
47
+ return (body.models ?? []).map((model) => model.name ?? "unnamed");
48
+ }
49
+ catch {
50
+ return null;
51
+ }
52
+ }
53
+ }
54
+ export function parseHostPort(value) {
55
+ if (!value)
56
+ return null;
57
+ const withScheme = value.includes("://") ? value : `http://${value}`;
58
+ try {
59
+ const parsed = new URL(withScheme);
60
+ return { host: parsed.hostname || DEFAULT_HOST, port: Number(parsed.port || DEFAULT_PORT) };
61
+ }
62
+ catch {
63
+ return null;
64
+ }
65
+ }
66
+ //# sourceMappingURL=ollama.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../../src/devcc/services/ollama.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { ServiceAdapter, ServiceStatus } from "./types.js";
2
+ export interface PostgresServiceOptions {
3
+ host?: string;
4
+ port?: number;
5
+ /** Only report the service when one of these is true. */
6
+ hints?: boolean;
7
+ }
8
+ /** Parse `postgres://user:pass@host:5432/db` style URLs for host/port. */
9
+ export declare function parsePostgresUrl(url: string | undefined): {
10
+ host: string;
11
+ port: number;
12
+ } | null;
13
+ /**
14
+ * PostgreSQL adapter.
15
+ *
16
+ * Detection is intentionally conservative: we only claim Postgres is relevant
17
+ * when the project mentions it (DATABASE_URL / a pg dependency) or something is
18
+ * actually listening on the port.
19
+ */
20
+ export declare class PostgresService implements ServiceAdapter {
21
+ readonly id = "postgres";
22
+ readonly name = "PostgreSQL";
23
+ readonly category: "database";
24
+ private readonly host;
25
+ private readonly port;
26
+ constructor(options?: PostgresServiceOptions);
27
+ detect(): Promise<boolean>;
28
+ getStatus(): Promise<ServiceStatus>;
29
+ }
30
+ //# sourceMappingURL=postgres.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../../src/devcc/services/postgres.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/D,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,yDAAyD;IACzD,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAS/F;AAED;;;;;;GAMG;AACH,qBAAa,eAAgB,YAAW,cAAc;IACpD,QAAQ,CAAC,EAAE,cAAa;IACxB,QAAQ,CAAC,IAAI,gBAAe;IAC5B,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAS;IAEvC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAQ;IAC7B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAQ;gBAEjB,OAAO,GAAE,sBAA2B;IAM1C,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAI1B,SAAS,IAAI,OAAO,CAAC,aAAa,CAAC;CAS1C"}
@@ -0,0 +1,47 @@
1
+ import { probeTcpPort } from "../utils/exec.js";
2
+ /** Parse `postgres://user:pass@host:5432/db` style URLs for host/port. */
3
+ export function parsePostgresUrl(url) {
4
+ if (!url)
5
+ return null;
6
+ try {
7
+ const parsed = new URL(url);
8
+ if (!parsed.protocol.startsWith("postgres"))
9
+ return null;
10
+ return { host: parsed.hostname || "127.0.0.1", port: Number(parsed.port || 5432) };
11
+ }
12
+ catch {
13
+ return null;
14
+ }
15
+ }
16
+ /**
17
+ * PostgreSQL adapter.
18
+ *
19
+ * Detection is intentionally conservative: we only claim Postgres is relevant
20
+ * when the project mentions it (DATABASE_URL / a pg dependency) or something is
21
+ * actually listening on the port.
22
+ */
23
+ export class PostgresService {
24
+ id = "postgres";
25
+ name = "PostgreSQL";
26
+ category = "database";
27
+ host;
28
+ port;
29
+ constructor(options = {}) {
30
+ const fromEnv = parsePostgresUrl(process.env.DATABASE_URL ?? process.env.POSTGRES_URL);
31
+ this.host = options.host ?? fromEnv?.host ?? "127.0.0.1";
32
+ this.port = options.port ?? fromEnv?.port ?? 5432;
33
+ }
34
+ async detect() {
35
+ return probeTcpPort(this.port, this.host);
36
+ }
37
+ async getStatus() {
38
+ const listening = await probeTcpPort(this.port, this.host);
39
+ return {
40
+ state: listening ? "running" : "stopped",
41
+ endpoint: `${this.host}:${this.port}`,
42
+ detail: listening ? "accepting connections" : "not listening",
43
+ checkedAt: new Date(),
44
+ };
45
+ }
46
+ }
47
+ //# sourceMappingURL=postgres.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres.js","sourceRoot":"","sources":["../../../src/devcc/services/postgres.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAU/C,0EAA0E;AAC1E,MAAM,UAAU,gBAAgB,CAAC,GAAuB;IACtD,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAA;IACrB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;QAC3B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,OAAO,IAAI,CAAA;QACxD,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,IAAI,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,EAAE,CAAA;IACpF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,OAAO,eAAe;IACjB,EAAE,GAAG,UAAU,CAAA;IACf,IAAI,GAAG,YAAY,CAAA;IACnB,QAAQ,GAAG,UAAmB,CAAA;IAEtB,IAAI,CAAQ;IACZ,IAAI,CAAQ;IAE7B,YAAY,UAAkC,EAAE;QAC9C,MAAM,OAAO,GAAG,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;QACtF,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,EAAE,IAAI,IAAI,WAAW,CAAA;QACxD,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,EAAE,IAAI,IAAI,IAAI,CAAA;IACnD,CAAC;IAED,KAAK,CAAC,MAAM;QACV,OAAO,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;IAC3C,CAAC;IAED,KAAK,CAAC,SAAS;QACb,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;QAC1D,OAAO;YACL,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;YACxC,QAAQ,EAAE,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE;YACrC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,eAAe;YAC7D,SAAS,EAAE,IAAI,IAAI,EAAE;SACtB,CAAA;IACH,CAAC;CACF"}
@@ -0,0 +1,20 @@
1
+ import type { ServiceAdapter, ServiceStatus } from "./types.js";
2
+ export interface RedisServiceOptions {
3
+ host?: string;
4
+ port?: number;
5
+ }
6
+ export declare function parseRedisUrl(url: string | undefined): {
7
+ host: string;
8
+ port: number;
9
+ } | null;
10
+ export declare class RedisService implements ServiceAdapter {
11
+ readonly id = "redis";
12
+ readonly name = "Redis";
13
+ readonly category: "database";
14
+ private readonly host;
15
+ private readonly port;
16
+ constructor(options?: RedisServiceOptions);
17
+ detect(): Promise<boolean>;
18
+ getStatus(): Promise<ServiceStatus>;
19
+ }
20
+ //# sourceMappingURL=redis.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../../../src/devcc/services/redis.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/D,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAS5F;AAED,qBAAa,YAAa,YAAW,cAAc;IACjD,QAAQ,CAAC,EAAE,WAAU;IACrB,QAAQ,CAAC,IAAI,WAAU;IACvB,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAS;IAEvC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAQ;IAC7B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAQ;gBAEjB,OAAO,GAAE,mBAAwB;IAMvC,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAI1B,SAAS,IAAI,OAAO,CAAC,aAAa,CAAC;CAS1C"}
@@ -0,0 +1,39 @@
1
+ import { probeTcpPort } from "../utils/exec.js";
2
+ export function parseRedisUrl(url) {
3
+ if (!url)
4
+ return null;
5
+ try {
6
+ const parsed = new URL(url);
7
+ if (!parsed.protocol.startsWith("redis"))
8
+ return null;
9
+ return { host: parsed.hostname || "127.0.0.1", port: Number(parsed.port || 6379) };
10
+ }
11
+ catch {
12
+ return null;
13
+ }
14
+ }
15
+ export class RedisService {
16
+ id = "redis";
17
+ name = "Redis";
18
+ category = "database";
19
+ host;
20
+ port;
21
+ constructor(options = {}) {
22
+ const fromEnv = parseRedisUrl(process.env.REDIS_URL);
23
+ this.host = options.host ?? fromEnv?.host ?? "127.0.0.1";
24
+ this.port = options.port ?? fromEnv?.port ?? 6379;
25
+ }
26
+ async detect() {
27
+ return probeTcpPort(this.port, this.host);
28
+ }
29
+ async getStatus() {
30
+ const listening = await probeTcpPort(this.port, this.host);
31
+ return {
32
+ state: listening ? "running" : "stopped",
33
+ endpoint: `${this.host}:${this.port}`,
34
+ detail: listening ? "accepting connections" : "not listening",
35
+ checkedAt: new Date(),
36
+ };
37
+ }
38
+ }
39
+ //# sourceMappingURL=redis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis.js","sourceRoot":"","sources":["../../../src/devcc/services/redis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAQ/C,MAAM,UAAU,aAAa,CAAC,GAAuB;IACnD,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAA;IACrB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;QAC3B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC;YAAE,OAAO,IAAI,CAAA;QACrD,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,IAAI,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,EAAE,CAAA;IACpF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED,MAAM,OAAO,YAAY;IACd,EAAE,GAAG,OAAO,CAAA;IACZ,IAAI,GAAG,OAAO,CAAA;IACd,QAAQ,GAAG,UAAmB,CAAA;IAEtB,IAAI,CAAQ;IACZ,IAAI,CAAQ;IAE7B,YAAY,UAA+B,EAAE;QAC3C,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;QACpD,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,EAAE,IAAI,IAAI,WAAW,CAAA;QACxD,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,EAAE,IAAI,IAAI,IAAI,CAAA;IACnD,CAAC;IAED,KAAK,CAAC,MAAM;QACV,OAAO,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;IAC3C,CAAC;IAED,KAAK,CAAC,SAAS;QACb,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;QAC1D,OAAO;YACL,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;YACxC,QAAQ,EAAE,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE;YACrC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,eAAe;YAC7D,SAAS,EAAE,IAAI,IAAI,EAAE;SACtB,CAAA;IACH,CAAC;CACF"}