1import{r as b,j as t,O as re,P as ke,a as be,Q as V,F as H,R as A,G as J,v as I,b as Ce,c as se,I as Ie,o as x,U as P,V as Re,B as Te,N as De,S as Pe,k as Oe,l as Ae,m as $e,n as Me}from"./index-BLzC7UhO.js";import{S as _e,I as Fe}from"./secret-dialog-B9lFsyc3.js";import{C as Le,R as qe}from"./row-menu-D5gEVJMO.js";import{b as B,R as Q,C as S,P as O,T as Ke,S as ze,a as Be}from"./section-table-DioVZOfC.js";import{c as Qe,u as Ve,b as He,d as Je,l as Ue,a as Ge}from"./configuration-resources-Cq2c1Iu6.js";import{C as We,P as Ze,a as Ye,R as oe,F as ie,f as Xe,M as et,D as tt,b as nt}from"./configuration-components-Dyb1Poc_.js";(function(){try{var r=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{};r.SENTRY_RELEASE={id:"c9a6608bed143be40b1e896102beac1a57255800"};var n=new r.Error().stack;n&&(r._sentryDebugIds=r._sentryDebugIds||{},r._sentryDebugIds[n]="430bfe6f-d95a-4226-8179-2c3f9fb5f71f",r._sentryDebugIdIdentifier="sentry-dbid-430bfe6f-d95a-4226-8179-2c3f9fb5f71f")}catch{}})();const le="min-h-0 w-full resize-none rounded-[8px] border-0 px-[12px] py-[10px] font-mono text-[13px] leading-[20px] shadow-none md:text-[13px]",at={key:"var(--blue-9)",string:"var(--green-9)",number:"var(--amber-9)",atom:"var(--purple-9)",punct:"var(--sand-10)"},rt=/("(?:\\.|[^"\\])*"\s*:)|("(?:\\.|[^"\\])*")|(-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)|(\btrue\b|\bfalse\b|\bnull\b)/g;function st(r){const n=[];let s=0,l=0;for(const d of r.matchAll(rt)){const m=d.index??0;m>s&&n.push(r.slice(s,m));const u=d[1]?"key":d[2]?"string":d[3]?"number":"atom";n.push(t.jsx("span",{style:{color:at[u]},children:d[0]},l+=1)),s=m+d[0].length}return s<r.length&&n.push(r.slice(s)),n}function ot({id:r,value:n,onChange:s,rows:l=6}){const d=b.useRef(null);return t.jsxs("div",{className:"relative overflow-hidden rounded-[8px] bg-[var(--sand-3)] transition-colors duration-150 [transition-timing-function:var(--ease-out)] focus-within:bg-[var(--sand-4)]",children:[t.jsxs("pre",{ref:d,"aria-hidden":!0,className:re(le,"pointer-events-none absolute inset-0 overflow-hidden whitespace-pre-wrap break-words text-[var(--sand-10)]"),children:[st(n),` 2`]}),t.jsx(ke,{id:r,rows:l,value:n,onChange:m=>s(m.target.value),onScroll:m=>{const u=d.current;u&&(u.scrollTop=m.currentTarget.scrollTop)},spellCheck:!1,className:re(le,"relative bg-transparent text-transparent caret-[var(--sand-12)] focus-visible:ring-0")})]})}const it=/^[A-Za-z_][A-Za-z0-9_]*$/;function lt(r){let n=r.trim();const s=n[0];if(s==='"'||s==="'"||s==="`"){const d=n.lastIndexOf(s);if(d===0)return null;const m=n.slice(d+1).trim();return m&&!m.startsWith("#")?null:(n=n.slice(1,d),s==='"'&&(n=n.replace(/\\n
2/g,` 3`).replace(/\\r/g,"\r")),n)}const l=n.search(/\s+#/);return l>=0&&(n=n.slice(0,l)),n.trimEnd()}function ct(r){const n=[];for(const s of r.split(/\r?\n/)){const l=s.trim();if(!l||l.startsWith("#"))continue;const d=l.startsWith("export ")?l.slice(7).trimStart():l,m=d.indexOf("=");if(m<1)return null;const u=d.slice(0,m).trim(),f=lt(d.slice(m+1));if(!it.test(u)||f===null)return null;n.push({key:u,value:f})}return n.length>0?n:null}function dt(r,n="Please try again later"){return r instanceof Error?r.message:n}function ut({open:r,onOpenChange:n,projectId:s,onCreated:l,reserved:d}){const{orgId:m}=be(),u=V({mutationFn:async({name:f,value:h})=>({secret:await Qe(s,{name:f.trim(),value:h}),orgId:m,projectId:s}),onSuccess:({secret:f,orgId:h,projectId:E})=>{const w=I.secrets(h,E);A.setQueryData(w,(j=[])=>[...j,f]),A.invalidateQueries({queryKey:w}),l(f),J({title:"Secret created",shapes:!1}),n(!1)},onError:f=>{H({title:dt(f,"Could not create Secret")})}});return t.jsx(_e,{open:r,onOpenChange:f=>{!f&&!u.isPending&&n(!1)},reserved:d,requireValue:!0,pending:u.isPending,footnote:"The value can be replaced later, but it cannot be read back.",onCreate:({name:f,value:h})=>u.mutate({name:f,value:h})})}const ce="environment-form",de="environment-name",mt="cursor-pointer transition-[transform,filter] duration-150 [transition-timing-function:var(--ease-out)] active:scale-[0.97] hover:brightness-95 bg-[var(--sand-12)] flex h-[40px] items-center px-[12px] rounded-[8px] font-medium text-[14px] leading-[20px] text-[var(--sand-1)] whitespace-nowrap disabled:opacity-60 disabled:cursor-not-allowed",pt=`${S} [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none`;let ue=0;function y(){return ue+=1,`row-${ue}`}const ft=[{label:"Name",track:"minmax(160px, 1fr)"},{label:"Environment ID",track:"max-content"},{label:"Version",track:"max-content"},{label:"Plain values",track:"max-content"},{label:"Secret bindings",track:"max-content"},{label:"Updated",track:"max-content"},{label:"",track:"44px",className:"justify-center px-0"}];function bt(r,n,s){return{id:r.id,cells:[t.jsx("span",{className:"min-w-px max-w-[320px] truncate text-[var(--sand-12)]",children:r.name},"name"),t.jsx(nt,{id:r.id,label:"Environment ID"},"id"),t.jsxs("span",{className:"tabular-nums text-[var(--sand-11)]",children:["v",r.version]},"version"),t.jsx("span",{className:"tabular-nums text-[var(--sand-11)]",children:Object.keys(r.spec.env??{}).length},"plain"),t.jsx("span",{className:"tabular-nums text-[var(--sand-11)]",children:Object.keys(r.secrets).length+r.networkSecrets.length},"bindings"),t.jsx("span",{className:"whitespace-nowrap text-[var(--sand-11)]",children:Te(r.updatedAt)},"updated"),t.jsx(qe,{label:r.name,items:[{label:"Edit",icon:t.jsx(Fe,{size:16}),onSelect:n},{label:"Delete",icon:t.jsx(De,{size:16}),onSelect:s,danger:!0}]},"menu")]}}function me(r,n="Please try again later"){return r instanceof Error?r.message:n}function ht(r){return Object.entries(r??{}).map(([n,s])=>({id:y(),key:n,value:s}))}function gt(r){return Object.entries(r).map(([n,s])=>({id:y(),key:n,secretId:s}))}function pe(r){return{id:y(),secretId:r,domain:"",port:443,header:"Authorization",template:"Bearer {{secret}}"}}function vt(r){const n={...r};return delete n.env,n}function xt(r,n){const s={};for(const l of r){const d=l.key.trim();if(!d)throw new Error(`${n} names cannot be blank`);if(Object.prototype.hasOwnProperty.call(s,d))throw new Error(`${n} contains duplicate name ${d}`);s[d]=l.value}return s}function yt(r){const n={};for(const s of r){const l=s.key.trim();if(!l||!s.secretId)throw new Error("Every Secret binding needs a variable name and Secret");if(Object.prototype.hasOwnProperty.call(n,l))throw new Error(`Secret bindings contain duplicate name ${l}`);n[l]=s.secretId}return n}function Et(r){const n=JSON.parse(r||"{}");if(!n||typeof n!="object"||Array.isArray(n))throw new Error("Computer defaults must be a JSON object");const s={...n};return delete s.env,s}function fe({label:r,secrets:n,value:s,onChange:l,disabled:d}){const m=n.some(u=>u.id===s);return t.jsxs(Pe,{value:s,onValueChange:l,disabled:d,children:[t.jsx(Oe,{"aria-label":r,className:Ke,children:s&&!m?t.jsxs("span",{className:"min-w-px truncate text-[var(--sand-10)]",children:["Bound Secret (",s,")"]}):t.jsx(Ae,{placeholder:"Select a Secret"})}),t.jsx($e,{className:ze,children:n.map(u=>t.jsx(Me,{value:u.id,className:Be,children:u.name},u.id))})]})}function It(){const{isLoaded:r,isSignedIn:n,orgId:s}=be(),{selectedProjectId:l,selectedProject:d,isProjectSelectionReady:m}=Ce(),[u,f]=b.useState(null),[h,E]=b.useState(null),[w,j]=b.useState(!1),[$,U]=b.useState(""),[M,N]=b.useState([]),[_,k]=b.useState([]),[G,C]=b.useState(null),[R,g]=b.useState([]),[W,Z]=b.useState("{}"),[T,D]=b.useState(null),he=I.environments(s,l),ge=I.secrets(s,l),Y=r&&!!n&&!!s&&m&&!!l,F=se({queryKey:he,queryFn:()=>Ue(l),enabled:Y}),X=se({queryKey:ge,queryFn:()=>Ge(l),enabled:Y}),ve=e=>{U((e==null?void 0:e.name)??""),N(ht(e==null?void 0:e.spec.env)),k(e?gt(e.secrets):[]),g(((e==null?void 0:e.networkSecrets)??[]).map(a=>({id:y(),...a}))),Z(JSON.stringify(e?vt(e.spec):{},null,2)),D(null)};b.useEffect(()=>{w&&ve(u)},[u,w]),b.useEffect(()=>{j(!1),C(null),f(null),E(null)},[l]);const L=()=>{j(!1),C(null),f(null),D(null)},xe=()=>{const e=$.trim();if(!e)throw new Error("Environment name is required");const a=xt(M,"Environment variables"),o=yt(_);for(const i of R){if(!i.secretId||!i.domain.trim()||!i.header.trim())throw new Error("Every Network Secret needs a Secret, domain, and header");if(i.port!==void 0&&(!Number.isInteger(i.port)||i.port<1||i.port>65535))throw new Error("Network Secret ports must be integers between 1 and 65535");if(!i.template.includes("{{secret}}"))throw new Error("Every Network Secret template must contain {{secret}}")}return{name:e,spec:{...Et(W),...Object.keys(a).length?{env:a}:{}},secrets:o,networkSecrets:R.map(i=>({secretId:i.secretId,domain:i.domain.trim(),port:i.port,header:i.header.trim(),template:i.template}))}},ye=(e,a)=>{const o=ct(e.clipboardData.getData("text"));o&&(e.preventDefault(),N(i=>i.flatMap((c,p)=>p===a?o.map(Ne=>({id:y(),...Ne})):[c])),Re({title:`Imported ${o.length} environment variable${o.length===1?"":"s"} â review before saving`}))},q=V({mutationFn:async()=>{const e=l,a=s;if(!e)throw new Error("Select a project first");const o=xe();
3return{environment:u?await Ve(e,u.id,o):await He(e,o),orgId:a,projectId:e}},onSuccess:async({orgId:e,projectId:a})=>{await A.invalidateQueries({queryKey:I.environments(e,a)}),J({title:u?"Environment updated":"Environment created",shapes:!1}),L()},onError:e=>{const a=me(e);D(a),H({title:"Could not save Environment"})}}),K=V({mutationFn:async e=>{const a=l,o=s;if(!a)throw new Error("Select a project first");return await Je(a,e.id),{orgId:o,projectId:a}},onSuccess:async({orgId:e,projectId:a})=>{var o;await A.invalidateQueries({queryKey:I.environments(e,a)}),J({title:"Environment deleted",shapes:!1}),E(null),(o=te.current)==null||o.focus()},onError:e=>{H({title:me(e,"Could not delete Environment")})}});function Ee(e){e.key==="Enter"&&e.target instanceof HTMLInputElement&&e.target.id!==de&&e.preventDefault()}const ee=b.useRef(null);b.useEffect(()=>{if(!T)return;const e=ee.current;e&&e.scrollTo({top:e.scrollHeight,behavior:"smooth"})},[T]);const te=b.useRef(null),Se=()=>{f(null),j(!0)},we=e=>{f(e),j(!0)},ne=F.data??[],v=X.data??[],je=v.map(e=>e.name),z=X.isError,ae=z?"Secrets could not be loaded. Refresh the page to try again.":"Create a Secret here without losing this Environment draft.";return t.jsxs(We,{title:"Environments",description:`Reusable Computer configuration for ${(d==null?void 0:d.name)??"the selected project"}.`,action:t.jsx("button",{ref:te,type:"button",onClick:Se,disabled:!l,className:mt,children:"New Environment"}),children:[l?t.jsx(Ye,{loading:F.isLoading,error:F.isError,children:t.jsx("div",{className:"w-full overflow-x-auto",children:t.jsx("div",{className:ne.length>0?"min-w-max":"w-full",children:t.jsx(Le,{label:"Environments",columns:ft,rows:ne.map(e=>bt(e,()=>we(e),()=>E(e))),emptyIcon:Ie,emptyTitle:"No Environments yet",emptyHint:"Create an Environment to reuse plain values and Secret bindings across Computers."})})})}):t.jsx(Ze,{}),t.jsxs(oe,{open:w,onClose:()=>!q.isPending&&L(),title:u?"Update Environment":"Create Environment",subtitle:"Plain values are visible in configuration. Secret values remain encrypted and are referenced by ID.",bodyRef:ee,footer:t.jsx(et,{formId:ce,onCancel:L,submitLabel:u?"Save changes":"Create Environment",pending:q.isPending,disabled:!$.trim()}),children:[t.jsxs("form",{id:ce,className:"flex flex-col gap-4",onKeyDown:Ee,onSubmit:e=>{e.preventDefault(),D(null),q.mutate()},children:[t.jsx(ie,{label:"Name",children:t.jsx(x,{id:de,autoFocus:!0,value:$,onChange:e=>U(e.target.value),placeholder:"name-your-environment",className:Xe,maxLength:256})}),t.jsx(B,{title:"Plain environment values",isEmpty:M.length===0,emptyText:"No plain values.",description:"Add values individually or paste .env contents into a variable name field.",addLabel:"Add",onAdd:()=>N(e=>[...e,{id:y(),key:"",value:""}]),children:M.map((e,a)=>t.jsxs(Q,{removeLabel:`Remove environment value ${e.key||a+1}`,onRemove:()=>N(o=>o.filter((i,c)=>c!==a)),children:[t.jsx(x,{"aria-label":`Plain environment variable ${a+1} name`,value:e.key,onPaste:o=>ye(o,a),onChange:o=>N(i=>i.map((c,p)=>p===a?{...c,key:o.target.value}:c)),placeholder:"NODE_ENV",className:S}),t.jsx(x,{"aria-label":`Plain environment variable ${a+1} value`,value:e.value,onChange:o=>N(i=>i.map((c,p)=>p===a?{...c,value:o.target.value}:c)),placeholder:"production",className:S})]},e.id))}),t.jsx(B,{title:"Environment Secrets",isEmpty:_.length===0,emptyText:v.length===0?ae:"No environment Secret bindings.",description:"Expose a Secret to guest processes under an environment variable.",action:t.jsxs("div",{className:"flex shrink-0 items-center gap-[8px]",children:[t.jsxs("button",{type:"button",onClick:()=>C("environment"),className:O,children:[t.jsx(P,{size:16}),"New Secret"]}),t.jsxs("button",{type:"button",disabled:v.length===0,onClick:()=>k(e=>{var a;return[...e,{id:y(),key:"",secretId:((a=v[0])==null?void 0:a.id)??""}]}),className:O,children:[t.jsx(P,{size:16}),"Add"]})]}),children:_.map((e,a)=>t.jsxs(Q,{removeLabel:`Remove Secret binding ${e.key||a+1}`,onRemove:()=>k(o=>o.filter((i,c)=>c!==a)),children:[t.jsx(x,{"aria-label":`Environment Secret binding ${a+1} variable name`,value:e.key,onChange:o=>k(i=>i.map((c,p)=>p===a?{...c,key:o.target.value}:c)),placeholder:"API_TOKEN",className:S}),t.jsx(fe,{label:`Environment Secret binding ${a+1} Secret`,secrets:v,disabled:z,value:e.secretId,onChange:o=>k(i=>i.map((c,p)=>p===a?{...c,secretId:o}:c))})]},e.id))}),t.jsx(B,{title:"Network Secrets",isEmpty:R.length===0,emptyText:v.length===0?ae:"No Network Secret bindings.",description:"Inject one HTTP header for matching destination domains.",action:t.jsxs("div",{className:"flex shrink-0 items-center gap-[8px]",children:[t.jsxs("button",{type:"button",onClick:()=>C("network"),className:O,children:[t.jsx(P,{size:16}),"New Secret"]}
3),t.jsxs("button",{type:"button",disabled:v.length===0,onClick:()=>g(e=>{var a;return[...e,pe(((a=v[0])==null?void 0:a.id)??"")]}),className:O,children:[t.jsx(P,{size:16}),"Add"]})]}),children:R.map((e,a)=>t.jsxs(Q,{removeLabel:`Remove Network Secret binding ${e.domain||a+1}`,onRemove:()=>g(o=>o.filter((i,c)=>c!==a)),children:[t.jsx(fe,{label:`Network Secret binding ${a+1} Secret`,secrets:v,disabled:z,value:e.secretId,onChange:o=>g(i=>i.map((c,p)=>p===a?{...c,secretId:o}:c))}),t.jsx(x,{"aria-label":`Network Secret binding ${a+1} domain`,value:e.domain,onChange:o=>g(i=>i.map((c,p)=>p===a?{...c,domain:o.target.value}:c)),placeholder:"api.example.com",className:S}),t.jsx(x,{"aria-label":`Network Secret binding ${a+1} port`,type:"number",min:1,max:65535,value:e.port??"",onChange:o=>g(i=>i.map((c,p)=>p===a?{...c,port:o.target.value===""?void 0:Number(o.target.value)}:c)),placeholder:"80, 443",className:pt}),t.jsx(x,{"aria-label":`Network Secret binding ${a+1} header`,value:e.header,onChange:o=>g(i=>i.map((c,p)=>p===a?{...c,header:o.target.value}:c)),placeholder:"Authorization",className:S}),t.jsx(x,{"aria-label":`Network Secret binding ${a+1} template`,value:e.template,onChange:o=>g(i=>i.map((c,p)=>p===a?{...c,template:o.target.value}:c)),placeholder:"Bearer {{secret}}",className:S})]},e.id))}),t.jsx(ie,{label:"Computer defaults (JSON)",hint:"Optional launch defaults such as template, vcpu, memoryMib, diskMib, autoPause, timeoutSeconds, and networkPolicy.",children:t.jsx(ot,{id:"environment-spec",value:W,onChange:Z})}),T&&t.jsx("p",{role:"alert",className:"rounded-md border border-[var(--red-a6)] bg-[var(--red-a3)] px-3 py-2 text-xs text-[var(--red-11)]",children:T})]}),l&&t.jsx(ut,{open:G!==null,onOpenChange:e=>!e&&C(null),projectId:l,reserved:je,onCreated:e=>{if(G==="network"){g(a=>[...a,pe(e.id)]);return}k(a=>[...a,{id:y(),key:e.name,secretId:e.id}])}})]}),t.jsx(oe,{open:!!h,onClose:()=>!K.isPending&&E(null),title:"Delete Environment",subtitle:t.jsxs(t.Fragment,{children:["Delete ",t.jsx("strong",{children:h==null?void 0:h.name}),"? Existing Computers keep their configuration snapshots."]}),danger:!0,footer:t.jsx(tt,{onCancel:()=>E(null),confirmLabel:"Delete Environment",onConfirm:()=>h&&K.mutate(h),pending:K.isPending})})]})}export{It 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.