buninu-linux 0.2.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.
- package/LICENSE +21 -0
- package/LICENSES/Bun-LICENSE.md +84 -0
- package/LICENSES/GCC-Runtime-Library-Exception-3.1.txt +73 -0
- package/LICENSES/GPL-2.0.txt +338 -0
- package/LICENSES/GPL-3.0.txt +674 -0
- package/LICENSES/LGPL-2.1.txt +501 -0
- package/LICENSES/Linux-syscall-note.txt +25 -0
- package/LICENSES/musl-COPYRIGHT.txt +193 -0
- package/NOTICE.md +184 -0
- package/README.md +537 -0
- package/build-image.sh +44 -0
- package/build-uki.sh +75 -0
- package/fetch-alpine.sh +80 -0
- package/fetch-bun.sh +41 -0
- package/fetch-plus-build.sh +11 -0
- package/hello/build-hello.sh +14 -0
- package/hello/hello.c +50 -0
- package/index.js +235 -0
- package/initramfs/bin/sh +3 -0
- package/initramfs/buninu/.bashrc +11 -0
- package/initramfs/buninu/ARCHITECTURE.md +452 -0
- package/initramfs/buninu/CHANGELOG.md +580 -0
- package/initramfs/buninu/LICENSE +21 -0
- package/initramfs/buninu/README.md +1161 -0
- package/initramfs/buninu/apps/bun/make-bunBin.sh +99 -0
- package/initramfs/buninu/apps/bunmsh/CHANGELOG.md +493 -0
- package/initramfs/buninu/apps/bunmsh/LICENSE +21 -0
- package/initramfs/buninu/apps/bunmsh/LICENSE-MICRO +58 -0
- package/initramfs/buninu/apps/bunmsh/LICENSE-MKSH +295 -0
- package/initramfs/buninu/apps/bunmsh/PORTING.md +192 -0
- package/initramfs/buninu/apps/bunmsh/README.md +1042 -0
- package/initramfs/buninu/apps/bunmsh/bunmsh +7 -0
- package/initramfs/buninu/apps/bunmsh/bunshell.md +61 -0
- package/initramfs/buninu/apps/bunmsh/help/README.md +2237 -0
- package/initramfs/buninu/apps/bunmsh/help/alias.md +22 -0
- package/initramfs/buninu/apps/bunmsh/help/basename.md +38 -0
- package/initramfs/buninu/apps/bunmsh/help/builtin.md +25 -0
- package/initramfs/buninu/apps/bunmsh/help/bun.md +27 -0
- package/initramfs/buninu/apps/bunmsh/help/bunmsh.md +47 -0
- package/initramfs/buninu/apps/bunmsh/help/cat.md +31 -0
- package/initramfs/buninu/apps/bunmsh/help/catfancy.md +35 -0
- package/initramfs/buninu/apps/bunmsh/help/cd.md +22 -0
- package/initramfs/buninu/apps/bunmsh/help/chmod.md +27 -0
- package/initramfs/buninu/apps/bunmsh/help/clear.md +21 -0
- package/initramfs/buninu/apps/bunmsh/help/colon.md +22 -0
- package/initramfs/buninu/apps/bunmsh/help/command.md +27 -0
- package/initramfs/buninu/apps/bunmsh/help/cp.md +28 -0
- package/initramfs/buninu/apps/bunmsh/help/curl.md +181 -0
- package/initramfs/buninu/apps/bunmsh/help/cut.md +25 -0
- package/initramfs/buninu/apps/bunmsh/help/date.md +25 -0
- package/initramfs/buninu/apps/bunmsh/help/dirname.md +25 -0
- package/initramfs/buninu/apps/bunmsh/help/echo.md +25 -0
- package/initramfs/buninu/apps/bunmsh/help/env.md +27 -0
- package/initramfs/buninu/apps/bunmsh/help/eval.md +22 -0
- package/initramfs/buninu/apps/bunmsh/help/exec.md +22 -0
- package/initramfs/buninu/apps/bunmsh/help/exit.md +21 -0
- package/initramfs/buninu/apps/bunmsh/help/export.md +22 -0
- package/initramfs/buninu/apps/bunmsh/help/false.md +22 -0
- package/initramfs/buninu/apps/bunmsh/help/find.md +33 -0
- package/initramfs/buninu/apps/bunmsh/help/getopts.md +28 -0
- package/initramfs/buninu/apps/bunmsh/help/grep.md +34 -0
- package/initramfs/buninu/apps/bunmsh/help/head.md +27 -0
- package/initramfs/buninu/apps/bunmsh/help/kill.md +43 -0
- package/initramfs/buninu/apps/bunmsh/help/ln.md +28 -0
- package/initramfs/buninu/apps/bunmsh/help/ls.md +37 -0
- package/initramfs/buninu/apps/bunmsh/help/lsbun.md +29 -0
- package/initramfs/buninu/apps/bunmsh/help/lsfancy.md +37 -0
- package/initramfs/buninu/apps/bunmsh/help/md5sum.md +21 -0
- package/initramfs/buninu/apps/bunmsh/help/mkdir.md +27 -0
- package/initramfs/buninu/apps/bunmsh/help/mktemp.md +26 -0
- package/initramfs/buninu/apps/bunmsh/help/mv.md +26 -0
- package/initramfs/buninu/apps/bunmsh/help/print.md +30 -0
- package/initramfs/buninu/apps/bunmsh/help/printf.md +25 -0
- package/initramfs/buninu/apps/bunmsh/help/pspa.md +38 -0
- package/initramfs/buninu/apps/bunmsh/help/pspac.md +57 -0
- package/initramfs/buninu/apps/bunmsh/help/pwd.md +21 -0
- package/initramfs/buninu/apps/bunmsh/help/read.md +27 -0
- package/initramfs/buninu/apps/bunmsh/help/readonly.md +27 -0
- package/initramfs/buninu/apps/bunmsh/help/realpath.md +21 -0
- package/initramfs/buninu/apps/bunmsh/help/rm.md +33 -0
- package/initramfs/buninu/apps/bunmsh/help/rmdir.md +27 -0
- package/initramfs/buninu/apps/bunmsh/help/sed.md +29 -0
- package/initramfs/buninu/apps/bunmsh/help/seq.md +29 -0
- package/initramfs/buninu/apps/bunmsh/help/serve.md +50 -0
- package/initramfs/buninu/apps/bunmsh/help/set.md +26 -0
- package/initramfs/buninu/apps/bunmsh/help/sha256sum.md +21 -0
- package/initramfs/buninu/apps/bunmsh/help/shift.md +23 -0
- package/initramfs/buninu/apps/bunmsh/help/sleep.md +25 -0
- package/initramfs/buninu/apps/bunmsh/help/sort.md +29 -0
- package/initramfs/buninu/apps/bunmsh/help/source.md +23 -0
- package/initramfs/buninu/apps/bunmsh/help/tab.md +30 -0
- package/initramfs/buninu/apps/bunmsh/help/tac.md +29 -0
- package/initramfs/buninu/apps/bunmsh/help/tail.md +27 -0
- package/initramfs/buninu/apps/bunmsh/help/tee.md +25 -0
- package/initramfs/buninu/apps/bunmsh/help/test.md +30 -0
- package/initramfs/buninu/apps/bunmsh/help/time.md +29 -0
- package/initramfs/buninu/apps/bunmsh/help/touch.md +26 -0
- package/initramfs/buninu/apps/bunmsh/help/tr.md +26 -0
- package/initramfs/buninu/apps/bunmsh/help/true.md +22 -0
- package/initramfs/buninu/apps/bunmsh/help/type.md +21 -0
- package/initramfs/buninu/apps/bunmsh/help/umask.md +22 -0
- package/initramfs/buninu/apps/bunmsh/help/unalias.md +28 -0
- package/initramfs/buninu/apps/bunmsh/help/uname.md +31 -0
- package/initramfs/buninu/apps/bunmsh/help/unset.md +28 -0
- package/initramfs/buninu/apps/bunmsh/help/wc.md +27 -0
- package/initramfs/buninu/apps/bunmsh/help/whence.md +26 -0
- package/initramfs/buninu/apps/bunmsh/help/which.md +41 -0
- package/initramfs/buninu/apps/bunmsh/help/yes.md +23 -0
- package/initramfs/buninu/apps/bunmsh/index.js +7 -0
- package/initramfs/buninu/apps/bunmsh/package.json +30 -0
- package/initramfs/buninu/apps/bunmsh/serve.js +468 -0
- package/initramfs/buninu/apps/bunmsh/single-exe/README.md +402 -0
- package/initramfs/buninu/apps/bunmsh/single-exe/assetsHelper.js +371 -0
- package/initramfs/buninu/apps/bunmsh/single-exe/assetsLoader.mjs +85 -0
- package/initramfs/buninu/apps/bunmsh/single-exe/assetsPacker.js +218 -0
- package/initramfs/buninu/apps/bunmsh/single-exe/compiled.js +527 -0
- package/initramfs/buninu/apps/bunmsh/single-exe/entry.mjs +17 -0
- package/initramfs/buninu/apps/bunmsh/src/cat-fancy.js +117 -0
- package/initramfs/buninu/apps/bunmsh/src/cat-operands.js +31 -0
- package/initramfs/buninu/apps/bunmsh/src/completion.js +363 -0
- package/initramfs/buninu/apps/bunmsh/src/curl.js +1191 -0
- package/initramfs/buninu/apps/bunmsh/src/environment.js +61 -0
- package/initramfs/buninu/apps/bunmsh/src/fancy-ls.js +186 -0
- package/initramfs/buninu/apps/bunmsh/src/find.js +119 -0
- package/initramfs/buninu/apps/bunmsh/src/history.js +198 -0
- package/initramfs/buninu/apps/bunmsh/src/main.js +850 -0
- package/initramfs/buninu/apps/bunmsh/src/mouse.js +103 -0
- package/initramfs/buninu/apps/bunmsh/src/shell.js +3932 -0
- package/initramfs/buninu/apps/bunmsh/test/catfancy.test.js +102 -0
- package/initramfs/buninu/apps/bunmsh/test/curl.test.js +335 -0
- package/initramfs/buninu/apps/bunmsh/test/reference-source.sh +1 -0
- package/initramfs/buninu/apps/bunmsh/test/reference.test.js +817 -0
- package/initramfs/buninu/apps/bunmsh/test/serve/README.md +3 -0
- package/initramfs/buninu/apps/bunmsh/test/serve/bad.json +1 -0
- package/initramfs/buninu/apps/bunmsh/test/serve/data.json +1 -0
- package/initramfs/buninu/apps/bunmsh/test/serve/data.json5 +1 -0
- package/initramfs/buninu/apps/bunmsh/test/serve/data.jsonc +2 -0
- package/initramfs/buninu/apps/bunmsh/test/serve/data.jsonl +2 -0
- package/initramfs/buninu/apps/bunmsh/test/serve/data.ndjson +1 -0
- package/initramfs/buninu/apps/bunmsh/test/serve/data.toml +3 -0
- package/initramfs/buninu/apps/bunmsh/test/serve/data.ts +15 -0
- package/initramfs/buninu/apps/bunmsh/test/serve/data.xml +1 -0
- package/initramfs/buninu/apps/bunmsh/test/serve/data.yaml +3 -0
- package/initramfs/buninu/apps/bunmsh/test/serve/data.yml +1 -0
- package/initramfs/buninu/apps/bunmsh/test/serve.test.js +241 -0
- package/initramfs/buninu/apps/bunmsh/test/shell.test.js +2092 -0
- package/initramfs/buninu/apps/bunmsh/test/shell1.test.js +1087 -0
- package/initramfs/buninu/apps/bunmsh/test/shell2.test.js +457 -0
- package/initramfs/buninu/apps/bunmsh/test/shell3.test.js +741 -0
- package/initramfs/buninu/apps/bunmsh/test/t.sh +12 -0
- package/initramfs/buninu/apps/bunx/bunx.js +172 -0
- package/initramfs/buninu/apps/cmdlist +48 -0
- package/initramfs/buninu/apps/jsgotty/LICENSE +23 -0
- package/initramfs/buninu/apps/jsgotty/LICENSES/Apache-2.0-zmodem.js.txt +201 -0
- package/initramfs/buninu/apps/jsgotty/NOTICE +21 -0
- package/initramfs/buninu/apps/jsgotty/README.en.md +294 -0
- package/initramfs/buninu/apps/jsgotty/README.md +296 -0
- package/initramfs/buninu/apps/jsgotty/client.mjs +700 -0
- package/initramfs/buninu/apps/jsgotty/env.sh +2 -0
- package/initramfs/buninu/apps/jsgotty/gotty.js +3334 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/.package-lock.json +35 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/node-addon-api/LICENSE.md +9 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/node-addon-api/README.md +319 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/node-addon-api/common.gypi +20 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/node-addon-api/except.gypi +25 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/node-addon-api/index.js +12 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/node-addon-api/napi-inl.deprecated.h +186 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/node-addon-api/napi-inl.h +6607 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/node-addon-api/napi.h +3201 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/node-addon-api/node_addon_api.gyp +32 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/node-addon-api/node_api.gyp +9 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/node-addon-api/noexcept.gypi +26 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/node-addon-api/nothing.c +0 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/node-addon-api/package-support.json +21 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/node-addon-api/package.json +480 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/node-addon-api/tools/README.md +73 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/node-addon-api/tools/check-napi.js +99 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/node-addon-api/tools/clang-format.js +71 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/node-addon-api/tools/conversion.js +301 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/node-addon-api/tools/eslint-format.js +79 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/ws/LICENSE +20 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/ws/README.md +548 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/ws/browser.js +8 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/ws/index.js +22 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/ws/lib/buffer-util.js +131 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/ws/lib/constants.js +19 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/ws/lib/event-target.js +292 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/ws/lib/extension.js +203 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/ws/lib/limiter.js +55 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/ws/lib/permessage-deflate.js +528 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/ws/lib/receiver.js +760 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/ws/lib/sender.js +607 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/ws/lib/stream.js +161 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/ws/lib/subprotocol.js +62 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/ws/lib/validation.js +152 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/ws/lib/websocket-server.js +562 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/ws/lib/websocket.js +1407 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/ws/package.json +70 -0
- package/initramfs/buninu/apps/jsgotty/node_modules/ws/wrapper.mjs +21 -0
- package/initramfs/buninu/apps/jsgotty/package-lock.json +46 -0
- package/initramfs/buninu/apps/jsgotty/package.json +19 -0
- package/initramfs/buninu/apps/jsgotty/patches/windowsPtyAgent.js +326 -0
- package/initramfs/buninu/apps/jsgotty/patches/windowsTerminal.js +204 -0
- package/initramfs/buninu/apps/jsgotty/rz.js +199 -0
- package/initramfs/buninu/apps/jsgotty/single-exe/README.md +384 -0
- package/initramfs/buninu/apps/jsgotty/single-exe/assetsHelper.js +371 -0
- package/initramfs/buninu/apps/jsgotty/single-exe/assetsLoader.mjs +85 -0
- package/initramfs/buninu/apps/jsgotty/single-exe/assetsPacker.js +218 -0
- package/initramfs/buninu/apps/jsgotty/single-exe/compiled.js +498 -0
- package/initramfs/buninu/apps/jsgotty/single-exe/entry.mjs +23 -0
- package/initramfs/buninu/apps/jsgotty/single-exe/packAssets.sh +7 -0
- package/initramfs/buninu/apps/jsgotty/static/css/index.css +13 -0
- package/initramfs/buninu/apps/jsgotty/static/css/kitty.css +61 -0
- package/initramfs/buninu/apps/jsgotty/static/css/xterm.css +218 -0
- package/initramfs/buninu/apps/jsgotty/static/css/xterm_customize.css +35 -0
- package/initramfs/buninu/apps/jsgotty/static/favicon.ico +0 -0
- package/initramfs/buninu/apps/jsgotty/static/help.md +125 -0
- package/initramfs/buninu/apps/jsgotty/static/icon.svg +66 -0
- package/initramfs/buninu/apps/jsgotty/static/icon_192.png +0 -0
- package/initramfs/buninu/apps/jsgotty/static/index.html +164 -0
- package/initramfs/buninu/apps/jsgotty/static/js/gotty.js +31537 -0
- package/initramfs/buninu/apps/jsgotty/static/js/gotty.js.LICENSE.txt +7 -0
- package/initramfs/buninu/apps/jsgotty/static/js/gotty.js.map +1 -0
- package/initramfs/buninu/apps/jsgotty/static/js/gotty.licenses.txt +650 -0
- package/initramfs/buninu/apps/jsgotty/static/js/kitty.js +1101 -0
- package/initramfs/buninu/apps/jsgotty/static/js/windows_bridge.js +194 -0
- package/initramfs/buninu/apps/jsgotty/static/js/xterm-addon-unicode11.js +2 -0
- package/initramfs/buninu/apps/jsgotty/static/js/zmodem.js +1 -0
- package/initramfs/buninu/apps/jsgotty/static/manifest.json +15 -0
- package/initramfs/buninu/apps/jsgotty/sz.js +273 -0
- package/initramfs/buninu/apps/jsgotty/tests/kitty-order.test.js +58 -0
- package/initramfs/buninu/apps/jsgotty/tests/websocket-origin.test.js +54 -0
- package/initramfs/buninu/apps/jsgotty/viu.mjs +422 -0
- package/initramfs/buninu/apps/jsgotty/wgotty +62 -0
- package/initramfs/buninu/apps/jsgotty/windows-bridge-node.js +60 -0
- package/initramfs/buninu/apps/jsgotty/zmodem-node.js +262 -0
- package/initramfs/buninu/apps/jsmdcui/CHANGELOG.md +1118 -0
- package/initramfs/buninu/apps/jsmdcui/LICENSE +22 -0
- package/initramfs/buninu/apps/jsmdcui/README.md +1283 -0
- package/initramfs/buninu/apps/jsmdcui/cdp-maze.js +141 -0
- package/initramfs/buninu/apps/jsmdcui/clean.sh +9 -0
- package/initramfs/buninu/apps/jsmdcui/demos/basic.jpg +0 -0
- package/initramfs/buninu/apps/jsmdcui/demos/chinese.md +32 -0
- package/initramfs/buninu/apps/jsmdcui/demos/event.md +170 -0
- package/initramfs/buninu/apps/jsmdcui/demos/good.jpg +0 -0
- package/initramfs/buninu/apps/jsmdcui/demos/image-processor.md +366 -0
- package/initramfs/buninu/apps/jsmdcui/demos/image-processor.zh-TW.md +366 -0
- package/initramfs/buninu/apps/jsmdcui/demos/img-change.md +73 -0
- package/initramfs/buninu/apps/jsmdcui/demos/imgtool-zh.md +298 -0
- package/initramfs/buninu/apps/jsmdcui/demos/imgtool.md +298 -0
- package/initramfs/buninu/apps/jsmdcui/demos/maze.md +149 -0
- package/initramfs/buninu/apps/jsmdcui/demos/reactive.md +40 -0
- package/initramfs/buninu/apps/jsmdcui/demos/reader.md +513 -0
- package/initramfs/buninu/apps/jsmdcui/demos/select.md +63 -0
- package/initramfs/buninu/apps/jsmdcui/demos/todo-zh.md +190 -0
- package/initramfs/buninu/apps/jsmdcui/demos/todo.md +191 -0
- package/initramfs/buninu/apps/jsmdcui/edit +9 -0
- package/initramfs/buninu/apps/jsmdcui/jsmdcui.sh +16 -0
- package/initramfs/buninu/apps/jsmdcui/llm-maze.txt +94 -0
- package/initramfs/buninu/apps/jsmdcui/package.json +29 -0
- package/initramfs/buninu/apps/jsmdcui/project_structure.txt +35 -0
- package/initramfs/buninu/apps/jsmdcui/runmd.mjs +1140 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/colorschemes/atom-dark.micro +33 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/colorschemes/bubblegum.micro +31 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/colorschemes/cmc-16.micro +47 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/colorschemes/cmc-tc.micro +43 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/colorschemes/darcula.micro +34 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/colorschemes/default.micro +1 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/colorschemes/dracula-tc.micro +49 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/colorschemes/dukedark-tc.micro +38 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/colorschemes/dukelight-tc.micro +38 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/colorschemes/dukeubuntu-tc.micro +38 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/colorschemes/geany.micro +29 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/colorschemes/gotham.micro +29 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/colorschemes/gruvbox-tc.micro +29 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/colorschemes/gruvbox.micro +26 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/colorschemes/material-tc.micro +36 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/colorschemes/monokai-dark.micro +28 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/colorschemes/monokai.micro +34 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/colorschemes/one-dark.micro +39 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/colorschemes/railscast.micro +37 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/colorschemes/simple.micro +33 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/colorschemes/solarized-tc.micro +31 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/colorschemes/solarized.micro +30 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/colorschemes/sunny-day.micro +29 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/colorschemes/twilight.micro +40 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/colorschemes/zenburn.micro +30 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/help/actions.md +161 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/help/cdp.md +130 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/help/colors.md +421 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/help/commands.md +161 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/help/copypaste.md +149 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/help/defaultkeys.md +148 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/help/help.md +1283 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/help/keybindings.md +355 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/help/linter.md +90 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/help/options.md +709 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/help/plugins.md +544 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/help/tutorial.md +112 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/jsplugins/cdp/cdp-server.js +1263 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/jsplugins/cdp/cdp.js +203 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/jsplugins/chapter/chapter.js +111 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/jsplugins/diff/diff.js +46 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/jsplugins/example/example.js +117 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/jsplugins/linter/linter.js +281 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/plugins/autoclose/autoclose.lua +75 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/plugins/ftoptions/ftoptions.lua +17 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/plugins/literate/README.md +5 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/plugins/literate/literate.lua +55 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/plugins/status/help/status.md +21 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/plugins/status/status.lua +62 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/LICENSE +22 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/PowerShell.yaml +128 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/README.md +63 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/ada.yaml +43 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/apacheconf.yaml +59 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/arduino.yaml +101 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/asciidoc.yaml +51 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/asm.yaml +123 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/ats.yaml +99 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/awk.yaml +44 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/b.yaml +87 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/bat.yaml +57 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/c.yaml +60 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/caddyfile.yaml +23 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/cake.yaml +7 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/clojure.yaml +38 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/cmake.yaml +42 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/coffeescript.yaml +56 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/colortest.yaml +19 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/conky.yaml +17 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/cpp.yaml +91 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/crontab.yaml +36 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/crystal.yaml +72 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/csharp.yaml +52 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/css.yaml +44 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/csx.yaml +8 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/cuda.yaml +68 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/cython.yaml +52 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/d.yaml +121 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/dart.yaml +46 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/default.yaml +10 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/dockerfile.yaml +36 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/dot.yaml +29 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/elixir.yaml +30 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/elm.yaml +38 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/erb.yaml +42 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/erlang.yaml +45 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/fish.yaml +48 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/forth.yaml +34 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/fortran.yaml +64 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/freebsd-kernel.yaml +14 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/fsharp.yaml +48 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/gdscript.yaml +61 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/gemini.yaml +19 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/gentoo-ebuild.yaml +48 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/gentoo-etc-portage.yaml +23 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/git-commit.yaml +35 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/git-config.yaml +14 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/git-rebase-todo.yaml +19 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/gleam.yaml +69 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/glsl.yaml +26 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/gnuplot.yaml +15 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/go.yaml +62 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/godoc.yaml +17 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/golo.yaml +73 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/gomod.yaml +31 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/graphql.yaml +47 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/groff.yaml +30 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/groovy.yaml +111 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/haml.yaml +16 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/hare.yaml +52 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/haskell.yaml +52 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/hc.yaml +52 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/html.yaml +70 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/html4.yaml +25 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/html5.yaml +25 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/ini.yaml +23 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/inputrc.yaml +14 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/java.yaml +37 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/javascript.yaml +124 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/jinja2.yaml +19 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/json.yaml +39 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/jsonnet.yaml +92 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/julia.yaml +57 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/justfile.yaml +40 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/keymap.yaml +27 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/kickstart.yaml +16 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/kotlin.yaml +66 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/kvlang.yaml +67 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/ledger.yaml +14 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/lfe.yaml +17 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/lilypond.yaml +26 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/lisp.yaml +17 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/log.yaml +92 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/lua.yaml +111 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/mail.yaml +25 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/makefile.yaml +38 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/man.yaml +12 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/markdown.yaml +65 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/mc.yaml +23 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/meson.yaml +51 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/micro.yaml +34 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/mpdconf.yaml +13 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/msbuild.yaml +6 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/nanorc.yaml +16 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/nftables.yaml +30 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/nginx.yaml +22 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/nim.yaml +27 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/nix.yaml +32 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/nu.yaml +114 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/objc.yaml +60 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/ocaml.yaml +43 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/octave.yaml +83 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/odin.yaml +64 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/pascal.yaml +45 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/patch.yaml +14 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/peg.yaml +16 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/perl.yaml +58 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/php.yaml +60 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/pkg-config.yaml +12 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/po.yaml +12 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/pony.yaml +37 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/pov.yaml +21 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/privoxy-action.yaml +14 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/privoxy-config.yaml +10 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/privoxy-filter.yaml +12 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/proto.yaml +40 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/prql.yaml +84 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/puppet.yaml +22 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/python2.yaml +60 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/python3.yaml +80 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/r.yaml +32 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/raku.yaml +42 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/reST.yaml +18 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/renpy.yaml +15 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/rpmspec.yaml +43 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/ruby.yaml +73 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/rust.yaml +78 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/sage.yaml +60 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/scad.yaml +53 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/scala.yaml +33 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/sed.yaml +13 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/sh.yaml +69 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/sls.yaml +15 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/smalltalk.yaml +55 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/solidity.yaml +41 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/sql.yaml +35 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/stata.yaml +67 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/svelte.yaml +27 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/swift.yaml +103 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/systemd.yaml +16 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/tcl.yaml +18 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/terraform.yaml +87 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/tex.yaml +32 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/toml.yaml +56 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/twig.yaml +55 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/typescript.yaml +49 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/v.yaml +80 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/vala.yaml +26 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/verilog.yaml +60 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/vhdl.yaml +37 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/vi.yaml +31 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/vue.yaml +64 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/xml.yaml +37 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/xresources.yaml +14 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/yaml.yaml +34 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/yum.yaml +12 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/zig.yaml +52 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/zscript.yaml +72 -0
- package/initramfs/buninu/apps/jsmdcui/runtime/syntax/zsh.yaml +52 -0
- package/initramfs/buninu/apps/jsmdcui/single-exe/README.md +396 -0
- package/initramfs/buninu/apps/jsmdcui/single-exe/assetsHelper.js +371 -0
- package/initramfs/buninu/apps/jsmdcui/single-exe/assetsLoader.mjs +85 -0
- package/initramfs/buninu/apps/jsmdcui/single-exe/assetsPacker.js +218 -0
- package/initramfs/buninu/apps/jsmdcui/single-exe/compiled.js +498 -0
- package/initramfs/buninu/apps/jsmdcui/single-exe/entry.mjs +17 -0
- package/initramfs/buninu/apps/jsmdcui/single-exe/packAssets.sh +7 -0
- package/initramfs/buninu/apps/jsmdcui/src/MDCUI_DEFAULT_EDIT +0 -0
- package/initramfs/buninu/apps/jsmdcui/src/buffer/backup.js +165 -0
- package/initramfs/buninu/apps/jsmdcui/src/buffer/buffer.js +126 -0
- package/initramfs/buninu/apps/jsmdcui/src/buffer/fixed3-codec.js +140 -0
- package/initramfs/buninu/apps/jsmdcui/src/buffer/loc.js +38 -0
- package/initramfs/buninu/apps/jsmdcui/src/buffer/message.js +29 -0
- package/initramfs/buninu/apps/jsmdcui/src/build-args.js +40 -0
- package/initramfs/buninu/apps/jsmdcui/src/config/clean.js +172 -0
- package/initramfs/buninu/apps/jsmdcui/src/config/colorscheme.js +99 -0
- package/initramfs/buninu/apps/jsmdcui/src/config/config.js +125 -0
- package/initramfs/buninu/apps/jsmdcui/src/config/defaults.js +109 -0
- package/initramfs/buninu/apps/jsmdcui/src/cui/fence-events.mjs +144 -0
- package/initramfs/buninu/apps/jsmdcui/src/cui/heading-ids.mjs +1568 -0
- package/initramfs/buninu/apps/jsmdcui/src/cui/id-collision.mjs +111 -0
- package/initramfs/buninu/apps/jsmdcui/src/cui/identity.mjs +26 -0
- package/initramfs/buninu/apps/jsmdcui/src/cui/kitty-debug.mjs +25 -0
- package/initramfs/buninu/apps/jsmdcui/src/cui/kitty-images.mjs +280 -0
- package/initramfs/buninu/apps/jsmdcui/src/cui/kitty-mode.mjs +6 -0
- package/initramfs/buninu/apps/jsmdcui/src/cui/rerender-queue.mjs +66 -0
- package/initramfs/buninu/apps/jsmdcui/src/cui/rpc.mjs +1554 -0
- package/initramfs/buninu/apps/jsmdcui/src/cui/server.mjs +128 -0
- package/initramfs/buninu/apps/jsmdcui/src/cui/table-render.mjs +286 -0
- package/initramfs/buninu/apps/jsmdcui/src/cui/table-row-edit.mjs +226 -0
- package/initramfs/buninu/apps/jsmdcui/src/cui/task-checkbox.mjs +60 -0
- package/initramfs/buninu/apps/jsmdcui/src/cui/template-components.mjs +253 -0
- package/initramfs/buninu/apps/jsmdcui/src/cui/text-block-resize.mjs +177 -0
- package/initramfs/buninu/apps/jsmdcui/src/cui/tui-links.mjs +560 -0
- package/initramfs/buninu/apps/jsmdcui/src/display/ansi-style.js +60 -0
- package/initramfs/buninu/apps/jsmdcui/src/highlight/highlighter.js +243 -0
- package/initramfs/buninu/apps/jsmdcui/src/highlight/parser.js +225 -0
- package/initramfs/buninu/apps/jsmdcui/src/index.js +9586 -0
- package/initramfs/buninu/apps/jsmdcui/src/lua/engine.js +68 -0
- package/initramfs/buninu/apps/jsmdcui/src/platform/archive.js +50 -0
- package/initramfs/buninu/apps/jsmdcui/src/platform/clipboard.js +278 -0
- package/initramfs/buninu/apps/jsmdcui/src/platform/commands.js +221 -0
- package/initramfs/buninu/apps/jsmdcui/src/platform/terminal.js +5 -0
- package/initramfs/buninu/apps/jsmdcui/src/plugins/js-bridge.js +3377 -0
- package/initramfs/buninu/apps/jsmdcui/src/plugins/manager.js +674 -0
- package/initramfs/buninu/apps/jsmdcui/src/runtime/encodings.js +10 -0
- package/initramfs/buninu/apps/jsmdcui/src/runtime/registry.js +134 -0
- package/initramfs/buninu/apps/jsmdcui/src/screen/cell-buffer.js +81 -0
- package/initramfs/buninu/apps/jsmdcui/src/screen/events.js +263 -0
- package/initramfs/buninu/apps/jsmdcui/src/screen/screen.js +249 -0
- package/initramfs/buninu/apps/jsmdcui/src/screen/vt100.js +571 -0
- package/initramfs/buninu/apps/jsmdcui/src/shell/shell.js +70 -0
- package/initramfs/buninu/apps/jsmdcui/testapp.md +78 -0
- package/initramfs/buninu/apps/jsmdcui/tests/assets-helper.test.js +150 -0
- package/initramfs/buninu/apps/jsmdcui/tests/backup.test.js +158 -0
- package/initramfs/buninu/apps/jsmdcui/tests/cat-markdown.test.js +139 -0
- package/initramfs/buninu/apps/jsmdcui/tests/cdp-security.test.js +32 -0
- package/initramfs/buninu/apps/jsmdcui/tests/cdp-websocket-test.html +46 -0
- package/initramfs/buninu/apps/jsmdcui/tests/cmphex3b64.js +95 -0
- package/initramfs/buninu/apps/jsmdcui/tests/compiled-runtime.test.js +139 -0
- package/initramfs/buninu/apps/jsmdcui/tests/config-settings.test.js +52 -0
- package/initramfs/buninu/apps/jsmdcui/tests/demo.test.js +448 -0
- package/initramfs/buninu/apps/jsmdcui/tests/docs-sync.test.js +14 -0
- package/initramfs/buninu/apps/jsmdcui/tests/fence-events.test.js +1293 -0
- package/initramfs/buninu/apps/jsmdcui/tests/heading-ids.test.js +559 -0
- package/initramfs/buninu/apps/jsmdcui/tests/heading-list-selector.test.js +2393 -0
- package/initramfs/buninu/apps/jsmdcui/tests/id-collision.test.js +514 -0
- package/initramfs/buninu/apps/jsmdcui/tests/jmigt.js +16 -0
- package/initramfs/buninu/apps/jsmdcui/tests/js-plugin-prompts.test.js +110 -0
- package/initramfs/buninu/apps/jsmdcui/tests/key-event.md +10 -0
- package/initramfs/buninu/apps/jsmdcui/tests/kitty-demo.md +184 -0
- package/initramfs/buninu/apps/jsmdcui/tests/kitty-images.test.js +288 -0
- package/initramfs/buninu/apps/jsmdcui/tests/kitty-mode.test.js +14 -0
- package/initramfs/buninu/apps/jsmdcui/tests/platform-commands.test.js +18 -0
- package/initramfs/buninu/apps/jsmdcui/tests/platform-terminal.test.js +8 -0
- package/initramfs/buninu/apps/jsmdcui/tests/pty-demo.js +492 -0
- package/initramfs/buninu/apps/jsmdcui/tests/rerender-queue.test.js +130 -0
- package/initramfs/buninu/apps/jsmdcui/tests/table-render.test.js +150 -0
- package/initramfs/buninu/apps/jsmdcui/tests/table-row-edit.test.js +138 -0
- package/initramfs/buninu/apps/jsmdcui/tests/task-checkbox.test.js +33 -0
- package/initramfs/buninu/apps/jsmdcui/tests/template-components.test.js +422 -0
- package/initramfs/buninu/apps/jsmdcui/tests/text-block-resize.test.js +222 -0
- package/initramfs/buninu/apps/jsmdcui/tests/textarea.md +8 -0
- package/initramfs/buninu/apps/jsmdcui/tests/tui-links.test.js +298 -0
- package/initramfs/buninu/apps/jsmdcui/tests/wui-responsive-images.test.js +60 -0
- package/initramfs/buninu/apps/jsmdcui/tests/wui.test.js +108 -0
- package/initramfs/buninu/apps/jsmdcui/tests/wv-client.js +96 -0
- package/initramfs/buninu/apps/jsmdcui/tui +7 -0
- package/initramfs/buninu/apps/jsmdcui/wui +9 -0
- package/initramfs/buninu/apps/musl-la/LICENSES/GPL-3.0.txt +674 -0
- package/initramfs/buninu/apps/musl-la/LICENSES/gcc_runtime_exception.txt +73 -0
- package/initramfs/buninu/apps/musl-la/LICENSE_musl.txt +193 -0
- package/initramfs/buninu/apps/musl-la/NOTICE +41 -0
- package/initramfs/buninu/apps/musl-la/ld-musl-aarch64.so.1 +0 -0
- package/initramfs/buninu/apps/musl-la/libgcc_s.so.1 +0 -0
- package/initramfs/buninu/apps/musl-la/libstdc++.so.6 +0 -0
- package/initramfs/buninu/apps/musl-la/musl-la.sh +36 -0
- package/initramfs/buninu/apps/native-bridge/native-bridge.js +199 -0
- package/initramfs/buninu/apps/native-bridge/package.json +8 -0
- package/initramfs/buninu/apps/tts/tts.js +214 -0
- package/initramfs/buninu/apps/xclip/xclip.js +121 -0
- package/initramfs/buninu/apps/xdg-open/xdg-open.js +151 -0
- package/initramfs/buninu/bin/bun.bat +37 -0
- package/initramfs/buninu/bin/bun.sh +57 -0
- package/initramfs/buninu/bin/buninu-help.bat +4 -0
- package/initramfs/buninu/bin/buninu-help.sh +7 -0
- package/initramfs/buninu/bin/bunmsh.bat +3 -0
- package/initramfs/buninu/bin/bunmsh.sh +5 -0
- package/initramfs/buninu/bin/bunx.bat +3 -0
- package/initramfs/buninu/bin/glow.bat +3 -0
- package/initramfs/buninu/bin/glow.sh +5 -0
- package/initramfs/buninu/bin/init.js +779 -0
- package/initramfs/buninu/bin/install.js +570 -0
- package/initramfs/buninu/bin/jmi.bat +3 -0
- package/initramfs/buninu/bin/jmi.sh +5 -0
- package/initramfs/buninu/bin/jsgotty.bat +3 -0
- package/initramfs/buninu/bin/jsgotty.sh +5 -0
- package/initramfs/buninu/bin/jsmdcui.bat +11 -0
- package/initramfs/buninu/bin/libsh-loader.c +135 -0
- package/initramfs/buninu/bin/libsh-loader.so +0 -0
- package/initramfs/buninu/bin/multicall.sh +103 -0
- package/initramfs/buninu/bin/native-bridge.bat +3 -0
- package/initramfs/buninu/bin/rz.bat +3 -0
- package/initramfs/buninu/bin/rz.sh +5 -0
- package/initramfs/buninu/bin/shc.js +5 -0
- package/initramfs/buninu/bin/showimg.bat +3 -0
- package/initramfs/buninu/bin/showimg.sh +5 -0
- package/initramfs/buninu/bin/switch_to_android.sh +9 -0
- package/initramfs/buninu/bin/switch_to_linux.sh +7 -0
- package/initramfs/buninu/bin/sz.bat +3 -0
- package/initramfs/buninu/bin/sz.sh +5 -0
- package/initramfs/buninu/bin/tts.bat +3 -0
- package/initramfs/buninu/bin/xclip.bat +3 -0
- package/initramfs/buninu/bin/xdg-open.bat +3 -0
- package/initramfs/buninu/demo-server.js +64 -0
- package/initramfs/buninu/icon.png +0 -0
- package/initramfs/buninu/package.json +59 -0
- package/initramfs/etc/resolv.conf +1 -0
- package/initramfs/init.js +339 -0
- package/initramfs/lib/ld-musl-x86_64.so.1 +0 -0
- package/initramfs/lib/libc.musl-x86_64.so.1 +0 -0
- package/initramfs/lib/libgcc_s.so.1 +0 -0
- package/initramfs/lib/libstdc++.so.6 +0 -0
- package/initramfs/usr/bin/env +7 -0
- package/package.json +42 -0
- package/run-qemu.sh +44 -0
- package/scripts/fetch.sh +26 -0
- package/scripts/pack-initramfs.sh +41 -0
- package/test/build-init-bootstrap.sh +23 -0
- package/test/init-bootstrap.c +55 -0
|
@@ -0,0 +1,1191 @@
|
|
|
1
|
+
// Fallback `curl`, implemented on Bun's own fetch(). It exists so scripts
|
|
2
|
+
// written against the system curl keep working on a device that only ships
|
|
3
|
+
// bunmsh: the tmpk installer scripts (`curl -kLO`, `curl -C - -kLO`,
|
|
4
|
+
// `curl -fsSL`, `curl -#k`, `curl -kfsS`) are the baseline, and enough of
|
|
5
|
+
// the request-shaping options are here to drive a JSON API such as
|
|
6
|
+
// OpenAI's from the shell.
|
|
7
|
+
//
|
|
8
|
+
// Where curl and fetch cannot agree the difference is documented in
|
|
9
|
+
// help/curl.md rather than papered over: fetch does not expose the wire
|
|
10
|
+
// header casing or the negotiated HTTP version, so `-i`/`-v` reconstruct
|
|
11
|
+
// them, and the progress meter is a look-alike, not a byte-for-byte copy.
|
|
12
|
+
import { createWriteStream, existsSync, mkdirSync, statSync } from "node:fs";
|
|
13
|
+
import { readFile } from "node:fs/promises";
|
|
14
|
+
import { basename as pathBasename, dirname as pathDirname, isAbsolute, resolve as resolvePath } from "node:path";
|
|
15
|
+
|
|
16
|
+
export const CURL_VERSION = "8.14.1";
|
|
17
|
+
|
|
18
|
+
const DEFAULT_USER_AGENT = `curl/${CURL_VERSION}`;
|
|
19
|
+
const REDIRECT_STATUS = new Set([301, 302, 303, 307, 308]);
|
|
20
|
+
const TRANSIENT_STATUS = new Set([408, 429, 500, 502, 503, 504]);
|
|
21
|
+
const encoder = new TextEncoder();
|
|
22
|
+
const decoder = new TextDecoder();
|
|
23
|
+
|
|
24
|
+
// Short flags spell the same options as their long names, so the parser
|
|
25
|
+
// only has to know one table. `-#` is a flag like any other here.
|
|
26
|
+
const SHORT_TO_LONG = {
|
|
27
|
+
"#": "progress-bar",
|
|
28
|
+
"4": "ipv4",
|
|
29
|
+
"6": "ipv6",
|
|
30
|
+
A: "user-agent",
|
|
31
|
+
a: "append",
|
|
32
|
+
b: "cookie",
|
|
33
|
+
C: "continue-at",
|
|
34
|
+
c: "cookie-jar",
|
|
35
|
+
D: "dump-header",
|
|
36
|
+
d: "data",
|
|
37
|
+
E: "cert",
|
|
38
|
+
e: "referer",
|
|
39
|
+
F: "form",
|
|
40
|
+
f: "fail",
|
|
41
|
+
G: "get",
|
|
42
|
+
g: "globoff",
|
|
43
|
+
H: "header",
|
|
44
|
+
h: "help",
|
|
45
|
+
I: "head",
|
|
46
|
+
i: "include",
|
|
47
|
+
J: "remote-header-name",
|
|
48
|
+
j: "junk-session-cookies",
|
|
49
|
+
k: "insecure",
|
|
50
|
+
L: "location",
|
|
51
|
+
l: "list-only",
|
|
52
|
+
m: "max-time",
|
|
53
|
+
N: "no-buffer",
|
|
54
|
+
n: "netrc",
|
|
55
|
+
O: "remote-name",
|
|
56
|
+
o: "output",
|
|
57
|
+
q: "disable",
|
|
58
|
+
R: "remote-time",
|
|
59
|
+
r: "range",
|
|
60
|
+
S: "show-error",
|
|
61
|
+
s: "silent",
|
|
62
|
+
T: "upload-file",
|
|
63
|
+
u: "user",
|
|
64
|
+
V: "version",
|
|
65
|
+
v: "verbose",
|
|
66
|
+
w: "write-out",
|
|
67
|
+
X: "request",
|
|
68
|
+
x: "proxy",
|
|
69
|
+
Z: "parallel",
|
|
70
|
+
z: "time-cond",
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const VALUE_OPTIONS = new Set([
|
|
74
|
+
"aws-sigv4", "cacert", "capath", "cert", "connect-timeout", "connect-to",
|
|
75
|
+
"continue-at", "cookie", "cookie-jar", "data", "data-ascii", "data-binary",
|
|
76
|
+
"data-raw", "data-urlencode", "dns-servers", "dump-header",
|
|
77
|
+
"expect100-timeout", "form", "form-string", "header", "interface", "json",
|
|
78
|
+
"key", "limit-rate", "local-port", "max-filesize", "max-redirs", "max-time",
|
|
79
|
+
"noproxy", "oauth2-bearer", "output", "output-dir", "proto-default", "proxy",
|
|
80
|
+
"proxy-header", "proxy-user", "range", "referer", "request", "resolve",
|
|
81
|
+
"retry", "retry-delay", "retry-max-time", "time-cond", "unix-socket",
|
|
82
|
+
"upload-file", "url", "user", "user-agent", "write-out",
|
|
83
|
+
]);
|
|
84
|
+
|
|
85
|
+
const BOOLEAN_OPTIONS = new Set([
|
|
86
|
+
"anyauth", "append", "basic", "compressed", "create-dirs", "digest",
|
|
87
|
+
"disable", "fail", "fail-early", "fail-with-body", "get", "globoff", "head",
|
|
88
|
+
"help", "http0.9", "http1.0", "http1.1", "http2", "http2-prior-knowledge",
|
|
89
|
+
"http3", "include", "insecure", "ipv4", "ipv6", "junk-session-cookies",
|
|
90
|
+
"keepalive", "list-only", "location", "location-trusted", "netrc",
|
|
91
|
+
"no-alpn", "no-buffer", "no-keepalive", "no-npn", "no-progress-meter",
|
|
92
|
+
"no-styled-output", "parallel", "path-as-is", "progress-bar",
|
|
93
|
+
"progress-meter", "raw", "remote-header-name", "remote-name",
|
|
94
|
+
"remote-name-all", "remote-time", "retry-all-errors",
|
|
95
|
+
"retry-connrefused", "show-error", "silent", "ssl", "ssl-no-revoke",
|
|
96
|
+
"ssl-reqd", "sslv2", "sslv3", "styled-output", "tcp-nodelay", "tlsv1",
|
|
97
|
+
"tlsv1.0", "tlsv1.1", "tlsv1.2", "tlsv1.3", "verbose", "version",
|
|
98
|
+
]);
|
|
99
|
+
|
|
100
|
+
// Recognised, parsed, and then deliberately dropped: they configure parts
|
|
101
|
+
// of libcurl that fetch() either does for us or does not expose. Accepting
|
|
102
|
+
// them keeps a script from dying on an option that would not have changed
|
|
103
|
+
// the bytes we fetch anyway.
|
|
104
|
+
const IGNORED_OPTIONS = new Set([
|
|
105
|
+
"anyauth", "aws-sigv4", "basic", "cacert", "capath", "cert", "connect-to",
|
|
106
|
+
"digest", "disable", "dns-servers", "expect100-timeout", "fail-early",
|
|
107
|
+
"globoff", "http0.9", "http1.0", "http1.1", "http2",
|
|
108
|
+
"http2-prior-knowledge", "http3", "interface", "ipv4", "ipv6",
|
|
109
|
+
"junk-session-cookies", "keepalive", "key", "limit-rate", "list-only",
|
|
110
|
+
"local-port", "max-filesize", "netrc", "no-alpn", "no-buffer",
|
|
111
|
+
"no-keepalive", "no-npn", "no-styled-output", "noproxy", "parallel",
|
|
112
|
+
"path-as-is", "proxy-header", "proxy-user", "raw", "remote-time",
|
|
113
|
+
"resolve", "ssl", "ssl-no-revoke", "ssl-reqd", "sslv2", "sslv3",
|
|
114
|
+
"styled-output", "tcp-nodelay", "time-cond", "tlsv1", "tlsv1.0",
|
|
115
|
+
"tlsv1.1", "tlsv1.2", "tlsv1.3", "unix-socket",
|
|
116
|
+
]);
|
|
117
|
+
|
|
118
|
+
// fetch() hands back lower-cased header names; servers and curl show them
|
|
119
|
+
// in the conventional casing. Rebuild that so `-i` output reads like curl's.
|
|
120
|
+
const HEADER_CASE = {
|
|
121
|
+
"content-md5": "Content-MD5",
|
|
122
|
+
dnt: "DNT",
|
|
123
|
+
etag: "ETag",
|
|
124
|
+
"last-event-id": "Last-Event-ID",
|
|
125
|
+
te: "TE",
|
|
126
|
+
"www-authenticate": "WWW-Authenticate",
|
|
127
|
+
"x-xss-protection": "X-XSS-Protection",
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
export function canonicalHeaderName(name) {
|
|
131
|
+
const lower = name.toLowerCase();
|
|
132
|
+
if (HEADER_CASE[lower]) return HEADER_CASE[lower];
|
|
133
|
+
return lower.split("-")
|
|
134
|
+
.map((part) => /^(id|ip|md5|ssl|tls|uri|url|xss)$/.test(part)
|
|
135
|
+
? part.toUpperCase()
|
|
136
|
+
: part.charAt(0).toUpperCase() + part.slice(1))
|
|
137
|
+
.join("-");
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function bytes(value) {
|
|
141
|
+
return value instanceof Uint8Array ? value : encoder.encode(String(value));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function concatBytes(parts) {
|
|
145
|
+
const total = parts.reduce((sum, part) => sum + part.byteLength, 0);
|
|
146
|
+
const merged = new Uint8Array(total);
|
|
147
|
+
let offset = 0;
|
|
148
|
+
for (const part of parts) {
|
|
149
|
+
merged.set(part, offset);
|
|
150
|
+
offset += part.byteLength;
|
|
151
|
+
}
|
|
152
|
+
return merged;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function resolveAgainst(cwd, value) {
|
|
156
|
+
return isAbsolute(value) ? value : resolvePath(cwd, value);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
class CurlError extends Error {
|
|
160
|
+
constructor(code, message) {
|
|
161
|
+
super(message);
|
|
162
|
+
this.code = code;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// ---------------------------------------------------------------- parsing
|
|
167
|
+
|
|
168
|
+
function emptyOptions() {
|
|
169
|
+
return {
|
|
170
|
+
urls: [],
|
|
171
|
+
// -o and -O queue up in argument order and pair with the URLs in the
|
|
172
|
+
// same order, the way curl matches them.
|
|
173
|
+
outputs: [],
|
|
174
|
+
headers: [],
|
|
175
|
+
data: [],
|
|
176
|
+
forms: [],
|
|
177
|
+
method: null,
|
|
178
|
+
silent: false,
|
|
179
|
+
showError: false,
|
|
180
|
+
verbose: false,
|
|
181
|
+
fail: false,
|
|
182
|
+
failWithBody: false,
|
|
183
|
+
include: false,
|
|
184
|
+
head: false,
|
|
185
|
+
location: false,
|
|
186
|
+
locationTrusted: false,
|
|
187
|
+
maxRedirects: 50,
|
|
188
|
+
insecure: false,
|
|
189
|
+
compressed: false,
|
|
190
|
+
progressBar: false,
|
|
191
|
+
progressMeter: null,
|
|
192
|
+
append: false,
|
|
193
|
+
createDirs: false,
|
|
194
|
+
remoteNameAll: false,
|
|
195
|
+
remoteHeaderName: false,
|
|
196
|
+
get: false,
|
|
197
|
+
outputDir: null,
|
|
198
|
+
continueAt: null,
|
|
199
|
+
uploadFile: null,
|
|
200
|
+
user: null,
|
|
201
|
+
bearer: null,
|
|
202
|
+
userAgent: null,
|
|
203
|
+
referer: null,
|
|
204
|
+
cookie: null,
|
|
205
|
+
range: null,
|
|
206
|
+
maxTime: null,
|
|
207
|
+
connectTimeout: null,
|
|
208
|
+
retry: 0,
|
|
209
|
+
retryDelay: null,
|
|
210
|
+
retryMaxTime: null,
|
|
211
|
+
retryAllErrors: false,
|
|
212
|
+
retryConnrefused: false,
|
|
213
|
+
protoDefault: null,
|
|
214
|
+
writeOut: null,
|
|
215
|
+
dumpHeader: null,
|
|
216
|
+
proxy: null,
|
|
217
|
+
help: false,
|
|
218
|
+
version: false,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export function parseCurlArguments(argv) {
|
|
223
|
+
const options = emptyOptions();
|
|
224
|
+
const args = argv.slice(1);
|
|
225
|
+
let operandsOnly = false;
|
|
226
|
+
|
|
227
|
+
const takeValue = (name, inline, index) => {
|
|
228
|
+
if (inline !== null) return { value: inline, index };
|
|
229
|
+
if (index + 1 >= args.length)
|
|
230
|
+
return { error: `curl: option ${name}: requires parameter` };
|
|
231
|
+
return { value: args[index + 1], index: index + 1 };
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
for (let i = 0; i < args.length; i++) {
|
|
235
|
+
const argument = args[i];
|
|
236
|
+
if (operandsOnly || argument === "-" || !argument.startsWith("-")) {
|
|
237
|
+
options.urls.push(argument);
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
if (argument === "--") { operandsOnly = true; continue; }
|
|
241
|
+
|
|
242
|
+
// Long option, optionally --name=value.
|
|
243
|
+
if (argument.startsWith("--")) {
|
|
244
|
+
const separator = argument.indexOf("=");
|
|
245
|
+
let name = separator < 0 ? argument.slice(2) : argument.slice(2, separator);
|
|
246
|
+
const inline = separator < 0 ? null : argument.slice(separator + 1);
|
|
247
|
+
let negated = false;
|
|
248
|
+
if (!BOOLEAN_OPTIONS.has(name) && !VALUE_OPTIONS.has(name) && name.startsWith("no-") &&
|
|
249
|
+
BOOLEAN_OPTIONS.has(name.slice(3))) {
|
|
250
|
+
negated = true;
|
|
251
|
+
name = name.slice(3);
|
|
252
|
+
}
|
|
253
|
+
if (VALUE_OPTIONS.has(name)) {
|
|
254
|
+
const taken = takeValue(`--${name}`, inline, i);
|
|
255
|
+
if (taken.error) return { error: taken.error };
|
|
256
|
+
i = taken.index;
|
|
257
|
+
const error = applyOption(options, name, taken.value);
|
|
258
|
+
if (error) return { error };
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
if (BOOLEAN_OPTIONS.has(name)) {
|
|
262
|
+
const error = applyOption(options, name, negated ? false : true);
|
|
263
|
+
if (error) return { error };
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
return { error: `curl: option ${argument.split("=")[0]}: is unknown` };
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Short cluster: every flag but the last must be value-less, and the
|
|
270
|
+
// tail of the cluster doubles as the last flag's value (-ofile).
|
|
271
|
+
for (let j = 1; j < argument.length; j++) {
|
|
272
|
+
const flag = argument[j];
|
|
273
|
+
const name = SHORT_TO_LONG[flag];
|
|
274
|
+
if (!name) return { error: `curl: option -${flag}: is unknown` };
|
|
275
|
+
if (VALUE_OPTIONS.has(name)) {
|
|
276
|
+
const inline = j + 1 < argument.length ? argument.slice(j + 1) : null;
|
|
277
|
+
const taken = takeValue(`-${flag}`, inline, i);
|
|
278
|
+
if (taken.error) return { error: taken.error };
|
|
279
|
+
i = taken.index;
|
|
280
|
+
const error = applyOption(options, name, taken.value);
|
|
281
|
+
if (error) return { error };
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
const error = applyOption(options, name, true);
|
|
285
|
+
if (error) return { error };
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return { options };
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function applyOption(options, name, value) {
|
|
292
|
+
if (IGNORED_OPTIONS.has(name)) return null;
|
|
293
|
+
switch (name) {
|
|
294
|
+
case "url": options.urls.push(value); return null;
|
|
295
|
+
case "output": options.outputs.push({ kind: "file", path: value }); return null;
|
|
296
|
+
case "remote-name": options.outputs.push({ kind: "remote" }); return null;
|
|
297
|
+
case "remote-name-all": options.remoteNameAll = value; return null;
|
|
298
|
+
case "remote-header-name": options.remoteHeaderName = value; return null;
|
|
299
|
+
case "output-dir": options.outputDir = value; return null;
|
|
300
|
+
case "create-dirs": options.createDirs = value; return null;
|
|
301
|
+
case "append": options.append = value; return null;
|
|
302
|
+
case "request": options.method = value; return null;
|
|
303
|
+
case "head": options.head = value; return null;
|
|
304
|
+
case "include": options.include = value; return null;
|
|
305
|
+
case "header": options.headers.push(value); return null;
|
|
306
|
+
case "user-agent": options.userAgent = value; return null;
|
|
307
|
+
case "referer": options.referer = value; return null;
|
|
308
|
+
case "cookie": options.cookie = value; return null;
|
|
309
|
+
case "user": options.user = value; return null;
|
|
310
|
+
case "oauth2-bearer": options.bearer = value; return null;
|
|
311
|
+
case "range": options.range = value; return null;
|
|
312
|
+
case "data": options.data.push({ kind: "data", value }); return null;
|
|
313
|
+
case "data-ascii": options.data.push({ kind: "data", value }); return null;
|
|
314
|
+
case "data-raw": options.data.push({ kind: "raw", value }); return null;
|
|
315
|
+
case "data-binary": options.data.push({ kind: "binary", value }); return null;
|
|
316
|
+
case "data-urlencode": options.data.push({ kind: "urlencode", value }); return null;
|
|
317
|
+
case "json": options.data.push({ kind: "json", value }); return null;
|
|
318
|
+
case "form": options.forms.push({ value, literal: false }); return null;
|
|
319
|
+
case "form-string": options.forms.push({ value, literal: true }); return null;
|
|
320
|
+
case "get": options.get = value; return null;
|
|
321
|
+
case "upload-file": options.uploadFile = value; return null;
|
|
322
|
+
case "location": options.location = value; return null;
|
|
323
|
+
case "location-trusted":
|
|
324
|
+
options.location = value;
|
|
325
|
+
options.locationTrusted = value;
|
|
326
|
+
return null;
|
|
327
|
+
case "max-redirs": {
|
|
328
|
+
const limit = Number(value);
|
|
329
|
+
if (!Number.isFinite(limit)) return `curl: option --max-redirs: expected a number`;
|
|
330
|
+
options.maxRedirects = limit < 0 ? Infinity : limit;
|
|
331
|
+
return null;
|
|
332
|
+
}
|
|
333
|
+
case "insecure": options.insecure = value; return null;
|
|
334
|
+
case "compressed": options.compressed = value; return null;
|
|
335
|
+
case "silent": options.silent = value; return null;
|
|
336
|
+
case "show-error": options.showError = value; return null;
|
|
337
|
+
case "verbose": options.verbose = value; return null;
|
|
338
|
+
case "fail": options.fail = value; return null;
|
|
339
|
+
case "fail-with-body":
|
|
340
|
+
options.fail = value;
|
|
341
|
+
options.failWithBody = value;
|
|
342
|
+
return null;
|
|
343
|
+
case "progress-bar": options.progressBar = value; return null;
|
|
344
|
+
case "no-progress-meter": options.progressMeter = !value; return null;
|
|
345
|
+
case "progress-meter": options.progressMeter = value; return null;
|
|
346
|
+
case "continue-at": options.continueAt = value; return null;
|
|
347
|
+
case "max-time": options.maxTime = parseSeconds(value); return null;
|
|
348
|
+
case "connect-timeout": options.connectTimeout = parseSeconds(value); return null;
|
|
349
|
+
case "retry": options.retry = Math.max(0, Number(value) || 0); return null;
|
|
350
|
+
case "retry-delay": options.retryDelay = parseSeconds(value); return null;
|
|
351
|
+
case "retry-max-time": options.retryMaxTime = parseSeconds(value); return null;
|
|
352
|
+
case "retry-all-errors": options.retryAllErrors = value; return null;
|
|
353
|
+
case "retry-connrefused": options.retryConnrefused = value; return null;
|
|
354
|
+
case "proto-default": options.protoDefault = value; return null;
|
|
355
|
+
case "write-out": options.writeOut = value; return null;
|
|
356
|
+
case "dump-header": options.dumpHeader = value; return null;
|
|
357
|
+
case "proxy": options.proxy = value; return null;
|
|
358
|
+
case "help": options.help = value; return null;
|
|
359
|
+
case "version": options.version = value; return null;
|
|
360
|
+
default: return null;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function parseSeconds(value) {
|
|
365
|
+
const seconds = Number(value);
|
|
366
|
+
return Number.isFinite(seconds) && seconds > 0 ? seconds : null;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// ------------------------------------------------------------------- URL
|
|
370
|
+
|
|
371
|
+
// curl guesses the protocol when the URL has none; so do we, except that a
|
|
372
|
+
// bare host always means http:// (https:// when the port says so), which is
|
|
373
|
+
// what every scheme-less URL in the tmpk scripts wants.
|
|
374
|
+
export function normalizeUrl(raw, protoDefault) {
|
|
375
|
+
const value = raw.trim();
|
|
376
|
+
if (/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(value)) return value;
|
|
377
|
+
const authority = value.split(/[/?#]/, 1)[0];
|
|
378
|
+
const port = authority.includes(":") ? authority.split(":").pop() : "";
|
|
379
|
+
let scheme = protoDefault ?? "http";
|
|
380
|
+
if (port === "443") scheme = "https";
|
|
381
|
+
else if (!protoDefault && /^ftp\./i.test(authority)) scheme = "ftp";
|
|
382
|
+
return `${scheme}://${value}`;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// ---------------------------------------------------------------- output
|
|
386
|
+
|
|
387
|
+
function openSink(target, io) {
|
|
388
|
+
if (target.kind === "stdout") {
|
|
389
|
+
return {
|
|
390
|
+
path: null,
|
|
391
|
+
async write(chunk) { await io.writeStdout(chunk); },
|
|
392
|
+
async close() {},
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
const path = target.path;
|
|
396
|
+
if (target.createDirs) {
|
|
397
|
+
const directory = pathDirname(path);
|
|
398
|
+
if (directory && !existsSync(directory)) mkdirSync(directory, { recursive: true });
|
|
399
|
+
}
|
|
400
|
+
let stream;
|
|
401
|
+
try {
|
|
402
|
+
stream = createWriteStream(path, { flags: target.append ? "a" : "w" });
|
|
403
|
+
} catch (error) {
|
|
404
|
+
throw new CurlError(23, `Failed writing body: ${error.message}`);
|
|
405
|
+
}
|
|
406
|
+
return {
|
|
407
|
+
path,
|
|
408
|
+
write(chunk) {
|
|
409
|
+
return new Promise((resolve, reject) => {
|
|
410
|
+
stream.write(chunk, (error) => error
|
|
411
|
+
? reject(new CurlError(23, "Failed writing body"))
|
|
412
|
+
: resolve());
|
|
413
|
+
});
|
|
414
|
+
},
|
|
415
|
+
close() {
|
|
416
|
+
return new Promise((resolve) => stream.end(resolve));
|
|
417
|
+
},
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// ------------------------------------------------------- progress display
|
|
422
|
+
|
|
423
|
+
function humanSize(value) {
|
|
424
|
+
if (!Number.isFinite(value) || value < 0) return " 0";
|
|
425
|
+
if (value < 100_000) return String(Math.round(value)).padStart(5);
|
|
426
|
+
if (value < 10_000 * 1024) return `${Math.round(value / 1024)}k`.padStart(5);
|
|
427
|
+
if (value < 100 * 1024 * 1024) return `${(value / (1024 * 1024)).toFixed(1)}M`.padStart(5);
|
|
428
|
+
if (value < 10_000 * 1024 * 1024) return `${Math.round(value / (1024 * 1024))}M`.padStart(5);
|
|
429
|
+
return `${(value / (1024 * 1024 * 1024)).toFixed(1)}G`.padStart(5);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
function humanTime(seconds) {
|
|
433
|
+
if (!Number.isFinite(seconds) || seconds < 0) return "--:--:--";
|
|
434
|
+
const whole = Math.round(seconds);
|
|
435
|
+
const hours = Math.floor(whole / 3600);
|
|
436
|
+
const minutes = Math.floor((whole % 3600) / 60);
|
|
437
|
+
return `${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}:${String(whole % 60).padStart(2, "0")}`;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
class ProgressDisplay {
|
|
441
|
+
constructor(io, style) {
|
|
442
|
+
this.io = io;
|
|
443
|
+
this.style = style;
|
|
444
|
+
this.started = performance.now();
|
|
445
|
+
this.total = null;
|
|
446
|
+
this.received = 0;
|
|
447
|
+
this.lastPaint = 0;
|
|
448
|
+
this.painted = false;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
begin(total) {
|
|
452
|
+
this.total = Number.isFinite(total) && total >= 0 ? total : null;
|
|
453
|
+
if (this.style === "meter") {
|
|
454
|
+
this.io.writeStderr(
|
|
455
|
+
" % Total % Received % Xferd Average Speed Time Time Time Current\n" +
|
|
456
|
+
" Dload Upload Total Spent Left Speed\n");
|
|
457
|
+
}
|
|
458
|
+
return this.paint(true);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
advance(size) {
|
|
462
|
+
this.received += size;
|
|
463
|
+
return this.paint(false);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
async paint(force) {
|
|
467
|
+
const now = performance.now();
|
|
468
|
+
if (!force && now - this.lastPaint < 200) return;
|
|
469
|
+
this.lastPaint = now;
|
|
470
|
+
this.painted = true;
|
|
471
|
+
const spent = (now - this.started) / 1000;
|
|
472
|
+
const speed = spent > 0 ? this.received / spent : 0;
|
|
473
|
+
if (this.style === "bar") {
|
|
474
|
+
const ratio = this.total ? Math.min(1, this.received / this.total) : 0;
|
|
475
|
+
const width = 72;
|
|
476
|
+
const filled = Math.round(ratio * width);
|
|
477
|
+
await this.io.writeStderr(
|
|
478
|
+
`\r${"#".repeat(filled)}${" ".repeat(width - filled)} ${(ratio * 100).toFixed(1)}%`);
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
const percent = this.total ? Math.floor((this.received / this.total) * 100) : 0;
|
|
482
|
+
const left = this.total && speed > 0
|
|
483
|
+
? humanTime((this.total - this.received) / speed)
|
|
484
|
+
: "--:--:--";
|
|
485
|
+
await this.io.writeStderr(
|
|
486
|
+
`\r${String(percent).padStart(3)} ${humanSize(this.total ?? 0)} ` +
|
|
487
|
+
`${String(percent).padStart(3)} ${humanSize(this.received)} ` +
|
|
488
|
+
` 0 ${humanSize(0)} ${humanSize(speed)} ${humanSize(0)} ` +
|
|
489
|
+
`${humanTime(this.total && speed > 0 ? this.total / speed : NaN)} ` +
|
|
490
|
+
`${humanTime(spent)} ${left} ${humanSize(speed)}`);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
async end() {
|
|
494
|
+
await this.paint(true);
|
|
495
|
+
if (this.painted) await this.io.writeStderr("\n");
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// ------------------------------------------------------------ request body
|
|
500
|
+
|
|
501
|
+
async function readStdinBytes(io) {
|
|
502
|
+
if (io.stdinBytes) return io.stdinBytes;
|
|
503
|
+
io.stdinBytes = await io.readStdin();
|
|
504
|
+
return io.stdinBytes;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
async function readOperandBytes(io, spec) {
|
|
508
|
+
if (spec === "-") return readStdinBytes(io);
|
|
509
|
+
const path = resolveAgainst(io.cwd, spec);
|
|
510
|
+
try {
|
|
511
|
+
return new Uint8Array(await readFile(path));
|
|
512
|
+
} catch {
|
|
513
|
+
throw new CurlError(26, `Failed to open/read local data from file/application`);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
function stripNewlines(data) {
|
|
518
|
+
return data.filter((byte) => byte !== 0x0a && byte !== 0x0d);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
async function buildDataBody(options, io) {
|
|
522
|
+
const parts = [];
|
|
523
|
+
let jsonRequested = false;
|
|
524
|
+
for (const entry of options.data) {
|
|
525
|
+
if (entry.kind === "raw") {
|
|
526
|
+
parts.push(bytes(entry.value));
|
|
527
|
+
continue;
|
|
528
|
+
}
|
|
529
|
+
if (entry.kind === "urlencode") {
|
|
530
|
+
parts.push(bytes(await urlencodeSegment(entry.value, io)));
|
|
531
|
+
continue;
|
|
532
|
+
}
|
|
533
|
+
if (entry.kind === "json") jsonRequested = true;
|
|
534
|
+
const usesFile = entry.value.startsWith("@");
|
|
535
|
+
if (!usesFile) {
|
|
536
|
+
parts.push(bytes(entry.value));
|
|
537
|
+
continue;
|
|
538
|
+
}
|
|
539
|
+
const data = await readOperandBytes(io, entry.value.slice(1));
|
|
540
|
+
// --data / --data-ascii / --json strip newlines from file input,
|
|
541
|
+
// --data-binary keeps the file byte-for-byte.
|
|
542
|
+
parts.push(entry.kind === "binary" || entry.kind === "json" ? data : stripNewlines(data));
|
|
543
|
+
}
|
|
544
|
+
const separator = bytes("&");
|
|
545
|
+
const merged = [];
|
|
546
|
+
parts.forEach((part, index) => {
|
|
547
|
+
if (index) merged.push(separator);
|
|
548
|
+
merged.push(part);
|
|
549
|
+
});
|
|
550
|
+
return { body: concatBytes(merged), json: jsonRequested };
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
export function curlEscape(text) {
|
|
554
|
+
let output = "";
|
|
555
|
+
for (const byte of encoder.encode(text)) {
|
|
556
|
+
const ch = String.fromCharCode(byte);
|
|
557
|
+
if (/[A-Za-z0-9\-._~]/.test(ch)) output += ch;
|
|
558
|
+
else if (ch === " ") output += "+";
|
|
559
|
+
else output += `%${byte.toString(16).toUpperCase().padStart(2, "0")}`;
|
|
560
|
+
}
|
|
561
|
+
return output;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
async function urlencodeSegment(spec, io) {
|
|
565
|
+
// content | =content | name=content | @file | name@file
|
|
566
|
+
if (spec.startsWith("=")) return curlEscape(spec.slice(1));
|
|
567
|
+
if (spec.startsWith("@"))
|
|
568
|
+
return curlEscape(decoder.decode(await readOperandBytes(io, spec.slice(1))));
|
|
569
|
+
const equals = spec.indexOf("=");
|
|
570
|
+
const at = spec.indexOf("@");
|
|
571
|
+
if (equals > 0 && (at < 0 || equals < at))
|
|
572
|
+
return `${spec.slice(0, equals)}=${curlEscape(spec.slice(equals + 1))}`;
|
|
573
|
+
if (at > 0) {
|
|
574
|
+
const content = decoder.decode(await readOperandBytes(io, spec.slice(at + 1)));
|
|
575
|
+
return `${spec.slice(0, at)}=${curlEscape(content)}`;
|
|
576
|
+
}
|
|
577
|
+
return curlEscape(spec);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
async function buildFormBody(options, io) {
|
|
581
|
+
const form = new FormData();
|
|
582
|
+
for (const entry of options.forms) {
|
|
583
|
+
const separator = entry.value.indexOf("=");
|
|
584
|
+
if (separator < 0)
|
|
585
|
+
throw new CurlError(2, `Illegally formatted input field: '${entry.value}'`);
|
|
586
|
+
const name = entry.value.slice(0, separator);
|
|
587
|
+
let value = entry.value.slice(separator + 1);
|
|
588
|
+
if (entry.literal || !(value.startsWith("@") || value.startsWith("<"))) {
|
|
589
|
+
form.append(name, value);
|
|
590
|
+
continue;
|
|
591
|
+
}
|
|
592
|
+
const upload = value.startsWith("@");
|
|
593
|
+
let spec = value.slice(1);
|
|
594
|
+
let filename = null;
|
|
595
|
+
let type = null;
|
|
596
|
+
// @file;type=...;filename=... — curl's per-part attributes.
|
|
597
|
+
const attributes = spec.split(";");
|
|
598
|
+
spec = attributes.shift();
|
|
599
|
+
for (const attribute of attributes) {
|
|
600
|
+
const [key, ...rest] = attribute.split("=");
|
|
601
|
+
if (key.trim() === "type") type = rest.join("=");
|
|
602
|
+
if (key.trim() === "filename") filename = rest.join("=");
|
|
603
|
+
}
|
|
604
|
+
const data = await readOperandBytes(io, spec);
|
|
605
|
+
if (!upload) {
|
|
606
|
+
form.append(name, decoder.decode(data));
|
|
607
|
+
continue;
|
|
608
|
+
}
|
|
609
|
+
const file = new File([data], filename ?? pathBasename(spec), type ? { type } : undefined);
|
|
610
|
+
form.append(name, file);
|
|
611
|
+
}
|
|
612
|
+
return form;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// ------------------------------------------------------------- headers
|
|
616
|
+
|
|
617
|
+
function buildHeaderList(options, prepared) {
|
|
618
|
+
const list = [];
|
|
619
|
+
const set = (name, value) => {
|
|
620
|
+
const index = list.findIndex((entry) => entry[0].toLowerCase() === name.toLowerCase());
|
|
621
|
+
if (index < 0) list.push([name, value]); else list[index] = [name, value];
|
|
622
|
+
};
|
|
623
|
+
set("User-Agent", options.userAgent ?? DEFAULT_USER_AGENT);
|
|
624
|
+
set("Accept", "*/*");
|
|
625
|
+
if (prepared.contentType) set("Content-Type", prepared.contentType);
|
|
626
|
+
if (options.referer) set("Referer", options.referer.replace(/;auto$/, ""));
|
|
627
|
+
if (options.cookie) set("Cookie", options.cookie);
|
|
628
|
+
if (options.range) set("Range", `bytes=${options.range}`);
|
|
629
|
+
if (options.bearer) set("Authorization", `Bearer ${options.bearer}`);
|
|
630
|
+
if (options.user) {
|
|
631
|
+
const credentials = options.user.includes(":") ? options.user : `${options.user}:`;
|
|
632
|
+
set("Authorization", `Basic ${Buffer.from(credentials).toString("base64")}`);
|
|
633
|
+
}
|
|
634
|
+
if (prepared.acceptJson) set("Accept", "application/json");
|
|
635
|
+
for (const raw of options.headers) {
|
|
636
|
+
const separator = raw.indexOf(":");
|
|
637
|
+
if (separator < 0) {
|
|
638
|
+
// "Name;" is curl's way of sending a header with an empty value.
|
|
639
|
+
if (raw.endsWith(";")) set(raw.slice(0, -1).trim(), "");
|
|
640
|
+
continue;
|
|
641
|
+
}
|
|
642
|
+
const name = raw.slice(0, separator).trim();
|
|
643
|
+
const value = raw.slice(separator + 1).trim();
|
|
644
|
+
if (!value) {
|
|
645
|
+
// "Name:" removes a header curl would otherwise send itself.
|
|
646
|
+
const index = list.findIndex((entry) => entry[0].toLowerCase() === name.toLowerCase());
|
|
647
|
+
if (index >= 0) list.splice(index, 1);
|
|
648
|
+
continue;
|
|
649
|
+
}
|
|
650
|
+
set(name, value);
|
|
651
|
+
}
|
|
652
|
+
return list;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
function formatResponseHeaders(response) {
|
|
656
|
+
const lines = [`HTTP/1.1 ${response.status} ${response.statusText}`.trimEnd()];
|
|
657
|
+
const cookies = typeof response.headers.getSetCookie === "function"
|
|
658
|
+
? response.headers.getSetCookie()
|
|
659
|
+
: [];
|
|
660
|
+
for (const [name, value] of response.headers) {
|
|
661
|
+
if (name.toLowerCase() === "set-cookie" && cookies.length) continue;
|
|
662
|
+
lines.push(`${canonicalHeaderName(name)}: ${value}`);
|
|
663
|
+
}
|
|
664
|
+
for (const cookie of cookies) lines.push(`Set-Cookie: ${cookie}`);
|
|
665
|
+
return `${lines.join("\r\n")}\r\n\r\n`;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// ---------------------------------------------------------------- errors
|
|
669
|
+
|
|
670
|
+
function describeFetchFailure(error, url, elapsed, received, options) {
|
|
671
|
+
const target = safeUrl(url);
|
|
672
|
+
const host = target?.hostname ?? url;
|
|
673
|
+
const port = target?.port || (target?.protocol === "https:" ? "443" : "80");
|
|
674
|
+
const code = error?.code ?? "";
|
|
675
|
+
if (error?.name === "TimeoutError" || error?.name === "AbortError")
|
|
676
|
+
return new CurlError(28,
|
|
677
|
+
`Operation timed out after ${Math.round(elapsed)} milliseconds with ${received} bytes received`);
|
|
678
|
+
if (code === "ENOTFOUND" || code === "EAI_AGAIN" || code === "DNSException" ||
|
|
679
|
+
/getaddrinfo|Could not resolve|dns/i.test(error?.message ?? ""))
|
|
680
|
+
return new CurlError(6, `Could not resolve host: ${host}`);
|
|
681
|
+
if (/^(CERT_|DEPTH_ZERO|SELF_SIGNED|UNABLE_TO_|ERR_TLS)/.test(code))
|
|
682
|
+
return new CurlError(60, `SSL certificate problem: ${error.message}`);
|
|
683
|
+
if (code === "ECONNRESET" || code === "ConnectionClosed")
|
|
684
|
+
return new CurlError(56, "Recv failure: Connection reset by peer");
|
|
685
|
+
return new CurlError(7,
|
|
686
|
+
`Failed to connect to ${host} port ${port} after ${Math.round(elapsed)} ms: ${
|
|
687
|
+
code === "ConnectionRefused" ? "Could not connect to server" : error?.message ?? "Connection failed"}`);
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
function safeUrl(value) {
|
|
691
|
+
try { return new URL(value); } catch { return null; }
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// --------------------------------------------------------------- write-out
|
|
695
|
+
|
|
696
|
+
function formatWriteOut(format, facts, io) {
|
|
697
|
+
let output = "";
|
|
698
|
+
for (let i = 0; i < format.length; i++) {
|
|
699
|
+
const ch = format[i];
|
|
700
|
+
if (ch === "\\" && i + 1 < format.length) {
|
|
701
|
+
const next = format[++i];
|
|
702
|
+
output += next === "n" ? "\n" : next === "t" ? "\t" : next === "r" ? "\r" : next;
|
|
703
|
+
continue;
|
|
704
|
+
}
|
|
705
|
+
if (ch === "%" && format[i + 1] === "%") { output += "%"; i++; continue; }
|
|
706
|
+
if (ch === "%" && format[i + 1] === "{") {
|
|
707
|
+
const end = format.indexOf("}", i + 2);
|
|
708
|
+
if (end < 0) { output += ch; continue; }
|
|
709
|
+
const name = format.slice(i + 2, end);
|
|
710
|
+
i = end;
|
|
711
|
+
output += writeOutVariable(name, facts, io);
|
|
712
|
+
continue;
|
|
713
|
+
}
|
|
714
|
+
output += ch;
|
|
715
|
+
}
|
|
716
|
+
return output;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
function writeOutVariable(name, facts, io) {
|
|
720
|
+
const seconds = (value) => (value / 1000).toFixed(6);
|
|
721
|
+
switch (name) {
|
|
722
|
+
case "url": return facts.url;
|
|
723
|
+
case "url_effective": return facts.effectiveUrl;
|
|
724
|
+
case "method": return facts.method;
|
|
725
|
+
case "scheme": return (safeUrl(facts.effectiveUrl)?.protocol ?? "").replace(":", "").toUpperCase();
|
|
726
|
+
case "http_code":
|
|
727
|
+
case "response_code": return String(facts.status);
|
|
728
|
+
case "http_version": return "1.1";
|
|
729
|
+
case "num_redirects": return String(facts.redirects);
|
|
730
|
+
case "num_headers": return String(facts.headerCount);
|
|
731
|
+
case "redirect_url": return facts.redirectUrl ?? "";
|
|
732
|
+
case "size_download": return String(facts.downloaded);
|
|
733
|
+
case "size_upload": return String(facts.uploaded);
|
|
734
|
+
case "size_header": return String(facts.headerBytes);
|
|
735
|
+
case "size_request": return String(facts.requestBytes);
|
|
736
|
+
case "speed_download":
|
|
737
|
+
return String(Math.round(facts.downloaded / Math.max(facts.elapsed / 1000, 1e-6)));
|
|
738
|
+
case "speed_upload":
|
|
739
|
+
return String(Math.round(facts.uploaded / Math.max(facts.elapsed / 1000, 1e-6)));
|
|
740
|
+
case "content_type": return facts.contentType ?? "";
|
|
741
|
+
case "filename_effective": return facts.filename ?? "";
|
|
742
|
+
case "remote_ip": return safeUrl(facts.effectiveUrl)?.hostname ?? "";
|
|
743
|
+
case "remote_port":
|
|
744
|
+
return safeUrl(facts.effectiveUrl)?.port ||
|
|
745
|
+
(safeUrl(facts.effectiveUrl)?.protocol === "https:" ? "443" : "80");
|
|
746
|
+
case "ssl_verify_result": return "0";
|
|
747
|
+
case "exitcode": return String(facts.exitCode);
|
|
748
|
+
case "errormsg": return facts.errorMessage ?? "";
|
|
749
|
+
case "time_total": return seconds(facts.elapsed);
|
|
750
|
+
case "time_starttransfer": return seconds(facts.headerElapsed);
|
|
751
|
+
case "time_pretransfer":
|
|
752
|
+
case "time_appconnect":
|
|
753
|
+
case "time_connect": return seconds(facts.connectElapsed);
|
|
754
|
+
case "time_namelookup": return seconds(0);
|
|
755
|
+
case "time_redirect": return seconds(facts.redirectElapsed);
|
|
756
|
+
case "header_json": return JSON.stringify(facts.headerJson);
|
|
757
|
+
case "json": return JSON.stringify({
|
|
758
|
+
http_code: facts.status,
|
|
759
|
+
method: facts.method,
|
|
760
|
+
num_redirects: facts.redirects,
|
|
761
|
+
size_download: facts.downloaded,
|
|
762
|
+
time_total: Number(seconds(facts.elapsed)),
|
|
763
|
+
url_effective: facts.effectiveUrl,
|
|
764
|
+
});
|
|
765
|
+
case "stderr": facts.writeOutTarget = "stderr"; return "";
|
|
766
|
+
case "stdout": facts.writeOutTarget = "stdout"; return "";
|
|
767
|
+
default:
|
|
768
|
+
io.writeStderr(`curl: unknown --write-out variable: '${name}'\n`);
|
|
769
|
+
return "";
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
// --------------------------------------------------------------- transfer
|
|
774
|
+
|
|
775
|
+
function remoteName(url) {
|
|
776
|
+
const parsed = safeUrl(url);
|
|
777
|
+
const name = pathBasename(parsed?.pathname ?? "");
|
|
778
|
+
return name && name !== "/" ? decodeURIComponent(name) : "";
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
function contentDispositionName(response) {
|
|
782
|
+
const disposition = response.headers.get("content-disposition");
|
|
783
|
+
if (!disposition) return null;
|
|
784
|
+
const match = /filename\*?=(?:UTF-8'')?"?([^";]+)"?/i.exec(disposition);
|
|
785
|
+
return match ? pathBasename(match[1].trim()) : null;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
async function performTransfer(rawUrl, target, options, io) {
|
|
789
|
+
const started = performance.now();
|
|
790
|
+
const url = normalizeUrl(rawUrl, options.protoDefault);
|
|
791
|
+
const parsed = safeUrl(url);
|
|
792
|
+
if (!parsed) throw new CurlError(3, "URL rejected: Malformed input to a URL function");
|
|
793
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:")
|
|
794
|
+
throw new CurlError(1,
|
|
795
|
+
`Protocol "${parsed.protocol.replace(":", "")}" not supported or disabled in libcurl`);
|
|
796
|
+
|
|
797
|
+
const prepared = await prepareRequest(options, io);
|
|
798
|
+
let method = options.method ?? prepared.method;
|
|
799
|
+
if (options.head) method = options.method ?? "HEAD";
|
|
800
|
+
let headers = buildHeaderList(options, prepared);
|
|
801
|
+
let body = prepared.body;
|
|
802
|
+
|
|
803
|
+
let requestUrl = url;
|
|
804
|
+
if (prepared.query)
|
|
805
|
+
requestUrl = `${url}${url.includes("?") ? "&" : "?"}${prepared.query}`;
|
|
806
|
+
|
|
807
|
+
// -O names the file after the URL that was typed, so the path is known
|
|
808
|
+
// before the first byte arrives — which is what -C - needs to size the
|
|
809
|
+
// partial download. Only -J has to wait for the response headers.
|
|
810
|
+
let filePath = null;
|
|
811
|
+
if (target.kind === "file") filePath = target.path === "-" ? null : target.path;
|
|
812
|
+
else if (target.kind === "remote" && !options.remoteHeaderName) {
|
|
813
|
+
filePath = remoteName(url);
|
|
814
|
+
if (!filePath) throw new CurlError(23, "Remote filename has no length");
|
|
815
|
+
}
|
|
816
|
+
if (filePath !== null) filePath = resolveOutputPath(filePath, options, io);
|
|
817
|
+
|
|
818
|
+
// Resume: ask for the tail we are missing and append to what is there.
|
|
819
|
+
let resumeFrom = 0;
|
|
820
|
+
if (options.continueAt !== null && filePath !== null) {
|
|
821
|
+
resumeFrom = options.continueAt === "-"
|
|
822
|
+
? (existsSync(filePath) ? statSync(filePath).size : 0)
|
|
823
|
+
: Number(options.continueAt) || 0;
|
|
824
|
+
if (resumeFrom > 0) headers.push(["Range", `bytes=${resumeFrom}-`]);
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
let effectiveUrl = requestUrl;
|
|
828
|
+
let redirects = 0;
|
|
829
|
+
let redirectUrl = null;
|
|
830
|
+
let redirectElapsed = 0;
|
|
831
|
+
let response = null;
|
|
832
|
+
const headerBlocks = [];
|
|
833
|
+
let connectElapsed = 0;
|
|
834
|
+
|
|
835
|
+
while (true) {
|
|
836
|
+
if (options.verbose) await logRequest(io, effectiveUrl, method, headers);
|
|
837
|
+
const attemptStarted = performance.now();
|
|
838
|
+
response = await fetchWithRetry(effectiveUrl, {
|
|
839
|
+
method,
|
|
840
|
+
headers,
|
|
841
|
+
body: method === "GET" || method === "HEAD" ? undefined : body,
|
|
842
|
+
redirect: "manual",
|
|
843
|
+
decompress: options.compressed,
|
|
844
|
+
...(options.insecure ? { tls: { rejectUnauthorized: false } } : {}),
|
|
845
|
+
...(options.proxy ? { proxy: normalizeUrl(options.proxy, "http") } : {}),
|
|
846
|
+
...(timeoutSignal(options)),
|
|
847
|
+
}, options, io, effectiveUrl, started);
|
|
848
|
+
connectElapsed = attemptStarted - started;
|
|
849
|
+
const block = formatResponseHeaders(response);
|
|
850
|
+
headerBlocks.push(block);
|
|
851
|
+
if (options.verbose) await logResponse(io, block);
|
|
852
|
+
|
|
853
|
+
const location = response.headers.get("location");
|
|
854
|
+
if (REDIRECT_STATUS.has(response.status) && location) {
|
|
855
|
+
redirectUrl = new URL(location, effectiveUrl).toString();
|
|
856
|
+
if (!options.location) break;
|
|
857
|
+
if (redirects >= options.maxRedirects)
|
|
858
|
+
throw new CurlError(47, `Maximum (${options.maxRedirects}) redirects followed`);
|
|
859
|
+
try { await response.body?.cancel(); } catch {}
|
|
860
|
+
redirects++;
|
|
861
|
+
const previous = new URL(effectiveUrl);
|
|
862
|
+
const next = new URL(redirectUrl);
|
|
863
|
+
// 301/302/303 turn a POST into a GET the way browsers and curl do;
|
|
864
|
+
// 307/308 keep the method and the body.
|
|
865
|
+
if ((response.status === 301 || response.status === 302 || response.status === 303) &&
|
|
866
|
+
method !== "HEAD" && method !== "GET") {
|
|
867
|
+
method = "GET";
|
|
868
|
+
body = undefined;
|
|
869
|
+
headers = headers.filter(([name]) =>
|
|
870
|
+
!["content-type", "content-length"].includes(name.toLowerCase()));
|
|
871
|
+
}
|
|
872
|
+
if (!options.locationTrusted && previous.host !== next.host)
|
|
873
|
+
headers = headers.filter(([name]) => name.toLowerCase() !== "authorization");
|
|
874
|
+
effectiveUrl = redirectUrl;
|
|
875
|
+
redirectElapsed = performance.now() - started;
|
|
876
|
+
continue;
|
|
877
|
+
}
|
|
878
|
+
break;
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
const headerElapsed = performance.now() - started;
|
|
882
|
+
const httpError = options.fail && response.status >= 400;
|
|
883
|
+
|
|
884
|
+
// -J is the one naming mode that has to wait for the response headers.
|
|
885
|
+
if (filePath === null && target.kind === "remote") {
|
|
886
|
+
const name = contentDispositionName(response) ?? remoteName(url);
|
|
887
|
+
if (!name) throw new CurlError(23, "Remote filename has no length");
|
|
888
|
+
filePath = resolveOutputPath(name, options, io);
|
|
889
|
+
}
|
|
890
|
+
const sinkTarget = filePath === null
|
|
891
|
+
? { kind: "stdout" }
|
|
892
|
+
: {
|
|
893
|
+
kind: "file",
|
|
894
|
+
path: filePath,
|
|
895
|
+
// A resumed transfer appends only when the server honoured the range.
|
|
896
|
+
append: options.append || (resumeFrom > 0 && response.status === 206),
|
|
897
|
+
createDirs: options.createDirs,
|
|
898
|
+
};
|
|
899
|
+
|
|
900
|
+
// A range request answered with 416 means the local copy already holds
|
|
901
|
+
// everything the server has, so the resume is a no-op, not a failure.
|
|
902
|
+
if (resumeFrom > 0 && response.status === 416) {
|
|
903
|
+
try { await response.body?.cancel(); } catch {}
|
|
904
|
+
return transferFacts(response, {
|
|
905
|
+
url, effectiveUrl, method, redirects, redirectUrl, headerBlocks,
|
|
906
|
+
downloaded: 0, uploaded: prepared.uploaded, filename: filePath,
|
|
907
|
+
started, headerElapsed, connectElapsed, redirectElapsed, headers, exitCode: 0,
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
if (httpError && !options.failWithBody) {
|
|
912
|
+
try { await response.body?.cancel(); } catch {}
|
|
913
|
+
const error = new CurlError(22, `The requested URL returned error: ${response.status}`);
|
|
914
|
+
// Keep the facts alive so -f -w '%{http_code}' still reports 404.
|
|
915
|
+
error.facts = transferFacts(response, {
|
|
916
|
+
url, effectiveUrl, method, redirects, redirectUrl, headerBlocks,
|
|
917
|
+
downloaded: 0, uploaded: prepared.uploaded, filename: filePath,
|
|
918
|
+
started, headerElapsed, connectElapsed, redirectElapsed, headers, exitCode: 22,
|
|
919
|
+
});
|
|
920
|
+
throw error;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
if (options.dumpHeader) {
|
|
924
|
+
const text = headerBlocks.join("");
|
|
925
|
+
if (options.dumpHeader === "-") await io.writeStdout(bytes(text));
|
|
926
|
+
else {
|
|
927
|
+
const dump = openSink({
|
|
928
|
+
kind: "file",
|
|
929
|
+
path: resolveAgainst(io.cwd, options.dumpHeader),
|
|
930
|
+
createDirs: options.createDirs,
|
|
931
|
+
}, io);
|
|
932
|
+
await dump.write(bytes(text));
|
|
933
|
+
await dump.close();
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
const sink = openSink(sinkTarget, io);
|
|
938
|
+
const showProgress = shouldShowProgress(options, sinkTarget, io);
|
|
939
|
+
const progress = showProgress
|
|
940
|
+
? new ProgressDisplay(io, options.progressBar ? "bar" : "meter")
|
|
941
|
+
: null;
|
|
942
|
+
|
|
943
|
+
let downloaded = 0;
|
|
944
|
+
try {
|
|
945
|
+
if (options.include) await sink.write(bytes(headerBlocks.join("")));
|
|
946
|
+
else if (options.head) await sink.write(bytes(headerBlocks.at(-1)));
|
|
947
|
+
if (progress) {
|
|
948
|
+
const length = Number(response.headers.get("content-length"));
|
|
949
|
+
await progress.begin(Number.isFinite(length) ? length : null);
|
|
950
|
+
}
|
|
951
|
+
if (response.body && method !== "HEAD") {
|
|
952
|
+
for await (const chunk of response.body) {
|
|
953
|
+
downloaded += chunk.byteLength;
|
|
954
|
+
await sink.write(chunk);
|
|
955
|
+
if (progress) await progress.advance(chunk.byteLength);
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
} catch (error) {
|
|
959
|
+
if (progress) await progress.end();
|
|
960
|
+
await sink.close();
|
|
961
|
+
if (error instanceof CurlError) throw error;
|
|
962
|
+
throw describeFetchFailure(error, effectiveUrl, performance.now() - started, downloaded, options);
|
|
963
|
+
}
|
|
964
|
+
if (progress) await progress.end();
|
|
965
|
+
await sink.close();
|
|
966
|
+
|
|
967
|
+
return transferFacts(response, {
|
|
968
|
+
url, effectiveUrl, method, redirects, redirectUrl, headerBlocks,
|
|
969
|
+
downloaded, uploaded: prepared.uploaded, filename: filePath,
|
|
970
|
+
started, headerElapsed, connectElapsed, redirectElapsed, headers,
|
|
971
|
+
exitCode: httpError ? 22 : 0,
|
|
972
|
+
});
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
// Everything --write-out can ask about, gathered in one shape so a failed
|
|
976
|
+
// transfer can report the same fields a successful one does.
|
|
977
|
+
function transferFacts(response, detail) {
|
|
978
|
+
return {
|
|
979
|
+
status: response.status,
|
|
980
|
+
exitCode: detail.exitCode,
|
|
981
|
+
response,
|
|
982
|
+
url: detail.url,
|
|
983
|
+
effectiveUrl: detail.effectiveUrl,
|
|
984
|
+
method: detail.method,
|
|
985
|
+
redirects: detail.redirects,
|
|
986
|
+
redirectUrl: detail.redirectUrl,
|
|
987
|
+
downloaded: detail.downloaded,
|
|
988
|
+
uploaded: detail.uploaded,
|
|
989
|
+
headerBytes: detail.headerBlocks.reduce((sum, block) => sum + block.length, 0),
|
|
990
|
+
requestBytes: detail.headers.reduce((sum, [name, value]) => sum + name.length + value.length + 4, 0),
|
|
991
|
+
headerCount: [...response.headers].length,
|
|
992
|
+
contentType: response.headers.get("content-type"),
|
|
993
|
+
filename: detail.filename,
|
|
994
|
+
headerJson: Object.fromEntries([...response.headers].map(([name, value]) => [name, [value]])),
|
|
995
|
+
elapsed: performance.now() - detail.started,
|
|
996
|
+
headerElapsed: detail.headerElapsed,
|
|
997
|
+
connectElapsed: detail.connectElapsed,
|
|
998
|
+
redirectElapsed: detail.redirectElapsed,
|
|
999
|
+
};
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
function timeoutSignal(options) {
|
|
1003
|
+
const seconds = options.maxTime ?? options.connectTimeout;
|
|
1004
|
+
return seconds ? { signal: AbortSignal.timeout(seconds * 1000) } : {};
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
function shouldShowProgress(options, target, io) {
|
|
1008
|
+
if (options.silent && !options.progressBar) return false;
|
|
1009
|
+
if (options.progressMeter === false) return false;
|
|
1010
|
+
if (options.progressBar) return true;
|
|
1011
|
+
// curl keeps the meter off when the body is being painted on the terminal.
|
|
1012
|
+
return !(target.kind === "stdout" && io.stdoutIsTTY);
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
async function fetchWithRetry(url, init, options, io, effectiveUrl, started) {
|
|
1016
|
+
const attempts = options.retry + 1;
|
|
1017
|
+
let lastError = null;
|
|
1018
|
+
for (let attempt = 0; attempt < attempts; attempt++) {
|
|
1019
|
+
if (attempt > 0) {
|
|
1020
|
+
const delay = options.retryDelay ?? Math.min(2 ** (attempt - 1), 60);
|
|
1021
|
+
if (!options.silent)
|
|
1022
|
+
await io.writeStderr(`Warning: Transient problem. Will retry in ${delay} seconds. ` +
|
|
1023
|
+
`${attempts - attempt - 1} retries left.\n`);
|
|
1024
|
+
await Bun.sleep(delay * 1000);
|
|
1025
|
+
}
|
|
1026
|
+
try {
|
|
1027
|
+
const response = await fetch(url, init);
|
|
1028
|
+
if (attempt + 1 < attempts && TRANSIENT_STATUS.has(response.status)) {
|
|
1029
|
+
try { await response.body?.cancel(); } catch {}
|
|
1030
|
+
lastError = null;
|
|
1031
|
+
continue;
|
|
1032
|
+
}
|
|
1033
|
+
return response;
|
|
1034
|
+
} catch (error) {
|
|
1035
|
+
lastError = error;
|
|
1036
|
+
const failure = describeFetchFailure(error, effectiveUrl, performance.now() - started, 0, options);
|
|
1037
|
+
const retryable = options.retryAllErrors || options.retryConnrefused ||
|
|
1038
|
+
[6, 7, 28, 56].includes(failure.code);
|
|
1039
|
+
if (attempt + 1 >= attempts || !retryable) throw failure;
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
if (lastError) throw describeFetchFailure(lastError, effectiveUrl, performance.now() - started, 0, options);
|
|
1043
|
+
// Ran out of retries on a transient HTTP status: do one last honest call.
|
|
1044
|
+
return fetch(url, init);
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
async function prepareRequest(options, io) {
|
|
1048
|
+
if (options.forms.length) {
|
|
1049
|
+
const form = await buildFormBody(options, io);
|
|
1050
|
+
return { body: form, method: "POST", contentType: null, uploaded: 0, acceptJson: false };
|
|
1051
|
+
}
|
|
1052
|
+
if (options.uploadFile) {
|
|
1053
|
+
const data = await readOperandBytes(io, options.uploadFile);
|
|
1054
|
+
return { body: data, method: "PUT", contentType: null, uploaded: data.byteLength, acceptJson: false };
|
|
1055
|
+
}
|
|
1056
|
+
if (options.data.length) {
|
|
1057
|
+
const { body, json } = await buildDataBody(options, io);
|
|
1058
|
+
if (options.get) return { body: undefined, method: "GET", query: decoder.decode(body), contentType: null, uploaded: 0, acceptJson: json };
|
|
1059
|
+
return {
|
|
1060
|
+
body,
|
|
1061
|
+
method: "POST",
|
|
1062
|
+
contentType: json ? "application/json" : "application/x-www-form-urlencoded",
|
|
1063
|
+
uploaded: body.byteLength,
|
|
1064
|
+
acceptJson: json,
|
|
1065
|
+
};
|
|
1066
|
+
}
|
|
1067
|
+
return { body: undefined, method: "GET", contentType: null, uploaded: 0, acceptJson: false };
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
async function logRequest(io, url, method, headers) {
|
|
1071
|
+
const parsed = safeUrl(url);
|
|
1072
|
+
const port = parsed?.port || (parsed?.protocol === "https:" ? "443" : "80");
|
|
1073
|
+
await io.writeStderr(`* Trying ${parsed?.hostname}:${port}...\n`);
|
|
1074
|
+
await io.writeStderr(`* Connected to ${parsed?.hostname} port ${port}\n`);
|
|
1075
|
+
await io.writeStderr(`> ${method} ${parsed ? parsed.pathname + parsed.search : url} HTTP/1.1\r\n`);
|
|
1076
|
+
await io.writeStderr(`> Host: ${parsed?.host}\r\n`);
|
|
1077
|
+
for (const [name, value] of headers) await io.writeStderr(`> ${name}: ${value}\r\n`);
|
|
1078
|
+
await io.writeStderr("> \r\n");
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
async function logResponse(io, block) {
|
|
1082
|
+
const lines = block.split("\r\n");
|
|
1083
|
+
if (lines.at(-1) === "") lines.pop();
|
|
1084
|
+
for (const line of lines) await io.writeStderr(`< ${line}\r\n`);
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
function resolveOutputPath(name, options, io) {
|
|
1088
|
+
let path = name;
|
|
1089
|
+
if (options.outputDir && !isAbsolute(path)) path = `${options.outputDir}/${path}`;
|
|
1090
|
+
return resolveAgainst(io.cwd, path);
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
// ------------------------------------------------------------------- main
|
|
1094
|
+
|
|
1095
|
+
const USAGE = `Usage: curl [options...] <url>
|
|
1096
|
+
-d, --data <data> HTTP POST data
|
|
1097
|
+
-f, --fail Fail fast with no output on HTTP errors
|
|
1098
|
+
-h, --help Get help for commands
|
|
1099
|
+
-o, --output <file> Write to file instead of stdout
|
|
1100
|
+
-O, --remote-name Write output to a file named as the remote file
|
|
1101
|
+
-s, --silent Silent mode
|
|
1102
|
+
-T, --upload-file <file> Transfer local FILE to destination
|
|
1103
|
+
-u, --user <user:password> Server user and password
|
|
1104
|
+
-A, --user-agent <name> Send User-Agent <name> to server
|
|
1105
|
+
-v, --verbose Make the operation more talkative
|
|
1106
|
+
-V, --version Show version number and quit
|
|
1107
|
+
|
|
1108
|
+
This is not the full help; this menu is split into categories.
|
|
1109
|
+
Use "curl --help" inside bunmsh for the built-in reference page.
|
|
1110
|
+
`;
|
|
1111
|
+
|
|
1112
|
+
export async function runCurl(argv, io) {
|
|
1113
|
+
const parsed = parseCurlArguments(argv);
|
|
1114
|
+
if (parsed.error) {
|
|
1115
|
+
await io.writeStderr(`${parsed.error}\n`);
|
|
1116
|
+
await io.writeStderr("curl: try 'curl --help' or 'curl --manual' for more information\n");
|
|
1117
|
+
return 2;
|
|
1118
|
+
}
|
|
1119
|
+
const options = parsed.options;
|
|
1120
|
+
if (options.help) {
|
|
1121
|
+
await io.writeStdout(bytes(USAGE));
|
|
1122
|
+
return 0;
|
|
1123
|
+
}
|
|
1124
|
+
if (options.version) {
|
|
1125
|
+
await io.writeStdout(bytes(
|
|
1126
|
+
`curl ${CURL_VERSION} (${process.platform}-${process.arch}) bunmsh/fetch Bun/${Bun.version}\n` +
|
|
1127
|
+
`Release-Date: ${new Date().toISOString().slice(0, 10)}\n` +
|
|
1128
|
+
`Protocols: http https\n` +
|
|
1129
|
+
`Features: alt-svc AsynchDNS HTTP2 HTTPS-proxy Largefile libz SSL UnixSockets\n`));
|
|
1130
|
+
return 0;
|
|
1131
|
+
}
|
|
1132
|
+
if (options.urls.length === 0) {
|
|
1133
|
+
await io.writeStderr("curl: try 'curl --help' or 'curl --manual' for more information\n");
|
|
1134
|
+
return 2;
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
let status = 0;
|
|
1138
|
+
for (const [index, rawUrl] of options.urls.entries()) {
|
|
1139
|
+
let target = options.outputs[index] ??
|
|
1140
|
+
(options.remoteNameAll ? { kind: "remote" } : { kind: "stdout" });
|
|
1141
|
+
let facts = null;
|
|
1142
|
+
let failure = null;
|
|
1143
|
+
try {
|
|
1144
|
+
facts = await performTransfer(rawUrl, target, options, io);
|
|
1145
|
+
if (facts.exitCode) status = facts.exitCode;
|
|
1146
|
+
} catch (error) {
|
|
1147
|
+
failure = error instanceof CurlError
|
|
1148
|
+
? error
|
|
1149
|
+
: describeFetchFailure(error, rawUrl, 0, 0, options);
|
|
1150
|
+
facts = failure.facts ?? null;
|
|
1151
|
+
status = failure.code;
|
|
1152
|
+
if (!options.silent || options.showError)
|
|
1153
|
+
await io.writeStderr(`curl: (${failure.code}) ${failure.message}\n`);
|
|
1154
|
+
}
|
|
1155
|
+
if (options.writeOut) {
|
|
1156
|
+
const format = options.writeOut.startsWith("@")
|
|
1157
|
+
? decoder.decode(await readOperandBytes(io, options.writeOut.slice(1)))
|
|
1158
|
+
: options.writeOut;
|
|
1159
|
+
const source = facts ?? {
|
|
1160
|
+
status: 0,
|
|
1161
|
+
url: rawUrl,
|
|
1162
|
+
effectiveUrl: normalizeUrl(rawUrl, options.protoDefault),
|
|
1163
|
+
method: options.method ?? "GET",
|
|
1164
|
+
redirects: 0,
|
|
1165
|
+
downloaded: 0,
|
|
1166
|
+
uploaded: 0,
|
|
1167
|
+
headerBytes: 0,
|
|
1168
|
+
requestBytes: 0,
|
|
1169
|
+
headerCount: 0,
|
|
1170
|
+
contentType: null,
|
|
1171
|
+
filename: null,
|
|
1172
|
+
headerJson: {},
|
|
1173
|
+
elapsed: 0,
|
|
1174
|
+
headerElapsed: 0,
|
|
1175
|
+
connectElapsed: 0,
|
|
1176
|
+
redirectElapsed: 0,
|
|
1177
|
+
redirectUrl: null,
|
|
1178
|
+
};
|
|
1179
|
+
const detail = {
|
|
1180
|
+
...source,
|
|
1181
|
+
exitCode: failure ? failure.code : (facts?.exitCode ?? 0),
|
|
1182
|
+
errorMessage: failure ? failure.message : "",
|
|
1183
|
+
writeOutTarget: "stdout",
|
|
1184
|
+
};
|
|
1185
|
+
const text = formatWriteOut(format, detail, io);
|
|
1186
|
+
if (detail.writeOutTarget === "stderr") await io.writeStderr(text);
|
|
1187
|
+
else await io.writeStdout(bytes(text));
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
return status;
|
|
1191
|
+
}
|