@synteq/cli 0.1.5 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/run.js +61 -2
- package/dist/api/client.d.ts +29 -37
- package/dist/api/client.js +42 -49
- package/dist/api/client.js.map +1 -1
- package/dist/api/factory.d.ts +3 -0
- package/dist/api/factory.js +1 -1
- package/dist/api/factory.js.map +1 -1
- package/dist/api/types.d.ts +14 -23
- package/dist/auth/scope.d.ts +19 -0
- package/dist/auth/scope.js +65 -0
- package/dist/auth/scope.js.map +1 -0
- package/dist/base/command.d.ts +1 -1
- package/dist/base/command.js +49 -0
- package/dist/base/command.js.map +1 -1
- package/dist/commands/account/index.d.ts +1 -0
- package/dist/commands/account/index.js +1 -0
- package/dist/commands/account/index.js.map +1 -1
- package/dist/commands/account/show.d.ts +1 -0
- package/dist/commands/account/show.js +1 -0
- package/dist/commands/account/show.js.map +1 -1
- package/dist/commands/api.d.ts +1 -0
- package/dist/commands/api.js +5 -4
- package/dist/commands/api.js.map +1 -1
- package/dist/commands/catalog.d.ts +1 -0
- package/dist/commands/catalog.js +6 -1
- package/dist/commands/catalog.js.map +1 -1
- package/dist/commands/config/index.d.ts +1 -0
- package/dist/commands/config/index.js +1 -0
- package/dist/commands/config/index.js.map +1 -1
- package/dist/commands/config/set-api-url.d.ts +1 -0
- package/dist/commands/config/set-api-url.js +38 -2
- package/dist/commands/config/set-api-url.js.map +1 -1
- package/dist/commands/config/show.d.ts +1 -0
- package/dist/commands/config/show.js +1 -0
- package/dist/commands/config/show.js.map +1 -1
- package/dist/commands/credits/add.d.ts +1 -0
- package/dist/commands/credits/add.js +1 -0
- package/dist/commands/credits/add.js.map +1 -1
- package/dist/commands/credits/index.d.ts +1 -0
- package/dist/commands/credits/index.js +1 -0
- package/dist/commands/credits/index.js.map +1 -1
- package/dist/commands/credits/list.d.ts +1 -0
- package/dist/commands/credits/list.js +1 -0
- package/dist/commands/credits/list.js.map +1 -1
- package/dist/commands/gpu/activity.d.ts +2 -0
- package/dist/commands/gpu/activity.js +7 -0
- package/dist/commands/gpu/activity.js.map +1 -1
- package/dist/commands/gpu/bandwidth.d.ts +2 -0
- package/dist/commands/gpu/bandwidth.js +5 -0
- package/dist/commands/gpu/bandwidth.js.map +1 -1
- package/dist/commands/gpu/boot-order.d.ts +2 -0
- package/dist/commands/gpu/boot-order.js +6 -0
- package/dist/commands/gpu/boot-order.js.map +1 -1
- package/dist/commands/gpu/console.d.ts +2 -0
- package/dist/commands/gpu/console.js +6 -0
- package/dist/commands/gpu/console.js.map +1 -1
- package/dist/commands/gpu/details.d.ts +3 -0
- package/dist/commands/gpu/details.js +10 -0
- package/dist/commands/gpu/details.js.map +1 -1
- package/dist/commands/gpu/index.d.ts +1 -0
- package/dist/commands/gpu/index.js +1 -0
- package/dist/commands/gpu/index.js.map +1 -1
- package/dist/commands/gpu/ip/add.d.ts +2 -0
- package/dist/commands/gpu/ip/add.js +7 -0
- package/dist/commands/gpu/ip/add.js.map +1 -1
- package/dist/commands/gpu/ip/list.d.ts +2 -0
- package/dist/commands/gpu/ip/list.js +5 -0
- package/dist/commands/gpu/ip/list.js.map +1 -1
- package/dist/commands/gpu/list.d.ts +1 -0
- package/dist/commands/gpu/list.js +1 -0
- package/dist/commands/gpu/list.js.map +1 -1
- package/dist/commands/gpu/order.d.ts +1 -0
- package/dist/commands/gpu/order.js +3 -0
- package/dist/commands/gpu/order.js.map +1 -1
- package/dist/commands/gpu/power.d.ts +2 -0
- package/dist/commands/gpu/power.js +7 -0
- package/dist/commands/gpu/power.js.map +1 -1
- package/dist/commands/gpu/reinstall.d.ts +2 -0
- package/dist/commands/gpu/reinstall.js +8 -0
- package/dist/commands/gpu/reinstall.js.map +1 -1
- package/dist/commands/gpu/resize.d.ts +2 -0
- package/dist/commands/gpu/resize.js +7 -0
- package/dist/commands/gpu/resize.js.map +1 -1
- package/dist/commands/gpu/stats.d.ts +2 -0
- package/dist/commands/gpu/stats.js +6 -0
- package/dist/commands/gpu/stats.js.map +1 -1
- package/dist/commands/help.d.ts +2 -0
- package/dist/commands/help.js +5 -0
- package/dist/commands/help.js.map +1 -1
- package/dist/commands/instant-metal/activity.d.ts +2 -0
- package/dist/commands/instant-metal/activity.js +7 -0
- package/dist/commands/instant-metal/activity.js.map +1 -1
- package/dist/commands/instant-metal/bandwidth.d.ts +2 -0
- package/dist/commands/instant-metal/bandwidth.js +5 -0
- package/dist/commands/instant-metal/bandwidth.js.map +1 -1
- package/dist/commands/instant-metal/boot-order.d.ts +2 -0
- package/dist/commands/instant-metal/boot-order.js +6 -0
- package/dist/commands/instant-metal/boot-order.js.map +1 -1
- package/dist/commands/instant-metal/console.d.ts +2 -0
- package/dist/commands/instant-metal/console.js +6 -0
- package/dist/commands/instant-metal/console.js.map +1 -1
- package/dist/commands/instant-metal/details.d.ts +3 -0
- package/dist/commands/instant-metal/details.js +10 -0
- package/dist/commands/instant-metal/details.js.map +1 -1
- package/dist/commands/instant-metal/index.d.ts +1 -0
- package/dist/commands/instant-metal/index.js +1 -0
- package/dist/commands/instant-metal/index.js.map +1 -1
- package/dist/commands/instant-metal/ip/add.d.ts +2 -0
- package/dist/commands/instant-metal/ip/add.js +7 -0
- package/dist/commands/instant-metal/ip/add.js.map +1 -1
- package/dist/commands/instant-metal/ip/list.d.ts +2 -0
- package/dist/commands/instant-metal/ip/list.js +5 -0
- package/dist/commands/instant-metal/ip/list.js.map +1 -1
- package/dist/commands/instant-metal/list.d.ts +1 -0
- package/dist/commands/instant-metal/list.js +1 -0
- package/dist/commands/instant-metal/list.js.map +1 -1
- package/dist/commands/instant-metal/order.d.ts +1 -0
- package/dist/commands/instant-metal/order.js +3 -0
- package/dist/commands/instant-metal/order.js.map +1 -1
- package/dist/commands/instant-metal/power.d.ts +2 -0
- package/dist/commands/instant-metal/power.js +7 -0
- package/dist/commands/instant-metal/power.js.map +1 -1
- package/dist/commands/instant-metal/reinstall.d.ts +2 -0
- package/dist/commands/instant-metal/reinstall.js +8 -0
- package/dist/commands/instant-metal/reinstall.js.map +1 -1
- package/dist/commands/instant-metal/resize.d.ts +2 -0
- package/dist/commands/instant-metal/resize.js +7 -0
- package/dist/commands/instant-metal/resize.js.map +1 -1
- package/dist/commands/instant-metal/stats.d.ts +2 -0
- package/dist/commands/instant-metal/stats.js +6 -0
- package/dist/commands/instant-metal/stats.js.map +1 -1
- package/dist/commands/login.d.ts +1 -0
- package/dist/commands/login.js +1 -0
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.d.ts +1 -0
- package/dist/commands/logout.js +1 -0
- package/dist/commands/logout.js.map +1 -1
- package/dist/commands/order/gpu.d.ts +1 -0
- package/dist/commands/order/gpu.js +3 -0
- package/dist/commands/order/gpu.js.map +1 -1
- package/dist/commands/order/instant-metal.d.ts +1 -0
- package/dist/commands/order/instant-metal.js +3 -0
- package/dist/commands/order/instant-metal.js.map +1 -1
- package/dist/commands/order/storage.d.ts +1 -0
- package/dist/commands/order/storage.js +2 -1
- package/dist/commands/order/storage.js.map +1 -1
- package/dist/commands/order/vps.d.ts +1 -0
- package/dist/commands/order/vps.js +3 -0
- package/dist/commands/order/vps.js.map +1 -1
- package/dist/commands/order.d.ts +1 -0
- package/dist/commands/order.js +1 -0
- package/dist/commands/order.js.map +1 -1
- package/dist/commands/os-images.d.ts +1 -0
- package/dist/commands/os-images.js +4 -1
- package/dist/commands/os-images.js.map +1 -1
- package/dist/commands/payments/index.d.ts +1 -0
- package/dist/commands/payments/index.js +1 -0
- package/dist/commands/payments/index.js.map +1 -1
- package/dist/commands/payments/methods/add.d.ts +1 -0
- package/dist/commands/payments/methods/add.js +1 -0
- package/dist/commands/payments/methods/add.js.map +1 -1
- package/dist/commands/payments/methods/delete.d.ts +1 -0
- package/dist/commands/payments/methods/delete.js +1 -0
- package/dist/commands/payments/methods/delete.js.map +1 -1
- package/dist/commands/payments/methods/index.d.ts +1 -0
- package/dist/commands/payments/methods/index.js +1 -0
- package/dist/commands/payments/methods/index.js.map +1 -1
- package/dist/commands/payments/methods/list.d.ts +1 -0
- package/dist/commands/payments/methods/list.js +1 -0
- package/dist/commands/payments/methods/list.js.map +1 -1
- package/dist/commands/payments/methods/set-default.d.ts +1 -0
- package/dist/commands/payments/methods/set-default.js +1 -0
- package/dist/commands/payments/methods/set-default.js.map +1 -1
- package/dist/commands/projects/index.d.ts +1 -0
- package/dist/commands/projects/index.js +1 -0
- package/dist/commands/projects/index.js.map +1 -1
- package/dist/commands/projects/list.d.ts +1 -0
- package/dist/commands/projects/list.js +1 -0
- package/dist/commands/projects/list.js.map +1 -1
- package/dist/commands/resources.d.ts +1 -0
- package/dist/commands/resources.js +33 -21
- package/dist/commands/resources.js.map +1 -1
- package/dist/commands/settings/index.d.ts +1 -0
- package/dist/commands/settings/index.js +1 -0
- package/dist/commands/settings/index.js.map +1 -1
- package/dist/commands/settings/render-mode.d.ts +1 -0
- package/dist/commands/settings/render-mode.js +1 -0
- package/dist/commands/settings/render-mode.js.map +1 -1
- package/dist/commands/ssh-key/add.d.ts +1 -0
- package/dist/commands/ssh-key/add.js +1 -0
- package/dist/commands/ssh-key/add.js.map +1 -1
- package/dist/commands/ssh-key/delete.d.ts +1 -0
- package/dist/commands/ssh-key/delete.js +1 -0
- package/dist/commands/ssh-key/delete.js.map +1 -1
- package/dist/commands/ssh-key/list.d.ts +1 -0
- package/dist/commands/ssh-key/list.js +1 -0
- package/dist/commands/ssh-key/list.js.map +1 -1
- package/dist/commands/storage/attach.d.ts +2 -1
- package/dist/commands/storage/attach.js +12 -11
- package/dist/commands/storage/attach.js.map +1 -1
- package/dist/commands/storage/detach.d.ts +1 -0
- package/dist/commands/storage/detach.js +3 -2
- package/dist/commands/storage/detach.js.map +1 -1
- package/dist/commands/storage/list.d.ts +1 -0
- package/dist/commands/storage/list.js +2 -1
- package/dist/commands/storage/list.js.map +1 -1
- package/dist/commands/storage/order.d.ts +2 -1
- package/dist/commands/storage/order.js +11 -10
- package/dist/commands/storage/order.js.map +1 -1
- package/dist/commands/storage/resize.d.ts +1 -0
- package/dist/commands/storage/resize.js +1 -0
- package/dist/commands/storage/resize.js.map +1 -1
- package/dist/commands/team/details.d.ts +1 -0
- package/dist/commands/team/details.js +1 -0
- package/dist/commands/team/details.js.map +1 -1
- package/dist/commands/team/invite.d.ts +1 -0
- package/dist/commands/team/invite.js +1 -0
- package/dist/commands/team/invite.js.map +1 -1
- package/dist/commands/team.d.ts +1 -0
- package/dist/commands/team.js +1 -0
- package/dist/commands/team.js.map +1 -1
- package/dist/commands/tickets/close.d.ts +1 -0
- package/dist/commands/tickets/close.js +1 -0
- package/dist/commands/tickets/close.js.map +1 -1
- package/dist/commands/tickets/create.d.ts +1 -0
- package/dist/commands/tickets/create.js +1 -0
- package/dist/commands/tickets/create.js.map +1 -1
- package/dist/commands/tickets/departments.d.ts +1 -0
- package/dist/commands/tickets/departments.js +1 -0
- package/dist/commands/tickets/departments.js.map +1 -1
- package/dist/commands/tickets/list.d.ts +1 -0
- package/dist/commands/tickets/list.js +1 -0
- package/dist/commands/tickets/list.js.map +1 -1
- package/dist/commands/tickets/open.d.ts +1 -0
- package/dist/commands/tickets/open.js +1 -0
- package/dist/commands/tickets/open.js.map +1 -1
- package/dist/commands/tickets/reopen.d.ts +11 -0
- package/dist/commands/tickets/reopen.js +34 -0
- package/dist/commands/tickets/reopen.js.map +1 -0
- package/dist/commands/tickets/reply.d.ts +1 -0
- package/dist/commands/tickets/reply.js +1 -0
- package/dist/commands/tickets/reply.js.map +1 -1
- package/dist/commands/transit.d.ts +1 -0
- package/dist/commands/transit.js +1 -0
- package/dist/commands/transit.js.map +1 -1
- package/dist/commands/tui/index.d.ts +1 -0
- package/dist/commands/tui/index.js +21 -0
- package/dist/commands/tui/index.js.map +1 -1
- package/dist/commands/vds/activity.d.ts +2 -0
- package/dist/commands/vds/activity.js +7 -0
- package/dist/commands/vds/activity.js.map +1 -1
- package/dist/commands/vds/bandwidth.d.ts +2 -0
- package/dist/commands/vds/bandwidth.js +5 -0
- package/dist/commands/vds/bandwidth.js.map +1 -1
- package/dist/commands/vds/boot-order.d.ts +2 -0
- package/dist/commands/vds/boot-order.js +6 -0
- package/dist/commands/vds/boot-order.js.map +1 -1
- package/dist/commands/vds/console.d.ts +2 -0
- package/dist/commands/vds/console.js +6 -0
- package/dist/commands/vds/console.js.map +1 -1
- package/dist/commands/vds/details.d.ts +3 -0
- package/dist/commands/vds/details.js +10 -0
- package/dist/commands/vds/details.js.map +1 -1
- package/dist/commands/vds/index.d.ts +1 -0
- package/dist/commands/vds/index.js +1 -0
- package/dist/commands/vds/index.js.map +1 -1
- package/dist/commands/vds/ip/add.d.ts +2 -0
- package/dist/commands/vds/ip/add.js +7 -0
- package/dist/commands/vds/ip/add.js.map +1 -1
- package/dist/commands/vds/ip/list.d.ts +2 -0
- package/dist/commands/vds/ip/list.js +5 -0
- package/dist/commands/vds/ip/list.js.map +1 -1
- package/dist/commands/vds/list.d.ts +1 -0
- package/dist/commands/vds/list.js +1 -0
- package/dist/commands/vds/list.js.map +1 -1
- package/dist/commands/vds/order.d.ts +2 -0
- package/dist/commands/vds/order.js +12 -3
- package/dist/commands/vds/order.js.map +1 -1
- package/dist/commands/vds/power.d.ts +2 -0
- package/dist/commands/vds/power.js +7 -0
- package/dist/commands/vds/power.js.map +1 -1
- package/dist/commands/vds/reinstall.d.ts +2 -0
- package/dist/commands/vds/reinstall.js +8 -0
- package/dist/commands/vds/reinstall.js.map +1 -1
- package/dist/commands/vds/resize.d.ts +2 -0
- package/dist/commands/vds/resize.js +7 -0
- package/dist/commands/vds/resize.js.map +1 -1
- package/dist/commands/vds/stats.d.ts +2 -0
- package/dist/commands/vds/stats.js +6 -0
- package/dist/commands/vds/stats.js.map +1 -1
- package/dist/commands/vps/activity.d.ts +1 -0
- package/dist/commands/vps/activity.js +5 -4
- package/dist/commands/vps/activity.js.map +1 -1
- package/dist/commands/vps/bandwidth.d.ts +1 -0
- package/dist/commands/vps/bandwidth.js +6 -5
- package/dist/commands/vps/bandwidth.js.map +1 -1
- package/dist/commands/vps/boot-order.d.ts +1 -0
- package/dist/commands/vps/boot-order.js +6 -5
- package/dist/commands/vps/boot-order.js.map +1 -1
- package/dist/commands/vps/console.d.ts +1 -0
- package/dist/commands/vps/console.js +10 -9
- package/dist/commands/vps/console.js.map +1 -1
- package/dist/commands/vps/details.d.ts +5 -0
- package/dist/commands/vps/details.js +21 -9
- package/dist/commands/vps/details.js.map +1 -1
- package/dist/commands/vps/ip/add.d.ts +1 -0
- package/dist/commands/vps/ip/add.js +11 -9
- package/dist/commands/vps/ip/add.js.map +1 -1
- package/dist/commands/vps/ip/list.d.ts +1 -0
- package/dist/commands/vps/ip/list.js +7 -6
- package/dist/commands/vps/ip/list.js.map +1 -1
- package/dist/commands/vps/list.d.ts +1 -0
- package/dist/commands/vps/list.js +5 -4
- package/dist/commands/vps/list.js.map +1 -1
- package/dist/commands/vps/order.d.ts +4 -2
- package/dist/commands/vps/order.js +26 -16
- package/dist/commands/vps/order.js.map +1 -1
- package/dist/commands/vps/power.d.ts +1 -0
- package/dist/commands/vps/power.js +15 -13
- package/dist/commands/vps/power.js.map +1 -1
- package/dist/commands/vps/reinstall.d.ts +1 -0
- package/dist/commands/vps/reinstall.js +15 -14
- package/dist/commands/vps/reinstall.js.map +1 -1
- package/dist/commands/vps/resize.d.ts +1 -0
- package/dist/commands/vps/resize.js +11 -9
- package/dist/commands/vps/resize.js.map +1 -1
- package/dist/commands/vps/stats.d.ts +1 -0
- package/dist/commands/vps/stats.js +8 -7
- package/dist/commands/vps/stats.js.map +1 -1
- package/dist/commands/whoami.d.ts +1 -0
- package/dist/commands/whoami.js +1 -0
- package/dist/commands/whoami.js.map +1 -1
- package/dist/help/help-filter.d.ts +10 -0
- package/dist/help/help-filter.js +9 -0
- package/dist/help/help-filter.js.map +1 -0
- package/dist/help/scope-aware-help.d.ts +30 -0
- package/dist/help/scope-aware-help.js +71 -0
- package/dist/help/scope-aware-help.js.map +1 -0
- package/dist/help.js +0 -1
- package/dist/help.js.map +1 -1
- package/dist/tui/App.js +1 -1
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/components/NumberInput.js +1 -1
- package/dist/tui/components/Sparkline.js +1 -1
- package/dist/tui/screens/Billing.js +10 -10
- package/dist/tui/screens/Billing.js.map +1 -1
- package/dist/tui/screens/Dashboard.js +1 -1
- package/dist/tui/screens/Dashboard.js.map +1 -1
- package/dist/tui/screens/Order.js +328 -99
- package/dist/tui/screens/Order.js.map +1 -1
- package/dist/tui/screens/Resources.js +35 -64
- package/dist/tui/screens/Resources.js.map +1 -1
- package/dist/tui/screens/Tickets.js +31 -22
- package/dist/tui/screens/Tickets.js.map +1 -1
- package/dist/ui/image-resolve.js +1 -1
- package/dist/ui/image-resolve.js.map +1 -1
- package/dist/ui/payment.d.ts +1 -1
- package/dist/ui/resource-detail.d.ts +3 -0
- package/dist/ui/{vps-detail.js → resource-detail.js} +8 -8
- package/dist/ui/resource-detail.js.map +1 -0
- package/dist/ui/resource-resolve.d.ts +4 -0
- package/dist/ui/resource-resolve.js +24 -0
- package/dist/ui/resource-resolve.js.map +1 -0
- package/dist/ui/wait.d.ts +1 -1
- package/dist/ui/wait.js +4 -4
- package/dist/ui/wait.js.map +1 -1
- package/dist/version-check-bin.d.ts +35 -0
- package/dist/version-check-bin.js +123 -0
- package/dist/version-check-bin.js.map +1 -0
- package/dist/version-check.d.ts +39 -0
- package/dist/version-check.js +148 -0
- package/dist/version-check.js.map +1 -0
- package/package.json +11 -6
- package/dist/commands/bare-metal/index.d.ts +0 -4
- package/dist/commands/bare-metal/index.js +0 -5
- package/dist/commands/bare-metal/index.js.map +0 -1
- package/dist/commands/bare-metal/list.d.ts +0 -9
- package/dist/commands/bare-metal/list.js +0 -38
- package/dist/commands/bare-metal/list.js.map +0 -1
- package/dist/commands/bare-metal/order.d.ts +0 -6
- package/dist/commands/bare-metal/order.js +0 -27
- package/dist/commands/bare-metal/order.js.map +0 -1
- package/dist/ui/vps-detail.d.ts +0 -3
- package/dist/ui/vps-detail.js.map +0 -1
- package/dist/ui/vps-resolve.d.ts +0 -4
- package/dist/ui/vps-resolve.js +0 -24
- package/dist/ui/vps-resolve.js.map +0 -1
|
@@ -39,8 +39,7 @@ const emptyDraft = {
|
|
|
39
39
|
const PROGRESS_STEPS = [
|
|
40
40
|
"kind",
|
|
41
41
|
"project",
|
|
42
|
-
"plan",
|
|
43
|
-
"location",
|
|
42
|
+
"plan-location",
|
|
44
43
|
"image",
|
|
45
44
|
"hostname",
|
|
46
45
|
"auth",
|
|
@@ -52,17 +51,15 @@ function stepsForKind(kind) {
|
|
|
52
51
|
if (kind === "vps") {
|
|
53
52
|
base.push("vps-spec", "image", "hostname", "auth", "payment", "summary");
|
|
54
53
|
}
|
|
55
|
-
else if (kind === "gpu" || kind === "dedicated") {
|
|
56
|
-
|
|
54
|
+
else if (kind === "gpu" || kind === "dedicated" || kind === "vds") {
|
|
55
|
+
// Split plan/tier picker + location picker into one step so we can probe
|
|
56
|
+
// per-location availability live (server-side /public/order/validate) and
|
|
57
|
+
// offer notify-me when the chosen location is out of stock.
|
|
58
|
+
base.push("plan-location", "image", "hostname", "auth", "payment", "summary");
|
|
57
59
|
}
|
|
58
60
|
else if (kind === "storage") {
|
|
59
61
|
base.push("size", "location", "hostname", "payment", "summary");
|
|
60
62
|
}
|
|
61
|
-
else if (kind === "vds") {
|
|
62
|
-
// VDS: pick a tier from the ladder, then the standard trailing steps.
|
|
63
|
-
// Server resolves cpu/ram/disk/price from tier_category_slug + tier_index.
|
|
64
|
-
base.push("vds-tier", "location", "image", "hostname", "auth", "payment", "summary");
|
|
65
|
-
}
|
|
66
63
|
else {
|
|
67
64
|
return PROGRESS_STEPS;
|
|
68
65
|
}
|
|
@@ -92,7 +89,7 @@ export function Order() {
|
|
|
92
89
|
(async () => {
|
|
93
90
|
try {
|
|
94
91
|
const [orderCatalog, storageCatalog, projects, methods, balance] = await Promise.all([
|
|
95
|
-
api.
|
|
92
|
+
api.orders.catalog().catch(() => null),
|
|
96
93
|
api.storage.catalog().catch(() => null),
|
|
97
94
|
api.projects.list().catch(() => []),
|
|
98
95
|
api.payments.methods().catch(() => []),
|
|
@@ -242,7 +239,7 @@ export function Order() {
|
|
|
242
239
|
? draft.sshKeyId
|
|
243
240
|
: undefined,
|
|
244
241
|
};
|
|
245
|
-
const out = await api.
|
|
242
|
+
const out = await api.orders.create(body);
|
|
246
243
|
setResult({
|
|
247
244
|
ok: true,
|
|
248
245
|
orderId: out.order_id,
|
|
@@ -288,7 +285,7 @@ function LivePriceFooter({ draft, cat, }) {
|
|
|
288
285
|
React.createElement(Text, { color: colors.dim }, "Est. monthly: "),
|
|
289
286
|
est ? (React.createElement(React.Fragment, null,
|
|
290
287
|
React.createElement(Text, { color: colors.accent, bold: true }, `$${est.amount.toFixed(2)}`),
|
|
291
|
-
React.createElement(Text, { color: colors.dim }, ` · ${est.label}`))) : (React.createElement(Text, { color: colors.dim }, "
|
|
288
|
+
React.createElement(Text, { color: colors.dim }, ` · ${est.label}`))) : (React.createElement(Text, { color: colors.dim }, "-"))));
|
|
292
289
|
}
|
|
293
290
|
function StepRouter(props) {
|
|
294
291
|
const { step, draft, setDraft, cat, goNext } = props;
|
|
@@ -297,12 +294,10 @@ function StepRouter(props) {
|
|
|
297
294
|
return React.createElement(KindStep, { draft: draft, setDraft: setDraft, goNext: goNext });
|
|
298
295
|
case "project":
|
|
299
296
|
return React.createElement(ProjectStep, { projects: cat.projects, draft: draft, setDraft: setDraft, goNext: goNext });
|
|
300
|
-
case "plan":
|
|
301
|
-
return (React.createElement(
|
|
297
|
+
case "plan-location":
|
|
298
|
+
return (React.createElement(PlanLocationStep, { catalog: cat.orderCatalog, userEmail: props.userEmail, draft: draft, setDraft: setDraft, goNext: goNext }));
|
|
302
299
|
case "vps-spec":
|
|
303
300
|
return (React.createElement(VpsSpecStep, { customConfig: cat.orderCatalog?.custom_config ?? null, locations: cat.orderCatalog?.locations ?? [], userEmail: props.userEmail, draft: draft, setDraft: setDraft, goNext: goNext }));
|
|
304
|
-
case "vds-tier":
|
|
305
|
-
return (React.createElement(VdsTierStep, { catalog: cat.orderCatalog, draft: draft, setDraft: setDraft, goNext: goNext }));
|
|
306
301
|
case "size":
|
|
307
302
|
return (React.createElement(SizeStep, { catalog: cat.storageCatalog, draft: draft, setDraft: setDraft, goNext: goNext }));
|
|
308
303
|
case "location":
|
|
@@ -325,7 +320,7 @@ function StepRouter(props) {
|
|
|
325
320
|
case "result":
|
|
326
321
|
return React.createElement(ResultStep, { result: props.result });
|
|
327
322
|
default:
|
|
328
|
-
return React.createElement(Text, null, "
|
|
323
|
+
return React.createElement(Text, null, "-");
|
|
329
324
|
}
|
|
330
325
|
}
|
|
331
326
|
function KindStep({ draft, setDraft, goNext, }) {
|
|
@@ -334,7 +329,7 @@ function KindStep({ draft, setDraft, goNext, }) {
|
|
|
334
329
|
{ value: "vds", label: "VDS", hint: "tier-based performance servers (order via web for now)" },
|
|
335
330
|
{ value: "gpu", label: "GPU", hint: "preset GPU-bearing plans" },
|
|
336
331
|
{ value: "dedicated", label: "Instant Metal", hint: "whole physical hosts" },
|
|
337
|
-
{ value: "storage", label: "Storage", hint: "block volume (attach to a
|
|
332
|
+
{ value: "storage", label: "Storage", hint: "block volume (attach to a resource later)" },
|
|
338
333
|
];
|
|
339
334
|
return (React.createElement(Panel, { title: "What are you ordering?", paddingX: 3, paddingY: 1, width: 80 },
|
|
340
335
|
React.createElement(Menu, { items: items, initialIndex: Math.max(0, items.findIndex((i) => i.value === draft.kind)), onSelect: (v) => {
|
|
@@ -375,33 +370,6 @@ function ProjectStep({ projects, draft, setDraft, goNext, }) {
|
|
|
375
370
|
goNext();
|
|
376
371
|
} })));
|
|
377
372
|
}
|
|
378
|
-
function PlanStep({ catalog, draft, setDraft, goNext, }) {
|
|
379
|
-
if (!catalog) {
|
|
380
|
-
return (React.createElement(Panel, { title: "Catalog unavailable", paddingX: 3, paddingY: 1, width: 80 },
|
|
381
|
-
React.createElement(Text, { color: colors.error }, "Couldn't load the order catalog. Try again later.")));
|
|
382
|
-
}
|
|
383
|
-
const category = draft.kind === "gpu" ? "gpu_cloud" : "dedicated";
|
|
384
|
-
const filtered = catalog.plans.filter((p) => p.category === category || p.category.replace("_", "-") === draft.kind);
|
|
385
|
-
const plans = filtered.length ? filtered : catalog.plans;
|
|
386
|
-
if (plans.length === 0) {
|
|
387
|
-
return (React.createElement(Panel, { title: "No plans in catalog", paddingX: 3, paddingY: 1, width: 80 },
|
|
388
|
-
React.createElement(Text, { color: colors.warning },
|
|
389
|
-
"No ",
|
|
390
|
-
draft.kind,
|
|
391
|
-
" plans are currently offered. Try a different resource type.")));
|
|
392
|
-
}
|
|
393
|
-
const items = plans.map((p) => ({
|
|
394
|
-
value: p.id,
|
|
395
|
-
label: planRowLabel(p),
|
|
396
|
-
hint: planRowHint(p),
|
|
397
|
-
disabled: p.in_stock ? undefined : "out of stock",
|
|
398
|
-
}));
|
|
399
|
-
return (React.createElement(Panel, { title: `Pick a ${draft.kind === "gpu" ? "GPU" : "Instant Metal"} plan`, paddingX: 3, paddingY: 1, width: 80 },
|
|
400
|
-
React.createElement(Menu, { items: items, initialIndex: Math.max(0, items.findIndex((i) => i.value === draft.planId)), onSelect: (v) => {
|
|
401
|
-
setDraft((d) => ({ ...d, planId: v, locationId: null }));
|
|
402
|
-
goNext();
|
|
403
|
-
} })));
|
|
404
|
-
}
|
|
405
373
|
function planRowLabel(p) {
|
|
406
374
|
return `${p.name} $${p.monthly_price}/mo`;
|
|
407
375
|
}
|
|
@@ -412,44 +380,303 @@ function planRowHint(p) {
|
|
|
412
380
|
const extra = p.gpu_model ? ` · ${p.gpu_model}` : "";
|
|
413
381
|
return `${cores} ${ram} ${disk}${extra}`;
|
|
414
382
|
}
|
|
415
|
-
//
|
|
416
|
-
//
|
|
417
|
-
//
|
|
418
|
-
// and
|
|
419
|
-
|
|
383
|
+
// Combined plan/tier + location picker for VDS, GPU Cloud, and Instant Metal.
|
|
384
|
+
// Mirrors what the VPS custom-spec step does: probe /public/order/validate
|
|
385
|
+
// per-location so the user sees which locations can actually fit the pick,
|
|
386
|
+
// and offer marketing.notifyStock when the chosen location is out of stock.
|
|
387
|
+
//
|
|
388
|
+
// The VPS custom-spec flow lives in its own step (VpsSpecStep) because the
|
|
389
|
+
// left pane is a slider grid rather than a plan/tier list - different shape,
|
|
390
|
+
// same idea.
|
|
391
|
+
function PlanLocationStep({ catalog, userEmail, draft, setDraft, goNext, }) {
|
|
392
|
+
const api = useApi();
|
|
420
393
|
if (!catalog) {
|
|
421
394
|
return (React.createElement(Panel, { title: "Catalog unavailable", paddingX: 3, paddingY: 1, width: 80 },
|
|
422
395
|
React.createElement(Text, { color: colors.error }, "Couldn't load the order catalog. Try again later.")));
|
|
423
396
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
397
|
+
const isVds = draft.kind === "vds";
|
|
398
|
+
const isDedicated = draft.kind === "dedicated";
|
|
399
|
+
let picks = [];
|
|
400
|
+
let leftTitle = "Pick a plan";
|
|
401
|
+
const validateKind = isVds ? "vds" : isDedicated ? "instant_metal" : "gpu_cloud";
|
|
402
|
+
if (isVds) {
|
|
403
|
+
// Find an enabled VDS category with a non-empty ladder. Usually
|
|
404
|
+
// exactly one (vds_performance); we take the first enabled.
|
|
405
|
+
const vdsCats = (catalog.categories ?? []).filter((c) => c.slug.startsWith("vds") &&
|
|
406
|
+
c.slider_config?.enabled &&
|
|
407
|
+
(c.slider_config.tiers?.length ?? 0) > 0);
|
|
408
|
+
if (vdsCats.length === 0) {
|
|
409
|
+
return (React.createElement(Panel, { title: "No VDS tiers configured", paddingX: 3, paddingY: 1, width: 80 },
|
|
410
|
+
React.createElement(Text, { color: colors.warning }, "No VDS tier ladders are enabled on this deployment. Pick a different resource kind or order VDS from the web console.")));
|
|
411
|
+
}
|
|
412
|
+
const cat = vdsCats[0];
|
|
413
|
+
leftTitle = `Pick a VDS tier (${cat.name ?? cat.slug})`;
|
|
414
|
+
const tiers = cat.slider_config?.tiers ?? [];
|
|
415
|
+
picks = tiers.map((t, i) => ({
|
|
416
|
+
key: `${cat.slug}#${i}`,
|
|
417
|
+
label: `Tier ${i} $${t.monthly_price}/mo`,
|
|
418
|
+
hint: `${t.cpu}c · ${t.ram_gb}GB RAM · ${t.disk_gb}GB disk · ${t.bandwidth_tb}TB BW`,
|
|
419
|
+
cpu_cores: t.cpu,
|
|
420
|
+
ram_gb: t.ram_gb,
|
|
421
|
+
disk_gb: t.disk_gb,
|
|
422
|
+
monthly_price: t.monthly_price,
|
|
423
|
+
in_stock: true, // VDS ladders don't carry a coarse in-stock flag; rely on per-loc probe below.
|
|
424
|
+
tierCategorySlug: cat.slug,
|
|
425
|
+
tierIndex: i,
|
|
426
|
+
dedicated: false,
|
|
427
|
+
}));
|
|
433
428
|
}
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
429
|
+
else {
|
|
430
|
+
const category = isDedicated ? "dedicated" : "gpu_cloud";
|
|
431
|
+
const filtered = catalog.plans.filter((p) => p.category === category || p.category.replace("_", "-") === draft.kind);
|
|
432
|
+
const plans = filtered.length ? filtered : catalog.plans;
|
|
433
|
+
if (plans.length === 0) {
|
|
434
|
+
return (React.createElement(Panel, { title: "No plans in catalog", paddingX: 3, paddingY: 1, width: 80 },
|
|
435
|
+
React.createElement(Text, { color: colors.warning },
|
|
436
|
+
"No ",
|
|
437
|
+
draft.kind,
|
|
438
|
+
" plans are currently offered. Try a different resource type.")));
|
|
439
|
+
}
|
|
440
|
+
leftTitle = `Pick a ${isDedicated ? "Instant Metal" : "GPU"} plan`;
|
|
441
|
+
picks = plans.map((p) => ({
|
|
442
|
+
key: p.id,
|
|
443
|
+
label: planRowLabel(p),
|
|
444
|
+
hint: planRowHint(p),
|
|
445
|
+
cpu_cores: p.cpu_cores,
|
|
446
|
+
ram_gb: p.ram_gb,
|
|
447
|
+
disk_gb: p.disk_gb,
|
|
448
|
+
monthly_price: p.monthly_price,
|
|
449
|
+
in_stock: p.in_stock,
|
|
450
|
+
planId: p.id,
|
|
451
|
+
dedicated: isDedicated,
|
|
452
|
+
}));
|
|
453
|
+
}
|
|
454
|
+
const locations = catalog.locations;
|
|
455
|
+
const hasLocations = locations.length > 0;
|
|
456
|
+
// Initial cursor: last-picked selection if present, else the first
|
|
457
|
+
// in-stock (plan-level) row; falls back to 0.
|
|
458
|
+
const initialPickIdx = (() => {
|
|
459
|
+
if (isVds && draft.tierIndex != null && draft.tierCategorySlug) {
|
|
460
|
+
const idx = picks.findIndex((p) => p.tierCategorySlug === draft.tierCategorySlug &&
|
|
461
|
+
p.tierIndex === draft.tierIndex);
|
|
462
|
+
if (idx >= 0)
|
|
463
|
+
return idx;
|
|
464
|
+
}
|
|
465
|
+
if (!isVds && draft.planId) {
|
|
466
|
+
const idx = picks.findIndex((p) => p.planId === draft.planId);
|
|
467
|
+
if (idx >= 0)
|
|
468
|
+
return idx;
|
|
469
|
+
}
|
|
470
|
+
const firstInStock = picks.findIndex((p) => p.in_stock);
|
|
471
|
+
return firstInStock >= 0 ? firstInStock : 0;
|
|
472
|
+
})();
|
|
473
|
+
const [pickCursor, setPickCursor] = useState(initialPickIdx);
|
|
474
|
+
const [locCursor, setLocCursor] = useState(() => {
|
|
475
|
+
const idx = locations.findIndex((l) => l.id === draft.locationId);
|
|
476
|
+
return idx >= 0 ? idx : 0;
|
|
477
|
+
});
|
|
478
|
+
const [pane, setPane] = useState("pick");
|
|
479
|
+
const [notifyState, setNotifyState] = useState("idle");
|
|
480
|
+
// Availability probe keyed on (pickCursor, location). Cleared whenever
|
|
481
|
+
// the pick changes so a stale in-stock badge can't survive a tier switch.
|
|
482
|
+
const [stockByLoc, setStockByLoc] = useState({});
|
|
483
|
+
const currentPick = picks[pickCursor];
|
|
484
|
+
useEffect(() => {
|
|
485
|
+
// Reset probe results when the pick changes - a Tier 2 might fit where
|
|
486
|
+
// Tier 3 does not (and vice versa), so old flags would lie.
|
|
487
|
+
setStockByLoc({});
|
|
488
|
+
setNotifyState("idle");
|
|
489
|
+
}, [pickCursor]);
|
|
490
|
+
useEffect(() => {
|
|
491
|
+
if (!hasLocations || !currentPick)
|
|
492
|
+
return;
|
|
493
|
+
if (!currentPick.in_stock)
|
|
494
|
+
return; // Plan globally OOS - nothing to probe.
|
|
495
|
+
let cancelled = false;
|
|
496
|
+
// Small debounce so switching picks quickly doesn't fire N * K validate
|
|
497
|
+
// calls.
|
|
498
|
+
const t = setTimeout(() => {
|
|
499
|
+
for (const loc of locations) {
|
|
500
|
+
api.orders
|
|
501
|
+
.validate({
|
|
502
|
+
cpu_cores: currentPick.cpu_cores,
|
|
503
|
+
ram_gb: currentPick.ram_gb,
|
|
504
|
+
disk_gb: currentPick.disk_gb,
|
|
505
|
+
location_id: loc.id,
|
|
506
|
+
dedicated: currentPick.dedicated,
|
|
507
|
+
kind: validateKind,
|
|
508
|
+
})
|
|
509
|
+
.then((res) => {
|
|
510
|
+
if (cancelled)
|
|
511
|
+
return;
|
|
512
|
+
setStockByLoc((m) => ({ ...m, [loc.id]: res.available }));
|
|
513
|
+
})
|
|
514
|
+
.catch(() => {
|
|
515
|
+
// Swallow - the location just stays unmarked; the server will
|
|
516
|
+
// fail the order if the spec truly can't fit, and we've already
|
|
517
|
+
// let the user see the pick.
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
}, 250);
|
|
521
|
+
return () => {
|
|
522
|
+
cancelled = true;
|
|
523
|
+
clearTimeout(t);
|
|
524
|
+
};
|
|
525
|
+
// Re-run whenever the pick's specs, the location list, or the kind changes.
|
|
526
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
527
|
+
}, [
|
|
528
|
+
hasLocations,
|
|
529
|
+
currentPick?.cpu_cores,
|
|
530
|
+
currentPick?.ram_gb,
|
|
531
|
+
currentPick?.disk_gb,
|
|
532
|
+
currentPick?.dedicated,
|
|
533
|
+
validateKind,
|
|
534
|
+
locations,
|
|
535
|
+
]);
|
|
536
|
+
const selLoc = hasLocations ? locations[locCursor] ?? null : null;
|
|
537
|
+
const planLevelOOS = Boolean(currentPick && !currentPick.in_stock);
|
|
538
|
+
const locStockKnown = selLoc ? stockByLoc[selLoc.id] !== undefined : false;
|
|
539
|
+
const selInStock = !hasLocations ||
|
|
540
|
+
(!planLevelOOS && (!locStockKnown || stockByLoc[selLoc?.id ?? ""] !== false));
|
|
541
|
+
const canContinue = Boolean(currentPick) && Boolean(selLoc) && selInStock;
|
|
542
|
+
const commit = () => {
|
|
543
|
+
if (!currentPick || !selLoc)
|
|
544
|
+
return;
|
|
545
|
+
setDraft((d) => ({
|
|
546
|
+
...d,
|
|
547
|
+
planId: currentPick.planId ?? null,
|
|
548
|
+
tierCategorySlug: currentPick.tierCategorySlug ?? null,
|
|
549
|
+
tierIndex: currentPick.tierIndex ?? null,
|
|
550
|
+
locationId: selLoc.id,
|
|
551
|
+
}));
|
|
552
|
+
goNext();
|
|
553
|
+
};
|
|
554
|
+
const requestNotify = async () => {
|
|
555
|
+
if (!selLoc || !currentPick)
|
|
556
|
+
return;
|
|
557
|
+
if (notifyState === "sending" || notifyState === "sent")
|
|
558
|
+
return;
|
|
559
|
+
if (!userEmail) {
|
|
560
|
+
setNotifyState("error");
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
setNotifyState("sending");
|
|
564
|
+
try {
|
|
565
|
+
await api.marketing.notifyStock({
|
|
566
|
+
email: userEmail,
|
|
567
|
+
location_id: selLoc.id,
|
|
568
|
+
plan_id: currentPick.planId ?? null,
|
|
569
|
+
note: `CLI order wizard - ${draft.kind}`,
|
|
570
|
+
config_json: {
|
|
571
|
+
cpu_cores: currentPick.cpu_cores,
|
|
572
|
+
ram_gb: currentPick.ram_gb,
|
|
573
|
+
disk_gb: currentPick.disk_gb,
|
|
574
|
+
dedicated: currentPick.dedicated,
|
|
575
|
+
kind: validateKind,
|
|
576
|
+
tier_category_slug: currentPick.tierCategorySlug ?? null,
|
|
577
|
+
tier_index: currentPick.tierIndex ?? null,
|
|
578
|
+
},
|
|
579
|
+
});
|
|
580
|
+
setNotifyState("sent");
|
|
581
|
+
}
|
|
582
|
+
catch {
|
|
583
|
+
setNotifyState("error");
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
useInput((input, key) => {
|
|
587
|
+
if (key.tab) {
|
|
588
|
+
if (hasLocations)
|
|
589
|
+
setPane((p) => (p === "pick" ? "loc" : "pick"));
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
if (pane === "pick") {
|
|
593
|
+
if (key.upArrow) {
|
|
594
|
+
setPickCursor((c) => (c === 0 ? picks.length - 1 : c - 1));
|
|
595
|
+
}
|
|
596
|
+
else if (key.downArrow) {
|
|
597
|
+
setPickCursor((c) => (c === picks.length - 1 ? 0 : c + 1));
|
|
598
|
+
}
|
|
599
|
+
else if (key.return || key.rightArrow) {
|
|
600
|
+
if (hasLocations)
|
|
601
|
+
setPane("loc");
|
|
602
|
+
else
|
|
603
|
+
commit();
|
|
604
|
+
}
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
// pane === "loc"
|
|
608
|
+
if (key.upArrow) {
|
|
609
|
+
setLocCursor((c) => (c === 0 ? locations.length - 1 : c - 1));
|
|
610
|
+
}
|
|
611
|
+
else if (key.downArrow) {
|
|
612
|
+
setLocCursor((c) => (c === locations.length - 1 ? 0 : c + 1));
|
|
613
|
+
}
|
|
614
|
+
else if (key.leftArrow) {
|
|
615
|
+
setPane("pick");
|
|
616
|
+
}
|
|
617
|
+
else if (key.return) {
|
|
618
|
+
if (canContinue)
|
|
619
|
+
commit();
|
|
620
|
+
else
|
|
621
|
+
void requestNotify();
|
|
622
|
+
}
|
|
623
|
+
});
|
|
624
|
+
const buttonLabel = canContinue
|
|
625
|
+
? "Continue"
|
|
626
|
+
: notifyState === "sent"
|
|
627
|
+
? "Requested ✓"
|
|
628
|
+
: notifyState === "sending"
|
|
629
|
+
? "Sending…"
|
|
630
|
+
: "Notify me";
|
|
631
|
+
const pickPanel = (React.createElement(Panel, { title: leftTitle, paddingX: 2, paddingY: 1, width: hasLocations ? 50 : 80, borderColor: pane === "pick" ? colors.accent : undefined },
|
|
632
|
+
React.createElement(Box, { flexDirection: "column" },
|
|
633
|
+
picks.map((p, i) => {
|
|
634
|
+
const isCursor = i === pickCursor;
|
|
635
|
+
const disabled = !p.in_stock;
|
|
636
|
+
return (React.createElement(Box, { key: p.key },
|
|
637
|
+
React.createElement(Text, { color: isCursor
|
|
638
|
+
? pane === "pick"
|
|
639
|
+
? colors.accent
|
|
640
|
+
: colors.text
|
|
641
|
+
: colors.dim }, isCursor ? `${glyphs.chevronRight} ` : " "),
|
|
642
|
+
React.createElement(Text, { bold: isCursor, color: disabled
|
|
643
|
+
? colors.dim
|
|
644
|
+
: isCursor && pane === "pick"
|
|
645
|
+
? colors.accent
|
|
646
|
+
: colors.text }, p.label),
|
|
647
|
+
React.createElement(Text, { color: colors.dim }, ` ${p.hint}`),
|
|
648
|
+
disabled ? (React.createElement(Text, { color: colors.dim }, " out of stock")) : null));
|
|
649
|
+
}),
|
|
650
|
+
React.createElement(Box, { marginTop: 1 },
|
|
651
|
+
React.createElement(ActionButton, { keybind: "\u21B5", label: buttonLabel, onPress: () => (canContinue ? commit() : void requestNotify()), focused: pane === "pick" && !hasLocations })),
|
|
652
|
+
selLoc && !canContinue && currentPick ? (React.createElement(Box, null,
|
|
653
|
+
React.createElement(Text, { color: notifyState === "sent" ? colors.dim : colors.warning }, notifyState === "sent"
|
|
654
|
+
? `We'll email you when ${selLoc.city ?? selLoc.name} has capacity for this ${isVds ? "tier" : "plan"}.`
|
|
655
|
+
: `${selLoc.city ?? selLoc.name} can't fit this ${isVds ? "tier" : "plan"} right now - we can email you when it can.`))) : null,
|
|
656
|
+
notifyState === "error" ? (React.createElement(Box, null,
|
|
657
|
+
React.createElement(Text, { color: colors.error }, "Couldn't save the notification - try again."))) : null)));
|
|
658
|
+
if (!hasLocations)
|
|
659
|
+
return pickPanel;
|
|
660
|
+
return (React.createElement(Box, { flexDirection: "row", width: 80 },
|
|
661
|
+
pickPanel,
|
|
662
|
+
React.createElement(Panel, { title: "Location", paddingX: 1, paddingY: 1, width: 30, borderColor: pane === "loc" ? colors.accent : undefined },
|
|
663
|
+
React.createElement(Box, { flexDirection: "column" }, locations.map((l, i) => {
|
|
664
|
+
const isCursor = i === locCursor;
|
|
665
|
+
const known = stockByLoc[l.id];
|
|
666
|
+
const oos = planLevelOOS || known === false;
|
|
667
|
+
const name = [l.city ?? l.name, l.country ?? ""]
|
|
668
|
+
.filter(Boolean)
|
|
669
|
+
.join(", ");
|
|
670
|
+
return (React.createElement(Box, { key: l.id, flexDirection: "column" },
|
|
671
|
+
React.createElement(Box, null,
|
|
672
|
+
React.createElement(Text, { color: isCursor
|
|
673
|
+
? pane === "loc"
|
|
674
|
+
? colors.accent
|
|
675
|
+
: colors.text
|
|
676
|
+
: colors.dim }, isCursor ? `${glyphs.chevronRight} ` : " "),
|
|
677
|
+
React.createElement(Text, { wrap: "truncate-end", bold: isCursor, dimColor: oos, color: oos ? colors.dim : isCursor ? colors.accent : colors.text }, name)),
|
|
678
|
+
oos ? (React.createElement(Text, { color: colors.dim }, " out of stock")) : known === undefined ? (React.createElement(Text, { color: colors.dim }, ` ${l.code ?? "checking…"}`)) : l.code ? (React.createElement(Text, { color: colors.dim }, ` ${l.code}`)) : null));
|
|
679
|
+
})))));
|
|
453
680
|
}
|
|
454
681
|
function VpsSpecStep({ customConfig, locations, userEmail, draft, setDraft, goNext, }) {
|
|
455
682
|
if (!customConfig?.enabled) {
|
|
@@ -492,8 +719,8 @@ function VpsSpecFieldsStep({ customConfig, locations, userEmail, draft, setDraft
|
|
|
492
719
|
let cancelled = false;
|
|
493
720
|
const t = setTimeout(() => {
|
|
494
721
|
for (const loc of locations) {
|
|
495
|
-
api.
|
|
496
|
-
.
|
|
722
|
+
api.orders
|
|
723
|
+
.validate({
|
|
497
724
|
cpu_cores: cpuN,
|
|
498
725
|
ram_gb: ramN,
|
|
499
726
|
disk_gb: diskN,
|
|
@@ -588,7 +815,7 @@ function VpsSpecFieldsStep({ customConfig, locations, userEmail, draft, setDraft
|
|
|
588
815
|
await api.marketing.notifyStock({
|
|
589
816
|
email: userEmail,
|
|
590
817
|
location_id: selLoc.id,
|
|
591
|
-
note: "CLI order wizard
|
|
818
|
+
note: "CLI order wizard - custom VPS",
|
|
592
819
|
config_json: {
|
|
593
820
|
cpu_cores: Number(cpu) || null,
|
|
594
821
|
ram_gb: Number(ramGb) || null,
|
|
@@ -672,9 +899,9 @@ function VpsSpecFieldsStep({ customConfig, locations, userEmail, draft, setDraft
|
|
|
672
899
|
!selInStock && selLoc ? (React.createElement(Box, null,
|
|
673
900
|
React.createElement(Text, { color: notifyState === "sent" ? colors.dim : colors.warning }, notifyState === "sent"
|
|
674
901
|
? `We'll email you when ${selLoc.city ?? selLoc.name} is back in stock.`
|
|
675
|
-
: `${selLoc.city ?? selLoc.name} is out of stock
|
|
902
|
+
: `${selLoc.city ?? selLoc.name} is out of stock - we can email you when it's back.`))) : null,
|
|
676
903
|
notifyState === "error" ? (React.createElement(Box, null,
|
|
677
|
-
React.createElement(Text, { color: colors.error }, "Couldn't save the notification
|
|
904
|
+
React.createElement(Text, { color: colors.error }, "Couldn't save the notification - try again."))) : null,
|
|
678
905
|
React.createElement(Box, { marginTop: 1 },
|
|
679
906
|
React.createElement(Text, { color: colors.dim }, hasLocations
|
|
680
907
|
? "Tab location/spec · ↑↓ move · ←/→ CPU type · Enter continue"
|
|
@@ -954,7 +1181,7 @@ function PaymentStep({ methods, creditBalance, balanceCurrency, estimatedCost, d
|
|
|
954
1181
|
else {
|
|
955
1182
|
if (!draft.paymentMethodId && !(draft.applyCredits && creditsCover)) {
|
|
956
1183
|
setErr(creditBalance > 0
|
|
957
|
-
? "Pick a payment method
|
|
1184
|
+
? "Pick a payment method - credits don't cover the full amount."
|
|
958
1185
|
: "Pick a payment method.");
|
|
959
1186
|
return;
|
|
960
1187
|
}
|
|
@@ -1015,7 +1242,7 @@ function PaymentStep({ methods, creditBalance, balanceCurrency, estimatedCost, d
|
|
|
1015
1242
|
isBitpay ? (React.createElement(Box, { marginTop: 1 },
|
|
1016
1243
|
React.createElement(Text, { color: colors.dim }, "BitPay opens a hosted checkout URL in your browser after submit."))) : null,
|
|
1017
1244
|
methods.length !== eligible.length ? (React.createElement(Box, { marginTop: 1 },
|
|
1018
|
-
React.createElement(Text, { color: colors.dim }, "Stripe ACH hidden
|
|
1245
|
+
React.createElement(Text, { color: colors.dim }, "Stripe ACH hidden - it can't settle instant charges. Pay an existing invoice in Billing instead."))) : null,
|
|
1019
1246
|
err ? (React.createElement(Box, { marginTop: 1 },
|
|
1020
1247
|
React.createElement(Text, { color: colors.error }, err))) : null,
|
|
1021
1248
|
React.createElement(Box, { marginTop: 1 },
|
|
@@ -1057,9 +1284,9 @@ function SummaryStep({ draft, cat, onSubmit, onEdit, }) {
|
|
|
1057
1284
|
const specLine = draft.kind === "vps"
|
|
1058
1285
|
? `${draft.customSpec.cpu_cores ?? "?"} vCPU · ${draft.customSpec.ram_gb ?? 0} GB RAM · ${draft.customSpec.disk_gb ?? "?"} GB disk${draft.customSpec.bandwidth_tb ? ` · ${draft.customSpec.bandwidth_tb} TB BW` : ""}${draft.customSpec._dedicated ? " · dedicated" : ""}`
|
|
1059
1286
|
: draft.kind === "vds" && vdsTier
|
|
1060
|
-
? `Tier ${draft.tierIndex}
|
|
1287
|
+
? `Tier ${draft.tierIndex} - ${vdsTier.cpu}c ${vdsTier.ram_gb}G ${vdsTier.disk_gb}G · ${vdsTier.bandwidth_tb}TB BW ($${vdsTier.monthly_price}/mo)`
|
|
1061
1288
|
: plan
|
|
1062
|
-
? `${plan.name}
|
|
1289
|
+
? `${plan.name} - ${plan.cpu_cores}c ${plan.ram_gb}G ${plan.disk_gb}G${plan.gpu_model ? ` · ${plan.gpu_model}` : ""}`
|
|
1063
1290
|
: undefined;
|
|
1064
1291
|
const paymentLabel = (() => {
|
|
1065
1292
|
const parts = [];
|
|
@@ -1072,17 +1299,17 @@ function SummaryStep({ draft, cat, onSubmit, onEdit, }) {
|
|
|
1072
1299
|
})();
|
|
1073
1300
|
return (React.createElement(Panel, { title: "Review your order", paddingX: 3, paddingY: 1, width: 80 },
|
|
1074
1301
|
React.createElement(Box, { flexDirection: "column" },
|
|
1075
|
-
React.createElement(Row, { label: "Kind", value: draft.kind ?? "
|
|
1076
|
-
React.createElement(Row, { label: "Project", value: projectName ?? draft.projectId ?? "
|
|
1077
|
-
draft.kind === "storage" ? (React.createElement(Row, { label: "Size", value: draft.storageSizeGb ? `${draft.storageSizeGb} GB` : "
|
|
1078
|
-
React.createElement(Row, { label: "Location", value: locName ?? draft.locationId ?? "
|
|
1079
|
-
draft.kind !== "storage" ? (React.createElement(Row, { label: "Image", value: imageName ?? draft.imageId ?? "
|
|
1080
|
-
React.createElement(Row, { label: draft.kind === "storage" ? "Name" : "Hostname", value: draft.hostname || "
|
|
1302
|
+
React.createElement(Row, { label: "Kind", value: draft.kind ?? "-" }),
|
|
1303
|
+
React.createElement(Row, { label: "Project", value: projectName ?? draft.projectId ?? "-" }),
|
|
1304
|
+
draft.kind === "storage" ? (React.createElement(Row, { label: "Size", value: draft.storageSizeGb ? `${draft.storageSizeGb} GB` : "-" })) : (React.createElement(Row, { label: "Spec", value: specLine ?? "-" })),
|
|
1305
|
+
React.createElement(Row, { label: "Location", value: locName ?? draft.locationId ?? "-" }),
|
|
1306
|
+
draft.kind !== "storage" ? (React.createElement(Row, { label: "Image", value: imageName ?? draft.imageId ?? "-" })) : null,
|
|
1307
|
+
React.createElement(Row, { label: draft.kind === "storage" ? "Name" : "Hostname", value: draft.hostname || "-" }),
|
|
1081
1308
|
draft.kind !== "storage" ? (React.createElement(Row, { label: "Auth", value: draft.authKind === "password"
|
|
1082
1309
|
? "root password (hidden)"
|
|
1083
1310
|
: draft.authKind === "ssh-paste"
|
|
1084
1311
|
? "pasted SSH public key"
|
|
1085
|
-
: "
|
|
1312
|
+
: "-" })) : null,
|
|
1086
1313
|
React.createElement(Row, { label: "Payment", value: paymentLabel }),
|
|
1087
1314
|
React.createElement(Box, { marginTop: 1 },
|
|
1088
1315
|
React.createElement(Menu, { items: [
|
|
@@ -1100,7 +1327,7 @@ function Row({ label, value }) {
|
|
|
1100
1327
|
return (React.createElement(Box, null,
|
|
1101
1328
|
React.createElement(Box, { width: 14 },
|
|
1102
1329
|
React.createElement(Text, { color: colors.dim }, label)),
|
|
1103
|
-
React.createElement(Text, { color: colors.text }, value === undefined || value === null || value === "" ? "
|
|
1330
|
+
React.createElement(Text, { color: colors.text }, value === undefined || value === null || value === "" ? "-" : String(value))));
|
|
1104
1331
|
}
|
|
1105
1332
|
function ResultStep({ result, }) {
|
|
1106
1333
|
if (!result) {
|
|
@@ -1117,13 +1344,13 @@ function ResultStep({ result, }) {
|
|
|
1117
1344
|
return (React.createElement(Panel, { title: "Order submitted", paddingX: 3, paddingY: 1, width: 80, borderColor: colors.success },
|
|
1118
1345
|
React.createElement(Box, { flexDirection: "column" },
|
|
1119
1346
|
React.createElement(Row, { label: "Status", value: result.status ?? "ok" }),
|
|
1120
|
-
React.createElement(Row, { label: "Order id", value: result.orderId ?? "
|
|
1121
|
-
React.createElement(Row, { label: "Invoice id", value: result.invoiceId ?? "
|
|
1347
|
+
React.createElement(Row, { label: "Order id", value: result.orderId ?? "-" }),
|
|
1348
|
+
React.createElement(Row, { label: "Invoice id", value: result.invoiceId ?? "-" }),
|
|
1122
1349
|
result.checkoutUrl ? React.createElement(Row, { label: "Checkout URL", value: result.checkoutUrl }) : null,
|
|
1123
1350
|
React.createElement(Box, { marginTop: 1 },
|
|
1124
1351
|
React.createElement(Text, { color: color }, result.checkoutUrl
|
|
1125
1352
|
? "Open the checkout URL in your browser to complete payment."
|
|
1126
|
-
: "All done
|
|
1353
|
+
: "All done - see Resources to watch provisioning.")),
|
|
1127
1354
|
React.createElement(Box, { marginTop: 1 },
|
|
1128
1355
|
React.createElement(Text, { color: colors.dim }, "Press Esc or Enter to return to Dashboard.")))));
|
|
1129
1356
|
}
|
|
@@ -1148,6 +1375,8 @@ function tipForStep(step, draft, cancelConfirm) {
|
|
|
1148
1375
|
return "↑↓ to choose, Enter to select. Esc to cancel.";
|
|
1149
1376
|
case "vps-spec":
|
|
1150
1377
|
return "Tab location/spec · ↑↓ move · Enter continue · Esc back.";
|
|
1378
|
+
case "plan-location":
|
|
1379
|
+
return "Tab pick/location · ↑↓ move · Enter continue (or Notify me if OOS) · Esc back.";
|
|
1151
1380
|
case "hostname":
|
|
1152
1381
|
return "Type a hostname (5–253 chars). Enter to confirm · Esc back.";
|
|
1153
1382
|
case "auth":
|
|
@@ -1182,7 +1411,7 @@ function buildCustomSpec(s) {
|
|
|
1182
1411
|
function fingerprint(pubKey) {
|
|
1183
1412
|
const parts = pubKey.trim().split(/\s+/);
|
|
1184
1413
|
if (parts.length === 0)
|
|
1185
|
-
return "
|
|
1414
|
+
return "-";
|
|
1186
1415
|
const algo = parts[0] ?? "";
|
|
1187
1416
|
const b64 = parts[1] ?? "";
|
|
1188
1417
|
const comment = parts.slice(2).join(" ");
|