@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,35 @@
1
+ import { bold as boldChunk, dim as dimChunk, fg, StyledText } from "@opentui/core";
2
+ import { theme } from "../app/theme.js";
3
+ /**
4
+ * Helpers for composing `StyledText` programmatically.
5
+ *
6
+ * The `t` template literal is convenient for fixed strings; these helpers cover
7
+ * the dynamic case (variable numbers of coloured segments) without fighting the
8
+ * template syntax.
9
+ */
10
+ export function chunk(text, color = theme.text) {
11
+ return fg(color)(text);
12
+ }
13
+ export function bold(text, color = theme.textBright) {
14
+ return boldChunk(fg(color)(text));
15
+ }
16
+ export function dim(text) {
17
+ return dimChunk(fg(theme.textDim)(text));
18
+ }
19
+ export function styled(...parts) {
20
+ return new StyledText(parts.map((part) => (typeof part === "string" ? chunk(part) : part)));
21
+ }
22
+ export function joinStyled(parts, separator, separatorColor = theme.textDim) {
23
+ const chunks = [];
24
+ for (const [index, part] of parts.entries()) {
25
+ if (index > 0)
26
+ chunks.push(chunk(separator, separatorColor));
27
+ chunks.push(...part.chunks);
28
+ }
29
+ return new StyledText(chunks);
30
+ }
31
+ /** Total display length of a styled line, for right-alignment maths. */
32
+ export function styledLength(text) {
33
+ return text.chunks.reduce((total, part) => total + part.text.length, 0);
34
+ }
35
+ //# sourceMappingURL=styled.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styled.js","sourceRoot":"","sources":["../../../src/devcc/components/styled.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,GAAG,IAAI,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAkB,MAAM,eAAe,CAAA;AAClG,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AAEvC;;;;;;GAMG;AAEH,MAAM,UAAU,KAAK,CAAC,IAAY,EAAE,QAAgB,KAAK,CAAC,IAAI;IAC5D,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAA;AACxB,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,IAAY,EAAE,QAAgB,KAAK,CAAC,UAAU;IACjE,OAAO,SAAS,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;AACnC,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,IAAY;IAC9B,OAAO,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;AAC1C,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,GAAG,KAA6B;IACrD,OAAO,IAAI,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AAC7F,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,KAAmB,EACnB,SAAiB,EACjB,cAAc,GAAG,KAAK,CAAC,OAAO;IAE9B,MAAM,MAAM,GAAgB,EAAE,CAAA;IAC9B,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QAC5C,IAAI,KAAK,GAAG,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC,CAAA;QAC5D,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAA;IAC7B,CAAC;IACD,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,CAAA;AAC/B,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,YAAY,CAAC,IAAgB;IAC3C,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;AACzE,CAAC"}
@@ -0,0 +1,89 @@
1
+ import type { DependencyService } from "../deps/DependencyService.js";
2
+ import type { GitService } from "../git/GitService.js";
3
+ import type { LogStore } from "../logs/LogBuffer.js";
4
+ import type { ProcessManager } from "../processes/ProcessManager.js";
5
+ import type { ServiceManager } from "../services/ServiceManager.js";
6
+ import type { ProjectEntry } from "../projects/ProjectRegistry.js";
7
+ import type { SystemMonitor } from "../system/SystemMonitor.js";
8
+ import type { AppStore, NotificationLevel, ViewId } from "./state.js";
9
+ /**
10
+ * Everything a command is allowed to touch.
11
+ *
12
+ * Commands are the single extension point: the palette, the keymap and any
13
+ * user-provided config entry all end up here, so a new capability only has to
14
+ * be registered once.
15
+ */
16
+ export interface CommandContext {
17
+ store: AppStore;
18
+ processes: ProcessManager;
19
+ services: ServiceManager;
20
+ git: GitService;
21
+ logs: LogStore;
22
+ system: SystemMonitor;
23
+ deps: DependencyService;
24
+ navigate: (view: ViewId) => void;
25
+ notify: (level: NotificationLevel, message: string, detail?: string) => void;
26
+ /** Modal yes/no. Resolves false when dismissed. */
27
+ confirm: (title: string, message: string) => Promise<boolean>;
28
+ /** Modal single-line prompt. Resolves null when cancelled. */
29
+ prompt: (title: string, placeholder?: string) => Promise<string | null>;
30
+ /** Open the in-app manual. */
31
+ showHelp: () => void;
32
+ runScript: (name: string) => Promise<void>;
33
+ /** Update one dependency to `version`, after confirmation. */
34
+ updateDependency: (name: string, version: string) => Promise<void>;
35
+ /** Projects the switcher can offer, current one first. */
36
+ listProjects: () => ProjectEntry[];
37
+ /** Projects currently open, in the order they were opened. */
38
+ openProjects: () => ProjectEntry[];
39
+ /** Open a project (or bring an open one to the front) without closing others. */
40
+ switchProject: (path: string) => Promise<void>;
41
+ /** Close an open project, stopping what devcc started there. Defaults to the current one. */
42
+ closeProject: (path?: string) => Promise<void>;
43
+ quit: () => void;
44
+ }
45
+ export interface CommandDefinition {
46
+ id: string;
47
+ title: string;
48
+ category?: string;
49
+ /** Displayed hint, e.g. `r`. Key handling itself lives in the keymap. */
50
+ shortcut?: string;
51
+ keywords?: string[];
52
+ /** Hide the command when it cannot apply right now. */
53
+ when?: (context: CommandContext) => boolean;
54
+ /** Ask for confirmation before running. Used for destructive operations. */
55
+ confirm?: {
56
+ title: string;
57
+ message: string;
58
+ };
59
+ execute: (context: CommandContext) => Promise<void> | void;
60
+ }
61
+ export interface CommandRegistryEvents {
62
+ changed: [];
63
+ }
64
+ /**
65
+ * Central command registry. Ids are unique; re-registering an id replaces it,
66
+ * which is what lets project config override a built-in.
67
+ */
68
+ export declare class CommandRegistry {
69
+ private readonly commands;
70
+ register(command: CommandDefinition): void;
71
+ registerAll(commands: readonly CommandDefinition[]): void;
72
+ unregister(id: string): boolean;
73
+ /** Drop every command. Used when the dashboard reattaches to another project. */
74
+ clear(): void;
75
+ has(id: string): boolean;
76
+ get(id: string): CommandDefinition | undefined;
77
+ list(): CommandDefinition[];
78
+ /** Commands whose `when` guard passes right now. */
79
+ available(context: CommandContext): CommandDefinition[];
80
+ /** Fuzzy search over `category title keywords`. */
81
+ search(query: string, context: CommandContext, limit?: number): CommandDefinition[];
82
+ /**
83
+ * Run a command by id, honouring its `confirm` guard.
84
+ * Returns false when the command does not exist or the user declined.
85
+ */
86
+ run(id: string, context: CommandContext): Promise<boolean>;
87
+ }
88
+ export declare function searchText(command: CommandDefinition): string;
89
+ //# sourceMappingURL=commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../src/devcc/core/commands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ import { fuzzyFilter } from "../utils/fuzzy.js";
2
+ /**
3
+ * Central command registry. Ids are unique; re-registering an id replaces it,
4
+ * which is what lets project config override a built-in.
5
+ */
6
+ export class CommandRegistry {
7
+ commands = new Map();
8
+ register(command) {
9
+ this.commands.set(command.id, command);
10
+ }
11
+ registerAll(commands) {
12
+ for (const command of commands)
13
+ this.register(command);
14
+ }
15
+ unregister(id) {
16
+ return this.commands.delete(id);
17
+ }
18
+ /** Drop every command. Used when the dashboard reattaches to another project. */
19
+ clear() {
20
+ this.commands.clear();
21
+ }
22
+ has(id) {
23
+ return this.commands.has(id);
24
+ }
25
+ get(id) {
26
+ return this.commands.get(id);
27
+ }
28
+ list() {
29
+ return [...this.commands.values()];
30
+ }
31
+ /** Commands whose `when` guard passes right now. */
32
+ available(context) {
33
+ return this.list().filter((command) => (command.when ? safeWhen(command, context) : true));
34
+ }
35
+ /** Fuzzy search over `category title keywords`. */
36
+ search(query, context, limit = 40) {
37
+ const candidates = this.available(context);
38
+ return fuzzyFilter(candidates, query, searchText, limit).map((match) => match.item);
39
+ }
40
+ /**
41
+ * Run a command by id, honouring its `confirm` guard.
42
+ * Returns false when the command does not exist or the user declined.
43
+ */
44
+ async run(id, context) {
45
+ const command = this.commands.get(id);
46
+ if (!command)
47
+ return false;
48
+ if (command.confirm) {
49
+ const confirmed = await context.confirm(command.confirm.title, command.confirm.message);
50
+ if (!confirmed)
51
+ return false;
52
+ }
53
+ await command.execute(context);
54
+ return true;
55
+ }
56
+ }
57
+ export function searchText(command) {
58
+ return [command.category, command.title, ...(command.keywords ?? [])].filter(Boolean).join(" ");
59
+ }
60
+ function safeWhen(command, context) {
61
+ try {
62
+ return command.when?.(context) ?? true;
63
+ }
64
+ catch {
65
+ return false;
66
+ }
67
+ }
68
+ //# sourceMappingURL=commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../../src/devcc/core/commands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ import type { ProcessDefinition } from "../processes/ManagedProcess.js";
2
+ import type { LogLevel } from "../utils/logger.js";
3
+ /** A command declared in project config: runs an executable and streams its logs. */
4
+ export interface CommandConfigEntry {
5
+ id: string;
6
+ title: string;
7
+ category?: string;
8
+ command: string;
9
+ args?: string[];
10
+ cwd?: string;
11
+ keywords?: string[];
12
+ /** Require a yes/no confirmation before running. */
13
+ confirm?: {
14
+ title: string;
15
+ message: string;
16
+ } | boolean;
17
+ }
18
+ /** An extra port/HTTP endpoint to watch in the Services view. */
19
+ export interface ServiceConfigEntry {
20
+ id: string;
21
+ name: string;
22
+ port: number;
23
+ host?: string;
24
+ healthPath?: string;
25
+ category?: "container" | "database" | "runtime" | "ai" | "web";
26
+ }
27
+ export interface RefreshIntervals {
28
+ system?: number;
29
+ services?: number;
30
+ git?: number;
31
+ clock?: number;
32
+ }
33
+ export interface DevccConfig {
34
+ /** Overrides the project name shown in the header. */
35
+ name?: string;
36
+ /**
37
+ * Extra project paths to offer in the project switcher, absolute or relative
38
+ * to this project. Recents and sibling directories are found automatically.
39
+ */
40
+ projects?: string[];
41
+ /** Extra directories to scan for sibling projects (default: the parent). */
42
+ projectSearchDirs?: string[];
43
+ processes?: ProcessDefinition[];
44
+ commands?: CommandConfigEntry[];
45
+ services?: ServiceConfigEntry[];
46
+ refresh?: RefreshIntervals;
47
+ /** Cap for each log source's ring buffer. */
48
+ maxLogLines?: number;
49
+ logLevel?: LogLevel;
50
+ }
51
+ export type ResolvedConfig = Required<Pick<DevccConfig, "processes" | "commands" | "services" | "projects" | "projectSearchDirs">> & Omit<DevccConfig, "processes" | "commands" | "services" | "projects" | "projectSearchDirs"> & {
52
+ refresh: Required<RefreshIntervals>;
53
+ };
54
+ export declare const DEFAULT_REFRESH: Required<RefreshIntervals>;
55
+ export declare const EMPTY_CONFIG: ResolvedConfig;
56
+ /** Identity helper that gives config files full type checking and completion. */
57
+ export declare function defineConfig(config: DevccConfig): DevccConfig;
58
+ export declare const CONFIG_FILENAMES: readonly [".devcc.ts", "devcc.config.ts", ".devcc.mts", "devcc.config.mts", ".devcc.js", "devcc.config.js", ".devcc.mjs", "devcc.config.mjs", ".devcc.json"];
59
+ export declare function findConfigFile(rootDir: string, exists?: (path: string) => boolean): string | null;
60
+ export interface ValidationResult {
61
+ config: ResolvedConfig;
62
+ issues: string[];
63
+ }
64
+ /**
65
+ * Validate and normalise a raw config object.
66
+ *
67
+ * Invalid entries are dropped with an explanatory issue rather than throwing:
68
+ * a typo in one process definition must not stop the dashboard from starting.
69
+ */
70
+ export declare function validateConfig(raw: unknown): ValidationResult;
71
+ export interface LoadedConfig extends ValidationResult {
72
+ filePath: string | null;
73
+ }
74
+ /**
75
+ * Load project config if present.
76
+ *
77
+ * TypeScript config files are transpiled on the fly with jiti so `.devcc.ts`
78
+ * works identically under Bun and Node.
79
+ */
80
+ export declare function loadConfig(rootDir: string): Promise<LoadedConfig>;
81
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/devcc/core/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,313 @@
1
+ import { existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { errorMessage } from "../utils/errors.js";
4
+ import { isLogLevel } from "../utils/logger.js";
5
+ export const DEFAULT_REFRESH = {
6
+ system: 1_500,
7
+ services: 5_000,
8
+ git: 8_000,
9
+ clock: 1_000,
10
+ };
11
+ export const EMPTY_CONFIG = {
12
+ processes: [],
13
+ commands: [],
14
+ services: [],
15
+ projects: [],
16
+ projectSearchDirs: [],
17
+ refresh: DEFAULT_REFRESH,
18
+ };
19
+ /** Identity helper that gives config files full type checking and completion. */
20
+ export function defineConfig(config) {
21
+ return config;
22
+ }
23
+ export const CONFIG_FILENAMES = [
24
+ ".devcc.ts",
25
+ "devcc.config.ts",
26
+ ".devcc.mts",
27
+ "devcc.config.mts",
28
+ ".devcc.js",
29
+ "devcc.config.js",
30
+ ".devcc.mjs",
31
+ "devcc.config.mjs",
32
+ ".devcc.json",
33
+ ];
34
+ export function findConfigFile(rootDir, exists = existsSync) {
35
+ for (const name of CONFIG_FILENAMES) {
36
+ const path = join(rootDir, name);
37
+ if (exists(path))
38
+ return path;
39
+ }
40
+ return null;
41
+ }
42
+ const PROCESS_KINDS = ["service", "task"];
43
+ /**
44
+ * Validate and normalise a raw config object.
45
+ *
46
+ * Invalid entries are dropped with an explanatory issue rather than throwing:
47
+ * a typo in one process definition must not stop the dashboard from starting.
48
+ */
49
+ export function validateConfig(raw) {
50
+ const issues = [];
51
+ if (raw === null || typeof raw !== "object") {
52
+ return { config: { ...EMPTY_CONFIG }, issues: ["Config must export an object"] };
53
+ }
54
+ const input = raw;
55
+ const seenProcessIds = new Set();
56
+ const processes = [];
57
+ for (const [index, entry] of asArray(input.processes, "processes", issues).entries()) {
58
+ const record = asRecord(entry);
59
+ if (!record) {
60
+ issues.push(`processes[${index}] must be an object`);
61
+ continue;
62
+ }
63
+ const id = asString(record.id);
64
+ const command = asString(record.command);
65
+ if (!id) {
66
+ issues.push(`processes[${index}] is missing "id"`);
67
+ continue;
68
+ }
69
+ if (!command) {
70
+ issues.push(`processes[${index}] ("${id}") is missing "command"`);
71
+ continue;
72
+ }
73
+ if (seenProcessIds.has(id)) {
74
+ issues.push(`processes[${index}] duplicates id "${id}"`);
75
+ continue;
76
+ }
77
+ seenProcessIds.add(id);
78
+ const kind = asString(record.kind);
79
+ processes.push({
80
+ id,
81
+ name: asString(record.name) ?? id,
82
+ command,
83
+ args: asStringArray(record.args),
84
+ cwd: asString(record.cwd),
85
+ env: asStringRecord(record.env),
86
+ kind: kind && PROCESS_KINDS.includes(kind) ? kind : "service",
87
+ autoStart: record.autoStart === true,
88
+ url: asString(record.url),
89
+ port: asPositiveInt(record.port),
90
+ killGraceMs: asPositiveInt(record.killGraceMs),
91
+ restartOnCrash: record.restartOnCrash === true,
92
+ maxCrashRestarts: asPositiveInt(record.maxCrashRestarts),
93
+ crashBackoffMs: asPositiveInt(record.crashBackoffMs),
94
+ maxCrashBackoffMs: asPositiveInt(record.maxCrashBackoffMs),
95
+ healthyAfterMs: asPositiveInt(record.healthyAfterMs),
96
+ dependsOn: asStringArray(record.dependsOn),
97
+ readiness: asReadiness(record.readiness, id, issues),
98
+ });
99
+ }
100
+ for (const definition of processes) {
101
+ for (const dependency of definition.dependsOn ?? []) {
102
+ if (!seenProcessIds.has(dependency)) {
103
+ issues.push(`processes "${definition.id}": dependsOn "${dependency}" is not a declared process`);
104
+ }
105
+ }
106
+ }
107
+ const seenCommandIds = new Set();
108
+ const commands = [];
109
+ for (const [index, entry] of asArray(input.commands, "commands", issues).entries()) {
110
+ const record = asRecord(entry);
111
+ if (!record) {
112
+ issues.push(`commands[${index}] must be an object`);
113
+ continue;
114
+ }
115
+ const id = asString(record.id);
116
+ const command = asString(record.command);
117
+ if (!id || !command) {
118
+ issues.push(`commands[${index}] needs both "id" and "command"`);
119
+ continue;
120
+ }
121
+ if (seenCommandIds.has(id)) {
122
+ issues.push(`commands[${index}] duplicates id "${id}"`);
123
+ continue;
124
+ }
125
+ seenCommandIds.add(id);
126
+ const confirm = record.confirm;
127
+ commands.push({
128
+ id,
129
+ title: asString(record.title) ?? id,
130
+ category: asString(record.category) ?? "Project",
131
+ command,
132
+ args: asStringArray(record.args),
133
+ cwd: asString(record.cwd),
134
+ keywords: asStringArray(record.keywords),
135
+ confirm: confirm === true
136
+ ? true
137
+ : (() => {
138
+ const confirmRecord = asRecord(confirm);
139
+ const title = asString(confirmRecord?.title);
140
+ const message = asString(confirmRecord?.message);
141
+ return title && message ? { title, message } : undefined;
142
+ })(),
143
+ });
144
+ }
145
+ const services = [];
146
+ const seenServiceIds = new Set();
147
+ for (const [index, entry] of asArray(input.services, "services", issues).entries()) {
148
+ const record = asRecord(entry);
149
+ if (!record) {
150
+ issues.push(`services[${index}] must be an object`);
151
+ continue;
152
+ }
153
+ const id = asString(record.id);
154
+ const port = asPositiveInt(record.port);
155
+ if (!id || port === undefined) {
156
+ issues.push(`services[${index}] needs "id" and a numeric "port"`);
157
+ continue;
158
+ }
159
+ if (seenServiceIds.has(id)) {
160
+ issues.push(`services[${index}] duplicates id "${id}"`);
161
+ continue;
162
+ }
163
+ seenServiceIds.add(id);
164
+ services.push({
165
+ id,
166
+ name: asString(record.name) ?? id,
167
+ port,
168
+ host: asString(record.host),
169
+ healthPath: asString(record.healthPath),
170
+ category: asServiceCategory(record.category),
171
+ });
172
+ }
173
+ const refreshInput = asRecord(input.refresh) ?? {};
174
+ const refresh = {
175
+ system: asPositiveInt(refreshInput.system) ?? DEFAULT_REFRESH.system,
176
+ services: asPositiveInt(refreshInput.services) ?? DEFAULT_REFRESH.services,
177
+ git: asPositiveInt(refreshInput.git) ?? DEFAULT_REFRESH.git,
178
+ clock: asPositiveInt(refreshInput.clock) ?? DEFAULT_REFRESH.clock,
179
+ };
180
+ const logLevel = asString(input.logLevel);
181
+ if (logLevel && !isLogLevel(logLevel))
182
+ issues.push(`Unknown logLevel "${logLevel}"`);
183
+ return {
184
+ config: {
185
+ name: asString(input.name),
186
+ projects: asStringArray(input.projects) ?? [],
187
+ projectSearchDirs: asStringArray(input.projectSearchDirs) ?? [],
188
+ processes,
189
+ commands,
190
+ services,
191
+ refresh,
192
+ maxLogLines: asPositiveInt(input.maxLogLines),
193
+ logLevel: logLevel && isLogLevel(logLevel) ? logLevel : undefined,
194
+ },
195
+ issues,
196
+ };
197
+ }
198
+ /**
199
+ * Load project config if present.
200
+ *
201
+ * TypeScript config files are transpiled on the fly with jiti so `.devcc.ts`
202
+ * works identically under Bun and Node.
203
+ */
204
+ export async function loadConfig(rootDir) {
205
+ const filePath = findConfigFile(rootDir);
206
+ if (!filePath)
207
+ return { filePath: null, config: { ...EMPTY_CONFIG }, issues: [] };
208
+ try {
209
+ const raw = await importConfigModule(filePath);
210
+ const result = validateConfig(raw);
211
+ return { ...result, filePath };
212
+ }
213
+ catch (error) {
214
+ return {
215
+ filePath,
216
+ config: { ...EMPTY_CONFIG },
217
+ issues: [`Failed to load ${filePath}: ${errorMessage(error)}`],
218
+ };
219
+ }
220
+ }
221
+ async function importConfigModule(filePath) {
222
+ if (filePath.endsWith(".json")) {
223
+ const { readFile } = await import("node:fs/promises");
224
+ return JSON.parse(await readFile(filePath, "utf8"));
225
+ }
226
+ const { createJiti } = await import("jiti");
227
+ const jiti = createJiti(import.meta.url, { interopDefault: true, moduleCache: false });
228
+ const loaded = await jiti.import(filePath);
229
+ return unwrapDefault(loaded);
230
+ }
231
+ function unwrapDefault(value) {
232
+ const record = asRecord(value);
233
+ if (record && "default" in record)
234
+ return unwrapDefault(record.default);
235
+ return value;
236
+ }
237
+ function asRecord(value) {
238
+ return typeof value === "object" && value !== null && !Array.isArray(value)
239
+ ? value
240
+ : undefined;
241
+ }
242
+ function asArray(value, field, issues) {
243
+ if (value === undefined)
244
+ return [];
245
+ if (!Array.isArray(value)) {
246
+ issues.push(`"${field}" must be an array`);
247
+ return [];
248
+ }
249
+ return value;
250
+ }
251
+ function asString(value) {
252
+ return typeof value === "string" && value.length > 0 ? value : undefined;
253
+ }
254
+ function asStringArray(value) {
255
+ if (!Array.isArray(value))
256
+ return undefined;
257
+ const items = value.filter((item) => typeof item === "string");
258
+ return items.length > 0 ? items : undefined;
259
+ }
260
+ function asStringRecord(value) {
261
+ const record = asRecord(value);
262
+ if (!record)
263
+ return undefined;
264
+ const entries = Object.entries(record).filter((entry) => typeof entry[1] === "string");
265
+ return entries.length > 0 ? Object.fromEntries(entries) : undefined;
266
+ }
267
+ function asPositiveInt(value) {
268
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : undefined;
269
+ }
270
+ /**
271
+ * Normalise a readiness block. `port` alone or `logPattern` alone is enough;
272
+ * a block with neither is dropped with an issue rather than silently waiting
273
+ * for nothing.
274
+ */
275
+ function asReadiness(value, processId, issues) {
276
+ if (value === undefined)
277
+ return undefined;
278
+ const record = asRecord(value);
279
+ if (!record) {
280
+ issues.push(`processes "${processId}": readiness must be an object`);
281
+ return undefined;
282
+ }
283
+ const port = asPositiveInt(record.port);
284
+ const logPattern = asString(record.logPattern);
285
+ if (port === undefined && logPattern === undefined) {
286
+ issues.push(`processes "${processId}": readiness needs a "port" or a "logPattern"`);
287
+ return undefined;
288
+ }
289
+ if (logPattern !== undefined) {
290
+ try {
291
+ new RegExp(logPattern, "iu");
292
+ }
293
+ catch {
294
+ issues.push(`processes "${processId}": readiness.logPattern is not a valid regex`);
295
+ return undefined;
296
+ }
297
+ }
298
+ return {
299
+ port,
300
+ host: asString(record.host),
301
+ logPattern,
302
+ timeoutMs: asPositiveInt(record.timeoutMs),
303
+ intervalMs: asPositiveInt(record.intervalMs),
304
+ };
305
+ }
306
+ function asServiceCategory(value) {
307
+ const categories = ["container", "database", "runtime", "ai", "web"];
308
+ const name = asString(value);
309
+ return name && categories.includes(name)
310
+ ? name
311
+ : "web";
312
+ }
313
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/devcc/core/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { EventEmitter } from "node:events";
2
+ /**
3
+ * Typed event bus.
4
+ *
5
+ * Backend services (processes, git, docker, system) emit events; the app layer
6
+ * translates them into state updates; views read state. Views never call into
7
+ * the backends' internals directly.
8
+ */
9
+ export type EventMap = Record<string, unknown[]>;
10
+ export declare class TypedEmitter<Events extends EventMap> extends EventEmitter<Events> {
11
+ }
12
+ /** A disposable subscription. Calling it twice is safe. */
13
+ export type Unsubscribe = () => void;
14
+ /** Collects unsubscribe functions so a component can tear everything down at once. */
15
+ export declare class Subscriptions {
16
+ private disposers;
17
+ add(unsubscribe: Unsubscribe): Unsubscribe;
18
+ dispose(): void;
19
+ get size(): number;
20
+ }
21
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../src/devcc/core/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE1C;;;;;;GAMG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAA;AAEhD,qBAAa,YAAY,CAAC,MAAM,SAAS,QAAQ,CAAE,SAAQ,YAAY,CAAC,MAAM,CAAC;CAAG;AAElF,2DAA2D;AAC3D,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAA;AAEpC,sFAAsF;AACtF,qBAAa,aAAa;IACxB,OAAO,CAAC,SAAS,CAAoB;IAErC,GAAG,CAAC,WAAW,EAAE,WAAW,GAAG,WAAW;IAK1C,OAAO,IAAI,IAAI;IAYf,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}