diff --git a/deno.lock b/deno.lock index 143ad66f..78ad3fe8 100644 --- a/deno.lock +++ b/deno.lock @@ -5,15 +5,15 @@ "jsr:@std/fmt@*": "1.0.8", "jsr:@std/internal@^1.0.5": "1.0.12", "npm:@commander-js/extra-typings@^12.1.0": "12.1.0_commander@12.1.0", - "npm:@inkjs/ui@2": "2.0.0_ink@5.2.1__@types+react@18.3.26__react@18.3.1_@types+react@18.3.26_react@18.3.1", + "npm:@inkjs/ui@2": "2.0.0_ink@5.2.1__@types+react@18.3.27__react@18.3.1_@types+react@18.3.27_react@18.3.1", "npm:@inquirer/prompts@^5.1.2": "5.5.0", "npm:@sfcompute/nodes-sdk-alpha@0.1.0-alpha.22": "0.1.0-alpha.22", "npm:@types/ms@~0.7.34": "0.7.34", "npm:@types/node@*": "24.2.0", - "npm:@types/react@^18.3.20": "18.3.26", + "npm:@types/react@^18.3.20": "18.3.27", "npm:@types/semver@^7.5.8": "7.7.1", "npm:async-retry@^1.3.3": "1.3.3", - "npm:axios@^1.8.4": "1.12.2", + "npm:axios@^1.8.4": "1.13.2", "npm:boxen@8.0.1": "8.0.1", "npm:boxen@^8.0.1": "8.0.1", "npm:chrono-node@^2.9.0": "2.9.0", @@ -22,17 +22,15 @@ "npm:cli-table3@0.6.5": "0.6.5", "npm:commander@^12.1.0": "12.1.0", "npm:date-fns@^4.1.0": "4.1.0", - "npm:dayjs@*": "1.11.13", - "npm:dayjs@1.11.13": "1.11.13", - "npm:dayjs@^1.11.13": "1.11.18", + "npm:dayjs@^1.11.13": "1.11.19", "npm:dotenv@^16.4.5": "16.6.1", - "npm:ink-link@^4.1.0": "4.1.0_ink@5.2.1__@types+react@18.3.26__react@18.3.1_@types+react@18.3.26_react@18.3.1", - "npm:ink-spinner@5": "5.0.0_ink@5.2.1__@types+react@18.3.26__react@18.3.1_react@18.3.1_@types+react@18.3.26", - "npm:ink-testing-library@4": "4.0.0_@types+react@18.3.26", - "npm:ink-text-input@6": "6.0.0_ink@5.2.1__@types+react@18.3.26__react@18.3.1_react@18.3.1_@types+react@18.3.26", - "npm:ink@^5.2.0": "5.2.1_@types+react@18.3.26_react@18.3.1", + "npm:ink-link@^4.1.0": "4.1.0_ink@5.2.1__@types+react@18.3.27__react@18.3.1_@types+react@18.3.27_react@18.3.1", + "npm:ink-spinner@5": "5.0.0_ink@5.2.1__@types+react@18.3.27__react@18.3.1_react@18.3.1_@types+react@18.3.27", + "npm:ink-testing-library@4": "4.0.0_@types+react@18.3.27", + "npm:ink-text-input@6": "6.0.0_ink@5.2.1__@types+react@18.3.27__react@18.3.1_react@18.3.1_@types+react@18.3.27", + "npm:ink@^5.2.0": "5.2.1_@types+react@18.3.27_react@18.3.1", "npm:inquirer@^10.1.2": "10.2.2", - "npm:little-date@1": "1.0.0", + "npm:little-date@1": "1.2.1", "npm:ms@^2.1.3": "2.1.3", "npm:node-fetch@^3.3.2": "3.3.2", "npm:openapi-fetch@~0.11.1": "0.11.3", @@ -42,7 +40,7 @@ "npm:prettier@^3.5.3": "3.6.2", "npm:react@^18.3.1": "18.3.1", "npm:semver@^7.6.3": "7.7.3", - "npm:shescape@^2.1.1": "2.1.6", + "npm:shescape@^2.1.1": "2.1.7", "npm:tiny-invariant@^1.3.3": "1.3.3", "npm:tweetnacl-util@*": "0.15.1", "npm:tweetnacl-util@~0.15.1": "0.15.1", @@ -85,7 +83,7 @@ "commander" ] }, - "@inkjs/ui@2.0.0_ink@5.2.1__@types+react@18.3.26__react@18.3.1_@types+react@18.3.26_react@18.3.1": { + "@inkjs/ui@2.0.0_ink@5.2.1__@types+react@18.3.27__react@18.3.1_@types+react@18.3.27_react@18.3.1": { "integrity": "sha512-5+8fJmwtF9UvikzLfph9sA+LS+l37Ij/szQltkuXLOAXwNkBX9innfzh4pLGXIB59vKEQUtc6D4qGvhD7h3pAg==", "dependencies": [ "chalk", @@ -118,7 +116,7 @@ "@inquirer/figures", "@inquirer/type@2.0.0", "@types/mute-stream", - "@types/node@22.18.12", + "@types/node@22.19.1", "@types/wrap-ansi", "ansi-escapes@4.3.2", "cli-width", @@ -145,8 +143,8 @@ "yoctocolors-cjs" ] }, - "@inquirer/figures@1.0.14": { - "integrity": "sha512-DbFgdt+9/OZYFM+19dbpXOSeAstPy884FPy1KjDu4anWwymZeOYhMY1mdFri172htv6mvc/uvIAAi7b7tvjJBQ==" + "@inquirer/figures@1.0.15": { + "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==" }, "@inquirer/input@2.3.0": { "integrity": "sha512-XfnpCStx2xgh1LIRqPXrTNEEByqQWoxsWYzNRSEUxJ5c6EQlhMogJ3vHKu8aXuTacebtaZzMAHwEL0kAflKOBw==", @@ -236,8 +234,8 @@ "@types/node@24.2.0" ] }, - "@types/node@22.18.12": { - "integrity": "sha512-BICHQ67iqxQGFSzfCFTT7MRQ5XcBjG5aeKh5Ok38UBbPe5fxTyE+aHFxwVrGyr8GNlqFMLKD1D3P2K/1ks8tog==", + "@types/node@22.19.1": { + "integrity": "sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==", "dependencies": [ "undici-types@6.21.0" ] @@ -251,8 +249,8 @@ "@types/prop-types@15.7.15": { "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==" }, - "@types/react@18.3.26": { - "integrity": "sha512-RFA/bURkcKzx/X9oumPG9Vp3D3JUgus/d0b67KB0t5S/raciymilkOa66olh78MUI92QLbEJevO7rvqU/kjwKA==", + "@types/react@18.3.27": { + "integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==", "dependencies": [ "@types/prop-types", "csstype" @@ -282,8 +280,8 @@ "type-fest@1.4.0" ] }, - "ansi-escapes@7.1.1": { - "integrity": "sha512-Zhl0ErHcSRUaVfGUeUdDuLgpkEo8KIFjB4Y9uAc46ScOpdDiU1Dbyplh7qWJeJ/ZHpbyMSM26+X3BySgnIz40Q==", + "ansi-escapes@7.2.0": { + "integrity": "sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==", "dependencies": [ "environment" ] @@ -315,8 +313,8 @@ "auto-bind@5.0.1": { "integrity": "sha512-ooviqdwwgfIfNmDwo94wlshcdzfO64XV0Cg6oDsDYBJfITDz1EngD2z7DkbvCWn+XIMsIqW27sEVF6qcpJrRcg==" }, - "axios@1.12.2": { - "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", + "axios@1.13.2": { + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", "dependencies": [ "follow-redirects", "form-data", @@ -428,8 +426,8 @@ "convert-to-spaces@2.0.1": { "integrity": "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==" }, - "csstype@3.1.3": { - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + "csstype@3.2.3": { + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==" }, "data-uri-to-buffer@4.0.1": { "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==" @@ -443,11 +441,8 @@ "date-fns@4.1.0": { "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==" }, - "dayjs@1.11.13": { - "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==" - }, - "dayjs@1.11.18": { - "integrity": "sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==" + "dayjs@1.11.19": { + "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==" }, "deepmerge@4.3.1": { "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" @@ -496,8 +491,8 @@ "hasown" ] }, - "es-toolkit@1.40.0": { - "integrity": "sha512-8o6w0KFmU0CiIl0/Q/BCEOabF2IJaELM1T2PWj6e8KqzHv1gdx+7JtFnDwOx1kJH/isJ5NwlDG1nCr1HrRF94Q==" + "es-toolkit@1.42.0": { + "integrity": "sha512-SLHIyY7VfDJBM8clz4+T2oquwTQxEzu263AyhVK4jREOAwJ+8eebaa4wM3nlvnAqhDrMm2EsA6hWHaQsMPQ1nA==" }, "escape-string-regexp@2.0.0": { "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" @@ -526,8 +521,8 @@ "follow-redirects@1.15.11": { "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==" }, - "form-data@4.0.4": { - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "form-data@4.0.5": { + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "dependencies": [ "asynckit", "combined-stream", @@ -600,7 +595,7 @@ "indent-string@5.0.0": { "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==" }, - "ink-link@4.1.0_ink@5.2.1__@types+react@18.3.26__react@18.3.1_@types+react@18.3.26_react@18.3.1": { + "ink-link@4.1.0_ink@5.2.1__@types+react@18.3.27__react@18.3.1_@types+react@18.3.27_react@18.3.1": { "integrity": "sha512-3nNyJXum0FJIKAXBK8qat2jEOM41nJ1J60NRivwgK9Xh92R5UMN/k4vbz0A9xFzhJVrlf4BQEmmxMgXkCE1Jeg==", "dependencies": [ "ink", @@ -608,7 +603,7 @@ "terminal-link" ] }, - "ink-spinner@5.0.0_ink@5.2.1__@types+react@18.3.26__react@18.3.1_react@18.3.1_@types+react@18.3.26": { + "ink-spinner@5.0.0_ink@5.2.1__@types+react@18.3.27__react@18.3.1_react@18.3.1_@types+react@18.3.27": { "integrity": "sha512-EYEasbEjkqLGyPOUc8hBJZNuC5GvXGMLu0w5gdTNskPc7Izc5vO3tdQEYnzvshucyGCBXc86ig0ujXPMWaQCdA==", "dependencies": [ "cli-spinners@2.9.2", @@ -616,7 +611,7 @@ "react" ] }, - "ink-testing-library@4.0.0_@types+react@18.3.26": { + "ink-testing-library@4.0.0_@types+react@18.3.27": { "integrity": "sha512-yF92kj3pmBvk7oKbSq5vEALO//o7Z9Ck/OaLNlkzXNeYdwfpxMQkSowGTFUCS5MSu9bWfSZMewGpp7bFc66D7Q==", "dependencies": [ "@types/react" @@ -625,7 +620,7 @@ "@types/react" ] }, - "ink-text-input@6.0.0_ink@5.2.1__@types+react@18.3.26__react@18.3.1_react@18.3.1_@types+react@18.3.26": { + "ink-text-input@6.0.0_ink@5.2.1__@types+react@18.3.27__react@18.3.1_react@18.3.1_@types+react@18.3.27": { "integrity": "sha512-Fw64n7Yha5deb1rHY137zHTAbSTNelUKuB5Kkk2HACXEtwIHBCf9OH2tP/LQ9fRYTl1F0dZgbW0zPnZk6FA9Lw==", "dependencies": [ "chalk", @@ -634,12 +629,12 @@ "type-fest@4.41.0" ] }, - "ink@5.2.1_@types+react@18.3.26_react@18.3.1": { + "ink@5.2.1_@types+react@18.3.27_react@18.3.1": { "integrity": "sha512-BqcUyWrG9zq5HIwW6JcfFHsIYebJkWWb4fczNah1goUO0vv5vneIlfwuS85twyJ5hYR/y18FlAYUxrO9ChIWVg==", "dependencies": [ "@alcalzone/ansi-tokenize", "@types/react", - "ansi-escapes@7.1.1", + "ansi-escapes@7.2.0", "ansi-styles@6.2.3", "auto-bind", "chalk", @@ -712,8 +707,8 @@ "js-tokens@4.0.0": { "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, - "little-date@1.0.0": { - "integrity": "sha512-41T/ktcwPzxC0OJ8E3wmaK0E1DL/QNR3n30kB9Dw6Ni6Eud24It8LZm70jK8lvDd+Mg+961fzKDcF6SQRL25cQ==", + "little-date@1.2.1": { + "integrity": "sha512-O5LUKWMw96qEyS+12mxnRP49MZEEM9fPWzIylgutX6RHf6F1JakvfNeBgteP0CIeEyNFiPM8nohTldtbmyjEqQ==", "dependencies": [ "date-fns@2.30.0" ] @@ -892,8 +887,8 @@ "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "bin": true }, - "shescape@2.1.6": { - "integrity": "sha512-c9Ns1I+Tl0TC+cpsOT1FeZcvFalfd0WfHeD/CMccJH20xwochmJzq6AqtenndlyAw/BUi3BMcv92dYLVrqX+dw==", + "shescape@2.1.7": { + "integrity": "sha512-Y1syY0ggm3ow7mE1zrcK9YrOhAqv/IGbm3+J9S+MXLukwXf/M8yzL3hZp7ubVeSy250TT7M5SVKikTZkKyib6w==", "dependencies": [ "which" ] @@ -1011,8 +1006,8 @@ "web-streams-polyfill@3.3.3": { "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==" }, - "which@5.0.0": { - "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", + "which@6.0.0": { + "integrity": "sha512-f+gEpIKMR9faW/JgAgPK1D7mekkFoqbmiwvNzuhsHetni20QSgzg9Vhn0g2JSJkkfehQnqdUAx7/e15qS1lPxg==", "dependencies": [ "isexe" ], @@ -1058,9 +1053,10 @@ } }, "redirects": { + "https://deno.land/std/assert/mod.ts": "https://deno.land/std@0.224.0/assert/mod.ts", "https://esm.sh/@colors/colors/safe?target=denonext": "https://esm.sh/@colors/colors@1.6.0/safe?target=denonext", "https://esm.sh/@types/ansi-align@~3.0.5/index.d.ts": "https://esm.sh/@types/ansi-align@3.0.5/index.d.ts", - "https://esm.sh/@types/semver@~7.5.8/index.d.ts": "https://esm.sh/@types/semver@7.5.8/index.d.ts", + "https://esm.sh/@types/semver@~7.7.1/index.d.ts": "https://esm.sh/@types/semver@7.7.1/index.d.ts", "https://esm.sh/ansi-align@^3.0.1?target=denonext": "https://esm.sh/ansi-align@3.0.1?target=denonext", "https://esm.sh/ansi-regex@^5.0.1?target=denonext": "https://esm.sh/ansi-regex@5.0.1?target=denonext", "https://esm.sh/ansi-regex@^6.0.1?target=denonext": "https://esm.sh/ansi-regex@6.2.2?target=denonext", @@ -1083,7 +1079,43 @@ "https://esm.sh/yn": "https://esm.sh/yn@5.1.0" }, "remote": { - "https://esm.sh/@colors/colors@1.6.0/denonext/safe.mjs": "672444cb6774ba3c81b20f5bbfcf418f90995a01009055adc0755143b482e5e2", + "https://deno.land/std@0.112.0/fmt/colors.ts": "8368ddf2d48dfe413ffd04cdbb7ae6a1009cf0dccc9c7ff1d76259d9c61a0621", + "https://deno.land/std@0.112.0/testing/_diff.ts": "ccd6c3af6e44c74bf1591acb1361995f5f50df64323a6e7fb3f16c8ea792c940", + "https://deno.land/std@0.112.0/testing/asserts.ts": "cb82284da34f9e863250efacb985886336a9bbdcd2cf81cc9311a32aff53da35", + "https://deno.land/std@0.224.0/assert/_constants.ts": "a271e8ef5a573f1df8e822a6eb9d09df064ad66a4390f21b3e31f820a38e0975", + "https://deno.land/std@0.224.0/assert/assert.ts": "09d30564c09de846855b7b071e62b5974b001bb72a4b797958fe0660e7849834", + "https://deno.land/std@0.224.0/assert/assert_almost_equals.ts": "9e416114322012c9a21fa68e187637ce2d7df25bcbdbfd957cd639e65d3cf293", + "https://deno.land/std@0.224.0/assert/assert_array_includes.ts": "14c5094471bc8e4a7895fc6aa5a184300d8a1879606574cb1cd715ef36a4a3c7", + "https://deno.land/std@0.224.0/assert/assert_equals.ts": "3bbca947d85b9d374a108687b1a8ba3785a7850436b5a8930d81f34a32cb8c74", + "https://deno.land/std@0.224.0/assert/assert_exists.ts": "43420cf7f956748ae6ed1230646567b3593cb7a36c5a5327269279c870c5ddfd", + "https://deno.land/std@0.224.0/assert/assert_false.ts": "3e9be8e33275db00d952e9acb0cd29481a44fa0a4af6d37239ff58d79e8edeff", + "https://deno.land/std@0.224.0/assert/assert_greater.ts": "5e57b201fd51b64ced36c828e3dfd773412c1a6120c1a5a99066c9b261974e46", + "https://deno.land/std@0.224.0/assert/assert_greater_or_equal.ts": "9870030f997a08361b6f63400273c2fb1856f5db86c0c3852aab2a002e425c5b", + "https://deno.land/std@0.224.0/assert/assert_instance_of.ts": "e22343c1fdcacfaea8f37784ad782683ec1cf599ae9b1b618954e9c22f376f2c", + "https://deno.land/std@0.224.0/assert/assert_is_error.ts": "f856b3bc978a7aa6a601f3fec6603491ab6255118afa6baa84b04426dd3cc491", + "https://deno.land/std@0.224.0/assert/assert_less.ts": "60b61e13a1982865a72726a5fa86c24fad7eb27c3c08b13883fb68882b307f68", + "https://deno.land/std@0.224.0/assert/assert_less_or_equal.ts": "d2c84e17faba4afe085e6c9123a63395accf4f9e00150db899c46e67420e0ec3", + "https://deno.land/std@0.224.0/assert/assert_match.ts": "ace1710dd3b2811c391946954234b5da910c5665aed817943d086d4d4871a8b7", + "https://deno.land/std@0.224.0/assert/assert_not_equals.ts": "78d45dd46133d76ce624b2c6c09392f6110f0df9b73f911d20208a68dee2ef29", + "https://deno.land/std@0.224.0/assert/assert_not_instance_of.ts": "3434a669b4d20cdcc5359779301a0588f941ffdc2ad68803c31eabdb4890cf7a", + "https://deno.land/std@0.224.0/assert/assert_not_match.ts": "df30417240aa2d35b1ea44df7e541991348a063d9ee823430e0b58079a72242a", + "https://deno.land/std@0.224.0/assert/assert_not_strict_equals.ts": "37f73880bd672709373d6dc2c5f148691119bed161f3020fff3548a0496f71b8", + "https://deno.land/std@0.224.0/assert/assert_object_match.ts": "411450fd194fdaabc0089ae68f916b545a49d7b7e6d0026e84a54c9e7eed2693", + "https://deno.land/std@0.224.0/assert/assert_rejects.ts": "4bee1d6d565a5b623146a14668da8f9eb1f026a4f338bbf92b37e43e0aa53c31", + "https://deno.land/std@0.224.0/assert/assert_strict_equals.ts": "b4f45f0fd2e54d9029171876bd0b42dd9ed0efd8f853ab92a3f50127acfa54f5", + "https://deno.land/std@0.224.0/assert/assert_string_includes.ts": "496b9ecad84deab72c8718735373feb6cdaa071eb91a98206f6f3cb4285e71b8", + "https://deno.land/std@0.224.0/assert/assert_throws.ts": "c6508b2879d465898dab2798009299867e67c570d7d34c90a2d235e4553906eb", + "https://deno.land/std@0.224.0/assert/assertion_error.ts": "ba8752bd27ebc51f723702fac2f54d3e94447598f54264a6653d6413738a8917", + "https://deno.land/std@0.224.0/assert/equal.ts": "bddf07bb5fc718e10bb72d5dc2c36c1ce5a8bdd3b647069b6319e07af181ac47", + "https://deno.land/std@0.224.0/assert/fail.ts": "0eba674ffb47dff083f02ced76d5130460bff1a9a68c6514ebe0cdea4abadb68", + "https://deno.land/std@0.224.0/assert/mod.ts": "48b8cb8a619ea0b7958ad7ee9376500fe902284bb36f0e32c598c3dc34cbd6f3", + "https://deno.land/std@0.224.0/assert/unimplemented.ts": "8c55a5793e9147b4f1ef68cd66496b7d5ba7a9e7ca30c6da070c1a58da723d73", + "https://deno.land/std@0.224.0/assert/unreachable.ts": "5ae3dbf63ef988615b93eb08d395dda771c96546565f9e521ed86f6510c29e19", + "https://deno.land/std@0.224.0/fmt/colors.ts": "508563c0659dd7198ba4bbf87e97f654af3c34eb56ba790260f252ad8012e1c5", + "https://deno.land/std@0.224.0/internal/diff.ts": "6234a4b493ebe65dc67a18a0eb97ef683626a1166a1906232ce186ae9f65f4e6", + "https://deno.land/std@0.224.0/internal/format.ts": "0a98ee226fd3d43450245b1844b47003419d34d210fa989900861c79820d21c2", + "https://deno.land/std@0.224.0/internal/mod.ts": "534125398c8e7426183e12dc255bb635d94e06d0f93c60a297723abe69d3b22e", + "https://esm.sh/@colors/colors@1.6.0/denonext/safe.mjs": "6b343b0dd3738994881fba8a5933bf99015ccfa81620ef38de39d9ef78c51fdb", "https://esm.sh/@colors/colors@1.6.0/safe?target=denonext": "6affb64b51a87ea13b07ae8e13b329bacfb225a344bf6bc721656ae6b3abb2ad", "https://esm.sh/ansi-align@3.0.1/denonext/ansi-align.mjs": "0f4b86c34935f09a6bf23d184bb50b9c5df453c1a78527cbeaae9bb03af30a63", "https://esm.sh/ansi-align@3.0.1?target=denonext": "a981bcdb5a9f6a67be186bb170525a411ee1260405b2290d7ee49a922457d697", @@ -1103,19 +1135,19 @@ "https://esm.sh/cli-boxes@3.0.0/denonext/cli-boxes.mjs": "88c1214ef2783f95a286491e6f2e8ee11ad0a7358298b1bd46ef918a3f466611", "https://esm.sh/cli-boxes@3.0.0?target=denonext": "d7d1902599ae669086784966b7a2682cbf7d1bdc3724038e365c5bf0a29a945e", "https://esm.sh/cli-table3@0.6.5": "028d5b5aa15ca57e687ed9660e0cf075f6cd17a98fec98eb78b4d5c43635c670", - "https://esm.sh/cli-table3@0.6.5/denonext/cli-table3.mjs": "c0acea9c53686e398125979242fc08aca90a80743fee36d36981eaf7eec9bc06", + "https://esm.sh/cli-table3@0.6.5/denonext/cli-table3.mjs": "8a03beafdce5f42d2566279f3ca42dc16235d5d29227f9c0859b037699fe8f4b", "https://esm.sh/dayjs@1.11.13": "89c34b8b3f7b970708114b4d264c9430c30eb0c2eab1419410c77ffefa18fe2c", - "https://esm.sh/dayjs@1.11.13/denonext/dayjs.mjs": "a6d8258bec464149ab2c9ae26e4bd3736897828586b03f8fea45403080bf8a80", - "https://esm.sh/dayjs@1.11.13/denonext/plugin/advancedFormat.mjs": "444d2692395ee582d230ce2622d27156c330f260980ca393c3b080fd6f103b64", - "https://esm.sh/dayjs@1.11.13/denonext/plugin/duration.mjs": "64bd1dd95adf21a54fcda2dd3161998cd2780a4789d43c14b63d33ed012d3938", - "https://esm.sh/dayjs@1.11.13/denonext/plugin/relativeTime.mjs": "b38196c727ee8c425eff06f091298f945b1f041fb8c3a0756b40081d6f067b3d", - "https://esm.sh/dayjs@1.11.13/denonext/plugin/timezone.mjs": "94d48607684cc8423f815fee4e72bf334c801cdf52d79caa00481a7e83c345f4", - "https://esm.sh/dayjs@1.11.13/denonext/plugin/utc.mjs": "7e89223a0933377aaa5fd52d97f116ed3d48c93d5b2ed305d86bde9e496b3e12", + "https://esm.sh/dayjs@1.11.13/denonext/dayjs.mjs": "6684fee7de01059065835aa6300306b0a753e4dfbaef3ba7db11c84f7afd3394", + "https://esm.sh/dayjs@1.11.13/denonext/plugin/advancedFormat.mjs": "d70fe83416f063d309e4ad4f1486b252f7544952f5dcaccc22eea99b35fa9534", + "https://esm.sh/dayjs@1.11.13/denonext/plugin/duration.mjs": "a24a30859a5253bba1c0ab23a67d759bbe4b6be86a8be5bf6c7624e7ea548127", + "https://esm.sh/dayjs@1.11.13/denonext/plugin/relativeTime.mjs": "a2d9b5a2bc66374087650609b6a24dd83073fe9d11564e874b91c7388d4fefd5", + "https://esm.sh/dayjs@1.11.13/es2022/plugin/timezone.mjs": "94d48607684cc8423f815fee4e72bf334c801cdf52d79caa00481a7e83c345f4", + "https://esm.sh/dayjs@1.11.13/es2022/plugin/utc.mjs": "e760160892182a9a92d2c92c3e74c381b678aa5034872422c880ec2d231c22ab", "https://esm.sh/dayjs@1.11.13/plugin/advancedFormat.js": "cbb82f21176632f2ad3590cc2c51356463d527be5a221545520d4a9034744fab", "https://esm.sh/dayjs@1.11.13/plugin/duration.js": "9f6f119d7af58b8e08424bf897daaa286cadaa63d58262140969102671296a51", "https://esm.sh/dayjs@1.11.13/plugin/relativeTime.js": "48ccbeb4a6e19c6320f41edc1028ac85e7baf8cd434faebe65e3208ec70cea6b", - "https://esm.sh/dayjs@1.11.13/plugin/timezone.js": "cfe2b0eec9855373de8fbc92d3503d25930ab3156522482e55f7a66bb3d4fb32", - "https://esm.sh/dayjs@1.11.13/plugin/utc.js": "2e41a0673e6e7c7c962983f1680911ef6feb27ded6007bc7705787ac1b2637b7", + "https://esm.sh/dayjs@1.11.13/plugin/timezone.js": "8885a15a7472e23b020957c28d9d49d3e5c00fd5b992bf5d733bfa4f952ed457", + "https://esm.sh/dayjs@1.11.13/plugin/utc.js": "3c51f2f90816004281990ed17d5010311c2b77875663127cbc773dc440ae7dde", "https://esm.sh/emoji-regex@10.6.0/denonext/emoji-regex.mjs": "bec0264591b37a7132b080ed5586e3fc577392b1444230d973d7209d04f4f6e5", "https://esm.sh/emoji-regex@10.6.0?target=denonext": "0b0ed0e68f224d09d771339aaf83dd19d31c149e6fb1213ea3a12ef8ee977188", "https://esm.sh/emoji-regex@8.0.0/denonext/emoji-regex.mjs": "3969ad7b107b6f585354a5019c24320e3d91d6bb70a96e2beead925247aed9dc", @@ -1137,7 +1169,7 @@ "https://esm.sh/tweetnacl-util@0.15.1": "e0fd14af65295558349a3500af602425f46c54b3af8c48e0c4eaf87371150bbd", "https://esm.sh/tweetnacl-util@0.15.1/denonext/tweetnacl-util.mjs": "816cc58f87948ec6974d0ebd06112972aadcf03180b5782545a8e0e9031b5e14", "https://esm.sh/tweetnacl@1.0.3": "278caeeeb136b538b5839595306abfe0ed8e0263a990a446fd30d89aaef9a8c5", - "https://esm.sh/tweetnacl@1.0.3/denonext/tweetnacl.mjs": "2a972244e194f6e965cbe26ddc858dab7642621548d432d8f666b31f2b7c6d31", + "https://esm.sh/tweetnacl@1.0.3/denonext/tweetnacl.mjs": "71347ea6adf760e1378fe39edf421fcbb2c05c21816e6762c7ae425084143830", "https://esm.sh/widest-line@5.0.0/denonext/widest-line.mjs": "9fbc109cfe353f84218bcccf4226a3cbf46b432a81337597f9457844a32c94d1", "https://esm.sh/widest-line@5.0.0?target=denonext": "8c98d5536e51a2c06ebdf6e4c32a7293701f24b16264ed5c84a966f864117c02", "https://esm.sh/wrap-ansi@9.0.2/denonext/wrap-ansi.mjs": "b162a4bee79e191c104203070dcdc38374981423ff1e18b67601499537125ddb", diff --git a/src/lib/buy/index.tsx b/src/lib/buy/index.tsx index f14293ff..435a6aec 100644 --- a/src/lib/buy/index.tsx +++ b/src/lib/buy/index.tsx @@ -7,9 +7,10 @@ import ms from "ms"; import console from "node:console"; import process from "node:process"; import { setTimeout } from "node:timers"; -import dayjs from "npm:dayjs@1.11.13"; -import duration from "npm:dayjs@1.11.13/plugin/duration.js"; -import relativeTime from "npm:dayjs@1.11.13/plugin/relativeTime.js"; +import boxen from "npm:boxen@8.0.1"; +import dayjs from "dayjs"; +import duration from "dayjs/plugin/duration"; +import relativeTime from "dayjs/plugin/relativeTime"; import parseDurationFromLibrary from "parse-duration"; import React, { useCallback, useEffect, useState } from "react"; import invariant from "tiny-invariant"; @@ -34,10 +35,12 @@ import { Row } from "../Row.tsx"; import { GPUS_PER_NODE } from "../constants.ts"; import { parseAccelerators } from "../index.ts"; import { analytics } from "../posthog.ts"; +import { components } from "../../schema.ts"; dayjs.extend(relativeTime); dayjs.extend(duration); +type ZoneInfo = components["schemas"]["node-api_ZoneInfo"]; export type SfBuyOptions = ReturnType["opts"]>; export function _registerBuy(program: Command) { @@ -234,6 +237,7 @@ export function QuoteComponent(props: { options: SfBuyOptions }) { export function QuoteAndBuy(props: { options: SfBuyOptions }) { const [orderProps, setOrderProps] = useState(null); + const [zone, setZone] = useState(); // submit a quote request, handle loading state useEffect(() => { @@ -243,6 +247,7 @@ export function QuoteAndBuy(props: { options: SfBuyOptions }) { let pricePerGpuHour = parsePricePerGpuHour(props.options.price); let startAt = start; let endsAt: Date; + let quoteZone: string | undefined; const coercedStart = parseStartDate(start); if (duration) { // If duration is set, calculate end from start + duration @@ -268,15 +273,34 @@ export function QuoteAndBuy(props: { options: SfBuyOptions }) { } pricePerGpuHour = getPricePerGpuHourFromQuote(quote); - startAt = parseStartDateOrNow(quote.start_at); - endsAt = dayjs(quote.end_at).toDate(); + quoteZone = "zone" in quote ? quote.zone : undefined; } const { type, accelerators, colocate, yes, standing, cluster } = props.options; + if (cluster) { + const api = await apiClient(); + const { data, error, response } = await api.GET(`/v0/zones/{id}`, { + params: { + path: { + id: cluster, + }, + }, + }); + if (error) { + return logAndQuit( + `Failed to get zone: ${JSON.stringify(error, null, 2)}`, + ); + } + if (!response.ok) { + return logAndQuit(`No zone found with slug: ${cluster}`); + } + setZone(data); + } + setOrderProps({ type, price: pricePerGpuHour, @@ -286,7 +310,9 @@ export function QuoteAndBuy(props: { options: SfBuyOptions }) { yes, standing, colocate, - cluster, + // If the user didn't specify a zone, use the zone from the quote + // This helps prevent price surprises/location mismatches + cluster: cluster ?? quoteZone, }); })(); }, [props.options]); @@ -300,7 +326,7 @@ export function QuoteAndBuy(props: { options: SfBuyOptions }) { ) - : ; + : ; } export function getTotalPrice( @@ -429,10 +455,60 @@ type BuyOrderProps = { yes?: boolean; standing?: boolean; cluster?: string; + zone?: ZoneInfo; }; +function VMWarning(props: BuyOrderProps) { + const startDate = props.startAt === "NOW" ? dayjs() : dayjs(props.startAt); + const endDate = dayjs(roundEndDate(props.endsAt)); + const realDuration = endDate.diff(startDate); + const realDurationString = ms(realDuration); + + // Build the equivalent sf nodes command + let equivalentCommand = `sf nodes create -n ${props.size}`; + + if (props.price) { + equivalentCommand += ` -p ${ + (props.price * GPUS_PER_NODE / 100).toFixed(2) + }`; + } + if (props.startAt !== "NOW") { + const startFormatted = startDate.toISOString(); + equivalentCommand += ` -s "${startFormatted}"`; + } + equivalentCommand += ` -d ${realDurationString}`; + if (props.yes) { + equivalentCommand += ` -y`; + } + if (props.cluster) { + equivalentCommand += ` -z ${props.cluster}`; + } else { + // TODO: add support for any-zone + // equivalentCommand += `--any-zone`; + } + + const warningMessage = boxen( + `\x1b[31mWe're deprecating \x1b[97msf buy\x1b[31m for Virtual Machines.\x1b[0m +\x1b[31mWe recommend you create a VM Node instead: \x1b[97m${equivalentCommand}\x1b[0m +\x1b[31m\x1b[97msf nodes\x1b[31m allows you to create, extend, and release specific machines directly.\x1b[0m`, + { + padding: 0.75, + borderColor: "red", + }, + ); + + return {warningMessage}; +} + function BuyOrder(props: BuyOrderProps) { const [isLoading, setIsLoading] = useState(false); + const { type, zone } = props; + const isVM = type?.endsWith("v") || zone?.delivery_type === "VM"; + const [vmWarningState, setVmWarningState] = useState< + "prompt" | "accepted" | "dismissed" | "not_applicable" + >( + isVM ? (props.yes ? "accepted" : "prompt") : "not_applicable", + ); const { exit } = useApp(); const [order, setOrder] = useState(null); @@ -522,6 +598,18 @@ function BuyOrder(props: BuyOrderProps) { [props, exit, submitOrder], ); + const handleDismissVMWarning = useCallback((submitValue: boolean) => { + if (!submitValue) { + setIsLoading(false); + setResultMessage( + "VM order not placed. We recommend you use 'sf nodes create' instead.", + ); + setTimeout(() => { + exit(); + }, 0); + } else setVmWarningState("accepted"); + }, [exit]); + useEffect(() => { if (!isLoading || !order?.id) { return; @@ -554,9 +642,47 @@ function BuyOrder(props: BuyOrderProps) { return ( - + {(vmWarningState === "prompt" || vmWarningState === "accepted") && ( + + + {vmWarningState === "prompt" && ( + <> + + Place an order for a legacy VM anyway?{" "} + + (y/n) + + + + + + )} + + )} + + {(vmWarningState === "dismissed" || vmWarningState === "not_applicable" || + vmWarningState === "accepted") && ( + + )} - {!isLoading && !props.yes && ( + {vmWarningState === "accepted" && !isLoading && !props.yes && ( + + Place order? (y/n) + + + + )} + + {(vmWarningState === "dismissed" || + vmWarningState === "not_applicable") && !isLoading && !props.yes && ( Place order? (y/n) @@ -836,11 +962,13 @@ export async function getQuote(options: QuoteOptions) { if (!response.ok) { switch (response.status) { case 400: - return logAndQuit(`Bad Request: ${error}`); + return logAndQuit(`Bad Request: ${JSON.stringify(error, null, 2)}`); case 401: return await logSessionTokenExpiredAndQuit(); case 500: - return logAndQuit(`Failed to get quote: ${error}`); + return logAndQuit( + `Failed to get quote: ${JSON.stringify(error, null, 2)}`, + ); default: return logAndQuit(`Failed to get quote: ${response.statusText}`); } diff --git a/src/lib/dev.ts b/src/lib/dev.ts index eb0348e5..e6f3add6 100644 --- a/src/lib/dev.ts +++ b/src/lib/dev.ts @@ -3,8 +3,8 @@ import * as console from "node:console"; import { confirm } from "@inquirer/prompts"; import { gray, green, white, yellow } from "jsr:@std/fmt/colors"; import type { Command } from "@commander-js/extra-typings"; -import dayjs from "npm:dayjs@1.11.13"; -import utc from "npm:dayjs@1.11.13/plugin/utc.js"; +import dayjs from "dayjs"; +import utc from "dayjs/plugin/utc"; import { deleteConfig, getConfigPath, diff --git a/src/lib/extend/index.tsx b/src/lib/extend/index.tsx index ccd8fbc2..bb85a6dd 100644 --- a/src/lib/extend/index.tsx +++ b/src/lib/extend/index.tsx @@ -1,7 +1,7 @@ import { type Command } from "@commander-js/extra-typings"; -import dayjs from "npm:dayjs@1.11.13"; -import duration from "npm:dayjs@1.11.13/plugin/duration.js"; -import relativeTime from "npm:dayjs@1.11.13/plugin/relativeTime.js"; +import dayjs from "dayjs"; +import duration from "dayjs/plugin/duration"; +import relativeTime from "dayjs/plugin/relativeTime"; import boxen from "npm:boxen@8.0.1"; import console from "node:console"; import process from "node:process"; diff --git a/src/lib/orders/OrderDisplay.tsx b/src/lib/orders/OrderDisplay.tsx index fafd7e2a..e073d643 100644 --- a/src/lib/orders/OrderDisplay.tsx +++ b/src/lib/orders/OrderDisplay.tsx @@ -1,6 +1,6 @@ import { Box, measureElement, Text, useInput } from "ink"; import process from "node:process"; -import dayjs from "npm:dayjs@1.11.13"; +import dayjs from "dayjs"; import React, { useEffect } from "react"; import { Row } from "../Row.tsx"; import { GPUS_PER_NODE } from "../constants.ts"; diff --git a/src/lib/orders/index.tsx b/src/lib/orders/index.tsx index 8215cf4f..38236e79 100644 --- a/src/lib/orders/index.tsx +++ b/src/lib/orders/index.tsx @@ -1,9 +1,9 @@ import { type Command, Option } from "@commander-js/extra-typings"; import { render } from "ink"; import * as console from "node:console"; -import dayjs from "npm:dayjs@1.11.13"; -import duration from "npm:dayjs@1.11.13/plugin/duration.js"; -import relativeTime from "npm:dayjs@1.11.13/plugin/relativeTime.js"; +import dayjs from "dayjs"; +import duration from "dayjs/plugin/duration"; +import relativeTime from "dayjs/plugin/relativeTime"; import React from "react"; import { getAuthToken, isLoggedIn } from "../../helpers/config.ts"; import { parseDurationArgument } from "../../helpers/duration.ts"; diff --git a/src/lib/scale/create.tsx b/src/lib/scale/create.tsx index 09bc1eae..6ebe8365 100644 --- a/src/lib/scale/create.tsx +++ b/src/lib/scale/create.tsx @@ -4,7 +4,10 @@ import Spinner from "ink-spinner"; import { Command, Option } from "@commander-js/extra-typings"; import process from "node:process"; import console from "node:console"; +import { setTimeout } from "node:timers"; +import boxen from "npm:boxen@8.0.1"; import dayjs from "dayjs"; +import { pluralizeNodes } from "../nodes/utils.ts"; import { apiClient } from "../../apiClient.ts"; import { logAndQuit } from "../../helpers/errors.ts"; @@ -12,6 +15,7 @@ import { logAndQuit } from "../../helpers/errors.ts"; import ConfirmInput from "../ConfirmInput.tsx"; import { GPUS_PER_NODE } from "../constants.ts"; import { getQuote } from "../buy/index.tsx"; +import { components } from "../../schema.ts"; import { acceleratorsToNodes, @@ -28,6 +32,44 @@ import { roundDateUpToNextMinute } from "../../helpers/units.ts"; import ProcurementDisplay from "./ProcurementDisplay.tsx"; import ConfirmationMessage from "./ConfirmationMessage.tsx"; +type ZoneInfo = components["schemas"]["node-api_ZoneInfo"]; + +function ScaleWarning(props: CreateProcurementCommandProps) { + const clusterName = props.zone || props.cluster; + const nodesRequired = acceleratorsToNodes(props.accelerators); + + // Build the equivalent sf nodes create --auto command + let equivalentCommand = `sf nodes create -n ${nodesRequired} --auto`; + + if (clusterName) { + equivalentCommand += ` -z ${clusterName}`; + } + if (props.price) { + // Convert from cents per GPU/hr to dollars per node/hr + const pricePerNodeHour = (props.price * GPUS_PER_NODE) / 100; + equivalentCommand += ` -p ${pricePerNodeHour.toFixed(2)}`; + } + if (props.yes) { + equivalentCommand += ` -y`; + } + + const warningMessage = boxen( + `\x1b[31mWe're deprecating \x1b[97msf scale\x1b[31m.\x1b[0m +\x1b[31mCreate auto reserved nodes using \x1b[97msf nodes\x1b[31m instead:\x1b[0m \x1b[97m${equivalentCommand}\x1b[0m +\x1b[31mThe above command creates ${nodesRequired} self-extending ${ + pluralizeNodes(nodesRequired) + } that ${ + nodesRequired === 1 ? "maintains" : "maintain" + } capacity automatically.\x1b[0m`, + { + padding: 0.75, + borderColor: "red", + }, + ); + + return {warningMessage}; +} + // TODO: When Ink supports React 19, use useTransition and startTransition function useCreateProcurement() { const [isLoading, setIsLoading] = useState(false); @@ -85,16 +127,24 @@ function useCreateProcurement() { }; } -type CreateProcurementCommandProps = ReturnType; +type CreateProcurementCommandProps = ReturnType & { + zoneInfo?: ZoneInfo; +}; function CreateProcurementCommand(props: CreateProcurementCommandProps) { const { exit } = useApp(); + const clusterName = props.zone || props.cluster; + const isVM = props.type?.endsWith("v") || + props.zoneInfo?.delivery_type === "VM"; + const [scaleWarningState, setScaleWarningState] = useState< + "prompt" | "accepted" | "dismissed" | "not_applicable" + >( + isVM ? (props.yes ? "accepted" : "prompt") : "not_applicable", + ); const [confirmationMessage, setConfirmationMessage] = useState< React.ReactNode >(); - const clusterName = props.zone || props.cluster; - const nodesRequired = useMemo( () => acceleratorsToNodes(props.accelerators), [props.accelerators], @@ -200,6 +250,22 @@ function CreateProcurementCommand(props: CreateProcurementCommandProps) { createProcurement, } = useCreateProcurement(); + useEffect(() => { + if (error) { + setTimeout(() => exit(new Error(error)), 0); + } else if (result) { + setTimeout(() => exit(), 0); + } + }, [error, result, exit]); + + const handleDismissScaleWarning = useCallback((submitValue: boolean) => { + if (!submitValue) { + exit(); + } else { + setScaleWarningState("accepted"); + } + }, [exit]); + const handleSubmit = (submitValue: boolean) => { if (!submitValue) { exit(); @@ -248,18 +314,56 @@ function CreateProcurementCommand(props: CreateProcurementCommandProps) { return ( - Successfully created procurement for {props.accelerators} {props.type} - {" "} - instances! + Successfully created procurement for{" "} + {props.accelerators / GPUS_PER_NODE} {props.type} nodes! ); } - if (confirmationMessage && !props.yes) { + // Show deprecation warning first + if (scaleWarningState === "prompt" && !props.yes) { return ( - + + + + Create a procurement anyway?{" "} + + (y/N) + + + + + ); + } + + // Show confirmation message after warning is dismissed + if (confirmationMessage && !props.yes && scaleWarningState === "accepted") { + return ( + + + {confirmationMessage} + + Create procurement? (y/N) + + + + ); + } + + // Show confirmation for non-VM procurements (h100i, etc.) + if ( + confirmationMessage && !props.yes && scaleWarningState === "not_applicable" + ) { + return ( + {confirmationMessage} Create procurement? (y/N) @@ -354,12 +458,37 @@ $ sf scale create -n 8 --horizon '30m' process.exit(1); } }) - .action((options) => { - render( + .action(async (options) => { + let zoneInfo: ZoneInfo | undefined; + const clusterName = options.zone || options.cluster; + + if (clusterName) { + const api = await apiClient(); + const { data, error, response } = await api.GET(`/v0/zones/{id}`, { + params: { + path: { + id: clusterName, + }, + }, + }); + if (error) { + return logAndQuit( + `Failed to get zone: ${JSON.stringify(error, null, 2)}`, + ); + } + if (!response.ok) { + return logAndQuit(`No zone found with slug: ${clusterName}`); + } + zoneInfo = data; + } + + const { waitUntilExit } = render( , ); + await waitUntilExit(); }); export default create; diff --git a/src/lib/sell.ts b/src/lib/sell.ts index 417cf4fb..dc4b1985 100644 --- a/src/lib/sell.ts +++ b/src/lib/sell.ts @@ -1,6 +1,6 @@ import type { Command } from "@commander-js/extra-typings"; import * as chrono from "chrono-node"; -import dayjs from "npm:dayjs"; +import dayjs from "dayjs"; import parseDuration from "parse-duration"; import { apiClient } from "../apiClient.ts"; import { isLoggedIn } from "../helpers/config.ts"; diff --git a/src/lib/sell/index.tsx b/src/lib/sell/index.tsx index 1818c15d..000ffcde 100644 --- a/src/lib/sell/index.tsx +++ b/src/lib/sell/index.tsx @@ -1,8 +1,8 @@ import type { Command } from "@commander-js/extra-typings"; import { clearInterval, setInterval } from "node:timers"; -import dayjs from "npm:dayjs@1.11.13"; -import duration from "npm:dayjs@1.11.13/plugin/duration.js"; -import relativeTime from "npm:dayjs@1.11.13/plugin/relativeTime.js"; +import dayjs from "dayjs"; +import duration from "dayjs/plugin/duration"; +import relativeTime from "dayjs/plugin/relativeTime"; import { apiClient } from "../../apiClient.ts"; import { components } from "../../schema.ts"; import {