PageSourceSearch

https://kalcend.ai/assets/CreateVPS-C-ig497F.js

js kalcend.ai collected 2026-10-05 12:08:18 UTC 12,759 bytes, 1 lines download raw bytes

1import{a3 as se,ac as Q,j as e,u as ae,r as i,a4 as ie,A as ne,Z as A,W as re,ao as oe,am as le,aj as I,b7 as F}from"./index-BTfcerCQ.js";import{u as T,r as ce,R as de}from"./useResourceQuery-c3hGxJCK.js";import{u as me,C as xe}from"./CreationRecovery-BwFj3CRG.js";import{p as pe,c as ue}from"./creation-receipt-zsUILuZj.js";import{c as he}from"./vps.service-SvnsPYND.js";import{u as ge}from"./compute-rental-prices-DznjrUxx.js";import{b as be,e as fe}from"./credentials.service-GXUgE63K.js";import{l as ve}from"./vpc-network.service-CgtsZ3i1.js";import{D as je,a as Se,f as $}from"./droplet-catalog-3LuwKRes.js";import{E as q}from"./external-link-QhT4jVJo.js";import"./compute-display-CuW_BjN7.js";import"./public-prices-wdLUpuWf.js";import"./retail-contract-Ka-PrhW-.js";const ye=[["path",{d:"M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z",key:"p7xjir"}]],we=se("cloud",ye),Ce="'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif",Ne="'JetBrains Mono', ui-monospace, SFMono-Regular, monospace",B="min-h-10 min-w-0 w-full px-3 py-2 bg-white/[0.04] border border-white/[0.06] text-sm text-[#cfcfcf] placeholder-[#5C5C5C] focus:outline-none focus:ring-2 focus:ring-white/[0.15] focus:border-white/[0.2] transition-all duration-200";function Fe(){const d=Q();return e.jsx(ke,{},d)}function ke(){const d=ae(),u=Q(),[x,_]=i.useState(""),[h,L]=i.useState("byovps"),c=T("vps-ssh-credentials",async t=>{const[a,te]=await Promise.all([be(t,["ssh"]),fe()]);return{credentials:a,toolUsedIds:te}},h==="byovps"),b=i.useMemo(()=>c.data?.credentials??[],[c.data]),w=i.useMemo(()=>c.data?.toolUsedIds??new Set,[c.data]),C=c.loading,[f,W]=i.useState(""),p=T("compute-creation-networks",async t=>ce(await ve(t)),h==="digitalocean"),n=i.useMemo(()=>p.data??[],[p.data]),v=p.loading,[o,R]=i.useState(""),[N,G]=i.useState(je),{saving:j,error:O,setError:k,begin:Y,finish:Z,isCurrent:P}=ie(),l=me(),m=j||!!l.attempt||!u,[V,S]=i.useState("idle"),s=h==="digitalocean",r=ge("vps"),y=r.options.find(t=>t.slug===N);i.useEffect(()=>{!o&&n.length&&R(n.find(t=>t.isDefault)?.id??n[0].id)},[n,o]);const z=t=>Se.find(a=>a.slug===t)?.label||t,J=(t,a)=>`${t.replace(/\d+$/,"")}-z${a}`,K=!!u&&!p.error&&!v&&n.length===0,g=b.find(t=>t.id===f),X=x.trim().length>0&&x.trim().length<=80,E=!!g&&g.status==="active"&&!g.managed&&!g.infraLocked&&!w.has(g.id),H=!!u&&!j&&(!!l.attempt||X&&(s?n.some(t=>t.id===o)&&!!y&&!r.error&&!r.loading&&!v&&!p.error:E&&!C&&!c.error)),D=i.useMemo(()=>b.map(t=>{const a=t.status!=="active"?"Credential is not active":t.managed?"Managed platform credential":t.infraLocked?"Already backs a VPS":w.has(t.id)?"In use as an agent tool — pick another":null;return{value:t.id,label:t.name,disabled:!!a,description:a??(t.isValidated?"Validated SSH credential":"SSH credential")}}),[b,w]),M=i.useMemo(()=>n.map(t=>({value:t.id,label:t.isDefault?`${t.name} (default)`:t.name,description:t.zone===null?z(t.region):`${z(t.region)} · ${J(t.region,t.zone)}`})),[n]),ee=async()=>{if(!(!H||!Y())){k(null),S("submitting");try{const t=l.beginRequest(s?{name:x.trim(),provider:"digitalocean",vpcId:o,sizeSlug:N,purchaseQuote:y?.purchaseQuote}:{name:x.trim(),provider:"byovps",sshCredentialId:f}),a=await he({...t.input,requestId:t.id});if(!P())return;a.success&&a.vpsId?(S("saving"),d(`/app/vps/${a.vpsId}`,{state:{message:pe(s?"Droplet":"VPS",a),type:a.provisionStatus==="failed"?"error":"success"}})):(l.failed(a),k(a.error||(s?"Could not confirm droplet creation.":"Could not confirm VPS creation.")),P()&&S("idle"))}catch(t){k(ue(t).error??null),P()&&S("idle")}finally{Z()}}},U=()=>{d("/app/credentials/create?mode=ssh")};return e.jsxs("div",{className:"w-full min-w-0 flex flex-col space-y-6 max-w-3xl mx-auto",style:{fontFamily:Ce},children:[e.jsxs("button",{onClick:()=>d("/app/vps"),className:"min-h-10 inline-flex items-center gap-2 text-sm text-[#8e8e8e] hover:text-white transition-colors w-fit",children:[e.jsx(ne,{size:14}),"Back to VPS instances"]}),e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-semibold tracking-[-0.02em] text-white",children:"Add VPS"}),e.jsx("p",{className:"mt-1 text-sm text-[#949494]",children:s?"Provision a managed DigitalOcean droplet. We create the box and bill your wallet — it boots in the background.":"Register a VPS using an existing SSH credential. Connection and sudo checks run in the background; the VPS detail page shows their outcome."})]}),!s&&e.jsxs("div",{className:"bg-white/[0.04] border border-white/[0.06] rounded p-4 flex items-start gap-2.5",children:[e.jsx(A,{size:14,className:"text-[#d4a04a] flex-shrink-0 mt-0.5"}),e.jsxs("p",{className:"text-xs text-[#949494]",children:["The SSH credential must be ",e.jsx("span",{className:"text-[#cfcfcf]",children:"sudo-allowed"})," — managing a server needs elevated access. That's the only requirement to connect a VPS; any capability or capacity checks happen later, when you put a specific workload on it."]})]}),!u&&e.jsx("p",{role:"alert",className:"text-sm text-red-400",children:"Select an organization to create resources."}),e.jsx(de,{query:s?p:c}),e.jsx(xe,{attempt:l.attempt,path:"/app/vps",saving:j}),!l.attempt&&s&&!!o&&!v&&!n.some(t=>t.id===o)&&e.jsx("p",{role:"alert",className:"text-sm text-amber-400",children:"The selected network is no longer available. Choose another network."}),!l.attempt&&!s&&!!f&&!C&&!E&&e.jsx("p",{role:"alert",className:"text-sm text-amber-400",children:"The selected SSH credential is no longer eligible. Choose another credential."}),O&&e.jsxs("div",{role:"alert",className:"bg-[#ef4444]/10 border border-[#ef4444]/20 rounded p-4 flex items-start gap-2.5",children:[e.jsx(re,{size:14,className:"text-[#ef4444] flex-shrink-0 mt-0.5"}),e.jsx("p",{className:"text-sm text-[#ef4444]",children:O})]}),e.jsxs("div",{className:"bg-[#1A1A1A] border border-white/[0.06] rounded p-6 space-y-6",children:[e.jsxs("div",{children:[e.jsx("label",{htmlFor:"vps-name",className:"block text-xs font-medium uppercase tracking-[0.08em] text-[#8e8e8e] mb-2",children:"Name"}),e.jsx("input",{id:"vps-name",type:"text",value:x,onChange:t=>_(t.target.value),placeholder:"e.g. prod-box-1",maxLength:80,disabled:m,className:B}),e.jsxs("p",{className:"mt-1.5 text-[11px] text-[#5C5C5C]",children:[x.length,"/80"]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-medium uppercase tracking-[0.08em] text-[#8e8e8e] mb-2",children:"Provider"}),e.jsxs("div",{role:"group","aria-label":"Provider",className:"min-h-10 max-w-full inline-flex flex-wrap p-0.5 bg-white/[0.04] border border-white/[0.06] rounded",children:[e.jsxs("button",{type:"button","aria-pressed":h==="byovps",onClick:()=>L("byovps"),disabled:m,className:`min-h-10 inline-flex items-center gap-1.5 px-3 py-1.5 rounded text-sm transition-colors disabled:opacity-40 ${s?"text-[#cfcfcf] hover:text-white":"bg-white text-[#0A0908] font-medium"}`,children:[e.jsx(oe,{size:12}),"Bring your own VPS"]}),e.jsxs("button",{type:"button","aria-pressed":h==="digitalocean",onClick:()=>L("digitalocean"),disabled:m,className:`min-h-10 inline-flex items-center gap-1.5 px-3 py-1.5 rounded text-sm transition-colors disabled:opacity-40 ${s?"bg-white text-[#0A0908] font-medium":"text-[#cfcfcf] hover:text-white"}`,children:[e.jsx(we,{size:12}),"DigitalOcean droplet"]})]}),e.jsx("p",{className:"mt-1.5 text-[11px] text-[#5C5C5C]",children:s?"We provision and manage a DigitalOcean droplet for you — billed to your wallet.":"Attach an existing SSH credential to a server you already run."})]}),s?e.jsxs(e.Fragment,{children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-medium uppercase tracking-[0.08em] text-[#8e8e8e] mb-2",children:"VPC Network"}),v?e.jsx("div",{className:"text-xs text-[#5C5C5C] py-2",children:"Loading networks…"}):K&&!l.attempt?e.jsxs("div",{className:"bg-[#60a5fa]/10 border border-[#60a5fa]/20 rounded p-4 flex items-start gap-2.5",children:[e.jsx(le,{size:15,className:"text-[#60a5fa] flex-shrink-0 mt-0.5"}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"text-[13px] text-[#cfcfcf]",children:"You need a VPC network before launching a droplet — the droplet runs in the network's region."}),e.jsxs("button",{type:"button",onClick:()=>d("/app/networks/create",{state:{fromDroplet:!0}}),className:"min-h-10 inline-flex items-center gap-1.5 px-3 py-1.5 bg-white text-[#0A0908] rounded text-xs font-medium hover:bg-white/90 transition-colors",children:[e.jsx(I,{size:13}),"Create a VPC network"]})]})]}):e.jsxs(e.Fragment,{children:[e.jsx(F,{label:"VPC network",options:M,value:o,onChange:t=>R(t),placeholder:"Select a VPC network",searchable:M.length>5,disabled:m}),e.jsxs("p",{className:"mt-1.5 text-[11px] text-[#5C5C5C]",children:["Launches into this network and inherits its region",o?` — ${z(n.find(t=>
1t.id===o)?.region||"")}`:"","."]})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-medium uppercase tracking-[0.08em] text-[#8e8e8e] mb-2",children:"Size"}),e.jsx("select",{"aria-label":"Size",value:N,onChange:t=>G(t.target.value),disabled:m,className:B,children:r.options.map(t=>e.jsxs("option",{value:t.slug,className:"bg-[#1A1A1A]",children:[t.label," — ",$(t.monthlyUsdCents)," / 30 days"]},t.slug))}),r.loading&&e.jsx("p",{role:"status",className:"mt-2 text-xs text-[#8e8e8e]",children:"Loading current rental prices…"}),!r.loading&&(r.error||!r.options.length)&&e.jsxs("p",{role:"alert",className:"mt-2 text-xs text-amber-400",children:[r.error??"VPS pricing is unavailable."," ",e.jsx("button",{type:"button",onClick:()=>void r.refresh(),children:"Retry prices"})]}),y&&e.jsxs("div",{className:"mt-4 bg-[#d4a04a]/10 border border-[#d4a04a]/20 rounded p-4 flex items-start gap-2.5",children:[e.jsx(A,{size:14,className:"text-[#d4a04a] flex-shrink-0 mt-0.5"}),e.jsxs("p",{className:"text-xs text-[#d4a04a]",children:[e.jsxs("span",{className:"font-medium",style:{fontFamily:Ne},children:[$(y.monthlyUsdCents)," every 30 days"]})," — charged from your balance now. Unfunded renewal creates debt and starts seven-day grace before deletion. Cancel anytime; unused prepaid time is credited after confirmed deletion. Trial credit cannot pay for rentals."]})]})]})]}):e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-medium uppercase tracking-[0.08em] text-[#8e8e8e] mb-2",children:"SSH credential"}),C?e.jsx("div",{className:"h-[42px] bg-white/[0.03] border border-white/[0.06] rounded animate-pulse"}):u&&!c.error&&b.length===0?e.jsxs("div",{className:"bg-white/[0.04] border border-white/[0.06] rounded p-5 space-y-4",children:[e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx(A,{size:16,className:"text-[#d4a04a] flex-shrink-0 mt-0.5"}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm text-white font-medium",children:"No SSH credentials in this organization"}),e.jsx("p",{className:"mt-1 text-xs text-[#8e8e8e]",children:"You need to create an SSH credential first. Once created, come back to this screen to register your VPS."})]})]}),e.jsxs("button",{onClick:U,className:"min-h-10 inline-flex items-center gap-2 px-4 py-2 bg-white text-[#0A0908] rounded text-sm font-medium hover:bg-white/90 transition-colors",children:[e.jsx(I,{size:14}),"Create SSH credential",e.jsx(q,{size:12})]})]}):e.jsxs(e.Fragment,{children:[e.jsx(F,{label:"SSH credential",options:D,value:f,onChange:t=>W(t),placeholder:"Select an SSH credential…",searchable:D.length>5,disabled:m}),e.jsxs("button",{onClick:U,disabled:m,className:"min-h-10 mt-2 inline-flex items-center gap-1.5 text-xs text-[#8e8e8e] hover:text-white transition-colors disabled:opacity-40",children:[e.jsx(I,{size:11}),"Create new SSH credential",e.jsx(q,{size:10})]})]})]}),V==="submitting"&&e.jsxs("div",{className:"bg-white/[0.04] border border-white/[0.06] rounded p-3 flex items-center gap-2.5",children:[e.jsx("div",{className:"w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin"}),e.jsx("p",{className:"text-xs text-[#cfcfcf]",children:s?"Creating the droplet…":"Submitting the VPS connection check…"})]})]}),e.jsxs("div",{className:"flex flex-wrap items-center justify-end gap-3",children:[e.jsx("button",{onClick:()=>d("/app/vps"),disabled:j,className:"min-h-10 px-4 py-2 text-sm text-[#cfcfcf] hover:text-white transition-colors disabled:opacity-40",children:"Cancel"}),e.jsx("button",{onClick:ee,disabled:!H,className:"min-h-10 inline-flex items-center gap-2 px-4 py-2 bg-white text-[#0A0908] rounded text-sm font-medium hover:bg-white/90 transition-colors disabled:opacity-40 disabled:cursor-not-allowed",children:V==="submitting"?s?"Creating…":"Submitting…":V==="saving"?"Saving…":l.attempt?"Retry original request":s?"Create droplet":"Save VPS"})]})]})}export{Fe as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.