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,50 @@
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 { byNameThenPid } from "../domain/process-tree.js";
6
+ export const findSpec = {
7
+ id: "proc.find",
8
+ summary: "proc.find.summary",
9
+ examples: ["kiriya proc find vite", "kiriya proc find server.js --json"],
10
+ safety: "read",
11
+ idempotent: true,
12
+ usesNetwork: false,
13
+ runsUserCommands: false,
14
+ input: {
15
+ positionals: [{ name: "text", description: "proc.find.arg.text", required: true, variadic: false }],
16
+ options: {},
17
+ parse(raw) {
18
+ const text = new RawReader(raw).positional(0)?.trim() ?? "";
19
+ if (text === "")
20
+ throw new UsageError("proc.find.text-missing");
21
+ return { text };
22
+ },
23
+ },
24
+ };
25
+ export class FindProcesses {
26
+ table;
27
+ spec = findSpec;
28
+ constructor(table) {
29
+ this.table = table;
30
+ }
31
+ async execute(input, context) {
32
+ const listing = await this.table.list(true, context.signal);
33
+ const needle = input.text.toLowerCase();
34
+ // kiriya's own command line holds the text, and so may the shell or wrapper that started it.
35
+ const selfPid = this.table.selfPid;
36
+ const launcher = listing.processes.find((entry) => entry.pid === selfPid)?.ppid ?? null;
37
+ const processes = listing.processes
38
+ .filter((entry) => {
39
+ if (entry.pid === selfPid)
40
+ return false;
41
+ if (entry.name.toLowerCase().includes(needle))
42
+ return true;
43
+ return entry.pid !== launcher && (entry.command?.toLowerCase().includes(needle) ?? false);
44
+ })
45
+ .sort(byNameThenPid);
46
+ const failures = processes.length === 0 ? [message("proc.find.none", { text: input.text })] : [];
47
+ return done({ processes, detailed: listing.detailed }, { failures });
48
+ }
49
+ }
50
+ //# sourceMappingURL=find-processes.use-case.js.map
@@ -0,0 +1,41 @@
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 { byNameThenPid } from "../domain/process-tree.js";
5
+ export const listSpec = {
6
+ id: "proc.list",
7
+ summary: "proc.list.summary",
8
+ examples: ["kiriya proc list", "kiriya proc list --name node", "kiriya proc list --full --json"],
9
+ safety: "read",
10
+ idempotent: true,
11
+ usesNetwork: false,
12
+ runsUserCommands: false,
13
+ input: {
14
+ positionals: [],
15
+ options: {
16
+ name: { type: "string", description: "proc.list.option.name", valueName: "<text>" },
17
+ full: { type: "boolean", description: "proc.list.option.full", sensitive: true },
18
+ },
19
+ parse(raw) {
20
+ const reader = new RawReader(raw);
21
+ return { name: reader.string("name"), full: reader.flag("full") };
22
+ },
23
+ },
24
+ };
25
+ export class ListProcesses {
26
+ table;
27
+ spec = listSpec;
28
+ constructor(table) {
29
+ this.table = table;
30
+ }
31
+ async execute(input, context) {
32
+ const listing = await this.table.list(input.full, context.signal);
33
+ const needle = input.name?.toLowerCase();
34
+ const processes = listing.processes
35
+ .filter((entry) => needle === undefined || entry.name.toLowerCase().includes(needle))
36
+ .sort(byNameThenPid);
37
+ const failures = input.name !== undefined && processes.length === 0 ? [message("proc.list.none", { name: input.name })] : [];
38
+ return done({ processes, detailed: listing.detailed }, { failures });
39
+ }
40
+ }
41
+ //# sourceMappingURL=list-processes.use-case.js.map
@@ -0,0 +1,40 @@
1
+ import { done } from "../../../core/domain/command.js";
2
+ import { NotFoundError, UsageError } from "../../../core/domain/errors.js";
3
+ import { RawReader } from "../../../core/domain/input-schema.js";
4
+ import { processTree } from "../domain/process-tree.js";
5
+ export const treeSpec = {
6
+ id: "proc.tree",
7
+ summary: "proc.tree.summary",
8
+ examples: ["kiriya proc tree", "kiriya proc tree 4100", "kiriya proc tree 4100 --json"],
9
+ safety: "read",
10
+ idempotent: true,
11
+ usesNetwork: false,
12
+ runsUserCommands: false,
13
+ input: {
14
+ positionals: [{ name: "pid", description: "proc.tree.arg.pid", required: false, variadic: false }],
15
+ options: {},
16
+ parse(raw) {
17
+ const text = new RawReader(raw).positional(0);
18
+ if (text === undefined)
19
+ return { pid: null };
20
+ if (!/^\d+$/.test(text))
21
+ throw new UsageError("proc.tree.pid-invalid", { pid: text });
22
+ return { pid: Number(text) };
23
+ },
24
+ },
25
+ };
26
+ export class ShowTree {
27
+ table;
28
+ spec = treeSpec;
29
+ constructor(table) {
30
+ this.table = table;
31
+ }
32
+ async execute(input, context) {
33
+ const { processes } = await this.table.list(true, context.signal);
34
+ if (input.pid !== null && !processes.some((entry) => entry.pid === input.pid)) {
35
+ throw new NotFoundError("proc.tree.no-pid", { pid: input.pid });
36
+ }
37
+ return done({ rows: processTree(processes, input.pid) });
38
+ }
39
+ }
40
+ //# sourceMappingURL=show-tree.use-case.js.map
@@ -0,0 +1,55 @@
1
+ import { byCodePoint } from "../../../core/domain/names.js";
2
+ /** A program name compared the same way everywhere: in lower case and without Windows' .exe. */
3
+ export function programKey(name) {
4
+ return name.toLowerCase().replace(/\.exe$/, "");
5
+ }
6
+ export function byNameThenPid(first, second) {
7
+ return byCodePoint(first.name.toLowerCase(), second.name.toLowerCase()) || first.pid - second.pid;
8
+ }
9
+ /**
10
+ * Processes with each parent before its children, children by id. A process whose parent
11
+ * is not listed is a root; parent ids that loop, as reused ids can make them, are walked once.
12
+ */
13
+ export function processTree(processes, rootPid) {
14
+ const byPid = new Map(processes.map((entry) => [entry.pid, entry]));
15
+ const children = new Map();
16
+ const roots = [];
17
+ for (const entry of processes) {
18
+ const parent = entry.ppid === null || entry.ppid === entry.pid ? undefined : byPid.get(entry.ppid);
19
+ if (parent === undefined) {
20
+ roots.push(entry);
21
+ }
22
+ else {
23
+ children.set(parent.pid, [...(children.get(parent.pid) ?? []), entry]);
24
+ }
25
+ }
26
+ const rows = [];
27
+ const visited = new Set();
28
+ const walk = (start) => {
29
+ const stack = [[start, 0]];
30
+ for (let next = stack.pop(); next !== undefined; next = stack.pop()) {
31
+ const [entry, depth] = next;
32
+ if (visited.has(entry.pid))
33
+ continue;
34
+ visited.add(entry.pid);
35
+ rows.push({ pid: entry.pid, ppid: entry.ppid, name: entry.name, depth });
36
+ const kids = [...(children.get(entry.pid) ?? [])].sort((first, second) => second.pid - first.pid);
37
+ for (const kid of kids)
38
+ stack.push([kid, depth + 1]);
39
+ }
40
+ };
41
+ if (rootPid !== null) {
42
+ const root = byPid.get(rootPid);
43
+ if (root !== undefined)
44
+ walk(root);
45
+ return rows;
46
+ }
47
+ const byId = (first, second) => first.pid - second.pid;
48
+ for (const root of [...roots].sort(byId))
49
+ walk(root);
50
+ for (const entry of [...processes].sort(byId))
51
+ if (!visited.has(entry.pid))
52
+ walk(entry);
53
+ return rows;
54
+ }
55
+ //# sourceMappingURL=process-tree.js.map
@@ -0,0 +1,28 @@
1
+ import { message } from "../../../core/domain/message.js";
2
+ import { columns, endedLines } from "../../../core/presentation/ended-processes.js";
3
+ /** Id, memory and name; with details also the parent id and, last, the command line. */
4
+ export const processesView = (output, format) => {
5
+ if (output.processes.length === 0)
6
+ return [];
7
+ const label = (key) => format.text(message(key));
8
+ const detailed = output.detailed;
9
+ const header = [
10
+ label("proc.column.pid"),
11
+ ...(detailed ? [label("proc.column.parent")] : []),
12
+ label("proc.column.memory"),
13
+ label("proc.column.name"),
14
+ ...(detailed ? [label("proc.column.command")] : []),
15
+ ];
16
+ const rows = output.processes.map((entry) => [
17
+ String(entry.pid),
18
+ ...(detailed ? [entry.ppid === null ? "" : String(entry.ppid)] : []),
19
+ entry.memoryBytes === null ? "" : format.bytes(entry.memoryBytes),
20
+ entry.name,
21
+ ...(detailed ? [entry.command ?? ""] : []),
22
+ ]);
23
+ const [first = "", ...rest] = columns([header, ...rows]);
24
+ return [format.bold(first), ...rest];
25
+ };
26
+ export const killView = (output, format) => endedLines(output.processes, format);
27
+ export const treeView = (output, format) => output.rows.map((row) => `${" ".repeat(row.depth)}${row.name} ${format.dim(String(row.pid))}`);
28
+ //# sourceMappingURL=proc.views.js.map
@@ -0,0 +1,19 @@
1
+ import { EndProcesses } from "./application/end-processes.use-case.js";
2
+ import { FindProcesses } from "./application/find-processes.use-case.js";
3
+ import { ListProcesses } from "./application/list-processes.use-case.js";
4
+ import { ShowTree } from "./application/show-tree.use-case.js";
5
+ import { killView, processesView, treeView } from "./presentation/proc.views.js";
6
+ export const procModule = {
7
+ id: "proc",
8
+ summary: "proc.summary",
9
+ about: "proc.about",
10
+ examples: ["kiriya proc find vite", "kiriya proc tree", "kiriya proc kill node"],
11
+ guide: "https://github.com/SatPaingOo/kiriya/blob/main/docs/modules/proc.md",
12
+ register(registrar, ports) {
13
+ registrar.add(new ListProcesses(ports.processTable), processesView);
14
+ registrar.add(new FindProcesses(ports.processTable), processesView);
15
+ registrar.add(new EndProcesses(ports.processTable), killView);
16
+ registrar.add(new ShowTree(ports.processTable), treeView);
17
+ },
18
+ };
19
+ //# sourceMappingURL=proc.module.js.map
@@ -0,0 +1,30 @@
1
+ import { done } from "../../../core/domain/command.js";
2
+ import { findTools, machineFacts, noInput, SYS_COMMAND, } from "./machine-facts.js";
3
+ export const reportSpec = {
4
+ id: "sys.report",
5
+ summary: "sys.report.summary",
6
+ examples: ["kiriya sys report", "kiriya sys report --json"],
7
+ ...SYS_COMMAND,
8
+ idempotent: false,
9
+ input: noInput,
10
+ };
11
+ /** Machine facts and tool versions to paste into a bug report; the host name and tool paths stay out. */
12
+ export class CreateReport {
13
+ system;
14
+ processRunner;
15
+ runtime;
16
+ spec = reportSpec;
17
+ constructor(system, processRunner, runtime) {
18
+ this.system = system;
19
+ this.processRunner = processRunner;
20
+ this.runtime = runtime;
21
+ }
22
+ async execute(_input, context) {
23
+ const [snapshot, tools] = await Promise.all([this.system.read(), findTools(this.processRunner, context.signal)]);
24
+ return done({
25
+ machine: machineFacts(snapshot, this.runtime),
26
+ tools: tools.map((tool) => ({ name: tool.name, version: tool.version, path: null })),
27
+ });
28
+ }
29
+ }
30
+ //# sourceMappingURL=create-report.use-case.js.map
@@ -0,0 +1,20 @@
1
+ import { done } from "../../../core/domain/command.js";
2
+ import { findTools, noInput, SYS_COMMAND } from "./machine-facts.js";
3
+ export const toolsSpec = {
4
+ id: "sys.tools",
5
+ summary: "sys.tools.summary",
6
+ examples: ["kiriya sys tools", "kiriya sys tools --json"],
7
+ ...SYS_COMMAND,
8
+ input: noInput,
9
+ };
10
+ export class FindTools {
11
+ processRunner;
12
+ spec = toolsSpec;
13
+ constructor(processRunner) {
14
+ this.processRunner = processRunner;
15
+ }
16
+ async execute(_input, context) {
17
+ return done({ tools: await findTools(this.processRunner, context.signal) });
18
+ }
19
+ }
20
+ //# sourceMappingURL=find-tools.use-case.js.map
@@ -0,0 +1,44 @@
1
+ import { KiriyaError } from "../../../core/domain/errors.js";
2
+ import { TOOLS, toolVersion } from "../domain/tools.js";
3
+ export const noInput = { positionals: [], options: {}, parse: () => ({}) };
4
+ export const SYS_COMMAND = { safety: "read", idempotent: true, usesNetwork: false, runsUserCommands: false };
5
+ export function machineFacts(snapshot, runtime) {
6
+ return {
7
+ os: snapshot.os,
8
+ osName: snapshot.osName,
9
+ kernel: snapshot.kernel,
10
+ arch: snapshot.arch,
11
+ cpuModel: snapshot.cpuModel,
12
+ cpuCount: snapshot.cpuCount,
13
+ memoryTotalBytes: snapshot.memoryTotalBytes,
14
+ memoryFreeBytes: snapshot.memoryFreeBytes,
15
+ locale: snapshot.locale,
16
+ timeZone: snapshot.timeZone,
17
+ node: runtime.nodeVersion,
18
+ kiriya: runtime.kiriyaVersion,
19
+ };
20
+ }
21
+ const PROBE_TIMEOUT_MS = 15_000;
22
+ async function probe(runner, tool, signal) {
23
+ for (const program of tool.programs) {
24
+ const found = await runner.find(program);
25
+ if (found === null)
26
+ continue;
27
+ try {
28
+ const result = await runner.run(found, tool.args, { timeoutMs: PROBE_TIMEOUT_MS, signal });
29
+ const version = toolVersion(tool, `${result.stdout}\n${result.stderr}`);
30
+ if (version !== null)
31
+ return { name: tool.name, version, path: found };
32
+ }
33
+ catch (error) {
34
+ if (!(error instanceof KiriyaError) || error.kind === "interrupted")
35
+ throw error;
36
+ }
37
+ }
38
+ return { name: tool.name, version: null, path: null };
39
+ }
40
+ /** Every known tool, looked for at the same time. */
41
+ export function findTools(runner, signal) {
42
+ return Promise.all(TOOLS.map((tool) => probe(runner, tool, signal)));
43
+ }
44
+ //# sourceMappingURL=machine-facts.js.map
@@ -0,0 +1,29 @@
1
+ import { done } from "../../../core/domain/command.js";
2
+ import { machineFacts, noInput, SYS_COMMAND } from "./machine-facts.js";
3
+ export const infoSpec = {
4
+ id: "sys.info",
5
+ summary: "sys.info.summary",
6
+ examples: ["kiriya sys info", "kiriya sys info --json"],
7
+ ...SYS_COMMAND,
8
+ // Free memory and uptime change from one run to the next.
9
+ idempotent: false,
10
+ input: noInput,
11
+ };
12
+ export class ShowInfo {
13
+ system;
14
+ runtime;
15
+ spec = infoSpec;
16
+ constructor(system, runtime) {
17
+ this.system = system;
18
+ this.runtime = runtime;
19
+ }
20
+ async execute() {
21
+ const snapshot = await this.system.read();
22
+ return done({
23
+ ...machineFacts(snapshot, this.runtime),
24
+ uptimeSeconds: snapshot.uptimeSeconds,
25
+ hostname: snapshot.hostname,
26
+ });
27
+ }
28
+ }
29
+ //# sourceMappingURL=show-info.use-case.js.map
@@ -0,0 +1,17 @@
1
+ export const TOOLS = [
2
+ { name: "node", programs: ["node"], args: ["--version"], version: /\bv(\d+\.\d+\.\d+)/ },
3
+ { name: "python", programs: ["python3", "python"], args: ["--version"], version: /\bPython (\d+\.\d+(?:\.\d+)?)/ },
4
+ { name: "dotnet", programs: ["dotnet"], args: ["--version"], version: /^(\d+\.\d+\.\d+\S*)\s*$/m },
5
+ { name: "java", programs: ["java"], args: ["-version"], version: /\bversion "([^"]+)"/ },
6
+ { name: "go", programs: ["go"], args: ["version"], version: /\bgo(\d+\.\d+(?:\.\d+)?)/ },
7
+ { name: "git", programs: ["git"], args: ["--version"], version: /\bgit version (\S+)/ },
8
+ { name: "docker", programs: ["docker"], args: ["--version"], version: /\bDocker version ([^,\s]+)/ },
9
+ ];
10
+ /**
11
+ * The version in a tool's output, or null. A stand-in that prints no version, such as
12
+ * the Microsoft Store's python or macOS's java without a JDK, does not count as installed.
13
+ */
14
+ export function toolVersion(tool, output) {
15
+ return tool.version.exec(output)?.[1] ?? null;
16
+ }
17
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1,67 @@
1
+ import { message } from "../../../core/domain/message.js";
2
+ function osRow(machine, format) {
3
+ const params = { name: machine.osName, kernel: machine.kernel, arch: machine.arch };
4
+ return ["sys.label.os", format.text(message("sys.info.os", params))];
5
+ }
6
+ function cpuRow(machine, format) {
7
+ return ["sys.label.cpu", format.text(message("sys.info.cpu", { model: machine.cpuModel, count: machine.cpuCount }))];
8
+ }
9
+ function memoryRow(machine, format) {
10
+ const params = { total: format.bytes(machine.memoryTotalBytes), free: format.bytes(machine.memoryFreeBytes) };
11
+ return ["sys.label.memory", format.text(message("sys.info.memory", params))];
12
+ }
13
+ function localeRow(machine, format) {
14
+ const params = { locale: machine.locale, timeZone: machine.timeZone };
15
+ return ["sys.label.locale", format.text(message("sys.info.locale", params))];
16
+ }
17
+ function uptime(seconds, format) {
18
+ const days = Math.floor(seconds / 86_400);
19
+ const hours = Math.floor((seconds % 86_400) / 3_600);
20
+ const minutes = Math.floor((seconds % 3_600) / 60);
21
+ return format.text(message("sys.info.uptime", { days, hours, minutes }));
22
+ }
23
+ export const infoView = (output, format) => {
24
+ const rows = [
25
+ osRow(output, format),
26
+ cpuRow(output, format),
27
+ memoryRow(output, format),
28
+ ["sys.label.uptime", uptime(output.uptimeSeconds, format)],
29
+ ["sys.label.host", output.hostname],
30
+ localeRow(output, format),
31
+ ["sys.label.node", output.node],
32
+ ["sys.label.kiriya", output.kiriya],
33
+ ];
34
+ const labels = rows.map(([key]) => format.text(message(key)));
35
+ const width = Math.max(...labels.map((label) => label.length));
36
+ return rows.map(([, value], index) => ` ${format.bold((labels[index] ?? "").padEnd(width))} ${value}`);
37
+ };
38
+ export const toolsView = (output, format) => {
39
+ const nameWidth = Math.max(...output.tools.map((tool) => tool.name.length));
40
+ const versionWidth = Math.max(0, ...output.tools.map((tool) => tool.version?.length ?? 0));
41
+ return output.tools.map((tool) => tool.version === null
42
+ ? ` ${tool.name.padEnd(nameWidth)} ${format.dim(format.text(message("sys.tools.not-found")))}`
43
+ : ` ${tool.name.padEnd(nameWidth)} ${tool.version.padEnd(versionWidth)} ${format.dim(tool.path ?? "")}`);
44
+ };
45
+ /** Markdown without colour, to paste into an issue as it is. */
46
+ export const reportView = (output, format) => {
47
+ const { machine, tools } = output;
48
+ const found = tools.flatMap((tool) => (tool.version === null ? [] : [`${tool.name} ${tool.version}`]));
49
+ const missing = tools.filter((tool) => tool.version === null).map((tool) => tool.name);
50
+ const toolText = [
51
+ found.join(", "),
52
+ missing.length > 0 ? format.text(message("sys.report.not-found", { names: missing.join(", ") })) : "",
53
+ ]
54
+ .filter((part) => part !== "")
55
+ .join("; ");
56
+ const rows = [
57
+ ["sys.label.kiriya", machine.kiriya],
58
+ ["sys.label.node", machine.node],
59
+ osRow(machine, format),
60
+ cpuRow(machine, format),
61
+ memoryRow(machine, format),
62
+ localeRow(machine, format),
63
+ ["sys.label.tools", toolText],
64
+ ];
65
+ return rows.map(([key, value]) => `- **${format.text(message(key))}:** ${value}`);
66
+ };
67
+ //# sourceMappingURL=sys.views.js.map
@@ -0,0 +1,17 @@
1
+ import { CreateReport } from "./application/create-report.use-case.js";
2
+ import { FindTools } from "./application/find-tools.use-case.js";
3
+ import { ShowInfo } from "./application/show-info.use-case.js";
4
+ import { infoView, reportView, toolsView } from "./presentation/sys.views.js";
5
+ export const sysModule = {
6
+ id: "sys",
7
+ summary: "sys.summary",
8
+ about: "sys.about",
9
+ examples: ["kiriya sys info", "kiriya sys tools", "kiriya sys report"],
10
+ guide: "https://github.com/SatPaingOo/kiriya/blob/main/docs/modules/sys.md",
11
+ register(registrar, ports) {
12
+ registrar.add(new ShowInfo(ports.system, ports.runtime), infoView);
13
+ registrar.add(new FindTools(ports.processRunner), toolsView);
14
+ registrar.add(new CreateReport(ports.system, ports.processRunner, ports.runtime), reportView);
15
+ },
16
+ };
17
+ //# sourceMappingURL=sys.module.js.map
@@ -0,0 +1,26 @@
1
+ import { InterruptedError } from "../../../core/domain/errors.js";
2
+ /** The time between attempts. */
3
+ export const INTERVAL_MS = 500;
4
+ /** The least time an attempt is given, so the last one, made at the deadline, can still succeed. */
5
+ export const LEAST_ATTEMPT_MS = 250;
6
+ /**
7
+ * Tries at once, then every INTERVAL_MS, until an attempt is ready or timeoutMs has passed.
8
+ * Each attempt is told how long it may take. Aborting the signal throws InterruptedError.
9
+ */
10
+ export async function poll(clock, timeoutMs, signal, attempt) {
11
+ const started = clock.now();
12
+ const deadline = started + timeoutMs;
13
+ let attempts = 0;
14
+ for (;;) {
15
+ if (signal.aborted)
16
+ throw new InterruptedError("core.error.interrupted");
17
+ attempts += 1;
18
+ const outcome = await attempt(Math.max(deadline - clock.now(), LEAST_ATTEMPT_MS));
19
+ const left = deadline - clock.now();
20
+ if (outcome.ready || left <= 0) {
21
+ return { ready: outcome.ready, last: outcome.value, attempts, waitedMs: clock.now() - started };
22
+ }
23
+ await clock.sleep(Math.min(INTERVAL_MS, left), signal);
24
+ }
25
+ }
26
+ //# sourceMappingURL=poll.js.map
@@ -0,0 +1,55 @@
1
+ import path from "node:path";
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 { readTimeout, TIMEOUT_OPTION } from "../domain/wait-input.js";
6
+ import { poll } from "./poll.js";
7
+ export const waitFileSpec = {
8
+ id: "wait.file",
9
+ summary: "wait.file.summary",
10
+ examples: ["kiriya wait file dist/app.js", "kiriya wait file .build.lock --gone --timeout 300"],
11
+ safety: "read",
12
+ idempotent: true,
13
+ usesNetwork: false,
14
+ runsUserCommands: false,
15
+ input: {
16
+ positionals: [{ name: "path", description: "wait.file.arg.path", required: true, variadic: false, path: true }],
17
+ options: {
18
+ gone: { type: "boolean", description: "wait.file.option.gone" },
19
+ timeout: TIMEOUT_OPTION,
20
+ },
21
+ parse(raw) {
22
+ const reader = new RawReader(raw);
23
+ return { path: reader.positional(0) ?? "", gone: reader.flag("gone"), timeoutSeconds: readTimeout(reader) };
24
+ },
25
+ },
26
+ };
27
+ export class WaitForFile {
28
+ fileSystem;
29
+ clock;
30
+ spec = waitFileSpec;
31
+ constructor(fileSystem, clock) {
32
+ this.fileSystem = fileSystem;
33
+ this.clock = clock;
34
+ }
35
+ async execute(input, context) {
36
+ const target = path.resolve(context.cwd, input.path);
37
+ const polled = await poll(this.clock, input.timeoutSeconds * 1000, context.signal, async () => {
38
+ const exists = (await this.fileSystem.stat(target)) !== null;
39
+ return { ready: exists !== input.gone, value: exists };
40
+ });
41
+ const data = {
42
+ path: target,
43
+ gone: input.gone,
44
+ ready: polled.ready,
45
+ attempts: polled.attempts,
46
+ waitedMs: polled.waitedMs,
47
+ };
48
+ if (polled.ready)
49
+ return done(data);
50
+ const params = { path: target, seconds: input.timeoutSeconds };
51
+ const failure = input.gone ? message("wait.file.still-there", params) : message("wait.file.timed-out", params);
52
+ return done(data, { failures: [failure] });
53
+ }
54
+ }
55
+ //# sourceMappingURL=wait-file.use-case.js.map
@@ -0,0 +1,76 @@
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 { formatTarget } from "../../../core/domain/targets.js";
6
+ import { failureReason } from "../domain/reasons.js";
7
+ import { parsePortTarget, readTimeout, TIMEOUT_OPTION } from "../domain/wait-input.js";
8
+ import { poll } from "./poll.js";
9
+ /** The longest one connection attempt may take, so a host that never answers is tried again. */
10
+ export const PORT_ATTEMPT_MS = 2_000;
11
+ export const waitPortSpec = {
12
+ id: "wait.port",
13
+ summary: "wait.port.summary",
14
+ examples: [
15
+ "kiriya wait port 5432",
16
+ "kiriya wait port db.internal:5432 --timeout 120",
17
+ "kiriya wait port 3000 --gone",
18
+ ],
19
+ safety: "read",
20
+ idempotent: true,
21
+ usesNetwork: true,
22
+ runsUserCommands: false,
23
+ input: {
24
+ positionals: [{ name: "target", description: "wait.port.arg.target", required: true, variadic: false }],
25
+ options: {
26
+ gone: { type: "boolean", description: "wait.port.option.gone" },
27
+ timeout: TIMEOUT_OPTION,
28
+ },
29
+ parse(raw) {
30
+ const reader = new RawReader(raw);
31
+ const text = reader.positional(0) ?? "";
32
+ const target = parsePortTarget(text);
33
+ if (target === null)
34
+ throw new UsageError("wait.port.target-invalid", { target: text });
35
+ return { target, gone: reader.flag("gone"), timeoutSeconds: readTimeout(reader) };
36
+ },
37
+ },
38
+ };
39
+ export class WaitForPort {
40
+ network;
41
+ clock;
42
+ spec = waitPortSpec;
43
+ constructor(network, clock) {
44
+ this.network = network;
45
+ this.clock = clock;
46
+ }
47
+ async execute(input, context) {
48
+ const { host, port } = input.target;
49
+ const polled = await poll(this.clock, input.timeoutSeconds * 1000, context.signal, async (allowedMs) => {
50
+ const outcome = await this.network.connect(host, port, Math.min(PORT_ATTEMPT_MS, allowedMs), context.signal);
51
+ return { ready: outcome.ok !== input.gone, value: outcome };
52
+ });
53
+ const { last } = polled;
54
+ const data = {
55
+ host,
56
+ port,
57
+ gone: input.gone,
58
+ ready: polled.ready,
59
+ attempts: polled.attempts,
60
+ waitedMs: polled.waitedMs,
61
+ address: last.ok ? last.address : null,
62
+ failure: last.ok ? null : last.failure,
63
+ code: last.ok ? null : last.code,
64
+ };
65
+ if (polled.ready)
66
+ return done(data);
67
+ const target = formatTarget(input.target);
68
+ const seconds = input.timeoutSeconds;
69
+ // Not ready with a connection that worked can only mean --gone.
70
+ const failure = last.ok
71
+ ? message("wait.port.still-listening", { target, seconds })
72
+ : message("wait.port.timed-out", { target, seconds, reason: failureReason(last.failure, host, last.code) });
73
+ return done(data, { failures: [failure] });
74
+ }
75
+ }
76
+ //# sourceMappingURL=wait-port.use-case.js.map