@aigne/afs-cli 1.11.0-beta.1 → 1.11.0-beta.11

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 (348) hide show
  1. package/README.md +262 -15
  2. package/dist/_virtual/rolldown_runtime.cjs +29 -0
  3. package/dist/_virtual/rolldown_runtime.mjs +7 -0
  4. package/dist/cli.cjs +40 -0
  5. package/dist/cli.d.cts +2 -0
  6. package/dist/cli.d.mts +2 -1
  7. package/dist/cli.mjs +36 -24
  8. package/dist/cli.mjs.map +1 -0
  9. package/dist/config/afs-loader.cjs +578 -0
  10. package/dist/config/afs-loader.d.cts +19 -0
  11. package/dist/config/afs-loader.d.cts.map +1 -0
  12. package/dist/config/afs-loader.d.mts +19 -0
  13. package/dist/config/afs-loader.d.mts.map +1 -0
  14. package/dist/config/afs-loader.mjs +576 -0
  15. package/dist/config/afs-loader.mjs.map +1 -0
  16. package/dist/config/env.cjs +46 -0
  17. package/dist/config/env.mjs +46 -0
  18. package/dist/config/env.mjs.map +1 -0
  19. package/dist/config/loader.cjs +219 -0
  20. package/dist/config/loader.mjs +217 -0
  21. package/dist/config/loader.mjs.map +1 -0
  22. package/dist/config/mount-commands.cjs +226 -0
  23. package/dist/config/mount-commands.d.cts +14 -0
  24. package/dist/config/mount-commands.d.cts.map +1 -0
  25. package/dist/config/mount-commands.d.mts +14 -0
  26. package/dist/config/mount-commands.d.mts.map +1 -0
  27. package/dist/config/mount-commands.mjs +220 -0
  28. package/dist/config/mount-commands.mjs.map +1 -0
  29. package/dist/config/schema.cjs +99 -0
  30. package/dist/config/schema.mjs +98 -0
  31. package/dist/config/schema.mjs.map +1 -0
  32. package/dist/core/commands/delete.cjs +41 -0
  33. package/dist/core/commands/delete.d.cts +18 -0
  34. package/dist/core/commands/delete.d.cts.map +1 -0
  35. package/dist/core/commands/delete.d.mts +18 -0
  36. package/dist/core/commands/delete.d.mts.map +1 -0
  37. package/dist/core/commands/delete.mjs +42 -0
  38. package/dist/core/commands/delete.mjs.map +1 -0
  39. package/dist/core/commands/exec.cjs +98 -0
  40. package/dist/core/commands/exec.d.cts +26 -0
  41. package/dist/core/commands/exec.d.cts.map +1 -0
  42. package/dist/core/commands/exec.d.mts +26 -0
  43. package/dist/core/commands/exec.d.mts.map +1 -0
  44. package/dist/core/commands/exec.mjs +99 -0
  45. package/dist/core/commands/exec.mjs.map +1 -0
  46. package/dist/core/commands/explain.cjs +278 -0
  47. package/dist/core/commands/explain.d.cts +25 -0
  48. package/dist/core/commands/explain.d.cts.map +1 -0
  49. package/dist/core/commands/explain.d.mts +25 -0
  50. package/dist/core/commands/explain.d.mts.map +1 -0
  51. package/dist/core/commands/explain.mjs +279 -0
  52. package/dist/core/commands/explain.mjs.map +1 -0
  53. package/dist/core/commands/explore.cjs +30 -0
  54. package/dist/core/commands/explore.d.mts +2 -0
  55. package/dist/core/commands/explore.mjs +31 -0
  56. package/dist/core/commands/explore.mjs.map +1 -0
  57. package/dist/core/commands/index.cjs +36 -0
  58. package/dist/core/commands/index.d.cts +21 -0
  59. package/dist/core/commands/index.d.cts.map +1 -0
  60. package/dist/core/commands/index.d.mts +24 -0
  61. package/dist/core/commands/index.d.mts.map +1 -0
  62. package/dist/core/commands/index.mjs +37 -0
  63. package/dist/core/commands/index.mjs.map +1 -0
  64. package/dist/core/commands/ls.cjs +57 -0
  65. package/dist/core/commands/ls.d.cts +21 -0
  66. package/dist/core/commands/ls.d.cts.map +1 -0
  67. package/dist/core/commands/ls.d.mts +21 -0
  68. package/dist/core/commands/ls.d.mts.map +1 -0
  69. package/dist/core/commands/ls.mjs +58 -0
  70. package/dist/core/commands/ls.mjs.map +1 -0
  71. package/dist/core/commands/mount.cjs +222 -0
  72. package/dist/core/commands/mount.d.cts +35 -0
  73. package/dist/core/commands/mount.d.cts.map +1 -0
  74. package/dist/core/commands/mount.d.mts +35 -0
  75. package/dist/core/commands/mount.d.mts.map +1 -0
  76. package/dist/core/commands/mount.mjs +223 -0
  77. package/dist/core/commands/mount.mjs.map +1 -0
  78. package/dist/core/commands/read.cjs +48 -0
  79. package/dist/core/commands/read.d.cts +17 -0
  80. package/dist/core/commands/read.d.cts.map +1 -0
  81. package/dist/core/commands/read.d.mts +17 -0
  82. package/dist/core/commands/read.d.mts.map +1 -0
  83. package/dist/core/commands/read.mjs +49 -0
  84. package/dist/core/commands/read.mjs.map +1 -0
  85. package/dist/core/commands/search.cjs +40 -0
  86. package/dist/core/commands/search.d.mts +2 -0
  87. package/dist/core/commands/search.mjs +41 -0
  88. package/dist/core/commands/search.mjs.map +1 -0
  89. package/dist/core/commands/serve.cjs +267 -0
  90. package/dist/core/commands/serve.d.mts +2 -0
  91. package/dist/core/commands/serve.mjs +267 -0
  92. package/dist/core/commands/serve.mjs.map +1 -0
  93. package/dist/core/commands/stat.cjs +53 -0
  94. package/dist/core/commands/stat.d.cts +17 -0
  95. package/dist/core/commands/stat.d.cts.map +1 -0
  96. package/dist/core/commands/stat.d.mts +17 -0
  97. package/dist/core/commands/stat.d.mts.map +1 -0
  98. package/dist/core/commands/stat.mjs +54 -0
  99. package/dist/core/commands/stat.mjs.map +1 -0
  100. package/dist/core/commands/types.cjs +18 -0
  101. package/dist/core/commands/types.d.cts +54 -0
  102. package/dist/core/commands/types.d.cts.map +1 -0
  103. package/dist/core/commands/types.d.mts +54 -0
  104. package/dist/core/commands/types.d.mts.map +1 -0
  105. package/dist/core/commands/types.mjs +19 -0
  106. package/dist/core/commands/types.mjs.map +1 -0
  107. package/dist/core/commands/write.cjs +70 -0
  108. package/dist/core/commands/write.d.cts +20 -0
  109. package/dist/core/commands/write.d.cts.map +1 -0
  110. package/dist/core/commands/write.d.mts +20 -0
  111. package/dist/core/commands/write.d.mts.map +1 -0
  112. package/dist/core/commands/write.mjs +71 -0
  113. package/dist/core/commands/write.mjs.map +1 -0
  114. package/dist/core/executor/index.cjs +196 -0
  115. package/dist/core/executor/index.d.cts +77 -0
  116. package/dist/core/executor/index.d.cts.map +1 -0
  117. package/dist/core/executor/index.d.mts +77 -0
  118. package/dist/core/executor/index.d.mts.map +1 -0
  119. package/dist/core/executor/index.mjs +195 -0
  120. package/dist/core/executor/index.mjs.map +1 -0
  121. package/dist/core/formatters/delete.cjs +37 -0
  122. package/dist/core/formatters/delete.d.cts +18 -0
  123. package/dist/core/formatters/delete.d.cts.map +1 -0
  124. package/dist/core/formatters/delete.d.mts +18 -0
  125. package/dist/core/formatters/delete.d.mts.map +1 -0
  126. package/dist/core/formatters/delete.mjs +37 -0
  127. package/dist/core/formatters/delete.mjs.map +1 -0
  128. package/dist/core/formatters/exec.cjs +60 -0
  129. package/dist/core/formatters/exec.d.cts +18 -0
  130. package/dist/core/formatters/exec.d.cts.map +1 -0
  131. package/dist/core/formatters/exec.d.mts +18 -0
  132. package/dist/core/formatters/exec.d.mts.map +1 -0
  133. package/dist/core/formatters/exec.mjs +60 -0
  134. package/dist/core/formatters/exec.mjs.map +1 -0
  135. package/dist/core/formatters/explain.cjs +99 -0
  136. package/dist/core/formatters/explain.d.cts +11 -0
  137. package/dist/core/formatters/explain.d.cts.map +1 -0
  138. package/dist/core/formatters/explain.d.mts +11 -0
  139. package/dist/core/formatters/explain.d.mts.map +1 -0
  140. package/dist/core/formatters/explain.mjs +98 -0
  141. package/dist/core/formatters/explain.mjs.map +1 -0
  142. package/dist/core/formatters/index.d.mts +9 -0
  143. package/dist/core/formatters/ls.cjs +179 -0
  144. package/dist/core/formatters/ls.d.cts +20 -0
  145. package/dist/core/formatters/ls.d.cts.map +1 -0
  146. package/dist/core/formatters/ls.d.mts +20 -0
  147. package/dist/core/formatters/ls.d.mts.map +1 -0
  148. package/dist/core/formatters/ls.mjs +179 -0
  149. package/dist/core/formatters/ls.mjs.map +1 -0
  150. package/dist/core/formatters/mount.cjs +55 -0
  151. package/dist/core/formatters/mount.d.cts +15 -0
  152. package/dist/core/formatters/mount.d.cts.map +1 -0
  153. package/dist/core/formatters/mount.d.mts +15 -0
  154. package/dist/core/formatters/mount.d.mts.map +1 -0
  155. package/dist/core/formatters/mount.mjs +55 -0
  156. package/dist/core/formatters/mount.mjs.map +1 -0
  157. package/dist/core/formatters/read.cjs +100 -0
  158. package/dist/core/formatters/read.d.cts +22 -0
  159. package/dist/core/formatters/read.d.cts.map +1 -0
  160. package/dist/core/formatters/read.d.mts +22 -0
  161. package/dist/core/formatters/read.d.mts.map +1 -0
  162. package/dist/core/formatters/read.mjs +100 -0
  163. package/dist/core/formatters/read.mjs.map +1 -0
  164. package/dist/core/formatters/search.cjs +44 -0
  165. package/dist/core/formatters/search.d.mts +1 -0
  166. package/dist/core/formatters/search.mjs +44 -0
  167. package/dist/core/formatters/search.mjs.map +1 -0
  168. package/dist/core/formatters/stat.cjs +155 -0
  169. package/dist/core/formatters/stat.d.cts +15 -0
  170. package/dist/core/formatters/stat.d.cts.map +1 -0
  171. package/dist/core/formatters/stat.d.mts +15 -0
  172. package/dist/core/formatters/stat.d.mts.map +1 -0
  173. package/dist/core/formatters/stat.mjs +155 -0
  174. package/dist/core/formatters/stat.mjs.map +1 -0
  175. package/dist/core/formatters/write.cjs +51 -0
  176. package/dist/core/formatters/write.d.cts +22 -0
  177. package/dist/core/formatters/write.d.cts.map +1 -0
  178. package/dist/core/formatters/write.d.mts +22 -0
  179. package/dist/core/formatters/write.d.mts.map +1 -0
  180. package/dist/core/formatters/write.mjs +51 -0
  181. package/dist/core/formatters/write.mjs.map +1 -0
  182. package/dist/core/helpers/exec-args.cjs +142 -0
  183. package/dist/core/helpers/exec-args.d.cts +46 -0
  184. package/dist/core/helpers/exec-args.d.cts.map +1 -0
  185. package/dist/core/helpers/exec-args.d.mts +46 -0
  186. package/dist/core/helpers/exec-args.d.mts.map +1 -0
  187. package/dist/core/helpers/exec-args.mjs +139 -0
  188. package/dist/core/helpers/exec-args.mjs.map +1 -0
  189. package/dist/core/helpers/stdin.cjs +41 -0
  190. package/dist/core/helpers/stdin.d.cts +15 -0
  191. package/dist/core/helpers/stdin.d.cts.map +1 -0
  192. package/dist/core/helpers/stdin.d.mts +15 -0
  193. package/dist/core/helpers/stdin.d.mts.map +1 -0
  194. package/dist/core/helpers/stdin.mjs +41 -0
  195. package/dist/core/helpers/stdin.mjs.map +1 -0
  196. package/dist/core/index.cjs +49 -0
  197. package/dist/core/index.d.cts +24 -0
  198. package/dist/core/index.d.mts +25 -0
  199. package/dist/core/index.mjs +24 -0
  200. package/dist/core/path-utils.cjs +1 -0
  201. package/dist/core/path-utils.mjs +3 -0
  202. package/dist/core/types.d.cts +24 -0
  203. package/dist/core/types.d.cts.map +1 -0
  204. package/dist/core/types.d.mts +24 -0
  205. package/dist/core/types.d.mts.map +1 -0
  206. package/dist/credential/auth-server.cjs +247 -0
  207. package/dist/credential/auth-server.mjs +247 -0
  208. package/dist/credential/auth-server.mjs.map +1 -0
  209. package/dist/credential/cli-auth-context.cjs +86 -0
  210. package/dist/credential/cli-auth-context.d.mts +1 -0
  211. package/dist/credential/cli-auth-context.mjs +86 -0
  212. package/dist/credential/cli-auth-context.mjs.map +1 -0
  213. package/dist/credential/index.cjs +5 -0
  214. package/dist/credential/index.d.mts +4 -0
  215. package/dist/credential/index.mjs +7 -0
  216. package/dist/credential/mcp-auth-context.cjs +192 -0
  217. package/dist/credential/mcp-auth-context.d.mts +1 -0
  218. package/dist/credential/mcp-auth-context.mjs +192 -0
  219. package/dist/credential/mcp-auth-context.mjs.map +1 -0
  220. package/dist/credential/resolver.cjs +127 -0
  221. package/dist/credential/resolver.d.mts +1 -0
  222. package/dist/credential/resolver.mjs +127 -0
  223. package/dist/credential/resolver.mjs.map +1 -0
  224. package/dist/credential/store.cjs +106 -0
  225. package/dist/credential/store.d.cts +30 -0
  226. package/dist/credential/store.d.cts.map +1 -0
  227. package/dist/credential/store.d.mts +30 -0
  228. package/dist/credential/store.d.mts.map +1 -0
  229. package/dist/credential/store.mjs +106 -0
  230. package/dist/credential/store.mjs.map +1 -0
  231. package/dist/errors.cjs +18 -0
  232. package/dist/errors.mjs +18 -0
  233. package/dist/errors.mjs.map +1 -0
  234. package/dist/explorer/actions.cjs +311 -0
  235. package/dist/explorer/actions.mjs +305 -0
  236. package/dist/explorer/actions.mjs.map +1 -0
  237. package/dist/explorer/components/dialog.cjs +508 -0
  238. package/dist/explorer/components/dialog.mjs +509 -0
  239. package/dist/explorer/components/dialog.mjs.map +1 -0
  240. package/dist/explorer/components/file-list.cjs +107 -0
  241. package/dist/explorer/components/file-list.mjs +107 -0
  242. package/dist/explorer/components/file-list.mjs.map +1 -0
  243. package/dist/explorer/components/function-bar.cjs +55 -0
  244. package/dist/explorer/components/function-bar.mjs +55 -0
  245. package/dist/explorer/components/function-bar.mjs.map +1 -0
  246. package/dist/explorer/components/index.cjs +5 -0
  247. package/dist/explorer/components/index.mjs +7 -0
  248. package/dist/explorer/components/metadata-panel.cjs +219 -0
  249. package/dist/explorer/components/metadata-panel.mjs +219 -0
  250. package/dist/explorer/components/metadata-panel.mjs.map +1 -0
  251. package/dist/explorer/components/status-bar.cjs +53 -0
  252. package/dist/explorer/components/status-bar.mjs +54 -0
  253. package/dist/explorer/components/status-bar.mjs.map +1 -0
  254. package/dist/explorer/keybindings.cjs +214 -0
  255. package/dist/explorer/keybindings.mjs +213 -0
  256. package/dist/explorer/keybindings.mjs.map +1 -0
  257. package/dist/explorer/screen.cjs +251 -0
  258. package/dist/explorer/screen.d.cts +23 -0
  259. package/dist/explorer/screen.d.cts.map +1 -0
  260. package/dist/explorer/screen.d.mts +23 -0
  261. package/dist/explorer/screen.d.mts.map +1 -0
  262. package/dist/explorer/screen.mjs +250 -0
  263. package/dist/explorer/screen.mjs.map +1 -0
  264. package/dist/explorer/state.cjs +53 -0
  265. package/dist/explorer/state.mjs +53 -0
  266. package/dist/explorer/state.mjs.map +1 -0
  267. package/dist/explorer/theme.cjs +160 -0
  268. package/dist/explorer/theme.mjs +157 -0
  269. package/dist/explorer/theme.mjs.map +1 -0
  270. package/dist/index.cjs +12 -0
  271. package/dist/index.d.cts +6 -0
  272. package/dist/index.d.mts +7 -4
  273. package/dist/index.mjs +7 -2
  274. package/dist/mcp/http-transport.cjs +87 -0
  275. package/dist/mcp/http-transport.mjs +87 -0
  276. package/dist/mcp/http-transport.mjs.map +1 -0
  277. package/dist/mcp/prompts.cjs +48 -0
  278. package/dist/mcp/prompts.mjs +48 -0
  279. package/dist/mcp/prompts.mjs.map +1 -0
  280. package/dist/mcp/resources.cjs +25 -0
  281. package/dist/mcp/resources.mjs +25 -0
  282. package/dist/mcp/resources.mjs.map +1 -0
  283. package/dist/mcp/server.cjs +74 -0
  284. package/dist/mcp/server.mjs +73 -0
  285. package/dist/mcp/server.mjs.map +1 -0
  286. package/dist/mcp/tools.cjs +152 -0
  287. package/dist/mcp/tools.mjs +152 -0
  288. package/dist/mcp/tools.mjs.map +1 -0
  289. package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/index.d.cts +10 -0
  290. package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/index.d.cts.map +1 -0
  291. package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/index.d.mts +10 -0
  292. package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/index.d.mts.map +1 -0
  293. package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/types.d.cts +46 -0
  294. package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/types.d.cts.map +1 -0
  295. package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/types.d.mts +46 -0
  296. package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/types.d.mts.map +1 -0
  297. package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/urlpattern.cjs +902 -0
  298. package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/urlpattern.mjs +902 -0
  299. package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/urlpattern.mjs.map +1 -0
  300. package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/index.cjs +6 -0
  301. package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/index.mjs +8 -0
  302. package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/index.mjs.map +1 -0
  303. package/dist/path-utils.cjs +105 -0
  304. package/dist/path-utils.d.cts +50 -0
  305. package/dist/path-utils.d.cts.map +1 -0
  306. package/dist/path-utils.d.mts +50 -0
  307. package/dist/path-utils.d.mts.map +1 -0
  308. package/dist/path-utils.mjs +104 -0
  309. package/dist/path-utils.mjs.map +1 -0
  310. package/dist/repl.cjs +491 -0
  311. package/dist/repl.d.cts +15 -0
  312. package/dist/repl.d.cts.map +1 -0
  313. package/dist/repl.d.mts +16 -0
  314. package/dist/repl.d.mts.map +1 -0
  315. package/dist/repl.mjs +491 -0
  316. package/dist/repl.mjs.map +1 -0
  317. package/dist/serve.cjs +146 -0
  318. package/dist/serve.d.cts +41 -0
  319. package/dist/serve.d.cts.map +1 -0
  320. package/dist/serve.d.mts +41 -0
  321. package/dist/serve.d.mts.map +1 -0
  322. package/dist/serve.mjs +146 -0
  323. package/dist/serve.mjs.map +1 -0
  324. package/dist/ui/header.cjs +12 -0
  325. package/dist/ui/header.mjs +13 -0
  326. package/dist/ui/header.mjs.map +1 -0
  327. package/dist/ui/index.cjs +8 -0
  328. package/dist/ui/index.mjs +9 -0
  329. package/dist/ui/index.mjs.map +1 -0
  330. package/dist/ui/terminal.cjs +88 -0
  331. package/dist/ui/terminal.mjs +88 -0
  332. package/dist/ui/terminal.mjs.map +1 -0
  333. package/dist/version.cjs +9 -0
  334. package/dist/version.d.cts +5 -0
  335. package/dist/version.d.cts.map +1 -0
  336. package/dist/version.d.mts +5 -0
  337. package/dist/version.d.mts.map +1 -0
  338. package/dist/version.mjs +9 -0
  339. package/dist/version.mjs.map +1 -0
  340. package/package.json +77 -11
  341. package/.turbo/turbo-build.log +0 -18
  342. package/.turbo/turbo-check-types.log +0 -4
  343. package/dist/version--p6A8sKX.mjs +0 -5
  344. package/src/cli.test.ts +0 -8
  345. package/src/cli.ts +0 -29
  346. package/src/index.ts +0 -7
  347. package/src/version.ts +0 -1
  348. package/tsconfig.json +0 -16
@@ -0,0 +1,24 @@
1
+ import { formatDeleteOutput } from "./formatters/delete.mjs";
2
+ import { formatExecOutput } from "./formatters/exec.mjs";
3
+ import { formatExplainOutput } from "./formatters/explain.mjs";
4
+ import { formatLsOutput } from "./formatters/ls.mjs";
5
+ import { formatMountListOutput } from "./formatters/mount.mjs";
6
+ import { formatReadOutput } from "./formatters/read.mjs";
7
+ import { formatStatOutput } from "./formatters/stat.mjs";
8
+ import { formatWriteOutput } from "./formatters/write.mjs";
9
+ import { cliPathToCanonical, parseCliPath } from "../path-utils.mjs";
10
+ import "./path-utils.mjs";
11
+ import { createDeleteCommand } from "./commands/delete.mjs";
12
+ import { readStdin } from "./helpers/stdin.mjs";
13
+ import { RESERVED_OPTIONS, parseExecArgs, parseExecArgsWithStdin, parseValueBySchema, schemaTypeToYargs } from "./helpers/exec-args.mjs";
14
+ import { createExecCommand } from "./commands/exec.mjs";
15
+ import { createExplainCommand } from "./commands/explain.mjs";
16
+ import { createLsCommand } from "./commands/ls.mjs";
17
+ import { createMountCommand } from "./commands/mount.mjs";
18
+ import { createReadCommand } from "./commands/read.mjs";
19
+ import { createStatCommand } from "./commands/stat.mjs";
20
+ import { createWriteCommand } from "./commands/write.mjs";
21
+ import { commandFactories } from "./commands/index.mjs";
22
+ import { AFSCommandExecutor } from "./executor/index.mjs";
23
+
24
+ export { AFSCommandExecutor, RESERVED_OPTIONS, cliPathToCanonical, commandFactories, createDeleteCommand, createExecCommand, createExplainCommand, createLsCommand, createMountCommand, createReadCommand, createStatCommand, createWriteCommand, formatDeleteOutput, formatExecOutput, formatExplainOutput, formatLsOutput, formatMountListOutput, formatReadOutput, formatStatOutput, formatWriteOutput, parseCliPath, parseExecArgs, parseExecArgsWithStdin, parseValueBySchema, readStdin, schemaTypeToYargs };
@@ -0,0 +1 @@
1
+ const require_path_utils = require('../path-utils.cjs');
@@ -0,0 +1,3 @@
1
+ import { cliPathToCanonical, parseCliPath } from "../path-utils.mjs";
2
+
3
+ export { };
@@ -0,0 +1,24 @@
1
+ //#region src/core/types.d.ts
2
+ /**
3
+ * CLI Core Types
4
+ *
5
+ * Minimal type definitions for the core CLI layer.
6
+ * Uses AFS native types (AFSListResult, AFSReadResult, etc.) directly.
7
+ */
8
+ type ViewType = "default" | "json" | "yaml" | "llm" | "human";
9
+ /**
10
+ * Simplified JSON Schema type for CLI parameter parsing
11
+ */
12
+ interface JSONSchema {
13
+ type?: "string" | "number" | "integer" | "boolean" | "array" | "object" | "null";
14
+ properties?: Record<string, JSONSchema>;
15
+ items?: JSONSchema;
16
+ required?: string[];
17
+ description?: string;
18
+ default?: unknown;
19
+ enum?: unknown[];
20
+ [key: string]: unknown;
21
+ }
22
+ //#endregion
23
+ export { JSONSchema, ViewType };
24
+ //# sourceMappingURL=types.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.cts","names":[],"sources":["../../src/core/types.ts"],"mappings":";;AAWA;;;;;KAAY,QAAA;;;;UASK,UAAA;EACf,IAAA;EACA,UAAA,GAAa,MAAA,SAAe,UAAA;EAC5B,KAAA,GAAQ,UAAA;EACR,QAAA;EACA,WAAA;EACA,OAAA;EACA,IAAA;EAAA,CACC,GAAA;AAAA"}
@@ -0,0 +1,24 @@
1
+ //#region src/core/types.d.ts
2
+ /**
3
+ * CLI Core Types
4
+ *
5
+ * Minimal type definitions for the core CLI layer.
6
+ * Uses AFS native types (AFSListResult, AFSReadResult, etc.) directly.
7
+ */
8
+ type ViewType = "default" | "json" | "yaml" | "llm" | "human";
9
+ /**
10
+ * Simplified JSON Schema type for CLI parameter parsing
11
+ */
12
+ interface JSONSchema {
13
+ type?: "string" | "number" | "integer" | "boolean" | "array" | "object" | "null";
14
+ properties?: Record<string, JSONSchema>;
15
+ items?: JSONSchema;
16
+ required?: string[];
17
+ description?: string;
18
+ default?: unknown;
19
+ enum?: unknown[];
20
+ [key: string]: unknown;
21
+ }
22
+ //#endregion
23
+ export { JSONSchema, ViewType };
24
+ //# sourceMappingURL=types.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.mts","names":[],"sources":["../../src/core/types.ts"],"mappings":";;AAWA;;;;;KAAY,QAAA;;;;UASK,UAAA;EACf,IAAA;EACA,UAAA,GAAa,MAAA,SAAe,UAAA;EAC5B,KAAA,GAAQ,UAAA;EACR,QAAA;EACA,WAAA;EACA,OAAA;EACA,IAAA;EAAA,CACC,GAAA;AAAA"}
@@ -0,0 +1,247 @@
1
+ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
+ let node_crypto = require("node:crypto");
3
+ let node_http = require("node:http");
4
+
5
+ //#region src/credential/auth-server.ts
6
+ /**
7
+ * Temporary HTTP Server for credential collection.
8
+ *
9
+ * Supports two modes:
10
+ * 1. Form collection: GET /auth renders a form from JSON Schema, POST /auth returns submitted data
11
+ * 2. OAuth callback: GET /callback captures query params for waitForCallback()
12
+ *
13
+ * Security:
14
+ * - Binds to 127.0.0.1 only (no external connections)
15
+ * - One-time nonce per request to prevent CSRF
16
+ * - Auto-closes after 5 minutes
17
+ * - POST data is never logged
18
+ */
19
+ const DEFAULT_TIMEOUT = 300 * 1e3;
20
+ const MAX_PORT_RETRIES = 3;
21
+ /**
22
+ * Create a temporary auth server bound to 127.0.0.1 with a random port.
23
+ */
24
+ async function createAuthServer(options) {
25
+ const timeout = options?.timeout ?? DEFAULT_TIMEOUT;
26
+ const nonce = (0, node_crypto.randomBytes)(16).toString("hex");
27
+ let closed = false;
28
+ let callbackResolve = null;
29
+ let formResolve = null;
30
+ let formSchema = null;
31
+ let formTitle = "AFS Credential Collection";
32
+ const server = (0, node_http.createServer)((req, res) => {
33
+ const url = new URL(req.url || "/", `http://127.0.0.1`);
34
+ const pathname = url.pathname;
35
+ res.setHeader("Access-Control-Allow-Origin", "*");
36
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
37
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
38
+ if (req.method === "OPTIONS") {
39
+ res.writeHead(204);
40
+ res.end();
41
+ return;
42
+ }
43
+ if (pathname === "/callback") handleCallback(url, req, res, nonce);
44
+ else if (pathname === "/auth" && req.method === "GET") handleFormGet(url, res, nonce);
45
+ else if (pathname === "/auth" && req.method === "POST") handleFormPost(req, res, nonce, url);
46
+ else {
47
+ res.writeHead(404, { "Content-Type": "text/plain" });
48
+ res.end("Not Found");
49
+ }
50
+ });
51
+ function handleCallback(url, _req, res, expectedNonce) {
52
+ if (url.searchParams.get("nonce") !== expectedNonce) {
53
+ res.writeHead(403, { "Content-Type": "text/plain" });
54
+ res.end("Forbidden: invalid nonce");
55
+ return;
56
+ }
57
+ const params = {};
58
+ for (const [key, value] of url.searchParams.entries()) if (key !== "nonce") params[key] = value;
59
+ res.writeHead(200, { "Content-Type": "text/html" });
60
+ res.end("<html><body><h2>Authorization complete.</h2><p>You can close this tab.</p></body></html>");
61
+ if (callbackResolve) {
62
+ callbackResolve(params);
63
+ callbackResolve = null;
64
+ }
65
+ }
66
+ function handleFormGet(url, res, expectedNonce) {
67
+ if (url.searchParams.get("nonce") !== expectedNonce) {
68
+ res.writeHead(403, { "Content-Type": "text/plain" });
69
+ res.end("Forbidden: invalid nonce");
70
+ return;
71
+ }
72
+ if (!formSchema) {
73
+ res.writeHead(400, { "Content-Type": "text/plain" });
74
+ res.end("No form schema available");
75
+ return;
76
+ }
77
+ const html = renderFormHTML(formSchema, formTitle, expectedNonce);
78
+ res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
79
+ res.end(html);
80
+ }
81
+ function handleFormPost(req, res, expectedNonce, url) {
82
+ if (url.searchParams.get("nonce") !== expectedNonce) {
83
+ res.writeHead(403, { "Content-Type": "text/plain" });
84
+ res.end("Forbidden: invalid nonce");
85
+ return;
86
+ }
87
+ let body = "";
88
+ req.on("data", (chunk) => {
89
+ body += chunk.toString();
90
+ });
91
+ req.on("end", () => {
92
+ let data;
93
+ if ((req.headers["content-type"] || "").includes("application/json")) try {
94
+ data = JSON.parse(body);
95
+ } catch {
96
+ res.writeHead(400, { "Content-Type": "text/plain" });
97
+ res.end("Invalid JSON");
98
+ return;
99
+ }
100
+ else {
101
+ const params = new URLSearchParams(body);
102
+ data = {};
103
+ for (const [key, value] of params.entries()) if (key !== "nonce") data[key] = value;
104
+ if (formSchema?.properties) for (const [key, value] of Object.entries(data)) {
105
+ const prop = formSchema.properties[key];
106
+ if (!prop) continue;
107
+ const strValue = String(value);
108
+ if (prop.type === "number" || prop.type === "integer") {
109
+ const num = Number(strValue);
110
+ if (!Number.isNaN(num) && strValue !== "") data[key] = num;
111
+ } else if (prop.type === "boolean") {
112
+ if (strValue === "true" || strValue === "1") data[key] = true;
113
+ else if (strValue === "false" || strValue === "0" || strValue === "") data[key] = false;
114
+ }
115
+ if (strValue === "" && prop.type !== "string") delete data[key];
116
+ }
117
+ }
118
+ res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
119
+ res.end("<html><body><h2>Credentials received.</h2><p>You can close this tab.</p></body></html>");
120
+ if (formResolve) {
121
+ formResolve(data);
122
+ formResolve = null;
123
+ }
124
+ });
125
+ }
126
+ const port = await startServer(server, MAX_PORT_RETRIES);
127
+ const autoCloseTimer = setTimeout(() => {
128
+ closeServer();
129
+ }, timeout);
130
+ function closeServer() {
131
+ if (closed) return;
132
+ closed = true;
133
+ clearTimeout(autoCloseTimer);
134
+ server.close();
135
+ if (callbackResolve) {
136
+ callbackResolve(null);
137
+ callbackResolve = null;
138
+ }
139
+ if (formResolve) {
140
+ formResolve(null);
141
+ formResolve = null;
142
+ }
143
+ }
144
+ const baseURL = `http://127.0.0.1:${port}`;
145
+ return {
146
+ baseURL,
147
+ callbackURL: `${baseURL}/callback?nonce=${nonce}`,
148
+ nonce,
149
+ port,
150
+ waitForCallback(opts) {
151
+ if (closed) return Promise.resolve(null);
152
+ return new Promise((resolve) => {
153
+ callbackResolve = resolve;
154
+ if (opts?.timeout) setTimeout(() => {
155
+ if (callbackResolve === resolve) {
156
+ callbackResolve = null;
157
+ resolve(null);
158
+ }
159
+ }, opts.timeout);
160
+ });
161
+ },
162
+ waitForForm(schema, opts) {
163
+ if (closed) return Promise.resolve(null);
164
+ formSchema = schema;
165
+ if (opts?.title) formTitle = opts.title;
166
+ return new Promise((resolve) => {
167
+ formResolve = resolve;
168
+ if (opts?.timeout) setTimeout(() => {
169
+ if (formResolve === resolve) {
170
+ formResolve = null;
171
+ resolve(null);
172
+ }
173
+ }, opts.timeout);
174
+ });
175
+ },
176
+ close: closeServer
177
+ };
178
+ }
179
+ async function startServer(server, maxRetries) {
180
+ for (let attempt = 0; attempt <= maxRetries; attempt++) try {
181
+ return await new Promise((resolve, reject) => {
182
+ server.listen(0, "127.0.0.1", () => {
183
+ const addr = server.address();
184
+ if (addr && typeof addr === "object") resolve(addr.port);
185
+ else reject(/* @__PURE__ */ new Error("Failed to get server address"));
186
+ });
187
+ server.on("error", reject);
188
+ });
189
+ } catch (err) {
190
+ if (attempt === maxRetries) throw new Error(`Failed to start auth server after ${maxRetries + 1} attempts: ${err.message}`);
191
+ server.close();
192
+ }
193
+ throw new Error("Failed to start auth server");
194
+ }
195
+ function renderFormHTML(schema, title, nonce) {
196
+ const properties = schema.properties || {};
197
+ const required = new Set(schema.required || []);
198
+ let fields = "";
199
+ for (const [key, prop] of Object.entries(properties)) {
200
+ const label = prop.description || key;
201
+ const isSensitive = prop.sensitive === true;
202
+ const isRequired = required.has(key);
203
+ const inputType = isSensitive ? "password" : "text";
204
+ const defaultValue = prop.default != null ? String(prop.default) : "";
205
+ fields += `
206
+ <div style="margin-bottom: 12px;">
207
+ <label for="${escapeHTML(key)}" style="display: block; font-weight: 600; margin-bottom: 4px;">
208
+ ${escapeHTML(label)}${isRequired ? " *" : ""}
209
+ </label>
210
+ <input
211
+ type="${inputType}"
212
+ id="${escapeHTML(key)}"
213
+ name="${escapeHTML(key)}"
214
+ value="${escapeHTML(defaultValue)}"
215
+ ${isRequired ? "required" : ""}
216
+ style="width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; font-size: 14px;"
217
+ autocomplete="off"
218
+ />
219
+ </div>`;
220
+ }
221
+ return `<!DOCTYPE html>
222
+ <html>
223
+ <head>
224
+ <meta charset="utf-8">
225
+ <title>${escapeHTML(title)}</title>
226
+ <style>
227
+ body { font-family: -apple-system, BlinkMacSystemFont, sans-serif; max-width: 480px; margin: 40px auto; padding: 0 20px; }
228
+ h2 { color: #333; }
229
+ button { background: #2563eb; color: white; border: none; padding: 10px 24px; border-radius: 4px; font-size: 14px; cursor: pointer; }
230
+ button:hover { background: #1d4ed8; }
231
+ </style>
232
+ </head>
233
+ <body>
234
+ <h2>${escapeHTML(title)}</h2>
235
+ <form method="POST" action="/auth?nonce=${escapeHTML(nonce)}">
236
+ ${fields}
237
+ <button type="submit">Submit</button>
238
+ </form>
239
+ </body>
240
+ </html>`;
241
+ }
242
+ function escapeHTML(str) {
243
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
244
+ }
245
+
246
+ //#endregion
247
+ exports.createAuthServer = createAuthServer;
@@ -0,0 +1,247 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { createServer } from "node:http";
3
+
4
+ //#region src/credential/auth-server.ts
5
+ /**
6
+ * Temporary HTTP Server for credential collection.
7
+ *
8
+ * Supports two modes:
9
+ * 1. Form collection: GET /auth renders a form from JSON Schema, POST /auth returns submitted data
10
+ * 2. OAuth callback: GET /callback captures query params for waitForCallback()
11
+ *
12
+ * Security:
13
+ * - Binds to 127.0.0.1 only (no external connections)
14
+ * - One-time nonce per request to prevent CSRF
15
+ * - Auto-closes after 5 minutes
16
+ * - POST data is never logged
17
+ */
18
+ const DEFAULT_TIMEOUT = 300 * 1e3;
19
+ const MAX_PORT_RETRIES = 3;
20
+ /**
21
+ * Create a temporary auth server bound to 127.0.0.1 with a random port.
22
+ */
23
+ async function createAuthServer(options) {
24
+ const timeout = options?.timeout ?? DEFAULT_TIMEOUT;
25
+ const nonce = randomBytes(16).toString("hex");
26
+ let closed = false;
27
+ let callbackResolve = null;
28
+ let formResolve = null;
29
+ let formSchema = null;
30
+ let formTitle = "AFS Credential Collection";
31
+ const server = createServer((req, res) => {
32
+ const url = new URL(req.url || "/", `http://127.0.0.1`);
33
+ const pathname = url.pathname;
34
+ res.setHeader("Access-Control-Allow-Origin", "*");
35
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
36
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
37
+ if (req.method === "OPTIONS") {
38
+ res.writeHead(204);
39
+ res.end();
40
+ return;
41
+ }
42
+ if (pathname === "/callback") handleCallback(url, req, res, nonce);
43
+ else if (pathname === "/auth" && req.method === "GET") handleFormGet(url, res, nonce);
44
+ else if (pathname === "/auth" && req.method === "POST") handleFormPost(req, res, nonce, url);
45
+ else {
46
+ res.writeHead(404, { "Content-Type": "text/plain" });
47
+ res.end("Not Found");
48
+ }
49
+ });
50
+ function handleCallback(url, _req, res, expectedNonce) {
51
+ if (url.searchParams.get("nonce") !== expectedNonce) {
52
+ res.writeHead(403, { "Content-Type": "text/plain" });
53
+ res.end("Forbidden: invalid nonce");
54
+ return;
55
+ }
56
+ const params = {};
57
+ for (const [key, value] of url.searchParams.entries()) if (key !== "nonce") params[key] = value;
58
+ res.writeHead(200, { "Content-Type": "text/html" });
59
+ res.end("<html><body><h2>Authorization complete.</h2><p>You can close this tab.</p></body></html>");
60
+ if (callbackResolve) {
61
+ callbackResolve(params);
62
+ callbackResolve = null;
63
+ }
64
+ }
65
+ function handleFormGet(url, res, expectedNonce) {
66
+ if (url.searchParams.get("nonce") !== expectedNonce) {
67
+ res.writeHead(403, { "Content-Type": "text/plain" });
68
+ res.end("Forbidden: invalid nonce");
69
+ return;
70
+ }
71
+ if (!formSchema) {
72
+ res.writeHead(400, { "Content-Type": "text/plain" });
73
+ res.end("No form schema available");
74
+ return;
75
+ }
76
+ const html = renderFormHTML(formSchema, formTitle, expectedNonce);
77
+ res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
78
+ res.end(html);
79
+ }
80
+ function handleFormPost(req, res, expectedNonce, url) {
81
+ if (url.searchParams.get("nonce") !== expectedNonce) {
82
+ res.writeHead(403, { "Content-Type": "text/plain" });
83
+ res.end("Forbidden: invalid nonce");
84
+ return;
85
+ }
86
+ let body = "";
87
+ req.on("data", (chunk) => {
88
+ body += chunk.toString();
89
+ });
90
+ req.on("end", () => {
91
+ let data;
92
+ if ((req.headers["content-type"] || "").includes("application/json")) try {
93
+ data = JSON.parse(body);
94
+ } catch {
95
+ res.writeHead(400, { "Content-Type": "text/plain" });
96
+ res.end("Invalid JSON");
97
+ return;
98
+ }
99
+ else {
100
+ const params = new URLSearchParams(body);
101
+ data = {};
102
+ for (const [key, value] of params.entries()) if (key !== "nonce") data[key] = value;
103
+ if (formSchema?.properties) for (const [key, value] of Object.entries(data)) {
104
+ const prop = formSchema.properties[key];
105
+ if (!prop) continue;
106
+ const strValue = String(value);
107
+ if (prop.type === "number" || prop.type === "integer") {
108
+ const num = Number(strValue);
109
+ if (!Number.isNaN(num) && strValue !== "") data[key] = num;
110
+ } else if (prop.type === "boolean") {
111
+ if (strValue === "true" || strValue === "1") data[key] = true;
112
+ else if (strValue === "false" || strValue === "0" || strValue === "") data[key] = false;
113
+ }
114
+ if (strValue === "" && prop.type !== "string") delete data[key];
115
+ }
116
+ }
117
+ res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
118
+ res.end("<html><body><h2>Credentials received.</h2><p>You can close this tab.</p></body></html>");
119
+ if (formResolve) {
120
+ formResolve(data);
121
+ formResolve = null;
122
+ }
123
+ });
124
+ }
125
+ const port = await startServer(server, MAX_PORT_RETRIES);
126
+ const autoCloseTimer = setTimeout(() => {
127
+ closeServer();
128
+ }, timeout);
129
+ function closeServer() {
130
+ if (closed) return;
131
+ closed = true;
132
+ clearTimeout(autoCloseTimer);
133
+ server.close();
134
+ if (callbackResolve) {
135
+ callbackResolve(null);
136
+ callbackResolve = null;
137
+ }
138
+ if (formResolve) {
139
+ formResolve(null);
140
+ formResolve = null;
141
+ }
142
+ }
143
+ const baseURL = `http://127.0.0.1:${port}`;
144
+ return {
145
+ baseURL,
146
+ callbackURL: `${baseURL}/callback?nonce=${nonce}`,
147
+ nonce,
148
+ port,
149
+ waitForCallback(opts) {
150
+ if (closed) return Promise.resolve(null);
151
+ return new Promise((resolve) => {
152
+ callbackResolve = resolve;
153
+ if (opts?.timeout) setTimeout(() => {
154
+ if (callbackResolve === resolve) {
155
+ callbackResolve = null;
156
+ resolve(null);
157
+ }
158
+ }, opts.timeout);
159
+ });
160
+ },
161
+ waitForForm(schema, opts) {
162
+ if (closed) return Promise.resolve(null);
163
+ formSchema = schema;
164
+ if (opts?.title) formTitle = opts.title;
165
+ return new Promise((resolve) => {
166
+ formResolve = resolve;
167
+ if (opts?.timeout) setTimeout(() => {
168
+ if (formResolve === resolve) {
169
+ formResolve = null;
170
+ resolve(null);
171
+ }
172
+ }, opts.timeout);
173
+ });
174
+ },
175
+ close: closeServer
176
+ };
177
+ }
178
+ async function startServer(server, maxRetries) {
179
+ for (let attempt = 0; attempt <= maxRetries; attempt++) try {
180
+ return await new Promise((resolve, reject) => {
181
+ server.listen(0, "127.0.0.1", () => {
182
+ const addr = server.address();
183
+ if (addr && typeof addr === "object") resolve(addr.port);
184
+ else reject(/* @__PURE__ */ new Error("Failed to get server address"));
185
+ });
186
+ server.on("error", reject);
187
+ });
188
+ } catch (err) {
189
+ if (attempt === maxRetries) throw new Error(`Failed to start auth server after ${maxRetries + 1} attempts: ${err.message}`);
190
+ server.close();
191
+ }
192
+ throw new Error("Failed to start auth server");
193
+ }
194
+ function renderFormHTML(schema, title, nonce) {
195
+ const properties = schema.properties || {};
196
+ const required = new Set(schema.required || []);
197
+ let fields = "";
198
+ for (const [key, prop] of Object.entries(properties)) {
199
+ const label = prop.description || key;
200
+ const isSensitive = prop.sensitive === true;
201
+ const isRequired = required.has(key);
202
+ const inputType = isSensitive ? "password" : "text";
203
+ const defaultValue = prop.default != null ? String(prop.default) : "";
204
+ fields += `
205
+ <div style="margin-bottom: 12px;">
206
+ <label for="${escapeHTML(key)}" style="display: block; font-weight: 600; margin-bottom: 4px;">
207
+ ${escapeHTML(label)}${isRequired ? " *" : ""}
208
+ </label>
209
+ <input
210
+ type="${inputType}"
211
+ id="${escapeHTML(key)}"
212
+ name="${escapeHTML(key)}"
213
+ value="${escapeHTML(defaultValue)}"
214
+ ${isRequired ? "required" : ""}
215
+ style="width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; font-size: 14px;"
216
+ autocomplete="off"
217
+ />
218
+ </div>`;
219
+ }
220
+ return `<!DOCTYPE html>
221
+ <html>
222
+ <head>
223
+ <meta charset="utf-8">
224
+ <title>${escapeHTML(title)}</title>
225
+ <style>
226
+ body { font-family: -apple-system, BlinkMacSystemFont, sans-serif; max-width: 480px; margin: 40px auto; padding: 0 20px; }
227
+ h2 { color: #333; }
228
+ button { background: #2563eb; color: white; border: none; padding: 10px 24px; border-radius: 4px; font-size: 14px; cursor: pointer; }
229
+ button:hover { background: #1d4ed8; }
230
+ </style>
231
+ </head>
232
+ <body>
233
+ <h2>${escapeHTML(title)}</h2>
234
+ <form method="POST" action="/auth?nonce=${escapeHTML(nonce)}">
235
+ ${fields}
236
+ <button type="submit">Submit</button>
237
+ </form>
238
+ </body>
239
+ </html>`;
240
+ }
241
+ function escapeHTML(str) {
242
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
243
+ }
244
+
245
+ //#endregion
246
+ export { createAuthServer };
247
+ //# sourceMappingURL=auth-server.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-server.mjs","names":[],"sources":["../../src/credential/auth-server.ts"],"sourcesContent":["/**\n * Temporary HTTP Server for credential collection.\n *\n * Supports two modes:\n * 1. Form collection: GET /auth renders a form from JSON Schema, POST /auth returns submitted data\n * 2. OAuth callback: GET /callback captures query params for waitForCallback()\n *\n * Security:\n * - Binds to 127.0.0.1 only (no external connections)\n * - One-time nonce per request to prevent CSRF\n * - Auto-closes after 5 minutes\n * - POST data is never logged\n */\n\nimport { randomBytes } from \"node:crypto\";\nimport { createServer, type IncomingMessage, type Server, type ServerResponse } from \"node:http\";\n\nconst DEFAULT_TIMEOUT = 5 * 60 * 1000; // 5 minutes\nconst MAX_PORT_RETRIES = 3;\n\nexport interface AuthServer {\n /** Base URL of the server, e.g. http://127.0.0.1:12345 */\n baseURL: string;\n\n /** Callback URL for OAuth redirects: baseURL + /callback */\n callbackURL: string;\n\n /** Wait for a callback request at /callback. Returns query params or null on timeout/close. */\n waitForCallback(options?: { timeout?: number }): Promise<Record<string, string> | null>;\n\n /**\n * Serve a form for collecting fields, wait for submission.\n * Returns submitted values or null on timeout/close.\n *\n * @param schema - JSON Schema describing fields to collect\n * @param options - Optional title and timeout\n */\n waitForForm(\n schema: Record<string, any>,\n options?: { title?: string; timeout?: number },\n ): Promise<Record<string, unknown> | null>;\n\n /** Close the server. Idempotent. */\n close(): void;\n\n /** The one-time nonce for this server session */\n readonly nonce: string;\n\n /** The port the server is listening on */\n readonly port: number;\n}\n\nexport interface CreateAuthServerOptions {\n /** Timeout in ms before auto-close. Default: 5 minutes. */\n timeout?: number;\n}\n\n/**\n * Create a temporary auth server bound to 127.0.0.1 with a random port.\n */\nexport async function createAuthServer(options?: CreateAuthServerOptions): Promise<AuthServer> {\n const timeout = options?.timeout ?? DEFAULT_TIMEOUT;\n const nonce = randomBytes(16).toString(\"hex\");\n\n let closed = false;\n let callbackResolve: ((value: Record<string, string> | null) => void) | null = null;\n let formResolve: ((value: Record<string, unknown> | null) => void) | null = null;\n let formSchema: Record<string, any> | null = null;\n let formTitle = \"AFS Credential Collection\";\n\n const server = createServer((req, res) => {\n const url = new URL(req.url || \"/\", `http://127.0.0.1`);\n const pathname = url.pathname;\n\n // CORS headers for local browser forms\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n res.setHeader(\"Access-Control-Allow-Methods\", \"GET, POST, OPTIONS\");\n res.setHeader(\"Access-Control-Allow-Headers\", \"Content-Type\");\n\n if (req.method === \"OPTIONS\") {\n res.writeHead(204);\n res.end();\n return;\n }\n\n if (pathname === \"/callback\") {\n handleCallback(url, req, res, nonce);\n } else if (pathname === \"/auth\" && req.method === \"GET\") {\n handleFormGet(url, res, nonce);\n } else if (pathname === \"/auth\" && req.method === \"POST\") {\n handleFormPost(req, res, nonce, url);\n } else {\n res.writeHead(404, { \"Content-Type\": \"text/plain\" });\n res.end(\"Not Found\");\n }\n });\n\n function handleCallback(\n url: URL,\n _req: IncomingMessage,\n res: ServerResponse,\n expectedNonce: string,\n ): void {\n const reqNonce = url.searchParams.get(\"nonce\");\n if (reqNonce !== expectedNonce) {\n res.writeHead(403, { \"Content-Type\": \"text/plain\" });\n res.end(\"Forbidden: invalid nonce\");\n return;\n }\n\n const params: Record<string, string> = {};\n for (const [key, value] of url.searchParams.entries()) {\n if (key !== \"nonce\") {\n params[key] = value;\n }\n }\n\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(\n \"<html><body><h2>Authorization complete.</h2><p>You can close this tab.</p></body></html>\",\n );\n\n if (callbackResolve) {\n callbackResolve(params);\n callbackResolve = null;\n }\n }\n\n function handleFormGet(url: URL, res: ServerResponse, expectedNonce: string): void {\n const reqNonce = url.searchParams.get(\"nonce\");\n if (reqNonce !== expectedNonce) {\n res.writeHead(403, { \"Content-Type\": \"text/plain\" });\n res.end(\"Forbidden: invalid nonce\");\n return;\n }\n\n if (!formSchema) {\n res.writeHead(400, { \"Content-Type\": \"text/plain\" });\n res.end(\"No form schema available\");\n return;\n }\n\n const html = renderFormHTML(formSchema, formTitle, expectedNonce);\n res.writeHead(200, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(html);\n }\n\n function handleFormPost(\n req: IncomingMessage,\n res: ServerResponse,\n expectedNonce: string,\n url: URL,\n ): void {\n const reqNonce = url.searchParams.get(\"nonce\");\n if (reqNonce !== expectedNonce) {\n res.writeHead(403, { \"Content-Type\": \"text/plain\" });\n res.end(\"Forbidden: invalid nonce\");\n return;\n }\n\n let body = \"\";\n req.on(\"data\", (chunk: Buffer) => {\n body += chunk.toString();\n });\n req.on(\"end\", () => {\n let data: Record<string, unknown>;\n const contentType = req.headers[\"content-type\"] || \"\";\n\n if (contentType.includes(\"application/json\")) {\n try {\n data = JSON.parse(body);\n } catch {\n res.writeHead(400, { \"Content-Type\": \"text/plain\" });\n res.end(\"Invalid JSON\");\n return;\n }\n } else {\n // URL-encoded form data\n const params = new URLSearchParams(body);\n data = {};\n for (const [key, value] of params.entries()) {\n if (key !== \"nonce\") {\n data[key] = value;\n }\n }\n // Coerce string values to match schema types (HTML forms always submit strings)\n if (formSchema?.properties) {\n for (const [key, value] of Object.entries(data)) {\n const prop = (formSchema.properties as Record<string, any>)[key];\n if (!prop) continue;\n const strValue = String(value);\n if (prop.type === \"number\" || prop.type === \"integer\") {\n const num = Number(strValue);\n if (!Number.isNaN(num) && strValue !== \"\") data[key] = num;\n } else if (prop.type === \"boolean\") {\n if (strValue === \"true\" || strValue === \"1\") data[key] = true;\n else if (strValue === \"false\" || strValue === \"0\" || strValue === \"\")\n data[key] = false;\n }\n // Remove empty strings for non-string optional fields (let defaults apply)\n if (strValue === \"\" && prop.type !== \"string\") {\n delete data[key];\n }\n }\n }\n }\n\n res.writeHead(200, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(\n \"<html><body><h2>Credentials received.</h2><p>You can close this tab.</p></body></html>\",\n );\n\n if (formResolve) {\n formResolve(data);\n formResolve = null;\n }\n });\n }\n\n // Start server with port retry\n const port = await startServer(server, MAX_PORT_RETRIES);\n\n // Auto-close timeout\n const autoCloseTimer = setTimeout(() => {\n closeServer();\n }, timeout);\n\n function closeServer(): void {\n if (closed) return;\n closed = true;\n clearTimeout(autoCloseTimer);\n server.close();\n\n // Resolve any pending waiters with null\n if (callbackResolve) {\n callbackResolve(null);\n callbackResolve = null;\n }\n if (formResolve) {\n formResolve(null);\n formResolve = null;\n }\n }\n\n const baseURL = `http://127.0.0.1:${port}`;\n\n return {\n baseURL,\n callbackURL: `${baseURL}/callback?nonce=${nonce}`,\n nonce,\n port,\n\n waitForCallback(opts?: { timeout?: number }): Promise<Record<string, string> | null> {\n if (closed) return Promise.resolve(null);\n\n return new Promise((resolve) => {\n callbackResolve = resolve;\n\n if (opts?.timeout) {\n setTimeout(() => {\n if (callbackResolve === resolve) {\n callbackResolve = null;\n resolve(null);\n }\n }, opts.timeout);\n }\n });\n },\n\n waitForForm(\n schema: Record<string, any>,\n opts?: { title?: string; timeout?: number },\n ): Promise<Record<string, unknown> | null> {\n if (closed) return Promise.resolve(null);\n\n formSchema = schema;\n if (opts?.title) formTitle = opts.title;\n\n return new Promise((resolve) => {\n formResolve = resolve;\n\n if (opts?.timeout) {\n setTimeout(() => {\n if (formResolve === resolve) {\n formResolve = null;\n resolve(null);\n }\n }, opts.timeout);\n }\n });\n },\n\n close: closeServer,\n };\n}\n\nasync function startServer(server: Server, maxRetries: number): Promise<number> {\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await new Promise<number>((resolve, reject) => {\n server.listen(0, \"127.0.0.1\", () => {\n const addr = server.address();\n if (addr && typeof addr === \"object\") {\n resolve(addr.port);\n } else {\n reject(new Error(\"Failed to get server address\"));\n }\n });\n server.on(\"error\", reject);\n });\n } catch (err: any) {\n if (attempt === maxRetries) {\n throw new Error(\n `Failed to start auth server after ${maxRetries + 1} attempts: ${err.message}`,\n );\n }\n // Close and retry\n server.close();\n }\n }\n throw new Error(\"Failed to start auth server\");\n}\n\nfunction renderFormHTML(schema: Record<string, any>, title: string, nonce: string): string {\n const properties = schema.properties || {};\n const required = new Set(schema.required || []);\n\n let fields = \"\";\n for (const [key, prop] of Object.entries(properties) as [string, any][]) {\n const label = prop.description || key;\n const isSensitive = prop.sensitive === true;\n const isRequired = required.has(key);\n const inputType = isSensitive ? \"password\" : \"text\";\n const defaultValue = prop.default != null ? String(prop.default) : \"\";\n\n fields += `\n <div style=\"margin-bottom: 12px;\">\n <label for=\"${escapeHTML(key)}\" style=\"display: block; font-weight: 600; margin-bottom: 4px;\">\n ${escapeHTML(label)}${isRequired ? \" *\" : \"\"}\n </label>\n <input\n type=\"${inputType}\"\n id=\"${escapeHTML(key)}\"\n name=\"${escapeHTML(key)}\"\n value=\"${escapeHTML(defaultValue)}\"\n ${isRequired ? \"required\" : \"\"}\n style=\"width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; font-size: 14px;\"\n autocomplete=\"off\"\n />\n </div>`;\n }\n\n return `<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <title>${escapeHTML(title)}</title>\n <style>\n body { font-family: -apple-system, BlinkMacSystemFont, sans-serif; max-width: 480px; margin: 40px auto; padding: 0 20px; }\n h2 { color: #333; }\n button { background: #2563eb; color: white; border: none; padding: 10px 24px; border-radius: 4px; font-size: 14px; cursor: pointer; }\n button:hover { background: #1d4ed8; }\n </style>\n</head>\n<body>\n <h2>${escapeHTML(title)}</h2>\n <form method=\"POST\" action=\"/auth?nonce=${escapeHTML(nonce)}\">\n ${fields}\n <button type=\"submit\">Submit</button>\n </form>\n</body>\n</html>`;\n}\n\nfunction escapeHTML(str: string): string {\n return str\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#39;\");\n}\n"],"mappings":"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"}