Initial Commit
This commit is contained in:
+34
@@ -0,0 +1,34 @@
|
||||
# dependencies (bun install)
|
||||
node_modules
|
||||
|
||||
# output
|
||||
out
|
||||
dist
|
||||
*.tgz
|
||||
|
||||
# code coverage
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# logs
|
||||
logs
|
||||
_.log
|
||||
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# caches
|
||||
.eslintcache
|
||||
.cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# IntelliJ based IDEs
|
||||
.idea
|
||||
|
||||
# Finder (MacOS) folder config
|
||||
.DS_Store
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "./node_modules/oxfmt/configuration_schema.json",
|
||||
"useTabs": false,
|
||||
"tabWidth": 2,
|
||||
"printWidth": 80,
|
||||
"singleQuote": false,
|
||||
"jsxSingleQuote": false,
|
||||
"quoteProps": "as-needed",
|
||||
"trailingComma": "all",
|
||||
"semi": true,
|
||||
"arrowParens": "always",
|
||||
"bracketSameLine": false,
|
||||
"bracketSpacing": true,
|
||||
"ignorePatterns": ["node_modules", ".next", "dist", "build", "components/ui"]
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
||||
"plugins": ["nextjs", "react", "import", "typescript"],
|
||||
"jsPlugins": ["oxlint-tailwindcss"],
|
||||
"settings": {
|
||||
"tailwindcss": {
|
||||
"entryPoint": "app/globals.css"
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
"nextjs/no-html-link-for-pages": "error",
|
||||
"nextjs/next-script-for-ga": "error",
|
||||
"typescript/no-import-type-side-effects": "error",
|
||||
"typescript/consistent-type-imports": "error",
|
||||
"typescript/restrict-template-expressions": "off",
|
||||
"typescript/no-floating-promises": "off",
|
||||
"typescript/no-base-to-string": "off",
|
||||
"typescript/unbound-method": "off",
|
||||
"tailwindcss/no-unknown-classes": "error",
|
||||
"tailwindcss/no-conflicting-classes": "error",
|
||||
"tailwindcss/enforce-sort-order": "warn",
|
||||
"tailwindcss/no-unnecessary-arbitrary-value": "warn",
|
||||
"tailwindcss/enforce-canonical": "warn"
|
||||
},
|
||||
"options": {
|
||||
"typeAware": true
|
||||
},
|
||||
"ignorePatterns": ["./components/ui/**/*"]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
# kuber
|
||||
|
||||
To install dependencies:
|
||||
|
||||
```bash
|
||||
bun install
|
||||
```
|
||||
|
||||
To run:
|
||||
|
||||
```bash
|
||||
bun run index.ts
|
||||
```
|
||||
|
||||
This project was created using `bun init` in bun v1.3.13. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
|
||||
@@ -0,0 +1,11 @@
|
||||
import { build } from "bun";
|
||||
|
||||
build({
|
||||
compile: true,
|
||||
sourcemap: true,
|
||||
minify: true,
|
||||
target: "bun",
|
||||
entrypoints: ["index.ts"],
|
||||
outdir: "dist",
|
||||
features: ["prod"],
|
||||
});
|
||||
@@ -0,0 +1,295 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "kuber",
|
||||
"dependencies": {
|
||||
"@cliffy/table": "npm:@jsr/cliffy__table",
|
||||
"@kubernetes/client-node": "^1.4.0",
|
||||
"citty": "^0.2.2",
|
||||
"zod": "^4.4.3",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest",
|
||||
"json-schema-to-typescript": "^15.0.4",
|
||||
"oxfmt": "^0.62.0",
|
||||
"oxlint": "^1.77.0",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@apidevtools/json-schema-ref-parser": ["@apidevtools/[email protected]", "", { "dependencies": { "@jsdevtools/ono": "^7.1.3", "@types/json-schema": "^7.0.15", "js-yaml": "^4.1.0" } }, "sha512-60vepv88RwcJtSHrD6MjIL6Ta3SOYbgfnkHb+ppAVK+o9mXprRtulx7VlRl3lN3bbvysAfCS7WMVfhUYemB0IQ=="],
|
||||
|
||||
"@cliffy/table": ["@jsr/[email protected]", "https://npm.jsr.io/~/11/@jsr/cliffy__table/1.2.1.tgz", { "dependencies": { "@jsr/std__fmt": "^1.0.10" } }, "sha512-C/edvcMwtnbFx0zyoeGRcC+ZRvGYqxEhRi19HpfbfiYS4ZErKjEwMJmavO/DN7Wxbk34UpJP+UQKL7nKe+dYkA=="],
|
||||
|
||||
"@jsdevtools/ono": ["@jsdevtools/[email protected]", "", {}, "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg=="],
|
||||
|
||||
"@jsep-plugin/assignment": ["@jsep-plugin/[email protected]", "", { "peerDependencies": { "jsep": "^0.4.0||^1.0.0" } }, "sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ=="],
|
||||
|
||||
"@jsep-plugin/regex": ["@jsep-plugin/[email protected]", "", { "peerDependencies": { "jsep": "^0.4.0||^1.0.0" } }, "sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg=="],
|
||||
|
||||
"@jsr/std__fmt": ["@jsr/[email protected]", "https://npm.jsr.io/~/11/@jsr/std__fmt/1.0.10.tgz", {}, "sha512-Q2N8XDNkh/c1IKTi+sO4Vm64M5m4W0o47qTURmMX0vgHm9AJ6jL7jEQ2kw0M1T2rBZiwAY78eUbYzFyOYWaCqQ=="],
|
||||
|
||||
"@kubernetes/client-node": ["@kubernetes/[email protected]", "", { "dependencies": { "@types/js-yaml": "^4.0.1", "@types/node": "^24.0.0", "@types/node-fetch": "^2.6.13", "@types/stream-buffers": "^3.0.3", "form-data": "^4.0.0", "hpagent": "^1.2.0", "isomorphic-ws": "^5.0.0", "js-yaml": "^4.1.0", "jsonpath-plus": "^10.3.0", "node-fetch": "^2.7.0", "openid-client": "^6.1.3", "rfc4648": "^1.3.0", "socks-proxy-agent": "^8.0.4", "stream-buffers": "^3.0.2", "tar-fs": "^3.0.9", "ws": "^8.18.2" } }, "sha512-Zge3YvF7DJi264dU1b3wb/GmzR99JhUpqTvp+VGHfwZT+g7EOOYNScDJNZwXy9cszyIGPIs0VHr+kk8e95qqrA=="],
|
||||
|
||||
"@oxfmt/binding-android-arm-eabi": ["@oxfmt/[email protected]", "", { "os": "android", "cpu": "arm" }, "sha512-pdsv0C4gPjJ8H1+sd8u0BDx+yLACTL+rgeMIOL1ln4ihSnhw8CWXtYWgvcSkyTfgGBIzFKab+d8rx9Xl4en/Kw=="],
|
||||
|
||||
"@oxfmt/binding-android-arm64": ["@oxfmt/[email protected]", "", { "os": "android", "cpu": "arm64" }, "sha512-WC3YQ7uS/KtDrjmqwBviwFKe9qeoi+eXx8aX1z/ffG23Md75myjrJaQqTuJvdOLPoa4EYTjDWH0dHXfwulCVog=="],
|
||||
|
||||
"@oxfmt/binding-darwin-arm64": ["@oxfmt/[email protected]", "", { "os": "darwin", "cpu": "arm64" }, "sha512-GM8Yf3LjjaR1I8PD0SfeoIlwhsh9GvSF+cQ8sf624Yxnjsyumn95aFzYfKJVefblfDIiOAnZ7QVm2sa21Er/0Q=="],
|
||||
|
||||
"@oxfmt/binding-darwin-x64": ["@oxfmt/[email protected]", "", { "os": "darwin", "cpu": "x64" }, "sha512-d5THp7F8bCxLqNogEXDORRsQD6dosf3EyFtnXfBer6v+8tGdcWIjoDX9WaXrrF/26zOmL8qHpPTKCEvpBDmZkQ=="],
|
||||
|
||||
"@oxfmt/binding-freebsd-x64": ["@oxfmt/[email protected]", "", { "os": "freebsd", "cpu": "x64" }, "sha512-1DnrtXGZooOZ0fHgAXZUaDQzBVh1CM2MNW4oBXyQ2aWKvCHjyljvT9fgBkOM0fEOb96X5eqtcfJ0YUVt9jj66g=="],
|
||||
|
||||
"@oxfmt/binding-linux-arm-gnueabihf": ["@oxfmt/[email protected]", "", { "os": "linux", "cpu": "arm" }, "sha512-4pQDHOYRH+Huqe0StIaWyvk2CVl/aTaqSrbZpA3/pLS2xH24ME7lBgYprhQF2fRkHBzhGGGKliwxFsDdHwx59g=="],
|
||||
|
||||
"@oxfmt/binding-linux-arm-musleabihf": ["@oxfmt/[email protected]", "", { "os": "linux", "cpu": "arm" }, "sha512-X0jAaZJFMCVKhB6YyWVTQ/wN2DLsBcZKSMqTS76bF6riT+XZdtg2FPEdjDvdVbunO9cG+tWiVaEs4Zs38lxYog=="],
|
||||
|
||||
"@oxfmt/binding-linux-arm64-gnu": ["@oxfmt/[email protected]", "", { "os": "linux", "cpu": "arm64" }, "sha512-682Z8T5s8T5ATArYtsejKvbIfd8LEAXyyDkKkoZVq8HND7Vx8TYLlrDjDSeYfodMeVwHOgkj13lJYR8cj6vUSg=="],
|
||||
|
||||
"@oxfmt/binding-linux-arm64-musl": ["@oxfmt/[email protected]", "", { "os": "linux", "cpu": "arm64" }, "sha512-lk25fAl7KWaLWVJcW0CHEXB7QlQZtx5eDkjpaGMK0hzXTjUe0Wmlu8IKuFHoviSOcEJedRTs4VE/506VqGxGew=="],
|
||||
|
||||
"@oxfmt/binding-linux-ppc64-gnu": ["@oxfmt/[email protected]", "", { "os": "linux", "cpu": "ppc64" }, "sha512-SFyNqHQLwySceWNLhiSldx7wPXRAzP0L0WcW9GegP3uWrpZGJiZlQO85NbHAFPEfxR9PhZ9qSnZryEh7+v+4Gw=="],
|
||||
|
||||
"@oxfmt/binding-linux-riscv64-gnu": ["@oxfmt/[email protected]", "", { "os": "linux", "cpu": "none" }, "sha512-KYj55C1ywJfHo6+aKDuEmUtVEdJALsC5GwayDGsI6FGz2GxFqNr/mA8nxVsNbJzm7sE5MRqTQ9ziImSzhYXysA=="],
|
||||
|
||||
"@oxfmt/binding-linux-riscv64-musl": ["@oxfmt/[email protected]", "", { "os": "linux", "cpu": "none" }, "sha512-BhZDNo5GOU5nC378RhD0/XpvaEBHsH3HLgJp8YZX3A0InC7oivzA63HsRmiXFLtLSHAstEVrDf6fbC7Rs8Jh/A=="],
|
||||
|
||||
"@oxfmt/binding-linux-s390x-gnu": ["@oxfmt/[email protected]", "", { "os": "linux", "cpu": "s390x" }, "sha512-UyAFmyHkgSgUJ/wOM4p3U8AC2yAFvRH5PNBs7TnK0fObTT/XSWcdr/lAzPSWaekHaZFaMeFZyk9n93Joq3J93A=="],
|
||||
|
||||
"@oxfmt/binding-linux-x64-gnu": ["@oxfmt/[email protected]", "", { "os": "linux", "cpu": "x64" }, "sha512-1iYMP0leytWazFubD/WnINJuIrzRPuoL1aWEJdlGezEzDbTxcd29R4r8IUzP2oWeKst5V02uMJgR2NILlPlG6w=="],
|
||||
|
||||
"@oxfmt/binding-linux-x64-musl": ["@oxfmt/[email protected]", "", { "os": "linux", "cpu": "x64" }, "sha512-4rA/URtJSTVNVAQz6Q8wf7SaRvOXVy+TizriT9hs/Y1XhLR/R+92uWKRQG8yFWRAIEBbFHJ6WevQcl/G9SXEfw=="],
|
||||
|
||||
"@oxfmt/binding-openharmony-arm64": ["@oxfmt/[email protected]", "", { "os": "none", "cpu": "arm64" }, "sha512-mSZuFHU2ar1KLUjXpI2QBQcJ1VsOB3mOCgQXuXCpKs19dgh4u+OaovNfrWDfiJb+ihJ2+f7YFcaO9bS2dlTCXA=="],
|
||||
|
||||
"@oxfmt/binding-win32-arm64-msvc": ["@oxfmt/[email protected]", "", { "os": "win32", "cpu": "arm64" }, "sha512-OfwuhkcjDlqC4EgDojtiV9mzpLqeB9KqTOWPOjLEYBVdDCVSxqW3qzp/xcIxsbtI0UgGCnKvAqYKyY25kf5JZw=="],
|
||||
|
||||
"@oxfmt/binding-win32-ia32-msvc": ["@oxfmt/[email protected]", "", { "os": "win32", "cpu": "ia32" }, "sha512-P9uDDNFRzghO3X8QAzhkjKhK7JvtABsVn8UYtFX7uor12IAnwNt8nNIctvfWj1JkQU/kE+fmLRPiw7XlrIHsZw=="],
|
||||
|
||||
"@oxfmt/binding-win32-x64-msvc": ["@oxfmt/[email protected]", "", { "os": "win32", "cpu": "x64" }, "sha512-dlI5SY7XYQCiCBafntWagCR6HcAJB/NpsLtdlPx8x08+Osz8Ok1HHz1GZuusegCe/VoJ6pAnF5a4pd5OZAq7qQ=="],
|
||||
|
||||
"@oxlint/binding-android-arm-eabi": ["@oxlint/[email protected]", "", { "os": "android", "cpu": "arm" }, "sha512-E06sKWS6PiI6HRxS1wyQg22HvApt01hI7fV+T3wUk3OSbaaP4a3hYGY/MIQDmASqCiRjBdpRQYkgMkqH82cWmQ=="],
|
||||
|
||||
"@oxlint/binding-android-arm64": ["@oxlint/[email protected]", "", { "os": "android", "cpu": "arm64" }, "sha512-NvsKz0KZxTp9cYWPLf+FXaSZwB3oO3peAjtukpOMBgse2vhQSoIIVqeO1yR0lEo/UcdZIDL18uq+kL0LzQ0ytA=="],
|
||||
|
||||
"@oxlint/binding-darwin-arm64": ["@oxlint/[email protected]", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bgjTn6nW4bQCFBvSvuHCpDD+sONvmpo4lGI4PxzMt1quBA+xYxhczk6RiCn3GZ9gY8uhaBbwhj9MdKGfu6T9DA=="],
|
||||
|
||||
"@oxlint/binding-darwin-x64": ["@oxlint/[email protected]", "", { "os": "darwin", "cpu": "x64" }, "sha512-aotaIttH1R6j1Rwhx0M0htgeZyGtVQqYNTVEYMN/UcgHPquGA6kmk9OyuDc3a2GKUQBC+3C3GVQCcrRPMYqAFA=="],
|
||||
|
||||
"@oxlint/binding-freebsd-x64": ["@oxlint/[email protected]", "", { "os": "freebsd", "cpu": "x64" }, "sha512-nNx/wta7ksRAdYvq+l4AWjXkLxEXHALhENxjj2cYbQAIR4ybaA5L+hCbE63HOmft5czQ6ks+hb8vmEAnn7YGPg=="],
|
||||
|
||||
"@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/[email protected]", "", { "os": "linux", "cpu": "arm" }, "sha512-tMLLjM7xXtzXisVCzkOTXNCy9bZVId2wteNwjohlFDR/jY6WagpEDA1c1wu4xRc20Hojaxj+V6DSR7gbKxijWA=="],
|
||||
|
||||
"@oxlint/binding-linux-arm-musleabihf": ["@oxlint/[email protected]", "", { "os": "linux", "cpu": "arm" }, "sha512-MiAFDFaqR0tmHTAyo0YDcZ5hyLREdYw/RQhc2R3cbT+8O3tB+zqPM2th9TTQ+Uo3jn/embS+DO+HyX9ztCPkOQ=="],
|
||||
|
||||
"@oxlint/binding-linux-arm64-gnu": ["@oxlint/[email protected]", "", { "os": "linux", "cpu": "arm64" }, "sha512-/xqQ3B16i1T4cyt/9Mn+4CpzhUXoBXp7kVpIwzOXNFLj5JmK1bIjsbSnX296Gg8A/o7oDtKWikFgBx0SLwztkw=="],
|
||||
|
||||
"@oxlint/binding-linux-arm64-musl": ["@oxlint/[email protected]", "", { "os": "linux", "cpu": "arm64" }, "sha512-LSbwuRKiNCenPDcbARqAZ5RfBy7gmj7vOvfJRLeCDU3gFtSxWbhv/+VTlaUqzUhNj1gFLHB8h7ALnxa/Az6z6g=="],
|
||||
|
||||
"@oxlint/binding-linux-ppc64-gnu": ["@oxlint/[email protected]", "", { "os": "linux", "cpu": "ppc64" }, "sha512-QWdcH31mXEUe5Nq1s0CfCpceaKjIo9uZtwDjAuL681g1axf+5x8xrg/eXWaw//4NCxYZ4V4e5Hu5tvdR+pTBlg=="],
|
||||
|
||||
"@oxlint/binding-linux-riscv64-gnu": ["@oxlint/[email protected]", "", { "os": "linux", "cpu": "none" }, "sha512-GnOfYgJxbcElOiPZaDFDl406ONddwvOWk2jvAAAEjwAl4GofNoHF+/HHUIBYa6bFCArlcGPi0XjC4cU1pkgF/Q=="],
|
||||
|
||||
"@oxlint/binding-linux-riscv64-musl": ["@oxlint/[email protected]", "", { "os": "linux", "cpu": "none" }, "sha512-AyEMTUCf0xY+hHF+IxqXFQIX0yQOIR8ykpY0lJNOw9xYqOzUX8dyZfRvlG0RfXwuQn2eonf/8NrMmDSZJjdqsA=="],
|
||||
|
||||
"@oxlint/binding-linux-s390x-gnu": ["@oxlint/[email protected]", "", { "os": "linux", "cpu": "s390x" }, "sha512-sPLzEcNvxd/oyVQ5oZo92CiHkFkpBeRop13E/P3TPY+hZfXHKCOWKI70TE2RYwMKFJDc20EMjH16L7NZICtKTw=="],
|
||||
|
||||
"@oxlint/binding-linux-x64-gnu": ["@oxlint/[email protected]", "", { "os": "linux", "cpu": "x64" }, "sha512-1Oh2ssH2L7lwyvkdSqaMUfsGfwU2Wfvew+obBUYjRVqhpBcUpwnsPSEr1IzVi9XqkuY10geiLsNKecqaZC34Dw=="],
|
||||
|
||||
"@oxlint/binding-linux-x64-musl": ["@oxlint/[email protected]", "", { "os": "linux", "cpu": "x64" }, "sha512-0j/2wRgNGO+Qj/M1uu/p57h/hFTTWWcfie0ufkbabeus2s5+/QqkCflnMOwLLN5m2GsNeWp4xdl4cPa4n7QCOQ=="],
|
||||
|
||||
"@oxlint/binding-openharmony-arm64": ["@oxlint/[email protected]", "", { "os": "none", "cpu": "arm64" }, "sha512-BJ/j54qS0usEnyDkLYURMj2iiD9h5Cyy+ppzeMSXBGRXaGRNWnj1Mw14NqWMR5E/PzdgB30OOCCzLzbRoduafw=="],
|
||||
|
||||
"@oxlint/binding-win32-arm64-msvc": ["@oxlint/[email protected]", "", { "os": "win32", "cpu": "arm64" }, "sha512-Yh8w+g2Lpx7StrvtYkoz9JJvXjB9wxgFChFNb85nrXm/wj/XTwGWS1hve9+900HL7llrntYB3YP+y32E3tRqzA=="],
|
||||
|
||||
"@oxlint/binding-win32-ia32-msvc": ["@oxlint/[email protected]", "", { "os": "win32", "cpu": "ia32" }, "sha512-zja5b7+6a7UsRFgAQSrnax5vrzliEyNPLCjfXONu/vTWswaIVZGFajJZptaeRvPE4LghtFdAzVFlexTm7MVTGA=="],
|
||||
|
||||
"@oxlint/binding-win32-x64-msvc": ["@oxlint/[email protected]", "", { "os": "win32", "cpu": "x64" }, "sha512-+teyvPDZ2RjUvo+SuCqS/UhaJl1QtdW5fWT5NJTV61V5MIuIS90Db9LixmtEGvXixyttiK62P96MSu3UlpviBw=="],
|
||||
|
||||
"@types/bun": ["@types/[email protected]", "", { "dependencies": { "bun-types": "1.3.14" } }, "sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw=="],
|
||||
|
||||
"@types/js-yaml": ["@types/[email protected]", "", {}, "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg=="],
|
||||
|
||||
"@types/json-schema": ["@types/[email protected]", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
|
||||
|
||||
"@types/lodash": ["@types/[email protected]", "", {}, "sha512-+K1NIO8I+F9/wNulfVvu23QYd0Pe9/OCqRrim4NoYIf1VoEDL90Ve4ClzpyqBLc7NpGGWRvYNCKZ1BE/Jpf8dQ=="],
|
||||
|
||||
"@types/node": ["@types/[email protected]", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q=="],
|
||||
|
||||
"@types/node-fetch": ["@types/[email protected]", "", { "dependencies": { "@types/node": "*", "form-data": "^4.0.4" } }, "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw=="],
|
||||
|
||||
"@types/stream-buffers": ["@types/[email protected]", "", { "dependencies": { "@types/node": "*" } }, "sha512-J+7VaHKNvlNPJPEJXX/fKa9DZtR/xPMwuIbe+yNOwp1YB+ApUOBv2aUpEoBJEi8nJgbgs1x8e73ttg0r1rSUdw=="],
|
||||
|
||||
"agent-base": ["[email protected]", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
|
||||
|
||||
"argparse": ["[email protected]", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
|
||||
|
||||
"asynckit": ["[email protected]", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="],
|
||||
|
||||
"b4a": ["[email protected]", "", { "peerDependencies": { "react-native-b4a": "*" }, "optionalPeers": ["react-native-b4a"] }, "sha512-aiqre1Nr0B/6DgE2N5vwTc+2/oQZ4Wh1t4NznYY4E00y8LCt6NqdRv81so00oo27D8MVKTpUa/MwUUtBLXCoDw=="],
|
||||
|
||||
"bare-events": ["[email protected]", "", { "peerDependencies": { "bare-abort-controller": "*" }, "optionalPeers": ["bare-abort-controller"] }, "sha512-Z0oHEHAFDZkffN8Qc39zNZjQlMDkPJRyyyZieU1VH7u8c5S+qHZ2S8ixdKIAxEjfHO7FJxXmJWgteOghVanIsg=="],
|
||||
|
||||
"bare-fs": ["[email protected]", "", { "dependencies": { "bare-events": "^2.5.4", "bare-path": "^3.0.0", "bare-stream": "^2.6.4", "bare-url": "^2.2.2", "fast-fifo": "^1.3.2" }, "peerDependencies": { "bare-buffer": "*" }, "optionalPeers": ["bare-buffer"] }, "sha512-fM+MhCvdQhZ7NV6S95a07gPSqjIYKn6mFaXfx266wN3ajZGl/+1AzH+ubkXQ0fFZvOe2nk9VHkzdYkQE5zMV3Q=="],
|
||||
|
||||
"bare-path": ["[email protected]", "", {}, "sha512-JprUlveX3QjApC1cTpsUOiscADftCGVWkzitbHsRqv84hzYwYHw2mbluddsq5TvI8mH/8Ov1f4BiMAdcB0oYnQ=="],
|
||||
|
||||
"bare-stream": ["[email protected]", "", { "dependencies": { "b4a": "^1.8.1", "streamx": "^2.25.0", "teex": "^1.0.1" }, "peerDependencies": { "bare-abort-controller": "*", "bare-buffer": "*", "bare-events": "*" }, "optionalPeers": ["bare-abort-controller", "bare-buffer", "bare-events"] }, "sha512-Kc+brLqvEqGkjyfiwJmImAOqLZL7OsoLKuavx+hJjgVV3nLTOjloJyPMFxjUPerGGHrNH0fLU06jjykMLWrERQ=="],
|
||||
|
||||
"bare-url": ["[email protected]", "", { "dependencies": { "bare-path": "^3.0.0" } }, "sha512-cD5ciQuKlx+eumTCfqbfiL+fhQm+dHbVNB/cX4+d+I/nx4JsVop9VoFEPAs5RJ6I84QR6bZIBjpd2kjDOYeWcg=="],
|
||||
|
||||
"bun-types": ["[email protected]", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="],
|
||||
|
||||
"call-bind-apply-helpers": ["[email protected]", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
|
||||
|
||||
"citty": ["[email protected]", "", {}, "sha512-+6vJA3L98yv+IdfKGZHBNiGW5KHn22e/JwID0Strsz8h4S/csAu/OuICwxrg44k5MRiZHWIo8XXuJgQTriRP4w=="],
|
||||
|
||||
"combined-stream": ["[email protected]", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="],
|
||||
|
||||
"debug": ["[email protected]", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||
|
||||
"delayed-stream": ["[email protected]", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="],
|
||||
|
||||
"dunder-proto": ["[email protected]", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
||||
|
||||
"end-of-stream": ["[email protected]", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="],
|
||||
|
||||
"es-define-property": ["[email protected]", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
|
||||
|
||||
"es-errors": ["[email protected]", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
|
||||
|
||||
"es-object-atoms": ["[email protected]", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw=="],
|
||||
|
||||
"es-set-tostringtag": ["[email protected]", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
|
||||
|
||||
"events-universal": ["[email protected]", "", { "dependencies": { "bare-events": "^2.7.0" } }, "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw=="],
|
||||
|
||||
"fast-fifo": ["[email protected]", "", {}, "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ=="],
|
||||
|
||||
"fdir": ["[email protected]", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
||||
|
||||
"form-data": ["[email protected]", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.4", "mime-types": "^2.1.35" } }, "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ=="],
|
||||
|
||||
"function-bind": ["[email protected]", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
|
||||
|
||||
"get-intrinsic": ["[email protected]", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
|
||||
|
||||
"get-proto": ["[email protected]", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
|
||||
|
||||
"gopd": ["[email protected]", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
|
||||
|
||||
"has-symbols": ["[email protected]", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
|
||||
|
||||
"has-tostringtag": ["[email protected]", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="],
|
||||
|
||||
"hasown": ["[email protected]", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="],
|
||||
|
||||
"hpagent": ["[email protected]", "", {}, "sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA=="],
|
||||
|
||||
"ip-address": ["[email protected]", "", {}, "sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ=="],
|
||||
|
||||
"is-extglob": ["[email protected]", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
|
||||
|
||||
"is-glob": ["[email protected]", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
|
||||
|
||||
"isomorphic-ws": ["[email protected]", "", { "peerDependencies": { "ws": "*" } }, "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw=="],
|
||||
|
||||
"jose": ["[email protected]", "", {}, "sha512-Bsdjwm3Qsd/P0jR+BHDe3LytDfY7WBq2HmCCLIwuVRHMuEC9ae7/R474GIUdF1NgCyZjzVo/A9DOiOBtXq8ZoQ=="],
|
||||
|
||||
"js-yaml": ["[email protected]", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ=="],
|
||||
|
||||
"jsep": ["[email protected]", "", {}, "sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw=="],
|
||||
|
||||
"json-schema-to-typescript": ["[email protected]", "", { "dependencies": { "@apidevtools/json-schema-ref-parser": "^11.5.5", "@types/json-schema": "^7.0.15", "@types/lodash": "^4.17.7", "is-glob": "^4.0.3", "js-yaml": "^4.1.0", "lodash": "^4.17.21", "minimist": "^1.2.8", "prettier": "^3.2.5", "tinyglobby": "^0.2.9" }, "bin": { "json2ts": "dist/src/cli.js" } }, "sha512-Su9oK8DR4xCmDsLlyvadkXzX6+GGXJpbhwoLtOGArAG61dvbW4YQmSEno2y66ahpIdmLMg6YUf/QHLgiwvkrHQ=="],
|
||||
|
||||
"jsonpath-plus": ["[email protected]", "", { "dependencies": { "@jsep-plugin/assignment": "^1.3.0", "@jsep-plugin/regex": "^1.0.4", "jsep": "^1.4.0" }, "bin": { "jsonpath": "bin/jsonpath-cli.js", "jsonpath-plus": "bin/jsonpath-cli.js" } }, "sha512-T92WWatJXmhBbKsgH/0hl+jxjdXrifi5IKeMY02DWggRxX0UElcbVzPlmgLTbvsPeW1PasQ6xE2Q75stkhGbsA=="],
|
||||
|
||||
"lodash": ["[email protected]", "", {}, "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q=="],
|
||||
|
||||
"math-intrinsics": ["[email protected]", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
|
||||
|
||||
"mime-db": ["[email protected]", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
|
||||
|
||||
"mime-types": ["[email protected]", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
|
||||
|
||||
"minimist": ["[email protected]", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
|
||||
|
||||
"ms": ["[email protected]", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||
|
||||
"node-fetch": ["[email protected]", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
|
||||
|
||||
"oauth4webapi": ["[email protected]", "", {}, "sha512-iwemM91xz8nryHti2yTmg5fhyEMVOkOXwHNqbvcATjyajb5oQxCQzrNOA6uElRHuMhQQTKUyFKV9y/CNyg25BQ=="],
|
||||
|
||||
"once": ["[email protected]", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
|
||||
|
||||
"openid-client": ["[email protected]", "", { "dependencies": { "jose": "^6.2.2", "oauth4webapi": "^3.8.5" } }, "sha512-QSw0BA08piujetEwfZsHoTrDpMEha7GDZDicQqVwX4u0ChCjefvjDB++TZ8BTg76UpwhzIQgdvvfgfl3HpCSAw=="],
|
||||
|
||||
"oxfmt": ["[email protected]", "", { "dependencies": { "tinypool": "2.1.0" }, "optionalDependencies": { "@oxfmt/binding-android-arm-eabi": "0.62.0", "@oxfmt/binding-android-arm64": "0.62.0", "@oxfmt/binding-darwin-arm64": "0.62.0", "@oxfmt/binding-darwin-x64": "0.62.0", "@oxfmt/binding-freebsd-x64": "0.62.0", "@oxfmt/binding-linux-arm-gnueabihf": "0.62.0", "@oxfmt/binding-linux-arm-musleabihf": "0.62.0", "@oxfmt/binding-linux-arm64-gnu": "0.62.0", "@oxfmt/binding-linux-arm64-musl": "0.62.0", "@oxfmt/binding-linux-ppc64-gnu": "0.62.0", "@oxfmt/binding-linux-riscv64-gnu": "0.62.0", "@oxfmt/binding-linux-riscv64-musl": "0.62.0", "@oxfmt/binding-linux-s390x-gnu": "0.62.0", "@oxfmt/binding-linux-x64-gnu": "0.62.0", "@oxfmt/binding-linux-x64-musl": "0.62.0", "@oxfmt/binding-openharmony-arm64": "0.62.0", "@oxfmt/binding-win32-arm64-msvc": "0.62.0", "@oxfmt/binding-win32-ia32-msvc": "0.62.0", "@oxfmt/binding-win32-x64-msvc": "0.62.0" }, "peerDependencies": { "svelte": "^5.0.0", "vite-plus": "*" }, "optionalPeers": ["svelte", "vite-plus"], "bin": { "oxfmt": "bin/oxfmt" } }, "sha512-vxgGHTmnDU9j4CX7dDBLzxgmHxfda/yPcgJkGCMUSCwRmz+euo/V08xXLNgXTeqAB9Fhf3Pe2nO1RNKLCVgphQ=="],
|
||||
|
||||
"oxlint": ["[email protected]", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.77.0", "@oxlint/binding-android-arm64": "1.77.0", "@oxlint/binding-darwin-arm64": "1.77.0", "@oxlint/binding-darwin-x64": "1.77.0", "@oxlint/binding-freebsd-x64": "1.77.0", "@oxlint/binding-linux-arm-gnueabihf": "1.77.0", "@oxlint/binding-linux-arm-musleabihf": "1.77.0", "@oxlint/binding-linux-arm64-gnu": "1.77.0", "@oxlint/binding-linux-arm64-musl": "1.77.0", "@oxlint/binding-linux-ppc64-gnu": "1.77.0", "@oxlint/binding-linux-riscv64-gnu": "1.77.0", "@oxlint/binding-linux-riscv64-musl": "1.77.0", "@oxlint/binding-linux-s390x-gnu": "1.77.0", "@oxlint/binding-linux-x64-gnu": "1.77.0", "@oxlint/binding-linux-x64-musl": "1.77.0", "@oxlint/binding-openharmony-arm64": "1.77.0", "@oxlint/binding-win32-arm64-msvc": "1.77.0", "@oxlint/binding-win32-ia32-msvc": "1.77.0", "@oxlint/binding-win32-x64-msvc": "1.77.0" }, "peerDependencies": { "oxlint-tsgolint": ">=7.0.2001", "vite-plus": "*" }, "optionalPeers": ["oxlint-tsgolint", "vite-plus"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-qnGh8XJHaQ0dprrDXNQZgS0FgjI6v+V3+X8DwmaV++5Aamy6jGKfDdQ1TUvhUxtmKFAbEf4/WeO5QZX+5WSngg=="],
|
||||
|
||||
"picomatch": ["[email protected]", "", {}, "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A=="],
|
||||
|
||||
"prettier": ["[email protected]", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g=="],
|
||||
|
||||
"pump": ["[email protected]", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA=="],
|
||||
|
||||
"rfc4648": ["[email protected]", "", {}, "sha512-rRg/6Lb+IGfJqO05HZkN50UtY7K/JhxJag1kP23+zyMfrvoB0B7RWv06MbOzoc79RgCdNTiUaNsTT1AJZ7Z+cg=="],
|
||||
|
||||
"smart-buffer": ["[email protected]", "", {}, "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="],
|
||||
|
||||
"socks": ["[email protected]", "", { "dependencies": { "ip-address": "^10.1.1", "smart-buffer": "^4.2.0" } }, "sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw=="],
|
||||
|
||||
"socks-proxy-agent": ["[email protected]", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" } }, "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw=="],
|
||||
|
||||
"stream-buffers": ["[email protected]", "", {}, "sha512-pqMqwQCso0PBJt2PQmDO0cFj0lyqmiwOMiMSkVtRokl7e+ZTRYgDHKnuZNbqjiJXgsg4nuqtD/zxuo9KqTp0Yw=="],
|
||||
|
||||
"streamx": ["[email protected]", "", { "dependencies": { "events-universal": "^1.0.0", "fast-fifo": "^1.3.2", "text-decoder": "^1.1.0" } }, "sha512-1Yowhzjf0ivGMrTIkY9hav5TxobO9qIVqUE41fiCGMGgc3CLlf4MY+9AHmZqBWgDTue0fY9zWjYFVyf6Diuobw=="],
|
||||
|
||||
"tar-fs": ["[email protected]", "", { "dependencies": { "pump": "^3.0.0", "tar-stream": "^3.1.5" }, "optionalDependencies": { "bare-fs": "^4.0.1", "bare-path": "^3.0.0" } }, "sha512-/hU4AXnIdZu+Gvl1pk0oI5f5HxWsCJRtY2aFaJdk9VvyL48DWU6iU5WAIPG+wIi1YvWA6eTJvIviP/tMAZZNwQ=="],
|
||||
|
||||
"tar-stream": ["[email protected]", "", { "dependencies": { "b4a": "^1.6.4", "bare-fs": "^4.5.5", "fast-fifo": "^1.2.0", "streamx": "^2.15.0" } }, "sha512-ojzvCvVaNp6aOTFmG7jaRD0meowIAuPc3cMMhSgKiVWws1GyHbGd/xvnyuRKcKlMpt3qvxx6r0hreCNITP9hIg=="],
|
||||
|
||||
"teex": ["[email protected]", "", { "dependencies": { "streamx": "^2.12.5" } }, "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg=="],
|
||||
|
||||
"text-decoder": ["[email protected]", "", { "dependencies": { "b4a": "^1.6.4" } }, "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ=="],
|
||||
|
||||
"tinyglobby": ["[email protected]", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g=="],
|
||||
|
||||
"tinypool": ["[email protected]", "", {}, "sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw=="],
|
||||
|
||||
"tr46": ["[email protected]", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="],
|
||||
|
||||
"typescript": ["[email protected]", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||
|
||||
"undici-types": ["[email protected]", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
|
||||
|
||||
"webidl-conversions": ["[email protected]", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="],
|
||||
|
||||
"whatwg-url": ["[email protected]", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="],
|
||||
|
||||
"wrappy": ["[email protected]", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
|
||||
|
||||
"ws": ["[email protected]", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw=="],
|
||||
|
||||
"zod": ["[email protected]", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="],
|
||||
|
||||
"@types/node-fetch/@types/node": ["@types/[email protected]", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg=="],
|
||||
|
||||
"@types/stream-buffers/@types/node": ["@types/[email protected]", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg=="],
|
||||
|
||||
"bun-types/@types/node": ["@types/[email protected]", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg=="],
|
||||
|
||||
"@types/node-fetch/@types/node/undici-types": ["[email protected]", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="],
|
||||
|
||||
"@types/stream-buffers/@types/node/undici-types": ["[email protected]", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="],
|
||||
|
||||
"bun-types/@types/node/undici-types": ["[email protected]", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="],
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import { defineCommand } from "citty";
|
||||
import { listDeployments } from "../lib/shared";
|
||||
import { toTable } from "../lib/format";
|
||||
|
||||
export const ps = defineCommand({
|
||||
meta: {
|
||||
name: "ps",
|
||||
description: "List deployments",
|
||||
},
|
||||
args: {
|
||||
all: {
|
||||
type: "boolean",
|
||||
alias: "a",
|
||||
description:
|
||||
"Show all stopped deployments (including those created by the run command)",
|
||||
},
|
||||
},
|
||||
async run({ args: { all } }) {
|
||||
console.log(
|
||||
toTable(
|
||||
(await listDeployments())
|
||||
.filter((d) => all || d.status?.replicas)
|
||||
.map((d) => ({
|
||||
name: d.metadata?.name,
|
||||
status: `${d.status?.availableReplicas}/${d.status?.replicas}`,
|
||||
})),
|
||||
),
|
||||
);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,26 @@
|
||||
import { defineCommand } from "citty";
|
||||
import { ctx } from "../lib/context";
|
||||
import { serviceToDeployment } from "../lib/convert";
|
||||
|
||||
export const up = defineCommand({
|
||||
meta: {
|
||||
name: "up",
|
||||
description: "Create and start deployments",
|
||||
},
|
||||
args: {
|
||||
build: {
|
||||
type: "boolean",
|
||||
default: true,
|
||||
alias: "b",
|
||||
description: "Build images before starting deployments",
|
||||
negativeDescription: "Don't build an image, even if it's policy",
|
||||
},
|
||||
},
|
||||
async run() {
|
||||
const { project, compose } = ctx();
|
||||
const cmp = await compose();
|
||||
console.dir(serviceToDeployment(project, "app", cmp.services!.app!), {
|
||||
depth: 999,
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,4 @@
|
||||
export const IMAGE_REGISTRY = "registry.neko-piranha.ts.net";
|
||||
export const LABELS = {
|
||||
"app.kubernetes.io/managed-by": "kuber",
|
||||
};
|
||||
Executable
+48
@@ -0,0 +1,48 @@
|
||||
version: "3.9"
|
||||
|
||||
services:
|
||||
app:
|
||||
image: registry.neko-piranha.ts.net/astral/buzz:frontend
|
||||
deploy:
|
||||
replicas: 2
|
||||
resources:
|
||||
limits:
|
||||
cpus: "1.0"
|
||||
memory: 1024M
|
||||
labels:
|
||||
- "swarm.autoscale=true"
|
||||
restart_policy:
|
||||
condition: any
|
||||
stop_grace_period: 1s
|
||||
healthcheck:
|
||||
test: ["CMD", "bun", "-e", "fetch('http://localhost:3000/')"]
|
||||
interval: 60s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 5s
|
||||
ports:
|
||||
- "8604:3000"
|
||||
networks:
|
||||
- buzz
|
||||
|
||||
backend:
|
||||
image: registry.neko-piranha.ts.net/astral/buzz:backend
|
||||
environment:
|
||||
NO_AUTH_CHECK: "true"
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: "1.0"
|
||||
memory: 512M
|
||||
restart_policy:
|
||||
condition: any
|
||||
update_config:
|
||||
monitor: 5s
|
||||
failure_action: rollback
|
||||
stop_grace_period: 1s
|
||||
networks:
|
||||
- buzz
|
||||
|
||||
networks:
|
||||
buzz:
|
||||
driver: overlay
|
||||
@@ -0,0 +1,19 @@
|
||||
import { defineCommand, runMain } from "citty";
|
||||
import { ps } from "./command/ps";
|
||||
import { up } from "./command/up";
|
||||
import { provideContext } from "./lib/context";
|
||||
import z, { ZodError } from "zod";
|
||||
|
||||
const main = defineCommand({
|
||||
meta: {
|
||||
name: "kuber",
|
||||
version: "1.0.0",
|
||||
description: "Docker Compose -> K8s translation layer",
|
||||
},
|
||||
subCommands: { ps, up },
|
||||
});
|
||||
|
||||
provideContext(() => runMain(main)).catch((e) => {
|
||||
if (e instanceof ZodError) console.error(z.prettifyError(e));
|
||||
else console.error(e);
|
||||
});
|
||||
@@ -0,0 +1,50 @@
|
||||
import { AsyncLocalStorage } from "node:async_hooks";
|
||||
import type { ComposeSpecification } from "../schema/docker.d";
|
||||
import { getProject, throwWhen } from "./shared";
|
||||
import { readCompose, resolveComposeFile } from "./yaml";
|
||||
|
||||
type AppContext = {
|
||||
project: string;
|
||||
cwd: string;
|
||||
path(): Promise<string | undefined>;
|
||||
compose(): Promise<ComposeSpecification>;
|
||||
};
|
||||
|
||||
const appContext = new AsyncLocalStorage<AppContext>();
|
||||
|
||||
export function provideContext<T>(fn: () => T): T {
|
||||
const cwd = process.cwd();
|
||||
const path = createCachedGetter("composeFile", () => resolveComposeFile(cwd));
|
||||
return appContext.run(
|
||||
{
|
||||
project: getProject(),
|
||||
cwd,
|
||||
path,
|
||||
compose: createCachedGetter("compose", () =>
|
||||
path()
|
||||
.then(throwWhen((path): path is undefined => path === undefined))
|
||||
.then(readCompose),
|
||||
),
|
||||
},
|
||||
fn,
|
||||
);
|
||||
}
|
||||
|
||||
export function ctx() {
|
||||
const store = appContext.getStore();
|
||||
if (!store) throw new Error("Not in context!");
|
||||
return store;
|
||||
}
|
||||
|
||||
const cache: Record<string, unknown> = {};
|
||||
export function createCachedGetter<T>(
|
||||
key: string,
|
||||
fn: () => Promise<T>,
|
||||
): () => Promise<T> {
|
||||
return async () => {
|
||||
if (key in cache) return cache[key] as T;
|
||||
const result = await fn();
|
||||
cache[key] = result;
|
||||
return result;
|
||||
};
|
||||
}
|
||||
+342
@@ -0,0 +1,342 @@
|
||||
import type {
|
||||
V1Container,
|
||||
V1ContainerPort,
|
||||
V1Deployment,
|
||||
V1Volume,
|
||||
V1VolumeMount,
|
||||
} from "@kubernetes/client-node";
|
||||
import type { Service } from "../schema/docker.d";
|
||||
import { toEnvVars } from "./format";
|
||||
import { IMAGE_REGISTRY, LABELS } from "../const";
|
||||
import { deepMerge } from "./shared";
|
||||
|
||||
type NormalizedMount = {
|
||||
name: string;
|
||||
kind: "bind" | "volume" | "tmpfs";
|
||||
target: string;
|
||||
source?: string;
|
||||
readOnly?: boolean;
|
||||
subPath?: string;
|
||||
sizeLimit?: string;
|
||||
};
|
||||
|
||||
type ServiceVolume = NonNullable<Service["volumes"]>[number];
|
||||
|
||||
function toPortNumber(value: number | string | undefined): number | undefined {
|
||||
if (typeof value === "number") return value;
|
||||
if (!value || value.includes("-")) return;
|
||||
|
||||
const port = Number(value);
|
||||
return Number.isInteger(port) ? port : undefined;
|
||||
}
|
||||
|
||||
function toProtocol(value: string | undefined): "TCP" | "UDP" {
|
||||
return value?.toUpperCase() === "UDP" ? "UDP" : "TCP";
|
||||
}
|
||||
|
||||
function toBoolean(value: boolean | string | undefined): boolean | undefined {
|
||||
if (typeof value === "boolean") return value;
|
||||
if (!value) return;
|
||||
|
||||
switch (value.toLowerCase()) {
|
||||
case "1":
|
||||
case "true":
|
||||
case "yes":
|
||||
case "on":
|
||||
case "ro":
|
||||
return true;
|
||||
case "0":
|
||||
case "false":
|
||||
case "no":
|
||||
case "off":
|
||||
case "rw":
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function toKubeName(value: string): string {
|
||||
return value
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9-]+/g, "-")
|
||||
.replace(/^-+|-+$/g, "")
|
||||
.slice(0, 63);
|
||||
}
|
||||
|
||||
function toBindVolumeName(source: string): string {
|
||||
return toKubeName(`bind-${Bun.hash(source).toString(36)}`);
|
||||
}
|
||||
|
||||
function isBindSource(source: string): boolean {
|
||||
return (
|
||||
source.startsWith(".") ||
|
||||
source.startsWith("/") ||
|
||||
source.startsWith("~") ||
|
||||
source.includes("/")
|
||||
);
|
||||
}
|
||||
|
||||
function parseStringMount(
|
||||
entry: string,
|
||||
index: number,
|
||||
): NormalizedMount | undefined {
|
||||
const parts = entry.split(":");
|
||||
|
||||
if (parts.length === 1) {
|
||||
return {
|
||||
name: `volume-${index}`,
|
||||
kind: "volume",
|
||||
target: entry,
|
||||
};
|
||||
}
|
||||
|
||||
const maybeMode = parts.at(-1);
|
||||
const hasMode = maybeMode === "ro" || maybeMode === "rw";
|
||||
const target = parts.at(hasMode ? -2 : -1);
|
||||
const source = parts.slice(0, hasMode ? -2 : -1).join(":");
|
||||
|
||||
if (!target) return;
|
||||
|
||||
return {
|
||||
name:
|
||||
source && isBindSource(source)
|
||||
? toBindVolumeName(source)
|
||||
: `volume-${index}`,
|
||||
kind: source && isBindSource(source) ? "bind" : "volume",
|
||||
source: source || undefined,
|
||||
target,
|
||||
readOnly: hasMode ? maybeMode === "ro" : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
function toMount(
|
||||
entry: ServiceVolume,
|
||||
index: number,
|
||||
): NormalizedMount | undefined {
|
||||
if (typeof entry === "string") return parseStringMount(entry, index);
|
||||
|
||||
if (!entry.target) return;
|
||||
if (
|
||||
entry.type !== "bind" &&
|
||||
entry.type !== "volume" &&
|
||||
entry.type !== "tmpfs"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
name: entry.source
|
||||
? entry.type === "bind"
|
||||
? toBindVolumeName(entry.source)
|
||||
: `${entry.type}-${toKubeName(entry.source) || index}`
|
||||
: `${entry.type}-${index}`,
|
||||
kind: entry.type,
|
||||
source: entry.source,
|
||||
target: entry.target,
|
||||
readOnly: toBoolean(entry.read_only),
|
||||
subPath: entry.volume?.subpath,
|
||||
sizeLimit:
|
||||
entry.type === "tmpfs" && entry.tmpfs?.size !== undefined
|
||||
? String(entry.tmpfs.size)
|
||||
: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
function toMounts(service: Service): NormalizedMount[] {
|
||||
const mounts =
|
||||
service.volumes?.flatMap((entry, index) => {
|
||||
const mount = toMount(entry, index);
|
||||
return mount ? [mount] : [];
|
||||
}) ?? [];
|
||||
|
||||
const tmpfs = (Array.isArray(service.tmpfs) ? service.tmpfs : [service.tmpfs])
|
||||
.filter((entry): entry is string => Boolean(entry))
|
||||
.map<NormalizedMount>((target, index) => ({
|
||||
name: `tmpfs-${mounts.length + index}`,
|
||||
kind: "tmpfs",
|
||||
target,
|
||||
}));
|
||||
|
||||
return [...mounts, ...tmpfs];
|
||||
}
|
||||
|
||||
function toVolumeMounts(
|
||||
mounts: NormalizedMount[],
|
||||
): V1VolumeMount[] | undefined {
|
||||
if (mounts.length === 0) return;
|
||||
|
||||
return mounts.map((mount) => ({
|
||||
name: mount.name,
|
||||
mountPath: mount.target,
|
||||
readOnly: mount.readOnly,
|
||||
subPath: mount.subPath,
|
||||
}));
|
||||
}
|
||||
|
||||
function toVolumes(
|
||||
project: string,
|
||||
mounts: NormalizedMount[],
|
||||
): V1Volume[] | undefined {
|
||||
if (mounts.length === 0) return;
|
||||
|
||||
return mounts.map((mount) => {
|
||||
if (mount.kind === "bind") {
|
||||
if (!mount.source) {
|
||||
return {
|
||||
name: mount.name,
|
||||
emptyDir: {},
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
name: mount.name,
|
||||
persistentVolumeClaim: {
|
||||
claimName: mount.name,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (mount.kind === "tmpfs") {
|
||||
return {
|
||||
name: mount.name,
|
||||
emptyDir: {
|
||||
medium: "Memory",
|
||||
sizeLimit: mount.sizeLimit,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (!mount.source) {
|
||||
return {
|
||||
name: mount.name,
|
||||
emptyDir: {},
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
name: mount.name,
|
||||
persistentVolumeClaim: {
|
||||
claimName: toKubeName(`${project}-${mount.source}`),
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function toContainerPorts(service: Service): V1Container["ports"] {
|
||||
return service.ports?.flatMap<V1ContainerPort>((entry, index) => {
|
||||
if (typeof entry === "number") {
|
||||
return [
|
||||
{
|
||||
name: `port-${index}`,
|
||||
containerPort: entry,
|
||||
protocol: "TCP" as const,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
if (typeof entry === "string") {
|
||||
const [portSpec, protocolSpec] = entry.split("/");
|
||||
if (!portSpec) return [];
|
||||
|
||||
const segments = portSpec.split(":");
|
||||
const target = toPortNumber(segments.at(-1));
|
||||
const published = toPortNumber(segments.at(-2));
|
||||
if (!target) return [];
|
||||
|
||||
return [
|
||||
{
|
||||
name: `port-${index}`,
|
||||
containerPort: target,
|
||||
hostPort: published,
|
||||
protocol: toProtocol(protocolSpec),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
const target = toPortNumber(entry.target);
|
||||
if (!target) return [];
|
||||
|
||||
return [
|
||||
{
|
||||
name: entry.name ?? `port-${index}`,
|
||||
containerPort: target,
|
||||
hostPort: toPortNumber(entry.published),
|
||||
protocol: toProtocol(entry.protocol),
|
||||
},
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
export function serviceToDeployment(
|
||||
project: string,
|
||||
name: string,
|
||||
service: Service,
|
||||
): V1Deployment {
|
||||
const mounts = toMounts(service);
|
||||
|
||||
return deepMerge(
|
||||
{
|
||||
apiVersion: "apps/v1",
|
||||
kind: "Deployment",
|
||||
metadata: {
|
||||
name,
|
||||
namespace: project,
|
||||
labels: LABELS,
|
||||
},
|
||||
spec: {
|
||||
strategy: {
|
||||
rollingUpdate: {
|
||||
maxSurge: "25%",
|
||||
maxUnavailable: "25%",
|
||||
},
|
||||
},
|
||||
selector: {
|
||||
matchLabels: { app: name },
|
||||
},
|
||||
template: {
|
||||
metadata: {
|
||||
labels: {
|
||||
app: name,
|
||||
},
|
||||
},
|
||||
spec: {
|
||||
restartPolicy: "Always",
|
||||
volumes: toVolumes(project, mounts),
|
||||
containers: [
|
||||
deepMerge(
|
||||
{
|
||||
name,
|
||||
imagePullPolicy: "Always",
|
||||
env: toEnvVars(service.environment),
|
||||
image: `${IMAGE_REGISTRY}/kuber/${project}-${name}:latest`,
|
||||
command:
|
||||
service.command instanceof Array
|
||||
? service.command
|
||||
: service.command
|
||||
? service.command.split(" ")
|
||||
: undefined,
|
||||
envFrom: service.env_file
|
||||
? [{ secretRef: { name: `${name}-env` } }]
|
||||
: undefined,
|
||||
ports: toContainerPorts(service),
|
||||
volumeMounts: toVolumeMounts(mounts),
|
||||
} satisfies V1Container,
|
||||
service["x-container"] ?? {},
|
||||
),
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
} satisfies V1Deployment,
|
||||
service["x-deployment"] ?? {},
|
||||
);
|
||||
}
|
||||
|
||||
export function serviceToSvc() {}
|
||||
|
||||
// todo
|
||||
// volumesToPvc
|
||||
// envFromToSecrets
|
||||
// composeToNamespace
|
||||
// serviceToSvc
|
||||
// serviceToIngress
|
||||
// composeToKubernetes (final function)
|
||||
@@ -0,0 +1,34 @@
|
||||
import { Table } from "@cliffy/table";
|
||||
import type { V1EnvVar } from "@kubernetes/client-node";
|
||||
import type { Service } from "../schema/docker.d";
|
||||
|
||||
function toTable(args: Record<string, string | number | undefined>[]): string {
|
||||
return new Table(
|
||||
Object.keys(args[0] ?? {}).map((e) => e.toUpperCase()),
|
||||
...args.map((e) => Object.values(e)),
|
||||
).toString();
|
||||
}
|
||||
|
||||
function toEnvVars(
|
||||
environment: Service["environment"],
|
||||
): V1EnvVar[] | undefined {
|
||||
if (!environment) return;
|
||||
|
||||
if (Array.isArray(environment)) {
|
||||
return environment.map((entry) => {
|
||||
const separator = entry.indexOf("=");
|
||||
const name = separator === -1 ? entry : entry.slice(0, separator);
|
||||
return {
|
||||
name,
|
||||
value: separator === -1 ? undefined : entry.slice(separator + 1),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
return Object.entries(environment).map(([name, value]) => ({
|
||||
name,
|
||||
value: value === null ? undefined : String(value),
|
||||
}));
|
||||
}
|
||||
|
||||
export { toEnvVars, toTable };
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
import { AppsV1Api, CoreV1Api, KubeConfig } from "@kubernetes/client-node";
|
||||
import { ResponseContext } from "@kubernetes/client-node/dist/gen/http/http.js";
|
||||
import { from } from "@kubernetes/client-node/dist/gen/rxjsStub.js";
|
||||
import http from "node:http";
|
||||
import https from "node:https";
|
||||
|
||||
const kc = new KubeConfig();
|
||||
kc.loadFromDefault();
|
||||
|
||||
const bunHttpLibrary = {
|
||||
send(request: {
|
||||
getUrl(): string;
|
||||
getHttpMethod(): { toString(): string };
|
||||
getBody(): unknown;
|
||||
getHeaders(): Record<string, string>;
|
||||
getSignal(): AbortSignal | undefined;
|
||||
getAgent(): http.Agent | https.Agent | undefined;
|
||||
}) {
|
||||
const result = new Promise<ResponseContext>((resolve, reject) => {
|
||||
const url = new URL(request.getUrl());
|
||||
const transport = url.protocol === "http:" ? http : https;
|
||||
const req = transport.request(
|
||||
url,
|
||||
{
|
||||
method: request.getHttpMethod().toString(),
|
||||
headers: request.getHeaders(),
|
||||
agent: request.getAgent(),
|
||||
},
|
||||
(response) => {
|
||||
const chunks: Buffer[] = [];
|
||||
|
||||
response.on("data", (chunk) => {
|
||||
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
||||
});
|
||||
|
||||
response.on("end", () => {
|
||||
const buffer = Buffer.concat(chunks);
|
||||
const headers: Record<string, string> = {};
|
||||
|
||||
for (const [key, value] of Object.entries(response.headers)) {
|
||||
if (Array.isArray(value)) headers[key] = value.join(", ");
|
||||
else if (value !== undefined) headers[key] = String(value);
|
||||
}
|
||||
|
||||
resolve(
|
||||
new ResponseContext(response.statusCode ?? 0, headers, {
|
||||
text: async () => buffer.toString("utf8"),
|
||||
binary: async () => buffer,
|
||||
}),
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
request.getSignal()?.addEventListener("abort", () => {
|
||||
req.destroy(new Error("Request aborted"));
|
||||
});
|
||||
|
||||
req.on("error", reject);
|
||||
|
||||
const body = request.getBody();
|
||||
if (body !== undefined && body !== null) req.write(body as string | Uint8Array);
|
||||
req.end();
|
||||
});
|
||||
|
||||
return from(result);
|
||||
},
|
||||
};
|
||||
|
||||
const makeApiClient = kc.makeApiClient.bind(kc);
|
||||
kc.makeApiClient = ((apiClientType) => {
|
||||
const client = makeApiClient(apiClientType) as unknown as {
|
||||
api: { configuration: { httpApi: typeof bunHttpLibrary } };
|
||||
};
|
||||
client.api.configuration.httpApi = bunHttpLibrary;
|
||||
return client;
|
||||
}) as typeof kc.makeApiClient;
|
||||
|
||||
export const core = kc.makeApiClient(CoreV1Api);
|
||||
export const apps = kc.makeApiClient(AppsV1Api);
|
||||
@@ -0,0 +1,60 @@
|
||||
import { basename } from "node:path";
|
||||
import { apps } from "./k8s";
|
||||
import { feature } from "bun:bundle";
|
||||
|
||||
export function getProject() {
|
||||
if (!feature("prod")) return "kube-system";
|
||||
const cwd = process.cwd();
|
||||
return basename(cwd);
|
||||
}
|
||||
|
||||
export async function listDeployments() {
|
||||
const { items } = await apps.listNamespacedDeployment({
|
||||
namespace: getProject(),
|
||||
});
|
||||
return items;
|
||||
}
|
||||
|
||||
export function throwWhen<T, Narrowed extends T>(
|
||||
condition: (arg: T) => arg is Narrowed,
|
||||
): (arg: T) => Exclude<T, Narrowed>;
|
||||
export function throwWhen<T>(condition: (arg: T) => unknown): (arg: T) => T;
|
||||
export function throwWhen<T>(condition: (arg: T) => unknown) {
|
||||
return (arg: T) => {
|
||||
if (condition(arg)) throw new Error("Condition matched");
|
||||
return arg;
|
||||
};
|
||||
}
|
||||
|
||||
export function deepMerge(target: any, source: any): any {
|
||||
if (
|
||||
typeof target !== "object" ||
|
||||
target === null ||
|
||||
typeof source !== "object" ||
|
||||
source === null
|
||||
) {
|
||||
return source;
|
||||
}
|
||||
|
||||
const result = Array.isArray(target) ? [...target] : { ...target };
|
||||
|
||||
for (const key of Object.keys(source)) {
|
||||
const targetValue = result[key];
|
||||
const sourceValue = source[key];
|
||||
|
||||
if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {
|
||||
result[key] = [...targetValue, ...sourceValue]; // or use a custom strategy
|
||||
} else if (
|
||||
targetValue &&
|
||||
typeof targetValue === "object" &&
|
||||
sourceValue &&
|
||||
typeof sourceValue === "object"
|
||||
) {
|
||||
result[key] = deepMerge(targetValue, sourceValue);
|
||||
} else {
|
||||
result[key] = sourceValue;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
import z from "zod";
|
||||
import { readdir } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import type { ComposeSpecification } from "../schema/docker.d";
|
||||
import JsonSchema from "../schema/docker.ts";
|
||||
import { file, YAML } from "bun";
|
||||
|
||||
const ComposeFileNames = new Set([
|
||||
"compose.yml",
|
||||
"compose.yaml",
|
||||
"docker-compose.yml",
|
||||
"docker-compose.yaml",
|
||||
]);
|
||||
|
||||
const ComposeSchema = z.fromJSONSchema(
|
||||
JsonSchema as unknown as Parameters<typeof z.fromJSONSchema>[0],
|
||||
) as z.ZodType<ComposeSpecification>;
|
||||
|
||||
export function readCompose(path: string): Promise<ComposeSpecification> {
|
||||
return file(path).text().then(YAML.parse).then(ComposeSchema.parse);
|
||||
}
|
||||
|
||||
export async function resolveComposeFile(
|
||||
path: string,
|
||||
): Promise<string | undefined> {
|
||||
const entries = await readdir(path, { withFileTypes: true });
|
||||
|
||||
return entries
|
||||
.filter((entry) => entry.isFile() && ComposeFileNames.has(entry.name))
|
||||
.map((entry) => join(path, entry.name))
|
||||
.sort()[0];
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "kuber",
|
||||
"module": "index.ts",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest",
|
||||
"json-schema-to-typescript": "^15.0.4",
|
||||
"oxfmt": "^0.62.0",
|
||||
"oxlint": "^1.77.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cliffy/table": "npm:@jsr/cliffy__table",
|
||||
"@kubernetes/client-node": "^1.4.0",
|
||||
"citty": "^0.2.2",
|
||||
"zod": "^4.4.3"
|
||||
}
|
||||
}
|
||||
Vendored
+2595
File diff suppressed because it is too large
Load Diff
+2440
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
// Environment setup & latest features
|
||||
"lib": ["ESNext"],
|
||||
"target": "ESNext",
|
||||
"module": "Preserve",
|
||||
"moduleDetection": "force",
|
||||
"jsx": "react-jsx",
|
||||
"allowJs": true,
|
||||
"types": ["bun"],
|
||||
|
||||
// Bundler mode
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"noEmit": true,
|
||||
|
||||
// Best practices
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"noImplicitOverride": true,
|
||||
"resolveJsonModule": true,
|
||||
|
||||
// Some stricter flags (disabled by default)
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"noPropertyAccessFromIndexSignature": false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user