kiriya 0.1.0

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 (282) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/LICENSE +21 -0
  3. package/README.md +87 -0
  4. package/dist/src/config/clean-rules.js +39 -0
  5. package/dist/src/config/config-keys.js +24 -0
  6. package/dist/src/config/dependency-directories.js +16 -0
  7. package/dist/src/config/modules.js +38 -0
  8. package/dist/src/config/protected-paths.js +32 -0
  9. package/dist/src/config/rebuildable-directories.js +20 -0
  10. package/dist/src/core/application/command-registry.js +57 -0
  11. package/dist/src/core/application/config-values.js +33 -0
  12. package/dist/src/core/application/path-guard.js +69 -0
  13. package/dist/src/core/application/paths.js +77 -0
  14. package/dist/src/core/application/plugin-loader.js +100 -0
  15. package/dist/src/core/application/process-ending.js +28 -0
  16. package/dist/src/core/application/root-scope.js +123 -0
  17. package/dist/src/core/application/safety.js +26 -0
  18. package/dist/src/core/application/text-input.js +44 -0
  19. package/dist/src/core/application/walk.js +34 -0
  20. package/dist/src/core/domain/command.js +8 -0
  21. package/dist/src/core/domain/encodings.js +70 -0
  22. package/dist/src/core/domain/errors.js +49 -0
  23. package/dist/src/core/domain/glob.js +57 -0
  24. package/dist/src/core/domain/global-options.js +10 -0
  25. package/dist/src/core/domain/input-schema.js +54 -0
  26. package/dist/src/core/domain/message.js +7 -0
  27. package/dist/src/core/domain/module.js +2 -0
  28. package/dist/src/core/domain/names.js +22 -0
  29. package/dist/src/core/domain/ports/clipboard.js +2 -0
  30. package/dist/src/core/domain/ports/clock.js +2 -0
  31. package/dist/src/core/domain/ports/command-catalog.js +2 -0
  32. package/dist/src/core/domain/ports/compression.js +2 -0
  33. package/dist/src/core/domain/ports/config-store.js +2 -0
  34. package/dist/src/core/domain/ports/confirmation.js +2 -0
  35. package/dist/src/core/domain/ports/environment.js +2 -0
  36. package/dist/src/core/domain/ports/file-content.js +2 -0
  37. package/dist/src/core/domain/ports/file-system.js +2 -0
  38. package/dist/src/core/domain/ports/hasher.js +2 -0
  39. package/dist/src/core/domain/ports/network.js +2 -0
  40. package/dist/src/core/domain/ports/opener.js +2 -0
  41. package/dist/src/core/domain/ports/passthrough.js +2 -0
  42. package/dist/src/core/domain/ports/plugin-inventory.js +2 -0
  43. package/dist/src/core/domain/ports/plugin-source.js +2 -0
  44. package/dist/src/core/domain/ports/port-table.js +2 -0
  45. package/dist/src/core/domain/ports/process-runner.js +2 -0
  46. package/dist/src/core/domain/ports/process-table.js +2 -0
  47. package/dist/src/core/domain/ports/protected-paths.js +2 -0
  48. package/dist/src/core/domain/ports/random-source.js +2 -0
  49. package/dist/src/core/domain/ports/standard-input.js +2 -0
  50. package/dist/src/core/domain/ports/system-info.js +2 -0
  51. package/dist/src/core/domain/ports/trash.js +2 -0
  52. package/dist/src/core/domain/secrets.js +59 -0
  53. package/dist/src/core/domain/targets.js +41 -0
  54. package/dist/src/core/domain/text-case.js +39 -0
  55. package/dist/src/core/domain/values/bytes.js +13 -0
  56. package/dist/src/core/domain/view.js +2 -0
  57. package/dist/src/core/infrastructure/node/can-listen.js +10 -0
  58. package/dist/src/core/infrastructure/node/closed-standard-input.adapter.js +12 -0
  59. package/dist/src/core/infrastructure/node/config-location.js +27 -0
  60. package/dist/src/core/infrastructure/node/fs-errors.js +22 -0
  61. package/dist/src/core/infrastructure/node/json-config-store.adapter.js +69 -0
  62. package/dist/src/core/infrastructure/node/node-compression.adapter.js +82 -0
  63. package/dist/src/core/infrastructure/node/node-environment.adapter.js +21 -0
  64. package/dist/src/core/infrastructure/node/node-file-content.adapter.js +99 -0
  65. package/dist/src/core/infrastructure/node/node-file-system.adapter.js +169 -0
  66. package/dist/src/core/infrastructure/node/node-hasher.adapter.js +32 -0
  67. package/dist/src/core/infrastructure/node/node-network.adapter.js +168 -0
  68. package/dist/src/core/infrastructure/node/node-plugin-source.adapter.js +89 -0
  69. package/dist/src/core/infrastructure/node/node-process-runner.adapter.js +48 -0
  70. package/dist/src/core/infrastructure/node/node-random-source.adapter.js +7 -0
  71. package/dist/src/core/infrastructure/node/node-standard-input.adapter.js +24 -0
  72. package/dist/src/core/infrastructure/node/node-system-info.adapter.js +63 -0
  73. package/dist/src/core/infrastructure/node/process-signals.js +51 -0
  74. package/dist/src/core/infrastructure/node/run-program.js +65 -0
  75. package/dist/src/core/infrastructure/node/system-clock.adapter.js +22 -0
  76. package/dist/src/core/infrastructure/node/typed-programs.js +45 -0
  77. package/dist/src/core/infrastructure/platform/linux/freedesktop-trash.adapter.js +115 -0
  78. package/dist/src/core/infrastructure/platform/linux/linux-clipboard.adapter.js +70 -0
  79. package/dist/src/core/infrastructure/platform/linux/linux-opener.adapter.js +21 -0
  80. package/dist/src/core/infrastructure/platform/linux/linux-port-table.adapter.js +97 -0
  81. package/dist/src/core/infrastructure/platform/linux/linux-process-table.adapter.js +61 -0
  82. package/dist/src/core/infrastructure/platform/macos/macos-clipboard.adapter.js +29 -0
  83. package/dist/src/core/infrastructure/platform/macos/macos-opener.adapter.js +13 -0
  84. package/dist/src/core/infrastructure/platform/macos/macos-port-table.adapter.js +86 -0
  85. package/dist/src/core/infrastructure/platform/macos/macos-process-table.adapter.js +62 -0
  86. package/dist/src/core/infrastructure/platform/macos/macos-trash.adapter.js +64 -0
  87. package/dist/src/core/infrastructure/platform/windows/system32.js +6 -0
  88. package/dist/src/core/infrastructure/platform/windows/windows-clipboard.adapter.js +50 -0
  89. package/dist/src/core/infrastructure/platform/windows/windows-opener.adapter.js +11 -0
  90. package/dist/src/core/infrastructure/platform/windows/windows-port-table.adapter.js +38 -0
  91. package/dist/src/core/infrastructure/platform/windows/windows-process-table.adapter.js +134 -0
  92. package/dist/src/core/infrastructure/platform/windows/windows-trash.adapter.js +86 -0
  93. package/dist/src/core/presentation/cli/argv.js +83 -0
  94. package/dist/src/core/presentation/cli/cli-application.js +201 -0
  95. package/dist/src/core/presentation/cli/cli-view-format.js +46 -0
  96. package/dist/src/core/presentation/cli/help.js +202 -0
  97. package/dist/src/core/presentation/cli/json-output.js +28 -0
  98. package/dist/src/core/presentation/cli/style.js +21 -0
  99. package/dist/src/core/presentation/cli/suggest.js +25 -0
  100. package/dist/src/core/presentation/cli/terminal-confirmation.js +63 -0
  101. package/dist/src/core/presentation/ended-processes.js +18 -0
  102. package/dist/src/core/presentation/i18n/translator.js +23 -0
  103. package/dist/src/core/presentation/list-preview.js +10 -0
  104. package/dist/src/core/presentation/mcp/elicitation.js +55 -0
  105. package/dist/src/core/presentation/mcp/mcp-application.js +60 -0
  106. package/dist/src/core/presentation/mcp/mcp-confirmation.js +59 -0
  107. package/dist/src/core/presentation/mcp/mcp-server.js +355 -0
  108. package/dist/src/core/presentation/mcp/protocol.js +32 -0
  109. package/dist/src/core/presentation/mcp/request-state.js +66 -0
  110. package/dist/src/core/presentation/mcp/tool-definitions.js +149 -0
  111. package/dist/src/core/presentation/mcp/tool-results.js +56 -0
  112. package/dist/src/i18n/locales/en.js +827 -0
  113. package/dist/src/main.js +154 -0
  114. package/dist/src/modules/archive/application/archive-sources.js +55 -0
  115. package/dist/src/modules/archive/application/create-tar.use-case.js +123 -0
  116. package/dist/src/modules/archive/application/create-zip.use-case.js +106 -0
  117. package/dist/src/modules/archive/application/extract-tar.use-case.js +240 -0
  118. package/dist/src/modules/archive/application/extract-zip.use-case.js +181 -0
  119. package/dist/src/modules/archive/application/tar-reader.js +45 -0
  120. package/dist/src/modules/archive/application/zip-reader.js +57 -0
  121. package/dist/src/modules/archive/archive.module.js +27 -0
  122. package/dist/src/modules/archive/domain/crc32.js +18 -0
  123. package/dist/src/modules/archive/domain/tar-format.js +97 -0
  124. package/dist/src/modules/archive/domain/tar-stream.js +223 -0
  125. package/dist/src/modules/archive/domain/zip-format.js +158 -0
  126. package/dist/src/modules/archive/presentation/tar.view.js +17 -0
  127. package/dist/src/modules/archive/presentation/untar.view.js +30 -0
  128. package/dist/src/modules/archive/presentation/unzip.view.js +24 -0
  129. package/dist/src/modules/archive/presentation/zip.view.js +17 -0
  130. package/dist/src/modules/clip/application/copy-text.use-case.js +43 -0
  131. package/dist/src/modules/clip/application/paste-text.use-case.js +25 -0
  132. package/dist/src/modules/clip/clip.module.js +16 -0
  133. package/dist/src/modules/clip/presentation/clip.views.js +7 -0
  134. package/dist/src/modules/completion/application/print-script.use-case.js +38 -0
  135. package/dist/src/modules/completion/application/suggest-words.use-case.js +37 -0
  136. package/dist/src/modules/completion/completion.module.js +14 -0
  137. package/dist/src/modules/completion/domain/scripts.js +91 -0
  138. package/dist/src/modules/completion/domain/suggest.js +134 -0
  139. package/dist/src/modules/completion/presentation/completion.views.js +6 -0
  140. package/dist/src/modules/config/application/config-commands.js +14 -0
  141. package/dist/src/modules/config/application/get-setting.use-case.js +25 -0
  142. package/dist/src/modules/config/application/list-config-keys.use-case.js +26 -0
  143. package/dist/src/modules/config/application/list-settings.use-case.js +28 -0
  144. package/dist/src/modules/config/application/set-setting.use-case.js +53 -0
  145. package/dist/src/modules/config/application/show-config-path.use-case.js +21 -0
  146. package/dist/src/modules/config/application/unset-setting.use-case.js +28 -0
  147. package/dist/src/modules/config/config.module.js +28 -0
  148. package/dist/src/modules/config/presentation/config.views.js +33 -0
  149. package/dist/src/modules/convert/application/convert-case.use-case.js +38 -0
  150. package/dist/src/modules/convert/application/convert-codecs.use-case.js +92 -0
  151. package/dist/src/modules/convert/application/convert-input.js +16 -0
  152. package/dist/src/modules/convert/application/convert-json.use-case.js +51 -0
  153. package/dist/src/modules/convert/application/convert-time.use-case.js +39 -0
  154. package/dist/src/modules/convert/application/decode-jwt.use-case.js +52 -0
  155. package/dist/src/modules/convert/convert.module.js +29 -0
  156. package/dist/src/modules/convert/domain/json-syntax.js +135 -0
  157. package/dist/src/modules/convert/domain/jwt.js +29 -0
  158. package/dist/src/modules/convert/domain/moments.js +20 -0
  159. package/dist/src/modules/convert/presentation/convert.views.js +44 -0
  160. package/dist/src/modules/docker/application/clean-engine.use-case.js +77 -0
  161. package/dist/src/modules/docker/application/compose-project.js +45 -0
  162. package/dist/src/modules/docker/application/docker-engine.js +40 -0
  163. package/dist/src/modules/docker/application/list-containers.use-case.js +69 -0
  164. package/dist/src/modules/docker/application/run-compose.use-case.js +83 -0
  165. package/dist/src/modules/docker/application/show-logs.use-case.js +51 -0
  166. package/dist/src/modules/docker/application/stop-project.use-case.js +56 -0
  167. package/dist/src/modules/docker/docker.module.js +23 -0
  168. package/dist/src/modules/docker/domain/compose-file.js +105 -0
  169. package/dist/src/modules/docker/domain/engine-output.js +65 -0
  170. package/dist/src/modules/docker/presentation/docker.views.js +63 -0
  171. package/dist/src/modules/doctor/application/run-checks.use-case.js +128 -0
  172. package/dist/src/modules/doctor/doctor.module.js +13 -0
  173. package/dist/src/modules/doctor/domain/versions.js +22 -0
  174. package/dist/src/modules/doctor/presentation/doctor.view.js +30 -0
  175. package/dist/src/modules/env/application/check-dotenv.use-case.js +116 -0
  176. package/dist/src/modules/env/application/inspect-path.use-case.js +71 -0
  177. package/dist/src/modules/env/application/path-entries.js +28 -0
  178. package/dist/src/modules/env/application/show-variables.use-case.js +47 -0
  179. package/dist/src/modules/env/domain/dotenv.js +62 -0
  180. package/dist/src/modules/env/env.module.js +17 -0
  181. package/dist/src/modules/env/presentation/env.views.js +43 -0
  182. package/dist/src/modules/files/application/clean-builds.use-case.js +149 -0
  183. package/dist/src/modules/files/application/compare-paths.use-case.js +127 -0
  184. package/dist/src/modules/files/application/copy-paths.use-case.js +101 -0
  185. package/dist/src/modules/files/application/create-paths.use-case.js +85 -0
  186. package/dist/src/modules/files/application/delete-paths.use-case.js +127 -0
  187. package/dist/src/modules/files/application/find-duplicates.use-case.js +105 -0
  188. package/dist/src/modules/files/application/find-files.use-case.js +131 -0
  189. package/dist/src/modules/files/application/hash-files.use-case.js +73 -0
  190. package/dist/src/modules/files/application/list-entries.use-case.js +87 -0
  191. package/dist/src/modules/files/application/measure-folders.use-case.js +102 -0
  192. package/dist/src/modules/files/application/move-entry.js +19 -0
  193. package/dist/src/modules/files/application/move-paths.use-case.js +82 -0
  194. package/dist/src/modules/files/application/read-text.use-case.js +92 -0
  195. package/dist/src/modules/files/application/rename-paths.use-case.js +184 -0
  196. package/dist/src/modules/files/application/replace-text.use-case.js +146 -0
  197. package/dist/src/modules/files/application/search-text.use-case.js +115 -0
  198. package/dist/src/modules/files/application/show-info.use-case.js +80 -0
  199. package/dist/src/modules/files/application/show-tree.use-case.js +75 -0
  200. package/dist/src/modules/files/application/sync-folders.use-case.js +162 -0
  201. package/dist/src/modules/files/application/text-files.js +46 -0
  202. package/dist/src/modules/files/application/transfers.js +35 -0
  203. package/dist/src/modules/files/domain/case-style.js +18 -0
  204. package/dist/src/modules/files/domain/filters.js +9 -0
  205. package/dist/src/modules/files/domain/sync-plan.js +35 -0
  206. package/dist/src/modules/files/domain/text-encoding.js +75 -0
  207. package/dist/src/modules/files/domain/values.js +28 -0
  208. package/dist/src/modules/files/files.module.js +70 -0
  209. package/dist/src/modules/files/presentation/clean.view.js +15 -0
  210. package/dist/src/modules/files/presentation/compare.view.js +50 -0
  211. package/dist/src/modules/files/presentation/copy.view.js +17 -0
  212. package/dist/src/modules/files/presentation/delete.view.js +16 -0
  213. package/dist/src/modules/files/presentation/dupes.view.js +20 -0
  214. package/dist/src/modules/files/presentation/find.view.js +16 -0
  215. package/dist/src/modules/files/presentation/grep.view.js +27 -0
  216. package/dist/src/modules/files/presentation/hash.view.js +15 -0
  217. package/dist/src/modules/files/presentation/info.view.js +36 -0
  218. package/dist/src/modules/files/presentation/list.view.js +17 -0
  219. package/dist/src/modules/files/presentation/move.view.js +14 -0
  220. package/dist/src/modules/files/presentation/new.view.js +8 -0
  221. package/dist/src/modules/files/presentation/read.view.js +6 -0
  222. package/dist/src/modules/files/presentation/rename.view.js +16 -0
  223. package/dist/src/modules/files/presentation/replace.view.js +26 -0
  224. package/dist/src/modules/files/presentation/size.view.js +24 -0
  225. package/dist/src/modules/files/presentation/sync.view.js +37 -0
  226. package/dist/src/modules/files/presentation/tree.view.js +22 -0
  227. package/dist/src/modules/gen/application/gen-options.js +18 -0
  228. package/dist/src/modules/gen/application/generate-passwords.use-case.js +39 -0
  229. package/dist/src/modules/gen/application/generate-tokens.use-case.js +38 -0
  230. package/dist/src/modules/gen/application/generate-ulids.use-case.js +40 -0
  231. package/dist/src/modules/gen/application/generate-uuids.use-case.js +32 -0
  232. package/dist/src/modules/gen/domain/identifiers.js +65 -0
  233. package/dist/src/modules/gen/domain/secrets.js +43 -0
  234. package/dist/src/modules/gen/gen.module.js +20 -0
  235. package/dist/src/modules/git/application/fetch-repositories.use-case.js +50 -0
  236. package/dist/src/modules/git/application/git-client.js +62 -0
  237. package/dist/src/modules/git/application/pull-repositories.use-case.js +67 -0
  238. package/dist/src/modules/git/application/repositories.js +67 -0
  239. package/dist/src/modules/git/application/show-status.use-case.js +49 -0
  240. package/dist/src/modules/git/application/switch-branch.use-case.js +118 -0
  241. package/dist/src/modules/git/domain/repository-status.js +37 -0
  242. package/dist/src/modules/git/git.module.js +25 -0
  243. package/dist/src/modules/git/presentation/git.views.js +100 -0
  244. package/dist/src/modules/net/application/check-connection.use-case.js +71 -0
  245. package/dist/src/modules/net/application/list-addresses.use-case.js +29 -0
  246. package/dist/src/modules/net/application/lookup-name.use-case.js +55 -0
  247. package/dist/src/modules/net/net.module.js +17 -0
  248. package/dist/src/modules/net/presentation/net.views.js +39 -0
  249. package/dist/src/modules/open/application/open-target.use-case.js +53 -0
  250. package/dist/src/modules/open/domain/targets.js +45 -0
  251. package/dist/src/modules/open/open.module.js +12 -0
  252. package/dist/src/modules/open/presentation/open.view.js +6 -0
  253. package/dist/src/modules/port/application/end-port-owners.use-case.js +68 -0
  254. package/dist/src/modules/port/application/find-free-port.use-case.js +40 -0
  255. package/dist/src/modules/port/application/find-listeners.use-case.js +34 -0
  256. package/dist/src/modules/port/application/port-owners.js +25 -0
  257. package/dist/src/modules/port/domain/port-number.js +8 -0
  258. package/dist/src/modules/port/port.module.js +17 -0
  259. package/dist/src/modules/port/presentation/port.views.js +27 -0
  260. package/dist/src/modules/proc/application/end-processes.use-case.js +77 -0
  261. package/dist/src/modules/proc/application/find-processes.use-case.js +50 -0
  262. package/dist/src/modules/proc/application/list-processes.use-case.js +41 -0
  263. package/dist/src/modules/proc/application/show-tree.use-case.js +40 -0
  264. package/dist/src/modules/proc/domain/process-tree.js +55 -0
  265. package/dist/src/modules/proc/presentation/proc.views.js +28 -0
  266. package/dist/src/modules/proc/proc.module.js +19 -0
  267. package/dist/src/modules/sys/application/create-report.use-case.js +30 -0
  268. package/dist/src/modules/sys/application/find-tools.use-case.js +20 -0
  269. package/dist/src/modules/sys/application/machine-facts.js +44 -0
  270. package/dist/src/modules/sys/application/show-info.use-case.js +29 -0
  271. package/dist/src/modules/sys/domain/tools.js +17 -0
  272. package/dist/src/modules/sys/presentation/sys.views.js +67 -0
  273. package/dist/src/modules/sys/sys.module.js +17 -0
  274. package/dist/src/modules/wait/application/poll.js +26 -0
  275. package/dist/src/modules/wait/application/wait-file.use-case.js +55 -0
  276. package/dist/src/modules/wait/application/wait-port.use-case.js +76 -0
  277. package/dist/src/modules/wait/application/wait-url.use-case.js +71 -0
  278. package/dist/src/modules/wait/domain/reasons.js +14 -0
  279. package/dist/src/modules/wait/domain/wait-input.js +50 -0
  280. package/dist/src/modules/wait/presentation/wait.views.js +31 -0
  281. package/dist/src/modules/wait/wait.module.js +21 -0
  282. package/package.json +57 -0
@@ -0,0 +1,135 @@
1
+ class Stop {
2
+ offset;
3
+ constructor(offset) {
4
+ this.offset = offset;
5
+ }
6
+ }
7
+ const NUMBER = /-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?/y;
8
+ /**
9
+ * Where JSON text first breaks the grammar, or null when it is valid. JSON.parse's
10
+ * messages differ between Node.js versions and often give no position, so kiriya
11
+ * finds the place itself and every version reports the same line and column.
12
+ */
13
+ export function findJsonProblem(text) {
14
+ try {
15
+ scan(text);
16
+ return null;
17
+ }
18
+ catch (error) {
19
+ if (!(error instanceof Stop))
20
+ throw error;
21
+ const offset = Math.min(error.offset, text.length);
22
+ const before = text.slice(0, offset);
23
+ const lineStart = before.lastIndexOf("\n") + 1;
24
+ return { offset, line: before.split("\n").length, column: offset - lineStart + 1 };
25
+ }
26
+ }
27
+ /** Throws Stop at the first character that breaks the grammar. Keeps its own stack, so deep nesting cannot overflow. */
28
+ function scan(text) {
29
+ let at = 0;
30
+ const fail = () => {
31
+ throw new Stop(at);
32
+ };
33
+ const skipSpace = () => {
34
+ while (at < text.length && " \t\n\r".includes(text.charAt(at)))
35
+ at += 1;
36
+ };
37
+ const expect = (char) => {
38
+ if (text.charAt(at) !== char)
39
+ fail();
40
+ at += 1;
41
+ };
42
+ const string = () => {
43
+ at += 1;
44
+ while (at < text.length) {
45
+ const code = text.charCodeAt(at);
46
+ if (code === 0x22) {
47
+ at += 1;
48
+ return;
49
+ }
50
+ if (code < 0x20)
51
+ fail();
52
+ if (code !== 0x5c) {
53
+ at += 1;
54
+ continue;
55
+ }
56
+ const escaped = text.charAt(at + 1);
57
+ if (escaped !== "" && '"\\/bfnrt'.includes(escaped)) {
58
+ at += 2;
59
+ }
60
+ else if (escaped === "u" && /^[0-9a-fA-F]{4}$/.test(text.slice(at + 2, at + 6))) {
61
+ at += 6;
62
+ }
63
+ else {
64
+ at += 1;
65
+ fail();
66
+ }
67
+ }
68
+ fail();
69
+ };
70
+ const key = () => {
71
+ skipSpace();
72
+ if (text.charAt(at) !== '"')
73
+ fail();
74
+ string();
75
+ skipSpace();
76
+ expect(":");
77
+ };
78
+ const scalar = () => {
79
+ if (text.charAt(at) === '"') {
80
+ string();
81
+ return;
82
+ }
83
+ for (const word of ["true", "false", "null"]) {
84
+ if (text.startsWith(word, at)) {
85
+ at += word.length;
86
+ return;
87
+ }
88
+ }
89
+ NUMBER.lastIndex = at;
90
+ if (!NUMBER.test(text))
91
+ fail();
92
+ at = NUMBER.lastIndex;
93
+ };
94
+ /** The closing characters of the arrays and objects the scan is inside. */
95
+ const open = [];
96
+ for (;;) {
97
+ // A value starts here.
98
+ skipSpace();
99
+ const char = text.charAt(at);
100
+ if (char === "{" || char === "[") {
101
+ const close = char === "{" ? "}" : "]";
102
+ at += 1;
103
+ skipSpace();
104
+ if (text.charAt(at) !== close) {
105
+ open.push(close);
106
+ if (close === "}")
107
+ key();
108
+ continue;
109
+ }
110
+ at += 1;
111
+ }
112
+ else {
113
+ scalar();
114
+ }
115
+ // A value ended: a comma leads to the next one, or the arrays and objects around it close.
116
+ for (;;) {
117
+ skipSpace();
118
+ const close = open.at(-1);
119
+ if (close === undefined) {
120
+ if (at !== text.length)
121
+ fail();
122
+ return;
123
+ }
124
+ if (text.charAt(at) === ",") {
125
+ at += 1;
126
+ if (close === "}")
127
+ key();
128
+ break;
129
+ }
130
+ expect(close);
131
+ open.pop();
132
+ }
133
+ }
134
+ }
135
+ //# sourceMappingURL=json-syntax.js.map
@@ -0,0 +1,29 @@
1
+ import { fromBase64, utf8Text } from "../../../core/domain/encodings.js";
2
+ function jsonObject(segment) {
3
+ const bytes = fromBase64(segment);
4
+ const text = bytes === null ? null : utf8Text(bytes);
5
+ if (text === null)
6
+ return null;
7
+ try {
8
+ const parsed = JSON.parse(text);
9
+ return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : null;
10
+ }
11
+ catch {
12
+ return null;
13
+ }
14
+ }
15
+ /** A JWT's header and payload, without looking at its signature; null when it is not a JWT. */
16
+ export function decodeJwt(token) {
17
+ const parts = token.trim().split(".");
18
+ if (parts.length !== 3)
19
+ return null;
20
+ const header = jsonObject(parts[0] ?? "");
21
+ const payload = jsonObject(parts[1] ?? "");
22
+ return header === null || payload === null ? null : { header, payload };
23
+ }
24
+ /** A NumericDate claim such as `exp`, in seconds, as epoch milliseconds; null when absent or not a number. */
25
+ export function claimTime(payload, claim) {
26
+ const value = payload[claim];
27
+ return typeof value === "number" && Number.isFinite(value) ? Math.round(value * 1000) : null;
28
+ }
29
+ //# sourceMappingURL=jwt.js.map
@@ -0,0 +1,20 @@
1
+ export const EPOCH_UNITS = ["auto", "seconds", "ms"];
2
+ /** JavaScript dates reach 8.64e15 milliseconds either side of 1970. */
3
+ const LIMIT_MS = 8.64e15;
4
+ /**
5
+ * A moment as epoch milliseconds, from a number or a date; null when it is neither.
6
+ * With `auto`, numbers below 10^11 are seconds: 10^11 seconds is the year 5138,
7
+ * while 10^11 milliseconds is only 1973.
8
+ */
9
+ export function parseMoment(value, unit) {
10
+ const trimmed = value.trim();
11
+ if (/^-?\d+(\.\d+)?$/.test(trimmed)) {
12
+ const number = Number(trimmed);
13
+ const seconds = unit === "seconds" || (unit === "auto" && Math.abs(number) < 1e11);
14
+ const ms = Math.round(seconds ? number * 1000 : number);
15
+ return Math.abs(ms) <= LIMIT_MS ? ms : null;
16
+ }
17
+ const parsed = Date.parse(trimmed);
18
+ return Number.isNaN(parsed) ? null : parsed;
19
+ }
20
+ //# sourceMappingURL=moments.js.map
@@ -0,0 +1,44 @@
1
+ import { message } from "../../../core/domain/message.js";
2
+ /** Only the result, so it can be piped or captured. */
3
+ export const outputView = (output) => output.output.split("\n");
4
+ /** Invalid JSON prints nothing here: the failure names the line and column. */
5
+ export const jsonView = (output, format) => {
6
+ if (!output.valid)
7
+ return [];
8
+ if (output.output === null)
9
+ return [format.green(format.text(message("convert.json.valid")))];
10
+ return output.output.split("\n");
11
+ };
12
+ export const jwtView = (output, format) => {
13
+ const lines = [
14
+ format.bold(format.text(message("convert.jwt.header"))),
15
+ ...JSON.stringify(output.header, null, 2).split("\n"),
16
+ "",
17
+ format.bold(format.text(message("convert.jwt.payload"))),
18
+ ...JSON.stringify(output.payload, null, 2).split("\n"),
19
+ ];
20
+ const times = [
21
+ ["convert.jwt.issued", output.issuedAt],
22
+ ["convert.jwt.not-before", output.notBefore],
23
+ [output.expired === true ? "convert.jwt.expired" : "convert.jwt.expires", output.expiresAt],
24
+ ];
25
+ const present = times.filter((entry) => entry[1] !== null);
26
+ if (present.length > 0)
27
+ lines.push("");
28
+ for (const [key, time] of present) {
29
+ const text = format.text(message(key, { time: format.time(Date.parse(time)) }));
30
+ lines.push(key === "convert.jwt.expired" ? format.red(text) : text);
31
+ }
32
+ return lines;
33
+ };
34
+ export const timeView = (output, format) => {
35
+ const rows = [
36
+ [format.text(message("convert.time.label.iso")), output.iso],
37
+ [format.text(message("convert.time.label.local")), format.time(output.epochMs)],
38
+ [format.text(message("convert.time.label.seconds")), String(output.epochSeconds)],
39
+ [format.text(message("convert.time.label.ms")), String(output.epochMs)],
40
+ ];
41
+ const width = Math.max(...rows.map(([label]) => label.length));
42
+ return rows.map(([label, value]) => ` ${label.padEnd(width)} ${value}`);
43
+ };
44
+ //# sourceMappingURL=convert.views.js.map
@@ -0,0 +1,77 @@
1
+ import { requireTypedConfirmation } from "../../../core/application/safety.js";
2
+ import { done, preview } from "../../../core/domain/command.js";
3
+ import { OperationFailedError } from "../../../core/domain/errors.js";
4
+ import { RawReader } from "../../../core/domain/input-schema.js";
5
+ import { message } from "../../../core/domain/message.js";
6
+ import { parseDiskUsage, reclaimedSpace } from "../domain/engine-output.js";
7
+ import { DockerEngine } from "./docker-engine.js";
8
+ /** The word a script passes as --confirm, since there is no single count to type. */
9
+ export const CLEAN_CONFIRMATION = "prune";
10
+ const PRUNE_TIMEOUT_MS = 10 * 60_000;
11
+ export const cleanSpec = {
12
+ id: "docker.clean",
13
+ summary: "docker.clean.summary",
14
+ examples: [
15
+ "kiriya docker clean",
16
+ "kiriya docker clean --apply",
17
+ "kiriya docker clean --volumes --apply --confirm=prune",
18
+ ],
19
+ safety: "destroy",
20
+ idempotent: true,
21
+ usesNetwork: false,
22
+ runsUserCommands: false,
23
+ input: {
24
+ positionals: [],
25
+ options: {
26
+ volumes: { type: "boolean", description: "docker.clean.option.volumes" },
27
+ apply: { type: "boolean", description: "docker.clean.option.apply" },
28
+ confirm: {
29
+ type: "string",
30
+ description: "docker.clean.option.confirm",
31
+ valueName: CLEAN_CONFIRMATION,
32
+ terminalOnly: true,
33
+ },
34
+ },
35
+ parse(raw) {
36
+ const reader = new RawReader(raw);
37
+ return { volumes: reader.flag("volumes"), apply: reader.flag("apply"), confirm: reader.string("confirm") };
38
+ },
39
+ },
40
+ };
41
+ /**
42
+ * Stopped containers, dangling images, unused networks and the build cache; unused
43
+ * anonymous volumes only with --volumes. Named volumes and images in use are never pruned.
44
+ */
45
+ export class CleanEngine {
46
+ processRunner;
47
+ spec = cleanSpec;
48
+ constructor(processRunner) {
49
+ this.processRunner = processRunner;
50
+ }
51
+ async execute(input, context) {
52
+ const engine = await DockerEngine.connect(this.processRunner, context.signal);
53
+ const df = await engine.capture(["system", "df", "--format", "{{json .}}"]);
54
+ if (df.code !== 0) {
55
+ throw new OperationFailedError("docker.command-failed", { command: "system df", detail: df.stderr.trim() });
56
+ }
57
+ const data = { usage: parseDiskUsage(df.stdout), volumes: input.volumes, results: [] };
58
+ if (!input.apply)
59
+ return preview(data, "--apply");
60
+ const warning = message(input.volumes ? "docker.clean.warn-volumes" : "docker.clean.warn");
61
+ await requireTypedConfirmation(context, warning, CLEAN_CONFIRMATION, input.confirm);
62
+ const targets = ["container", "image", "network", "builder", ...(input.volumes ? ["volume"] : [])];
63
+ const results = [];
64
+ const failures = [];
65
+ for (const target of targets) {
66
+ if (context.signal.aborted)
67
+ break;
68
+ const pruned = await engine.capture([target, "prune", "--force"], PRUNE_TIMEOUT_MS);
69
+ const succeeded = pruned.code === 0;
70
+ if (!succeeded)
71
+ failures.push(message("docker.clean.failed", { target, detail: pruned.stderr.trim() }));
72
+ results.push({ target, succeeded, reclaimed: reclaimedSpace(pruned.stdout) });
73
+ }
74
+ return done({ ...data, results }, { failures });
75
+ }
76
+ }
77
+ //# sourceMappingURL=clean-engine.use-case.js.map
@@ -0,0 +1,45 @@
1
+ import path from "node:path";
2
+ import { NotFoundError } from "../../../core/domain/errors.js";
3
+ import { COMPOSE_FILE_NAMES, parseCompose, projectNameFromFolder, } from "../domain/compose-file.js";
4
+ export const fileOption = {
5
+ type: "string",
6
+ description: "docker.option.file",
7
+ valueName: "<compose.yaml>",
8
+ path: true,
9
+ };
10
+ export const servicesPositional = {
11
+ name: "services",
12
+ description: "docker.arg.services",
13
+ required: false,
14
+ variadic: true,
15
+ };
16
+ /** The compose file --file names, or the one docker compose would pick in the working folder. */
17
+ export async function findComposeProject(fileSystem, content, cwd, fileArg) {
18
+ let file = null;
19
+ if (fileArg !== undefined) {
20
+ const target = path.resolve(cwd, fileArg);
21
+ if ((await fileSystem.stat(target))?.kind !== "file")
22
+ throw new NotFoundError("core.fs.not-found", { path: target });
23
+ file = target;
24
+ }
25
+ else {
26
+ for (const name of COMPOSE_FILE_NAMES) {
27
+ const candidate = path.join(cwd, name);
28
+ if ((await fileSystem.stat(candidate))?.kind === "file") {
29
+ file = candidate;
30
+ break;
31
+ }
32
+ }
33
+ }
34
+ if (file === null)
35
+ throw new NotFoundError("docker.no-compose-file", { folder: cwd });
36
+ const folder = path.dirname(file);
37
+ const text = new TextDecoder().decode(await content.read(file));
38
+ const summary = parseCompose(text, projectNameFromFolder(path.basename(folder)));
39
+ return { name: summary.project, file, folder, services: summary.services };
40
+ }
41
+ /** Arguments for `docker compose` that pin the file and folder, so it never picks up another project. */
42
+ export function composeArgs(project, args) {
43
+ return ["compose", "--file", project.file, "--project-directory", project.folder, ...args];
44
+ }
45
+ //# sourceMappingURL=compose-project.js.map
@@ -0,0 +1,40 @@
1
+ import { CapabilityUnavailableError } from "../../../core/domain/errors.js";
2
+ const PROBE_TIMEOUT_MS = 30_000;
3
+ /** The docker CLI with a running engine behind it. */
4
+ export class DockerEngine {
5
+ runner;
6
+ docker;
7
+ signal;
8
+ constructor(runner, docker, signal) {
9
+ this.runner = runner;
10
+ this.docker = docker;
11
+ this.signal = signal;
12
+ }
13
+ /** CapabilityUnavailableError when docker is not on PATH, or its engine does not answer. */
14
+ static async connect(runner, signal) {
15
+ const docker = await runner.find("docker");
16
+ if (docker === null)
17
+ throw new CapabilityUnavailableError("docker.not-installed");
18
+ const probe = await runner.run(docker, ["version", "--format", "{{.Server.Version}}"], {
19
+ timeoutMs: PROBE_TIMEOUT_MS,
20
+ signal,
21
+ });
22
+ if (probe.code !== 0 || probe.stdout.trim() === "")
23
+ throw new CapabilityUnavailableError("docker.not-running");
24
+ return new DockerEngine(runner, docker, signal);
25
+ }
26
+ /** For output kiriya reads. */
27
+ capture(args, timeoutMs = 60_000) {
28
+ return this.runner.run(this.docker, args, { timeoutMs, signal: this.signal });
29
+ }
30
+ /** For output a person reads as it arrives, such as a build or logs; no time limit, and the exit code back. */
31
+ async stream(args, passthrough) {
32
+ const result = await this.runner.run(this.docker, args, {
33
+ timeoutMs: 0,
34
+ signal: this.signal,
35
+ onOutput: (text, stream) => passthrough.write(text, stream),
36
+ });
37
+ return result.code;
38
+ }
39
+ }
40
+ //# sourceMappingURL=docker-engine.js.map
@@ -0,0 +1,69 @@
1
+ import { done } from "../../../core/domain/command.js";
2
+ import { NotFoundError, OperationFailedError } from "../../../core/domain/errors.js";
3
+ import { RawReader } from "../../../core/domain/input-schema.js";
4
+ import { parseContainers, parseProjects } from "../domain/engine-output.js";
5
+ import { composeArgs, fileOption, findComposeProject } from "./compose-project.js";
6
+ import { DockerEngine } from "./docker-engine.js";
7
+ export const psSpec = {
8
+ id: "docker.ps",
9
+ summary: "docker.ps.summary",
10
+ examples: ["kiriya docker ps", "kiriya docker ps --projects", "kiriya docker ps --file deploy/compose.yaml --json"],
11
+ safety: "read",
12
+ idempotent: true,
13
+ usesNetwork: false,
14
+ runsUserCommands: false,
15
+ input: {
16
+ positionals: [],
17
+ options: { file: fileOption, projects: { type: "boolean", description: "docker.ps.option.projects" } },
18
+ parse(raw) {
19
+ const reader = new RawReader(raw);
20
+ return { file: reader.string("file"), projects: reader.flag("projects") };
21
+ },
22
+ },
23
+ };
24
+ /** The containers of the project here; every compose project with --projects, or when there is no project here. */
25
+ export class ListContainers {
26
+ fileSystem;
27
+ content;
28
+ processRunner;
29
+ spec = psSpec;
30
+ constructor(fileSystem, content, processRunner) {
31
+ this.fileSystem = fileSystem;
32
+ this.content = content;
33
+ this.processRunner = processRunner;
34
+ }
35
+ async execute(input, context) {
36
+ const project = input.projects ? null : await this.projectHere(input, context.cwd);
37
+ const engine = await DockerEngine.connect(this.processRunner, context.signal);
38
+ if (project === null) {
39
+ const listed = await engine.capture(["compose", "ls", "--all", "--format", "json"]);
40
+ if (listed.code !== 0)
41
+ throw new OperationFailedError("docker.command-failed", {
42
+ command: "compose ls",
43
+ detail: listed.stderr.trim(),
44
+ });
45
+ return done({ mode: "projects", projects: parseProjects(listed.stdout) });
46
+ }
47
+ const listed = await engine.capture(composeArgs(project, ["ps", "--all", "--format", "json"]));
48
+ if (listed.code !== 0)
49
+ throw new OperationFailedError("docker.command-failed", { command: "compose ps", detail: listed.stderr.trim() });
50
+ return done({
51
+ mode: "project",
52
+ project: project.name,
53
+ file: project.file,
54
+ containers: parseContainers(listed.stdout),
55
+ });
56
+ }
57
+ async projectHere(input, cwd) {
58
+ try {
59
+ return await findComposeProject(this.fileSystem, this.content, cwd, input.file);
60
+ }
61
+ catch (error) {
62
+ if (input.file === undefined && error instanceof NotFoundError && error.detail.key === "docker.no-compose-file") {
63
+ return null;
64
+ }
65
+ throw error;
66
+ }
67
+ }
68
+ }
69
+ //# sourceMappingURL=list-containers.use-case.js.map
@@ -0,0 +1,83 @@
1
+ import { done } from "../../../core/domain/command.js";
2
+ import { RawReader } from "../../../core/domain/input-schema.js";
3
+ import { message } from "../../../core/domain/message.js";
4
+ import { portMappings } from "../domain/compose-file.js";
5
+ import { composeArgs, fileOption, findComposeProject, servicesPositional } from "./compose-project.js";
6
+ import { DockerEngine } from "./docker-engine.js";
7
+ /** `up` and `rebuild` differ only in the compose arguments and their messages. */
8
+ class StartProject {
9
+ spec;
10
+ variant;
11
+ fileSystem;
12
+ content;
13
+ processRunner;
14
+ constructor(spec, variant, fileSystem, content, processRunner) {
15
+ this.spec = spec;
16
+ this.variant = variant;
17
+ this.fileSystem = fileSystem;
18
+ this.content = content;
19
+ this.processRunner = processRunner;
20
+ }
21
+ async execute(input, context) {
22
+ const project = await findComposeProject(this.fileSystem, this.content, context.cwd, input.file);
23
+ const engine = await DockerEngine.connect(this.processRunner, context.signal);
24
+ const code = await engine.stream(composeArgs(project, this.variant.args(input)), context.passthrough);
25
+ const started = project.services.filter((service) => input.services.length === 0 || input.services.includes(service.name));
26
+ const output = {
27
+ project: project.name,
28
+ file: project.file,
29
+ services: input.services,
30
+ succeeded: code === 0,
31
+ ports: code === 0 ? portMappings(started) : [],
32
+ };
33
+ const failures = code === 0 ? [] : [message(this.variant.failed, { project: project.name, code })];
34
+ return done(output, { failures });
35
+ }
36
+ }
37
+ /** Starting a compose project runs whatever programs its compose file names, so it is never an MCP tool. */
38
+ const COMPOSE_START = { idempotent: true, usesNetwork: false, runsUserCommands: true };
39
+ export const upSpec = {
40
+ id: "docker.up",
41
+ summary: "docker.up.summary",
42
+ examples: ["kiriya docker up", "kiriya docker up api db --build", "kiriya docker up --file deploy/compose.yaml"],
43
+ safety: "write",
44
+ ...COMPOSE_START,
45
+ input: {
46
+ positionals: [servicesPositional],
47
+ options: { file: fileOption, build: { type: "boolean", description: "docker.up.option.build" } },
48
+ parse(raw) {
49
+ const reader = new RawReader(raw);
50
+ return { services: reader.positionalsFrom(0), file: reader.string("file"), build: reader.flag("build") };
51
+ },
52
+ },
53
+ };
54
+ export const rebuildSpec = {
55
+ id: "docker.rebuild",
56
+ summary: "docker.rebuild.summary",
57
+ examples: ["kiriya docker rebuild", "kiriya docker rebuild api"],
58
+ safety: "write",
59
+ ...COMPOSE_START,
60
+ input: {
61
+ positionals: [servicesPositional],
62
+ options: { file: fileOption },
63
+ parse(raw) {
64
+ const reader = new RawReader(raw);
65
+ return { services: reader.positionalsFrom(0), file: reader.string("file"), build: true };
66
+ },
67
+ },
68
+ };
69
+ export function createUp(fileSystem, content, runner) {
70
+ const variant = {
71
+ args: (input) => ["up", "--detach", ...(input.build ? ["--build"] : []), ...input.services],
72
+ failed: "docker.up.failed",
73
+ };
74
+ return new StartProject(upSpec, variant, fileSystem, content, runner);
75
+ }
76
+ export function createRebuild(fileSystem, content, runner) {
77
+ const variant = {
78
+ args: (input) => ["up", "--detach", "--build", "--force-recreate", ...input.services],
79
+ failed: "docker.rebuild.failed",
80
+ };
81
+ return new StartProject(rebuildSpec, variant, fileSystem, content, runner);
82
+ }
83
+ //# sourceMappingURL=run-compose.use-case.js.map
@@ -0,0 +1,51 @@
1
+ import { done } from "../../../core/domain/command.js";
2
+ import { UsageError } from "../../../core/domain/errors.js";
3
+ import { RawReader } from "../../../core/domain/input-schema.js";
4
+ import { message } from "../../../core/domain/message.js";
5
+ import { composeArgs, fileOption, findComposeProject, servicesPositional } from "./compose-project.js";
6
+ import { DockerEngine } from "./docker-engine.js";
7
+ export const logsSpec = {
8
+ id: "docker.logs",
9
+ summary: "docker.logs.summary",
10
+ examples: ["kiriya docker logs", "kiriya docker logs api -f", "kiriya docker logs db --tail all"],
11
+ safety: "read",
12
+ idempotent: true,
13
+ usesNetwork: false,
14
+ runsUserCommands: false,
15
+ input: {
16
+ positionals: [servicesPositional],
17
+ options: {
18
+ file: fileOption,
19
+ follow: { type: "boolean", description: "docker.logs.option.follow", short: "f", terminalOnly: true },
20
+ tail: { type: "string", description: "docker.logs.option.tail", valueName: "<n|all>" },
21
+ },
22
+ parse(raw) {
23
+ const reader = new RawReader(raw);
24
+ const tail = reader.string("tail") ?? "200";
25
+ if (tail !== "all" && !/^[0-9]+$/.test(tail))
26
+ throw new UsageError("docker.logs.tail-invalid", { value: tail });
27
+ return { services: reader.positionalsFrom(0), file: reader.string("file"), follow: reader.flag("follow"), tail };
28
+ },
29
+ },
30
+ };
31
+ /** The logs arrive through the passthrough as docker prints them; --follow runs until Ctrl+C. */
32
+ export class ShowLogs {
33
+ fileSystem;
34
+ content;
35
+ processRunner;
36
+ spec = logsSpec;
37
+ constructor(fileSystem, content, processRunner) {
38
+ this.fileSystem = fileSystem;
39
+ this.content = content;
40
+ this.processRunner = processRunner;
41
+ }
42
+ async execute(input, context) {
43
+ const project = await findComposeProject(this.fileSystem, this.content, context.cwd, input.file);
44
+ const engine = await DockerEngine.connect(this.processRunner, context.signal);
45
+ const args = ["logs", "--tail", input.tail, ...(input.follow ? ["--follow"] : []), ...input.services];
46
+ const code = await engine.stream(composeArgs(project, args), context.passthrough);
47
+ const failures = code === 0 ? [] : [message("docker.logs.failed", { project: project.name, code })];
48
+ return done({ project: project.name, succeeded: code === 0 }, { failures });
49
+ }
50
+ }
51
+ //# sourceMappingURL=show-logs.use-case.js.map
@@ -0,0 +1,56 @@
1
+ import { requireTypedConfirmation } from "../../../core/application/safety.js";
2
+ import { done } from "../../../core/domain/command.js";
3
+ import { RawReader } from "../../../core/domain/input-schema.js";
4
+ import { message } from "../../../core/domain/message.js";
5
+ import { composeArgs, fileOption, findComposeProject } from "./compose-project.js";
6
+ import { DockerEngine } from "./docker-engine.js";
7
+ export const downSpec = {
8
+ id: "docker.down",
9
+ summary: "docker.down.summary",
10
+ examples: ["kiriya docker down", "kiriya docker down --volumes", "kiriya docker down --volumes --confirm=my-project"],
11
+ safety: "destroy",
12
+ idempotent: true,
13
+ usesNetwork: false,
14
+ runsUserCommands: false,
15
+ input: {
16
+ positionals: [],
17
+ options: {
18
+ file: fileOption,
19
+ volumes: { type: "boolean", description: "docker.down.option.volumes" },
20
+ confirm: {
21
+ type: "string",
22
+ description: "docker.down.option.confirm",
23
+ valueName: "<project>",
24
+ terminalOnly: true,
25
+ },
26
+ },
27
+ parse(raw) {
28
+ const reader = new RawReader(raw);
29
+ return { file: reader.string("file"), volumes: reader.flag("volumes"), confirm: reader.string("confirm") };
30
+ },
31
+ },
32
+ };
33
+ export class StopProject {
34
+ fileSystem;
35
+ content;
36
+ processRunner;
37
+ spec = downSpec;
38
+ constructor(fileSystem, content, processRunner) {
39
+ this.fileSystem = fileSystem;
40
+ this.content = content;
41
+ this.processRunner = processRunner;
42
+ }
43
+ async execute(input, context) {
44
+ const project = await findComposeProject(this.fileSystem, this.content, context.cwd, input.file);
45
+ const engine = await DockerEngine.connect(this.processRunner, context.signal);
46
+ if (input.volumes) {
47
+ const warning = message("docker.down.warn-volumes", { project: project.name });
48
+ await requireTypedConfirmation(context, warning, project.name, input.confirm);
49
+ }
50
+ const args = composeArgs(project, ["down", ...(input.volumes ? ["--volumes"] : [])]);
51
+ const code = await engine.stream(args, context.passthrough);
52
+ const failures = code === 0 ? [] : [message("docker.down.failed", { project: project.name, code })];
53
+ return done({ project: project.name, volumes: input.volumes, succeeded: code === 0 }, { failures });
54
+ }
55
+ }
56
+ //# sourceMappingURL=stop-project.use-case.js.map