feat: vpc create wizard (#96)

This commit is contained in:
Julian Sommer
2026-03-27 15:07:20 +10:00
committed by GitHub
parent de1340a331
commit 3f642524a8
66 changed files with 1735 additions and 121 deletions
@@ -45,7 +45,8 @@
"unicorn/filename-case": [
"error",
{ "cases": { "kebabCase": true, "camelCase": true } }
]
],
"unicorn/number-literal-case": "off"
},
"overrides": [
{
@@ -1 +1 @@
import{At as e,Pt as t,it as n,kt as r}from"./awsClient.js";var i=class extends t.classBuilder().ep(r).m(function(t,n,r,i){return[e(r,t.getEndpointParameterInstructions())]}).s(`AmazonEC2`,`DescribeInstances`,{}).n(`EC2Client`,`DescribeInstancesCommand`).sc(n).build(){};export{i as t};
import{It as e,Lt as t,Vt as n,lt as r}from"./awsClient.js";var i=class extends n.classBuilder().ep(e).m(function(e,n,r,i){return[t(r,e.getEndpointParameterInstructions())]}).s(`AmazonEC2`,`DescribeInstances`,{}).n(`EC2Client`,`DescribeInstancesCommand`).sc(r).build(){};export{i as t};
+1 -1
View File
@@ -1 +1 @@
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{d as r}from"./ec22.js";import{t as i}from"./page-heading.js";var a=t(),o=e();function s(){let e=(0,a.c)(2),{data:t}=n(r),s=`${t?.Regions?.[0]?.RegionName} Dashboard`,c;return e[0]===s?c=e[1]:(c=(0,o.jsx)(i,{title:s}),e[0]=s,e[1]=c),c}export{s as component};
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{d as r}from"./ec23.js";import{t as i}from"./page-heading.js";var a=t(),o=e();function s(){let e=(0,a.c)(2),{data:t}=n(r),s=`${t?.Regions?.[0]?.RegionName} Dashboard`,c;return e[0]===s?c=e[1]:(c=(0,o.jsx)(i,{title:s}),e[0]=s,e[1]=c),c}export{s as component};
+1 -1
View File
@@ -1 +1 @@
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{t as r}from"./back-link.js";import{n as i}from"./ec22.js";import{t as a}from"./index.js";import{t as o}from"./page-heading.js";import{t as s}from"./state-badge.js";import{t as c}from"./ami-details.js";var l=t(),u=e();function d(){let e=(0,l.c)(14),{id:t}=a.useParams(),d;e[0]===t?d=e[1]:(d=i(t),e[0]=t,e[1]=d);let{data:f}=n(d),p=f?.Images?.[0];if(!p?.ImageId){let t;return e[2]===Symbol.for(`react.memo_cache_sentinel`)?(t=(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(r,{to:`/ec2/describe-images`,children:`Back to images`}),(0,u.jsx)(`p`,{className:`text-muted-foreground`,children:`Image not found.`})]}),e[2]=t):t=e[2],t}let m;e[3]===Symbol.for(`react.memo_cache_sentinel`)?(m=(0,u.jsx)(r,{to:`/ec2/describe-images`,children:`Back to images`}),e[3]=m):m=e[3];let h;e[4]===p.State?h=e[5]:(h=(0,u.jsx)(s,{state:p.State}),e[4]=p.State,e[5]=h);let g;e[6]!==p.ImageId||e[7]!==h?(g=(0,u.jsx)(o,{actions:h,subtitle:`EC2 Image Details`,title:p.ImageId}),e[6]=p.ImageId,e[7]=h,e[8]=g):g=e[8];let _;e[9]===p?_=e[10]:(_=(0,u.jsx)(c,{image:p,showExtendedDetails:!0}),e[9]=p,e[10]=_);let v;return e[11]!==g||e[12]!==_?(v=(0,u.jsxs)(u.Fragment,{children:[m,(0,u.jsxs)(`div`,{className:`space-y-6`,children:[g,_]})]}),e[11]=g,e[12]=_,e[13]=v):v=e[13],v}export{d as component};
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{t as r}from"./back-link.js";import{n as i}from"./ec23.js";import{t as a}from"./index.js";import{t as o}from"./page-heading.js";import{t as s}from"./state-badge.js";import{t as c}from"./ami-details.js";var l=t(),u=e();function d(){let e=(0,l.c)(14),{id:t}=a.useParams(),d;e[0]===t?d=e[1]:(d=i(t),e[0]=t,e[1]=d);let{data:f}=n(d),p=f?.Images?.[0];if(!p?.ImageId){let t;return e[2]===Symbol.for(`react.memo_cache_sentinel`)?(t=(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(r,{to:`/ec2/describe-images`,children:`Back to images`}),(0,u.jsx)(`p`,{className:`text-muted-foreground`,children:`Image not found.`})]}),e[2]=t):t=e[2],t}let m;e[3]===Symbol.for(`react.memo_cache_sentinel`)?(m=(0,u.jsx)(r,{to:`/ec2/describe-images`,children:`Back to images`}),e[3]=m):m=e[3];let h;e[4]===p.State?h=e[5]:(h=(0,u.jsx)(s,{state:p.State}),e[4]=p.State,e[5]=h);let g;e[6]!==p.ImageId||e[7]!==h?(g=(0,u.jsx)(o,{actions:h,subtitle:`EC2 Image Details`,title:p.ImageId}),e[6]=p.ImageId,e[7]=h,e[8]=g):g=e[8];let _;e[9]===p?_=e[10]:(_=(0,u.jsx)(c,{image:p,showExtendedDetails:!0}),e[9]=p,e[10]=_);let v;return e[11]!==g||e[12]!==_?(v=(0,u.jsxs)(u.Fragment,{children:[m,(0,u.jsxs)(`div`,{className:`space-y-6`,children:[g,_]})]}),e[11]=g,e[12]=_,e[13]=v):v=e[13],v}export{d as component};
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1 +1 @@
import{a as e,n as t,r as n}from"./compiler-runtime.js";import{t as r}from"./useSuspenseQuery.js";import{t as i}from"./error-banner.js";import{a}from"./utils.js";import{t as o}from"./useNavigate.js";import{t as s}from"./button.js";import{t as c}from"./back-link.js";import{t as l}from"./trash-2.js";import{d as u}from"./ec2.js";import{s as d}from"./ec22.js";import{r as f}from"./index.js";import{t as p}from"./page-heading.js";import{n as m,t as h}from"./detail-row.js";import{t as g}from"./delete-confirmation-dialog.js";var _=e(n()),v=t();function y(){let{id:e}=f.useParams(),t=o(),{data:n}=r(d(e)),y=n.KeyPairs?.[0],b=u(),[x,S]=(0,_.useState)(!1),C=async()=>{try{await b.mutateAsync(e),t({to:`/ec2/describe-key-pairs`})}finally{S(!1)}};if(!y?.KeyPairId)return(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(c,{to:`/ec2/describe-key-pairs`,children:`Back to key pairs`}),(0,v.jsx)(`p`,{className:`text-muted-foreground`,children:`Key pair not found.`})]});let w=a(y.CreateTime);return(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(c,{to:`/ec2/describe-key-pairs`,children:`Back to key pairs`}),b.error&&(0,v.jsx)(i,{error:b.error,msg:`Failed to delete key pair`}),(0,v.jsxs)(`div`,{className:`space-y-6`,children:[(0,v.jsx)(p,{actions:(0,v.jsxs)(s,{onClick:()=>S(!0),size:`sm`,variant:`destructive`,children:[(0,v.jsx)(l,{className:`size-4`}),`Delete`]}),subtitle:`EC2 Key Pair Details`,title:y.KeyName??``}),(0,v.jsxs)(m,{children:[(0,v.jsx)(m.Header,{children:`Key Pair Information`}),(0,v.jsxs)(m.Content,{children:[(0,v.jsx)(h,{label:`Key Name`,value:y.KeyName}),(0,v.jsx)(h,{label:`Key Pair ID`,value:y.KeyPairId}),(0,v.jsx)(h,{label:`Key Type`,value:y.KeyType}),(0,v.jsx)(h,{label:`Key Fingerprint`,value:y.KeyFingerprint}),(0,v.jsx)(h,{label:`Creation Date`,value:w})]})]}),y.Tags&&y.Tags.length>0&&(0,v.jsxs)(m,{children:[(0,v.jsx)(m.Header,{children:`Tags`}),(0,v.jsx)(m.Content,{children:y.Tags.map(e=>(0,v.jsx)(h,{label:e.Key??``,value:e.Value},e.Key))})]})]}),(0,v.jsx)(g,{description:`Are you sure you want to delete the key pair "${y.KeyName}"? This action cannot be undone. Any instances using this key pair will no longer be able to be accessed with it.`,isPending:b.isPending,onConfirm:C,onOpenChange:S,open:x,title:`Delete Key Pair`})]})}export{y as component};
import{a as e,n as t,r as n}from"./compiler-runtime.js";import{t as r}from"./useSuspenseQuery.js";import{t as i}from"./error-banner.js";import{a}from"./utils.js";import{t as o}from"./useNavigate.js";import{t as s}from"./button.js";import{t as c}from"./back-link.js";import{t as l}from"./trash-2.js";import{f as u}from"./ec22.js";import{s as d}from"./ec23.js";import{r as f}from"./index.js";import{t as p}from"./page-heading.js";import{n as m,t as h}from"./detail-row.js";import{t as g}from"./delete-confirmation-dialog.js";var _=e(n()),v=t();function y(){let{id:e}=f.useParams(),t=o(),{data:n}=r(d(e)),y=n.KeyPairs?.[0],b=u(),[x,S]=(0,_.useState)(!1),C=async()=>{try{await b.mutateAsync(e),t({to:`/ec2/describe-key-pairs`})}finally{S(!1)}};if(!y?.KeyPairId)return(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(c,{to:`/ec2/describe-key-pairs`,children:`Back to key pairs`}),(0,v.jsx)(`p`,{className:`text-muted-foreground`,children:`Key pair not found.`})]});let w=a(y.CreateTime);return(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(c,{to:`/ec2/describe-key-pairs`,children:`Back to key pairs`}),b.error&&(0,v.jsx)(i,{error:b.error,msg:`Failed to delete key pair`}),(0,v.jsxs)(`div`,{className:`space-y-6`,children:[(0,v.jsx)(p,{actions:(0,v.jsxs)(s,{onClick:()=>S(!0),size:`sm`,variant:`destructive`,children:[(0,v.jsx)(l,{className:`size-4`}),`Delete`]}),subtitle:`EC2 Key Pair Details`,title:y.KeyName??``}),(0,v.jsxs)(m,{children:[(0,v.jsx)(m.Header,{children:`Key Pair Information`}),(0,v.jsxs)(m.Content,{children:[(0,v.jsx)(h,{label:`Key Pair ID`,value:y.KeyPairId}),(0,v.jsx)(h,{label:`Key Name`,value:y.KeyName}),(0,v.jsx)(h,{label:`Key Type`,value:y.KeyType}),(0,v.jsx)(h,{label:`Key Fingerprint`,value:y.KeyFingerprint}),(0,v.jsx)(h,{label:`Creation Date`,value:w})]})]}),y.Tags&&y.Tags.length>0&&(0,v.jsxs)(m,{children:[(0,v.jsx)(m.Header,{children:`Tags`}),(0,v.jsx)(m.Content,{children:y.Tags.map(e=>(0,v.jsx)(h,{label:e.Key??``,value:e.Value},e.Key))})]})]}),(0,v.jsx)(g,{description:`Are you sure you want to delete the key pair "${y.KeyName}"? This action cannot be undone. Any instances using this key pair will no longer be able to be accessed with it.`,isPending:b.isPending,onConfirm:C,onOpenChange:S,open:x,title:`Delete Key Pair`})]})}export{y as component};
+1 -1
View File
@@ -1 +1 @@
import{a as e,n as t,r as n}from"./compiler-runtime.js";import{t as r}from"./useSuspenseQuery.js";import{t as i}from"./error-banner.js";import{t as a}from"./link.js";import{t as o}from"./useNavigate.js";import{t as s}from"./button.js";import{t as c}from"./back-link.js";import{t as l}from"./trash-2.js";import{f as u}from"./ec2.js";import{l as d,o as f}from"./ec22.js";import{i as p}from"./index.js";import{t as m}from"./page-heading.js";import{t as h}from"./state-badge.js";import{n as g,t as _}from"./detail-row.js";import{t as v}from"./delete-confirmation-dialog.js";var y=e(n()),b=t();function x(){let{id:e}=p.useParams(),t=o(),{data:n}=r(d(e)),{data:x}=r(f),S=u(),[C,w]=(0,y.useState)(!1),T=n.PlacementGroups?.[0],E=x.Reservations?.flatMap(e=>e.Instances??[]).filter(e=>e.Placement?.GroupName===T?.GroupName)??[];return T?.GroupId?(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(c,{to:`/ec2/describe-placement-groups`,children:`Back to placement groups`}),S.error&&(0,b.jsx)(i,{error:S.error,msg:`Failed to delete placement group`}),(0,b.jsxs)(`div`,{className:`space-y-6`,children:[(0,b.jsx)(m,{actions:(0,b.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,b.jsxs)(s,{onClick:()=>w(!0),size:`sm`,variant:`destructive`,children:[(0,b.jsx)(l,{className:`size-4`}),`Delete`]}),(0,b.jsx)(h,{state:T.State})]}),subtitle:`EC2 Placement Group Details`,title:T.GroupName??T.GroupId}),(0,b.jsxs)(g,{children:[(0,b.jsx)(g.Header,{children:`Placement Group Information`}),(0,b.jsxs)(g.Content,{children:[(0,b.jsx)(_,{label:`Group ID`,value:T.GroupId}),(0,b.jsx)(_,{label:`Group Name`,value:T.GroupName}),(0,b.jsx)(_,{label:`Strategy`,value:T.Strategy}),(0,b.jsx)(_,{label:`State`,value:T.State}),(0,b.jsx)(_,{label:`Spread Level`,value:T.SpreadLevel})]})]}),(0,b.jsxs)(g,{children:[(0,b.jsx)(g.Header,{children:`Instances`}),E.length>0?E.map(e=>(0,b.jsxs)(g.Content,{children:[(0,b.jsx)(_,{label:`Instance ID`,value:e.InstanceId?(0,b.jsx)(a,{className:`text-primary hover:underline`,params:{id:e.InstanceId},to:`/ec2/describe-instances/$id`,children:e.InstanceId}):void 0}),(0,b.jsx)(_,{label:`State`,value:e.State?.Name}),(0,b.jsx)(_,{label:`Instance Type`,value:e.InstanceType}),(0,b.jsx)(_,{label:`Availability Zone`,value:e.Placement?.AvailabilityZone})]},e.InstanceId)):(0,b.jsx)(g.Content,{children:(0,b.jsx)(`p`,{className:`text-muted-foreground`,children:`No instances in this placement group.`})})]})]}),(0,b.jsx)(v,{description:`Are you sure you want to delete the placement group "${T.GroupName}"? The group must have no running instances.`,isPending:S.isPending,onConfirm:async()=>{if(T?.GroupName)try{await S.mutateAsync(T.GroupName),t({to:`/ec2/describe-placement-groups`})}finally{w(!1)}},onOpenChange:w,open:C,title:`Delete Placement Group`})]}):(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(c,{to:`/ec2/describe-placement-groups`,children:`Back to placement groups`}),(0,b.jsx)(`p`,{className:`text-muted-foreground`,children:`Placement group not found.`})]})}export{x as component};
import{a as e,n as t,r as n}from"./compiler-runtime.js";import{t as r}from"./useSuspenseQuery.js";import{t as i}from"./error-banner.js";import{t as a}from"./link.js";import{t as o}from"./useNavigate.js";import{t as s}from"./button.js";import{t as c}from"./back-link.js";import{t as l}from"./trash-2.js";import{p as u}from"./ec22.js";import{l as d,o as f}from"./ec23.js";import{i as p}from"./index.js";import{t as m}from"./page-heading.js";import{t as h}from"./state-badge.js";import{n as g,t as _}from"./detail-row.js";import{t as v}from"./delete-confirmation-dialog.js";var y=e(n()),b=t();function x(){let{id:e}=p.useParams(),t=o(),{data:n}=r(d(e)),{data:x}=r(f),S=u(),[C,w]=(0,y.useState)(!1),T=n.PlacementGroups?.[0],E=x.Reservations?.flatMap(e=>e.Instances??[]).filter(e=>e.Placement?.GroupName===T?.GroupName)??[];return T?.GroupId?(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(c,{to:`/ec2/describe-placement-groups`,children:`Back to placement groups`}),S.error&&(0,b.jsx)(i,{error:S.error,msg:`Failed to delete placement group`}),(0,b.jsxs)(`div`,{className:`space-y-6`,children:[(0,b.jsx)(m,{actions:(0,b.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,b.jsxs)(s,{onClick:()=>w(!0),size:`sm`,variant:`destructive`,children:[(0,b.jsx)(l,{className:`size-4`}),`Delete`]}),(0,b.jsx)(h,{state:T.State})]}),subtitle:`EC2 Placement Group Details`,title:T.GroupName??T.GroupId}),(0,b.jsxs)(g,{children:[(0,b.jsx)(g.Header,{children:`Placement Group Information`}),(0,b.jsxs)(g.Content,{children:[(0,b.jsx)(_,{label:`Group ID`,value:T.GroupId}),(0,b.jsx)(_,{label:`Group Name`,value:T.GroupName}),(0,b.jsx)(_,{label:`Strategy`,value:T.Strategy}),(0,b.jsx)(_,{label:`State`,value:T.State}),(0,b.jsx)(_,{label:`Spread Level`,value:T.SpreadLevel})]})]}),(0,b.jsxs)(g,{children:[(0,b.jsx)(g.Header,{children:`Instances`}),E.length>0?E.map(e=>(0,b.jsxs)(g.Content,{children:[(0,b.jsx)(_,{label:`Instance ID`,value:e.InstanceId?(0,b.jsx)(a,{className:`text-primary hover:underline`,params:{id:e.InstanceId},to:`/ec2/describe-instances/$id`,children:e.InstanceId}):void 0}),(0,b.jsx)(_,{label:`State`,value:e.State?.Name}),(0,b.jsx)(_,{label:`Instance Type`,value:e.InstanceType}),(0,b.jsx)(_,{label:`Availability Zone`,value:e.Placement?.AvailabilityZone})]},e.InstanceId)):(0,b.jsx)(g.Content,{children:(0,b.jsx)(`p`,{className:`text-muted-foreground`,children:`No instances in this placement group.`})})]})]}),(0,b.jsx)(v,{description:`Are you sure you want to delete the placement group "${T.GroupName}"? The group must have no running instances.`,isPending:S.isPending,onConfirm:async()=>{if(T?.GroupName)try{await S.mutateAsync(T.GroupName),t({to:`/ec2/describe-placement-groups`})}finally{w(!1)}},onOpenChange:w,open:C,title:`Delete Placement Group`})]}):(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(c,{to:`/ec2/describe-placement-groups`,children:`Back to placement groups`}),(0,b.jsx)(`p`,{className:`text-muted-foreground`,children:`Placement group not found.`})]})}export{x as component};
+1 -1
View File
@@ -1 +1 @@
import{a as e,n as t,r as n}from"./compiler-runtime.js";import{t as r}from"./useSuspenseQuery.js";import{t as i}from"./error-banner.js";import{a}from"./utils.js";import{t as o}from"./link.js";import{t as s}from"./useNavigate.js";import{t as c}from"./button.js";import{t as l}from"./createLucideIcon.js";import{t as u}from"./back-link.js";import{t as d}from"./trash-2.js";import{n as f,p}from"./ec2.js";import{d as m,f as h}from"./ec22.js";import{A as g,a as _}from"./index.js";import{t as v}from"./page-heading.js";import{t as y}from"./state-badge.js";import{n as b,t as x}from"./detail-row.js";import{a as S,i as C,l as w,n as T,o as E,r as D,s as O,t as k}from"./alert-dialog.js";import{i as A,t as j}from"./field.js";import{t as M}from"./delete-confirmation-dialog.js";var N=l(`copy`,[[`rect`,{width:`14`,height:`14`,x:`8`,y:`8`,rx:`2`,ry:`2`,key:`17jyea`}],[`path`,{d:`M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2`,key:`zix9uf`}]]),P=e(n()),F=t();function I(){let{id:e}=_.useParams(),t=s(),{data:n}=r(h(e)),{data:l}=r(m),I=n.Snapshots?.[0],L=p(),R=f(),[z,B]=(0,P.useState)(!1),[V,H]=(0,P.useState)(!1),[U,W]=(0,P.useState)(``),G=l.Regions?.[0]?.RegionName??`ap-southeast-2`,K=I?.State===`completed`,q=async()=>{try{await L.mutateAsync(e),t({to:`/ec2/describe-snapshots`})}finally{B(!1)}},J=async()=>{try{await R.mutateAsync({sourceSnapshotId:e,sourceRegion:G,description:U||void 0}),H(!1),W(``)}catch{}};if(!I?.SnapshotId)return(0,F.jsxs)(F.Fragment,{children:[(0,F.jsx)(u,{to:`/ec2/describe-snapshots`,children:`Back to snapshots`}),(0,F.jsx)(`p`,{className:`text-muted-foreground`,children:`Snapshot not found.`})]});let Y=a(I.StartTime);return(0,F.jsxs)(F.Fragment,{children:[(0,F.jsx)(u,{to:`/ec2/describe-snapshots`,children:`Back to snapshots`}),L.error&&(0,F.jsx)(i,{error:L.error,msg:`Failed to delete snapshot`}),R.error&&(0,F.jsx)(i,{error:R.error,msg:`Failed to copy snapshot`}),(0,F.jsxs)(`div`,{className:`space-y-6`,children:[(0,F.jsx)(v,{actions:(0,F.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,F.jsxs)(c,{disabled:!K,onClick:()=>B(!0),size:`sm`,variant:`destructive`,children:[(0,F.jsx)(d,{className:`size-4`}),`Delete`]}),(0,F.jsxs)(c,{disabled:!K,onClick:()=>H(!0),size:`sm`,variant:`outline`,children:[(0,F.jsx)(N,{className:`size-4`}),`Copy Snapshot`]}),(0,F.jsx)(y,{state:I.State})]}),subtitle:`EC2 Snapshot Details`,title:I.SnapshotId}),(0,F.jsxs)(b,{children:[(0,F.jsx)(b.Header,{children:`Snapshot Information`}),(0,F.jsxs)(b.Content,{children:[(0,F.jsx)(x,{label:`Snapshot ID`,value:I.SnapshotId}),(0,F.jsx)(x,{label:`Volume ID`,value:I.VolumeId?(0,F.jsx)(o,{className:`text-primary hover:underline`,params:{id:I.VolumeId},to:`/ec2/describe-volumes/$id`,children:I.VolumeId}):void 0}),(0,F.jsx)(x,{label:`Volume Size`,value:`${I.VolumeSize} GiB`}),(0,F.jsx)(x,{label:`State`,value:I.State}),(0,F.jsx)(x,{label:`Description`,value:I.Description}),(0,F.jsx)(x,{label:`Progress`,value:I.Progress}),(0,F.jsx)(x,{label:`Start Time`,value:Y}),(0,F.jsx)(x,{label:`Owner ID`,value:I.OwnerId}),(0,F.jsx)(x,{label:`Encrypted`,value:I.Encrypted?`Yes`:`No`})]})]})]}),(0,F.jsx)(M,{description:`Are you sure you want to delete the snapshot "${I.SnapshotId}"? This action cannot be undone.`,isPending:L.isPending,onConfirm:q,onOpenChange:B,open:z,title:`Delete Snapshot`}),(0,F.jsx)(k,{onOpenChange:H,open:V,children:(0,F.jsxs)(C,{children:[(0,F.jsxs)(O,{children:[(0,F.jsx)(w,{children:`Copy Snapshot`}),(0,F.jsx)(S,{children:`Create a copy of this snapshot in the current region.`})]}),(0,F.jsxs)(j,{children:[(0,F.jsx)(A,{children:(0,F.jsx)(`label`,{htmlFor:`copyDescription`,children:`Description (optional)`})}),(0,F.jsx)(g,{id:`copyDescription`,onChange:e=>W(e.target.value),placeholder:`Description for the snapshot copy`,value:U})]}),(0,F.jsxs)(E,{children:[(0,F.jsx)(D,{children:`Cancel`}),(0,F.jsx)(T,{disabled:R.isPending,onClick:J,children:R.isPending?`Copying…`:`Copy Snapshot`})]})]})})]})}export{I as component};
import{a as e,n as t,r as n}from"./compiler-runtime.js";import{t as r}from"./useSuspenseQuery.js";import{t as i}from"./error-banner.js";import{a}from"./utils.js";import{t as o}from"./link.js";import{t as s}from"./useNavigate.js";import{t as c}from"./button.js";import{t as l}from"./createLucideIcon.js";import{t as u}from"./back-link.js";import{t as d}from"./trash-2.js";import{m as f,n as p}from"./ec22.js";import{d as m,f as h}from"./ec23.js";import{A as g,a as _}from"./index.js";import{t as v}from"./page-heading.js";import{t as y}from"./state-badge.js";import{n as b,t as x}from"./detail-row.js";import{a as S,i as C,l as w,n as T,o as E,r as D,s as O,t as k}from"./alert-dialog.js";import{i as A,t as j}from"./field.js";import{t as M}from"./delete-confirmation-dialog.js";var N=l(`copy`,[[`rect`,{width:`14`,height:`14`,x:`8`,y:`8`,rx:`2`,ry:`2`,key:`17jyea`}],[`path`,{d:`M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2`,key:`zix9uf`}]]),P=e(n()),F=t();function I(){let{id:e}=_.useParams(),t=s(),{data:n}=r(h(e)),{data:l}=r(m),I=n.Snapshots?.[0],L=f(),R=p(),[z,B]=(0,P.useState)(!1),[V,H]=(0,P.useState)(!1),[U,W]=(0,P.useState)(``),G=l.Regions?.[0]?.RegionName??`ap-southeast-2`,K=I?.State===`completed`,q=async()=>{try{await L.mutateAsync(e),t({to:`/ec2/describe-snapshots`})}finally{B(!1)}},J=async()=>{try{await R.mutateAsync({sourceSnapshotId:e,sourceRegion:G,description:U||void 0}),H(!1),W(``)}catch{}};if(!I?.SnapshotId)return(0,F.jsxs)(F.Fragment,{children:[(0,F.jsx)(u,{to:`/ec2/describe-snapshots`,children:`Back to snapshots`}),(0,F.jsx)(`p`,{className:`text-muted-foreground`,children:`Snapshot not found.`})]});let Y=a(I.StartTime);return(0,F.jsxs)(F.Fragment,{children:[(0,F.jsx)(u,{to:`/ec2/describe-snapshots`,children:`Back to snapshots`}),L.error&&(0,F.jsx)(i,{error:L.error,msg:`Failed to delete snapshot`}),R.error&&(0,F.jsx)(i,{error:R.error,msg:`Failed to copy snapshot`}),(0,F.jsxs)(`div`,{className:`space-y-6`,children:[(0,F.jsx)(v,{actions:(0,F.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,F.jsxs)(c,{disabled:!K,onClick:()=>B(!0),size:`sm`,variant:`destructive`,children:[(0,F.jsx)(d,{className:`size-4`}),`Delete`]}),(0,F.jsxs)(c,{disabled:!K,onClick:()=>H(!0),size:`sm`,variant:`outline`,children:[(0,F.jsx)(N,{className:`size-4`}),`Copy Snapshot`]}),(0,F.jsx)(y,{state:I.State})]}),subtitle:`EC2 Snapshot Details`,title:I.SnapshotId}),(0,F.jsxs)(b,{children:[(0,F.jsx)(b.Header,{children:`Snapshot Information`}),(0,F.jsxs)(b.Content,{children:[(0,F.jsx)(x,{label:`Snapshot ID`,value:I.SnapshotId}),(0,F.jsx)(x,{label:`Volume ID`,value:I.VolumeId?(0,F.jsx)(o,{className:`text-primary hover:underline`,params:{id:I.VolumeId},to:`/ec2/describe-volumes/$id`,children:I.VolumeId}):void 0}),(0,F.jsx)(x,{label:`Volume Size`,value:`${I.VolumeSize} GiB`}),(0,F.jsx)(x,{label:`State`,value:I.State}),(0,F.jsx)(x,{label:`Description`,value:I.Description}),(0,F.jsx)(x,{label:`Progress`,value:I.Progress}),(0,F.jsx)(x,{label:`Start Time`,value:Y}),(0,F.jsx)(x,{label:`Owner ID`,value:I.OwnerId}),(0,F.jsx)(x,{label:`Encrypted`,value:I.Encrypted?`Yes`:`No`})]})]})]}),(0,F.jsx)(M,{description:`Are you sure you want to delete the snapshot "${I.SnapshotId}"? This action cannot be undone.`,isPending:L.isPending,onConfirm:q,onOpenChange:B,open:z,title:`Delete Snapshot`}),(0,F.jsx)(k,{onOpenChange:H,open:V,children:(0,F.jsxs)(C,{children:[(0,F.jsxs)(O,{children:[(0,F.jsx)(w,{children:`Copy Snapshot`}),(0,F.jsx)(S,{children:`Create a copy of this snapshot in the current region.`})]}),(0,F.jsxs)(j,{children:[(0,F.jsx)(A,{children:(0,F.jsx)(`label`,{htmlFor:`copyDescription`,children:`Description (optional)`})}),(0,F.jsx)(g,{id:`copyDescription`,onChange:e=>W(e.target.value),placeholder:`Description for the snapshot copy`,value:U})]}),(0,F.jsxs)(E,{children:[(0,F.jsx)(D,{children:`Cancel`}),(0,F.jsx)(T,{disabled:R.isPending,onClick:J,children:R.isPending?`Copying…`:`Copy Snapshot`})]})]})})]})}export{I as component};
+1 -1
View File
@@ -1 +1 @@
import{a as e,n as t,r as n}from"./compiler-runtime.js";import{t as r}from"./useSuspenseQuery.js";import{t as i}from"./error-banner.js";import{s as a}from"./utils.js";import{t as o}from"./link.js";import{t as s}from"./useNavigate.js";import{t as c}from"./button.js";import{t as l}from"./back-link.js";import{t as u}from"./trash-2.js";import{m as d}from"./ec2.js";import{m as f}from"./ec22.js";import{o as p}from"./index.js";import{t as m}from"./page-heading.js";import{t as h}from"./state-badge.js";import{n as g,t as _}from"./detail-row.js";import{t as v}from"./delete-confirmation-dialog.js";var y=e(n()),b=t();function x(){let{id:e}=p.useParams(),t=s(),{data:n}=r(f(e)),x=n.Subnets?.[0],S=d(),[C,w]=(0,y.useState)(!1),T=async()=>{try{await S.mutateAsync(e),t({to:`/ec2/describe-subnets`})}finally{w(!1)}};if(!x?.SubnetId)return(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(l,{to:`/ec2/describe-subnets`,children:`Back to Subnets`}),(0,b.jsx)(`p`,{className:`text-muted-foreground`,children:`Subnet not found.`})]});let E=a(x.Tags);return(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(l,{to:`/ec2/describe-subnets`,children:`Back to Subnets`}),S.error&&(0,b.jsx)(i,{error:S.error,msg:`Failed to delete subnet`}),(0,b.jsxs)(`div`,{className:`space-y-6`,children:[(0,b.jsx)(m,{actions:(0,b.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,b.jsxs)(c,{onClick:()=>w(!0),size:`sm`,variant:`destructive`,children:[(0,b.jsx)(u,{className:`size-4`}),`Delete`]}),(0,b.jsx)(h,{state:x.State})]}),subtitle:`Subnet Details`,title:E?`${x.SubnetId} (${E})`:x.SubnetId}),(0,b.jsxs)(g,{children:[(0,b.jsx)(g.Header,{children:`Subnet Information`}),(0,b.jsxs)(g.Content,{children:[(0,b.jsx)(_,{label:`Subnet ID`,value:x.SubnetId}),(0,b.jsx)(_,{label:`VPC ID`,value:x.VpcId?(0,b.jsx)(o,{className:`text-primary hover:underline`,params:{id:x.VpcId},to:`/ec2/describe-vpcs/$id`,children:x.VpcId}):`—`}),(0,b.jsx)(_,{label:`State`,value:x.State}),(0,b.jsx)(_,{label:`CIDR Block`,value:x.CidrBlock}),(0,b.jsx)(_,{label:`Availability Zone`,value:x.AvailabilityZone}),(0,b.jsx)(_,{label:`Available IP Count`,value:x.AvailableIpAddressCount?.toString()}),(0,b.jsx)(_,{label:`Map Public IP on Launch`,value:x.MapPublicIpOnLaunch?`Yes`:`No`}),(0,b.jsx)(_,{label:`Default for AZ`,value:x.DefaultForAz?`Yes`:`No`})]})]})]}),(0,b.jsx)(v,{description:`Are you sure you want to delete the subnet "${x.SubnetId}"? This action cannot be undone.`,isPending:S.isPending,onConfirm:T,onOpenChange:w,open:C,title:`Delete Subnet`})]})}export{x as component};
import{a as e,n as t,r as n}from"./compiler-runtime.js";import{t as r}from"./useSuspenseQuery.js";import{t as i}from"./error-banner.js";import{s as a}from"./utils.js";import{t as o}from"./link.js";import{t as s}from"./useNavigate.js";import{t as c}from"./button.js";import{t as l}from"./back-link.js";import{t as u}from"./trash-2.js";import{h as d}from"./ec22.js";import{m as f}from"./ec23.js";import{o as p}from"./index.js";import{t as m}from"./page-heading.js";import{t as h}from"./state-badge.js";import{n as g,t as _}from"./detail-row.js";import{t as v}from"./delete-confirmation-dialog.js";var y=e(n()),b=t();function x(){let{id:e}=p.useParams(),t=s(),{data:n}=r(f(e)),x=n.Subnets?.[0],S=d(),[C,w]=(0,y.useState)(!1),T=async()=>{try{await S.mutateAsync(e),t({to:`/ec2/describe-subnets`})}finally{w(!1)}};if(!x?.SubnetId)return(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(l,{to:`/ec2/describe-subnets`,children:`Back to Subnets`}),(0,b.jsx)(`p`,{className:`text-muted-foreground`,children:`Subnet not found.`})]});let E=a(x.Tags);return(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(l,{to:`/ec2/describe-subnets`,children:`Back to Subnets`}),S.error&&(0,b.jsx)(i,{error:S.error,msg:`Failed to delete subnet`}),(0,b.jsxs)(`div`,{className:`space-y-6`,children:[(0,b.jsx)(m,{actions:(0,b.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,b.jsxs)(c,{onClick:()=>w(!0),size:`sm`,variant:`destructive`,children:[(0,b.jsx)(u,{className:`size-4`}),`Delete`]}),(0,b.jsx)(h,{state:x.State})]}),subtitle:`Subnet Details`,title:E?`${x.SubnetId} (${E})`:x.SubnetId}),(0,b.jsxs)(g,{children:[(0,b.jsx)(g.Header,{children:`Subnet Information`}),(0,b.jsxs)(g.Content,{children:[(0,b.jsx)(_,{label:`Subnet ID`,value:x.SubnetId}),(0,b.jsx)(_,{label:`VPC ID`,value:x.VpcId?(0,b.jsx)(o,{className:`text-primary hover:underline`,params:{id:x.VpcId},to:`/ec2/describe-vpcs/$id`,children:x.VpcId}):`—`}),(0,b.jsx)(_,{label:`State`,value:x.State}),(0,b.jsx)(_,{label:`CIDR Block`,value:x.CidrBlock}),(0,b.jsx)(_,{label:`Availability Zone`,value:x.AvailabilityZone}),(0,b.jsx)(_,{label:`Available IP Count`,value:x.AvailableIpAddressCount?.toString()}),(0,b.jsx)(_,{label:`Map Public IP on Launch`,value:x.MapPublicIpOnLaunch?`Yes`:`No`}),(0,b.jsx)(_,{label:`Default for AZ`,value:x.DefaultForAz?`Yes`:`No`})]})]})]}),(0,b.jsx)(v,{description:`Are you sure you want to delete the subnet "${x.SubnetId}"? This action cannot be undone.`,isPending:S.isPending,onConfirm:T,onOpenChange:w,open:C,title:`Delete Subnet`})]})}export{x as component};
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1 +1 @@
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{t as r}from"./error-banner.js";import{t as i}from"./useNavigate.js";import{t as a}from"./back-link.js";import{x as o}from"./ec2.js";import{g as s}from"./ec22.js";import{A as c,c as l}from"./index.js";import{t as u}from"./page-heading.js";import{i as d,n as f,t as p}from"./field.js";import{r as m,t as h}from"./zod.js";import{l as g}from"./ec23.js";import{t as _}from"./form-actions.js";var v=t(),y=e();function b(){let e=(0,v.c)(53),{id:t}=l.useParams(),b=i(),x;e[0]===t?x=e[1]:(x=s(t),e[0]=t,e[1]=x);let{data:S}=n(x),C=S.Volumes?.[0],w=C?.VolumeId,T=o(),E=C?.Size??1,D;e[2]===E?D=e[3]:(D=h(g.refine(e=>e.size>E,{message:`New size must be greater than current size (${E} GiB)`,path:[`size`]})),e[2]=E,e[3]=D);let O;e[4]===E?O=e[5]:(O={size:E},e[4]=E,e[5]=O);let k;e[6]!==D||e[7]!==O?(k={resolver:D,defaultValues:O},e[6]=D,e[7]=O,e[8]=k):k=e[8];let{handleSubmit:A,register:j,formState:M}=m(k),{errors:N,isSubmitting:P}=M;if(!w){let t;return e[9]===Symbol.for(`react.memo_cache_sentinel`)?(t=(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(a,{to:`/ec2/describe-volumes`,children:`Back to volumes`}),(0,y.jsx)(`p`,{className:`text-muted-foreground`,children:`Volume not found.`})]}),e[9]=t):t=e[9],t}let F;e[10]!==T||e[11]!==b||e[12]!==w?(F=async e=>{await T.mutateAsync({...e,volumeId:w}),b({to:`/ec2/describe-volumes/$id`,params:{id:w}})},e[10]=T,e[11]=b,e[12]=w,e[13]=F):F=e[13];let I=F,L,R;e[14]===w?(L=e[15],R=e[16]):(L=(0,y.jsx)(a,{params:{id:w},to:`/ec2/describe-volumes/$id`,children:`Back to volume`}),R=(0,y.jsx)(u,{subtitle:w,title:`Resize Volume`}),e[14]=w,e[15]=L,e[16]=R);let z;e[17]===T.error?z=e[18]:(z=T.error&&(0,y.jsx)(r,{error:T.error,msg:`Failed to resize volume`}),e[17]=T.error,e[18]=z);let B;e[19]!==A||e[20]!==I?(B=A(I),e[19]=A,e[20]=I,e[21]=B):B=e[21];let V;e[22]===E?V=e[23]:(V=(0,y.jsx)(`div`,{className:`space-y-2`,children:(0,y.jsxs)(`p`,{className:`text-sm text-muted-foreground`,children:[`Current size: `,E,` GiB`]})}),e[22]=E,e[23]=V);let H;e[24]===Symbol.for(`react.memo_cache_sentinel`)?(H=(0,y.jsx)(d,{children:(0,y.jsx)(`label`,{htmlFor:`size`,children:`New size (GiB)`})}),e[24]=H):H=e[24];let U=!!N.size,W=E+1,G;e[25]===j?G=e[26]:(G=j(`size`,{valueAsNumber:!0}),e[25]=j,e[26]=G);let K;e[27]!==U||e[28]!==W||e[29]!==G?(K=(0,y.jsx)(c,{"aria-invalid":U,id:`size`,min:W,type:`number`,...G}),e[27]=U,e[28]=W,e[29]=G,e[30]=K):K=e[30];let q;e[31]===N.size?q=e[32]:(q=(0,y.jsx)(f,{errors:[N.size]}),e[31]=N.size,e[32]=q);let J;e[33]!==K||e[34]!==q?(J=(0,y.jsxs)(p,{children:[H,K,q]}),e[33]=K,e[34]=q,e[35]=J):J=e[35];let Y;e[36]!==b||e[37]!==w?(Y=()=>b({to:`/ec2/describe-volumes/$id`,params:{id:w}}),e[36]=b,e[37]=w,e[38]=Y):Y=e[38];let X;e[39]!==P||e[40]!==T.isPending||e[41]!==Y?(X=(0,y.jsx)(_,{isPending:T.isPending,isSubmitting:P,onCancel:Y,pendingLabel:`Resizing\\u2026`,submitLabel:`Resize Volume`}),e[39]=P,e[40]=T.isPending,e[41]=Y,e[42]=X):X=e[42];let Z;e[43]!==V||e[44]!==J||e[45]!==X||e[46]!==B?(Z=(0,y.jsxs)(`form`,{className:`max-w-4xl space-y-6`,onSubmit:B,children:[V,J,X]}),e[43]=V,e[44]=J,e[45]=X,e[46]=B,e[47]=Z):Z=e[47];let Q;return e[48]!==Z||e[49]!==L||e[50]!==R||e[51]!==z?(Q=(0,y.jsxs)(y.Fragment,{children:[L,R,z,Z]}),e[48]=Z,e[49]=L,e[50]=R,e[51]=z,e[52]=Q):Q=e[52],Q}export{b as component};
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{t as r}from"./error-banner.js";import{t as i}from"./useNavigate.js";import{t as a}from"./back-link.js";import{l as o}from"./ec2.js";import{S as s}from"./ec22.js";import{g as c}from"./ec23.js";import{A as l,c as u}from"./index.js";import{t as d}from"./page-heading.js";import{i as f,n as p,t as m}from"./field.js";import{r as h,t as g}from"./zod.js";import{t as _}from"./form-actions.js";var v=t(),y=e();function b(){let e=(0,v.c)(53),{id:t}=u.useParams(),b=i(),x;e[0]===t?x=e[1]:(x=c(t),e[0]=t,e[1]=x);let{data:S}=n(x),C=S.Volumes?.[0],w=C?.VolumeId,T=s(),E=C?.Size??1,D;e[2]===E?D=e[3]:(D=g(o.refine(e=>e.size>E,{message:`New size must be greater than current size (${E} GiB)`,path:[`size`]})),e[2]=E,e[3]=D);let O;e[4]===E?O=e[5]:(O={size:E},e[4]=E,e[5]=O);let k;e[6]!==D||e[7]!==O?(k={resolver:D,defaultValues:O},e[6]=D,e[7]=O,e[8]=k):k=e[8];let{handleSubmit:A,register:j,formState:M}=h(k),{errors:N,isSubmitting:P}=M;if(!w){let t;return e[9]===Symbol.for(`react.memo_cache_sentinel`)?(t=(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(a,{to:`/ec2/describe-volumes`,children:`Back to volumes`}),(0,y.jsx)(`p`,{className:`text-muted-foreground`,children:`Volume not found.`})]}),e[9]=t):t=e[9],t}let F;e[10]!==T||e[11]!==b||e[12]!==w?(F=async e=>{await T.mutateAsync({...e,volumeId:w}),b({to:`/ec2/describe-volumes/$id`,params:{id:w}})},e[10]=T,e[11]=b,e[12]=w,e[13]=F):F=e[13];let I=F,L,R;e[14]===w?(L=e[15],R=e[16]):(L=(0,y.jsx)(a,{params:{id:w},to:`/ec2/describe-volumes/$id`,children:`Back to volume`}),R=(0,y.jsx)(d,{subtitle:w,title:`Resize Volume`}),e[14]=w,e[15]=L,e[16]=R);let z;e[17]===T.error?z=e[18]:(z=T.error&&(0,y.jsx)(r,{error:T.error,msg:`Failed to resize volume`}),e[17]=T.error,e[18]=z);let B;e[19]!==A||e[20]!==I?(B=A(I),e[19]=A,e[20]=I,e[21]=B):B=e[21];let V;e[22]===E?V=e[23]:(V=(0,y.jsx)(`div`,{className:`space-y-2`,children:(0,y.jsxs)(`p`,{className:`text-sm text-muted-foreground`,children:[`Current size: `,E,` GiB`]})}),e[22]=E,e[23]=V);let H;e[24]===Symbol.for(`react.memo_cache_sentinel`)?(H=(0,y.jsx)(f,{children:(0,y.jsx)(`label`,{htmlFor:`size`,children:`New size (GiB)`})}),e[24]=H):H=e[24];let U=!!N.size,W=E+1,G;e[25]===j?G=e[26]:(G=j(`size`,{valueAsNumber:!0}),e[25]=j,e[26]=G);let K;e[27]!==U||e[28]!==W||e[29]!==G?(K=(0,y.jsx)(l,{"aria-invalid":U,id:`size`,min:W,type:`number`,...G}),e[27]=U,e[28]=W,e[29]=G,e[30]=K):K=e[30];let q;e[31]===N.size?q=e[32]:(q=(0,y.jsx)(p,{errors:[N.size]}),e[31]=N.size,e[32]=q);let J;e[33]!==K||e[34]!==q?(J=(0,y.jsxs)(m,{children:[H,K,q]}),e[33]=K,e[34]=q,e[35]=J):J=e[35];let Y;e[36]!==b||e[37]!==w?(Y=()=>b({to:`/ec2/describe-volumes/$id`,params:{id:w}}),e[36]=b,e[37]=w,e[38]=Y):Y=e[38];let X;e[39]!==P||e[40]!==T.isPending||e[41]!==Y?(X=(0,y.jsx)(_,{isPending:T.isPending,isSubmitting:P,onCancel:Y,pendingLabel:`Resizing\\u2026`,submitLabel:`Resize Volume`}),e[39]=P,e[40]=T.isPending,e[41]=Y,e[42]=X):X=e[42];let Z;e[43]!==V||e[44]!==J||e[45]!==X||e[46]!==B?(Z=(0,y.jsxs)(`form`,{className:`max-w-4xl space-y-6`,onSubmit:B,children:[V,J,X]}),e[43]=V,e[44]=J,e[45]=X,e[46]=B,e[47]=Z):Z=e[47];let Q;return e[48]!==Z||e[49]!==L||e[50]!==R||e[51]!==z?(Q=(0,y.jsxs)(y.Fragment,{children:[L,R,z,Z]}),e[48]=Z,e[49]=L,e[50]=R,e[51]=z,e[52]=Q):Q=e[52],Q}export{b as component};
+1 -1
View File
@@ -1 +1 @@
import{a as e,n as t,r as n}from"./compiler-runtime.js";import{t as r}from"./useSuspenseQuery.js";import{t as i}from"./error-banner.js";import{s as a}from"./utils.js";import{t as o}from"./link.js";import{t as s}from"./useNavigate.js";import{t as c}from"./button.js";import{t as l}from"./back-link.js";import{t as u}from"./trash-2.js";import{g as d}from"./ec2.js";import{h as f,v as p}from"./ec22.js";import{l as m}from"./index.js";import{t as h}from"./page-heading.js";import{t as g}from"./state-badge.js";import{n as _,t as v}from"./detail-row.js";import{t as y}from"./delete-confirmation-dialog.js";var b=e(n()),x=t();function S(){let{id:e}=m.useParams(),t=s(),{data:n}=r(p(e)),{data:S}=r(f),C=n.Vpcs?.[0],w=d(),[T,E]=(0,b.useState)(!1),D=S.Subnets?.filter(t=>t.VpcId===e)??[],O=async()=>{try{await w.mutateAsync(e),t({to:`/ec2/describe-vpcs`})}finally{E(!1)}};if(!C?.VpcId)return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(l,{to:`/ec2/describe-vpcs`,children:`Back to VPCs`}),(0,x.jsx)(`p`,{className:`text-muted-foreground`,children:`VPC not found.`})]});let k=a(C.Tags);return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(l,{to:`/ec2/describe-vpcs`,children:`Back to VPCs`}),w.error&&(0,x.jsx)(i,{error:w.error,msg:`Failed to delete VPC`}),(0,x.jsxs)(`div`,{className:`space-y-6`,children:[(0,x.jsx)(h,{actions:(0,x.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,x.jsxs)(c,{onClick:()=>E(!0),size:`sm`,variant:`destructive`,children:[(0,x.jsx)(u,{className:`size-4`}),`Delete`]}),(0,x.jsx)(g,{state:C.State})]}),subtitle:`VPC Details`,title:k?`${C.VpcId} (${k})`:C.VpcId}),(0,x.jsxs)(_,{children:[(0,x.jsx)(_.Header,{children:`VPC Information`}),(0,x.jsxs)(_.Content,{children:[(0,x.jsx)(v,{label:`VPC ID`,value:C.VpcId}),(0,x.jsx)(v,{label:`State`,value:C.State}),(0,x.jsx)(v,{label:`CIDR Block`,value:C.CidrBlock}),(0,x.jsx)(v,{label:`Is Default`,value:C.IsDefault?`Yes`:`No`}),(0,x.jsx)(v,{label:`DHCP Options ID`,value:C.DhcpOptionsId}),(0,x.jsx)(v,{label:`Instance Tenancy`,value:C.InstanceTenancy}),(0,x.jsx)(v,{label:`Owner ID`,value:C.OwnerId})]})]}),D.length>0&&(0,x.jsxs)(_,{children:[(0,x.jsxs)(_.Header,{children:[`Subnets (`,D.length,`)`]}),D.map(e=>e.SubnetId?(0,x.jsxs)(_.Content,{children:[(0,x.jsx)(v,{label:`Subnet ID`,value:(0,x.jsx)(o,{className:`text-primary hover:underline`,params:{id:e.SubnetId},to:`/ec2/describe-subnets/$id`,children:e.SubnetId})}),(0,x.jsx)(v,{label:`CIDR Block`,value:e.CidrBlock}),(0,x.jsx)(v,{label:`Availability Zone`,value:e.AvailabilityZone}),(0,x.jsx)(v,{label:`State`,value:e.State})]},e.SubnetId):null)]})]}),(0,x.jsx)(y,{description:`Are you sure you want to delete the VPC "${C.VpcId}"? This action cannot be undone. The VPC must have no associated subnets or internet gateways.`,isPending:w.isPending,onConfirm:O,onOpenChange:E,open:T,title:`Delete VPC`})]})}export{S as component};
import{a as e,n as t,r as n}from"./compiler-runtime.js";import{t as r}from"./useSuspenseQuery.js";import{t as i}from"./error-banner.js";import{s as a}from"./utils.js";import{t as o}from"./link.js";import{t as s}from"./useNavigate.js";import{t as c}from"./button.js";import{t as l}from"./back-link.js";import{t as u}from"./trash-2.js";import{_ as d}from"./ec22.js";import{h as f,v as p}from"./ec23.js";import{l as m}from"./index.js";import{t as h}from"./page-heading.js";import{t as g}from"./state-badge.js";import{n as _,t as v}from"./detail-row.js";import{t as y}from"./delete-confirmation-dialog.js";var b=e(n()),x=t();function S(){let{id:e}=m.useParams(),t=s(),{data:n}=r(p(e)),{data:S}=r(f),C=n.Vpcs?.[0],w=d(),[T,E]=(0,b.useState)(!1),D=S.Subnets?.filter(t=>t.VpcId===e)??[],O=async()=>{try{await w.mutateAsync(e),t({to:`/ec2/describe-vpcs`})}finally{E(!1)}};if(!C?.VpcId)return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(l,{to:`/ec2/describe-vpcs`,children:`Back to VPCs`}),(0,x.jsx)(`p`,{className:`text-muted-foreground`,children:`VPC not found.`})]});let k=a(C.Tags);return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(l,{to:`/ec2/describe-vpcs`,children:`Back to VPCs`}),w.error&&(0,x.jsx)(i,{error:w.error,msg:`Failed to delete VPC`}),(0,x.jsxs)(`div`,{className:`space-y-6`,children:[(0,x.jsx)(h,{actions:(0,x.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,x.jsxs)(c,{onClick:()=>E(!0),size:`sm`,variant:`destructive`,children:[(0,x.jsx)(u,{className:`size-4`}),`Delete`]}),(0,x.jsx)(g,{state:C.State})]}),subtitle:`VPC Details`,title:k?`${C.VpcId} (${k})`:C.VpcId}),(0,x.jsxs)(_,{children:[(0,x.jsx)(_.Header,{children:`VPC Information`}),(0,x.jsxs)(_.Content,{children:[(0,x.jsx)(v,{label:`VPC ID`,value:C.VpcId}),(0,x.jsx)(v,{label:`State`,value:C.State}),(0,x.jsx)(v,{label:`CIDR Block`,value:C.CidrBlock}),(0,x.jsx)(v,{label:`Is Default`,value:C.IsDefault?`Yes`:`No`}),(0,x.jsx)(v,{label:`DHCP Options ID`,value:C.DhcpOptionsId}),(0,x.jsx)(v,{label:`Instance Tenancy`,value:C.InstanceTenancy}),(0,x.jsx)(v,{label:`Owner ID`,value:C.OwnerId})]})]}),D.length>0&&(0,x.jsxs)(_,{children:[(0,x.jsxs)(_.Header,{children:[`Subnets (`,D.length,`)`]}),D.map(e=>e.SubnetId?(0,x.jsxs)(_.Content,{children:[(0,x.jsx)(v,{label:`Subnet ID`,value:(0,x.jsx)(o,{className:`text-primary hover:underline`,params:{id:e.SubnetId},to:`/ec2/describe-subnets/$id`,children:e.SubnetId})}),(0,x.jsx)(v,{label:`CIDR Block`,value:e.CidrBlock}),(0,x.jsx)(v,{label:`Availability Zone`,value:e.AvailabilityZone}),(0,x.jsx)(v,{label:`State`,value:e.State})]},e.SubnetId):null)]})]}),(0,x.jsx)(y,{description:`Are you sure you want to delete the VPC "${C.VpcId}"? This action cannot be undone. The VPC must have no associated subnets or internet gateways.`,isPending:w.isPending,onConfirm:O,onOpenChange:E,open:T,title:`Delete VPC`})]})}export{S as component};
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./error-banner.js";import{t as r}from"./useNavigate.js";import{t as i}from"./back-link.js";import{en as a,tn as o}from"./awsClient.js";import{t as s}from"./s3.js";import{A as c}from"./index.js";import{t as l}from"./page-heading.js";import{i as u,n as d,t as f}from"./field.js";import{r as p,t as m}from"./zod.js";import{t as h}from"./form-actions.js";var g=t(),_=a({bucketName:o().min(3,`Bucket name must be at least 3 characters`).max(63,`Bucket name must be at most 63 characters`).regex(/^[a-z0-9][a-z0-9.-]*[a-z0-9]$/,`Must start and end with a lowercase letter or number`).regex(/^[a-z0-9.-]+$/,`Only lowercase letters, numbers, hyphens, and periods allowed`).refine(e=>!e.includes(`..`),`Must not contain consecutive periods`).refine(e=>!(e.includes(`.-`)||e.includes(`-.`)),`Must not contain adjacent period and hyphen`)}),v=e();function y(){let e=(0,g.c)(35),t=r(),a=s(),o;e[0]===Symbol.for(`react.memo_cache_sentinel`)?(o={resolver:m(_)},e[0]=o):o=e[0];let{handleSubmit:y,register:b,formState:x}=p(o),{errors:S,isSubmitting:C}=x,w;e[1]!==a||e[2]!==t?(w=async e=>{await a.mutateAsync(e),t({to:`/s3/ls`})},e[1]=a,e[2]=t,e[3]=w):w=e[3];let T=w,E,D;e[4]===Symbol.for(`react.memo_cache_sentinel`)?(E=(0,v.jsx)(i,{to:`/s3/ls`,children:`Back to buckets`}),D=(0,v.jsx)(l,{title:`Create Bucket`}),e[4]=E,e[5]=D):(E=e[4],D=e[5]);let O;e[6]===a.error?O=e[7]:(O=a.error&&(0,v.jsx)(n,{error:a.error,msg:`Failed to create bucket`}),e[6]=a.error,e[7]=O);let k;e[8]!==y||e[9]!==T?(k=y(T),e[8]=y,e[9]=T,e[10]=k):k=e[10];let A;e[11]===Symbol.for(`react.memo_cache_sentinel`)?(A=(0,v.jsx)(u,{children:(0,v.jsx)(`label`,{htmlFor:`bucketName`,children:`Bucket Name`})}),e[11]=A):A=e[11];let j=!!S.bucketName,M;e[12]===b?M=e[13]:(M=b(`bucketName`),e[12]=b,e[13]=M);let N;e[14]!==j||e[15]!==M?(N=(0,v.jsx)(c,{"aria-invalid":j,id:`bucketName`,placeholder:`my-bucket`,type:`text`,...M}),e[14]=j,e[15]=M,e[16]=N):N=e[16];let P;e[17]===S.bucketName?P=e[18]:(P=(0,v.jsx)(d,{errors:[S.bucketName]}),e[17]=S.bucketName,e[18]=P);let F;e[19]!==N||e[20]!==P?(F=(0,v.jsxs)(f,{children:[A,N,P]}),e[19]=N,e[20]=P,e[21]=F):F=e[21];let I;e[22]===t?I=e[23]:(I=()=>t({to:`/s3/ls`}),e[22]=t,e[23]=I);let L;e[24]!==a.isPending||e[25]!==C||e[26]!==I?(L=(0,v.jsx)(h,{isPending:a.isPending,isSubmitting:C,onCancel:I,pendingLabel:`Creating\\u2026`,submitLabel:`Create Bucket`}),e[24]=a.isPending,e[25]=C,e[26]=I,e[27]=L):L=e[27];let R;e[28]!==F||e[29]!==L||e[30]!==k?(R=(0,v.jsxs)(`form`,{className:`max-w-4xl space-y-6`,onSubmit:k,children:[F,L]}),e[28]=F,e[29]=L,e[30]=k,e[31]=R):R=e[31];let z;return e[32]!==R||e[33]!==O?(z=(0,v.jsxs)(v.Fragment,{children:[E,D,O,R]}),e[32]=R,e[33]=O,e[34]=z):z=e[34],z}export{y as component};
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./error-banner.js";import{t as r}from"./useNavigate.js";import{t as i}from"./back-link.js";import{ln as a,un as o}from"./awsClient.js";import{t as s}from"./s3.js";import{A as c}from"./index.js";import{t as l}from"./page-heading.js";import{i as u,n as d,t as f}from"./field.js";import{r as p,t as m}from"./zod.js";import{t as h}from"./form-actions.js";var g=t(),_=a({bucketName:o().min(3,`Bucket name must be at least 3 characters`).max(63,`Bucket name must be at most 63 characters`).regex(/^[a-z0-9][a-z0-9.-]*[a-z0-9]$/,`Must start and end with a lowercase letter or number`).regex(/^[a-z0-9.-]+$/,`Only lowercase letters, numbers, hyphens, and periods allowed`).refine(e=>!e.includes(`..`),`Must not contain consecutive periods`).refine(e=>!(e.includes(`.-`)||e.includes(`-.`)),`Must not contain adjacent period and hyphen`)}),v=e();function y(){let e=(0,g.c)(35),t=r(),a=s(),o;e[0]===Symbol.for(`react.memo_cache_sentinel`)?(o={resolver:m(_)},e[0]=o):o=e[0];let{handleSubmit:y,register:b,formState:x}=p(o),{errors:S,isSubmitting:C}=x,w;e[1]!==a||e[2]!==t?(w=async e=>{await a.mutateAsync(e),t({to:`/s3/ls`})},e[1]=a,e[2]=t,e[3]=w):w=e[3];let T=w,E,D;e[4]===Symbol.for(`react.memo_cache_sentinel`)?(E=(0,v.jsx)(i,{to:`/s3/ls`,children:`Back to buckets`}),D=(0,v.jsx)(l,{title:`Create Bucket`}),e[4]=E,e[5]=D):(E=e[4],D=e[5]);let O;e[6]===a.error?O=e[7]:(O=a.error&&(0,v.jsx)(n,{error:a.error,msg:`Failed to create bucket`}),e[6]=a.error,e[7]=O);let k;e[8]!==y||e[9]!==T?(k=y(T),e[8]=y,e[9]=T,e[10]=k):k=e[10];let A;e[11]===Symbol.for(`react.memo_cache_sentinel`)?(A=(0,v.jsx)(u,{children:(0,v.jsx)(`label`,{htmlFor:`bucketName`,children:`Bucket Name`})}),e[11]=A):A=e[11];let j=!!S.bucketName,M;e[12]===b?M=e[13]:(M=b(`bucketName`),e[12]=b,e[13]=M);let N;e[14]!==j||e[15]!==M?(N=(0,v.jsx)(c,{"aria-invalid":j,id:`bucketName`,placeholder:`my-bucket`,type:`text`,...M}),e[14]=j,e[15]=M,e[16]=N):N=e[16];let P;e[17]===S.bucketName?P=e[18]:(P=(0,v.jsx)(d,{errors:[S.bucketName]}),e[17]=S.bucketName,e[18]=P);let F;e[19]!==N||e[20]!==P?(F=(0,v.jsxs)(f,{children:[A,N,P]}),e[19]=N,e[20]=P,e[21]=F):F=e[21];let I;e[22]===t?I=e[23]:(I=()=>t({to:`/s3/ls`}),e[22]=t,e[23]=I);let L;e[24]!==a.isPending||e[25]!==C||e[26]!==I?(L=(0,v.jsx)(h,{isPending:a.isPending,isSubmitting:C,onCancel:I,pendingLabel:`Creating\\u2026`,submitLabel:`Create Bucket`}),e[24]=a.isPending,e[25]=C,e[26]=I,e[27]=L):L=e[27];let R;e[28]!==F||e[29]!==L||e[30]!==k?(R=(0,v.jsxs)(`form`,{className:`max-w-4xl space-y-6`,onSubmit:k,children:[F,L]}),e[28]=F,e[29]=L,e[30]=k,e[31]=R):R=e[31];let z;return e[32]!==R||e[33]!==O?(z=(0,v.jsxs)(v.Fragment,{children:[E,D,O,R]}),e[32]=R,e[33]=O,e[34]=z):z=e[34],z}export{y as component};
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./error-banner.js";import{t as r}from"./useNavigate.js";import{t as i}from"./back-link.js";import{a,i as o,n as s,r as c,t as l}from"./select.js";import{o as u}from"./ec2.js";import{A as d}from"./index.js";import{t as f}from"./page-heading.js";import{i as p,n as m,t as h}from"./field.js";import{n as g,r as _,t as v}from"./zod.js";import{r as y}from"./ec23.js";import{t as b}from"./form-actions.js";var x=t(),S=e();function C(){let e=(0,x.c)(47),t=r(),C=u(),w;e[0]===Symbol.for(`react.memo_cache_sentinel`)?(w={resolver:v(y),defaultValues:{groupName:``,strategy:`spread`}},e[0]=w):w=e[0];let{control:T,handleSubmit:E,register:D,formState:O}=_(w),{errors:k,isSubmitting:A}=O,j;e[1]!==C||e[2]!==t?(j=async e=>{t({to:`/ec2/describe-placement-groups/$id`,params:{id:(await C.mutateAsync(e)).PlacementGroup?.GroupId??``}})},e[1]=C,e[2]=t,e[3]=j):j=e[3];let M=j,N,P;e[4]===Symbol.for(`react.memo_cache_sentinel`)?(N=(0,S.jsx)(i,{to:`/ec2/describe-placement-groups`,children:`Back to placement groups`}),P=(0,S.jsx)(f,{title:`Create Placement Group`}),e[4]=N,e[5]=P):(N=e[4],P=e[5]);let F;e[6]===C.error?F=e[7]:(F=C.error&&(0,S.jsx)(n,{error:C.error,msg:`Failed to create placement group`}),e[6]=C.error,e[7]=F);let I;e[8]!==E||e[9]!==M?(I=E(M),e[8]=E,e[9]=M,e[10]=I):I=e[10];let L;e[11]===Symbol.for(`react.memo_cache_sentinel`)?(L=(0,S.jsx)(p,{children:(0,S.jsx)(`label`,{htmlFor:`groupName`,children:`Group Name`})}),e[11]=L):L=e[11];let R=!!k.groupName,z;e[12]===D?z=e[13]:(z=D(`groupName`),e[12]=D,e[13]=z);let B;e[14]!==R||e[15]!==z?(B=(0,S.jsx)(d,{"aria-invalid":R,id:`groupName`,placeholder:`my-placement-group`,...z}),e[14]=R,e[15]=z,e[16]=B):B=e[16];let V;e[17]===k.groupName?V=e[18]:(V=(0,S.jsx)(m,{errors:[k.groupName]}),e[17]=k.groupName,e[18]=V);let H;e[19]!==B||e[20]!==V?(H=(0,S.jsxs)(h,{children:[L,B,V]}),e[19]=B,e[20]=V,e[21]=H):H=e[21];let U;e[22]===Symbol.for(`react.memo_cache_sentinel`)?(U=(0,S.jsx)(p,{children:(0,S.jsx)(`label`,{htmlFor:`strategy`,children:`Strategy`})}),e[22]=U):U=e[22];let W;e[23]===k.strategy?W=e[24]:(W=e=>{let{field:t}=e;return(0,S.jsxs)(l,{onValueChange:e=>t.onChange(e),value:t.value??``,children:[(0,S.jsx)(o,{"aria-invalid":!!k.strategy,className:`w-full`,id:`strategy`,children:(0,S.jsx)(a,{})}),(0,S.jsxs)(s,{children:[(0,S.jsx)(c,{value:`spread`,children:`spread`}),(0,S.jsx)(c,{value:`cluster`,children:`cluster`})]})]})},e[23]=k.strategy,e[24]=W);let G;e[25]!==T||e[26]!==W?(G=(0,S.jsx)(g,{control:T,name:`strategy`,render:W}),e[25]=T,e[26]=W,e[27]=G):G=e[27];let K;e[28]===k.strategy?K=e[29]:(K=(0,S.jsx)(m,{errors:[k.strategy]}),e[28]=k.strategy,e[29]=K);let q;e[30]!==G||e[31]!==K?(q=(0,S.jsxs)(h,{children:[U,G,K]}),e[30]=G,e[31]=K,e[32]=q):q=e[32];let J;e[33]===t?J=e[34]:(J=()=>t({to:`/ec2/describe-placement-groups`}),e[33]=t,e[34]=J);let Y;e[35]!==C.isPending||e[36]!==A||e[37]!==J?(Y=(0,S.jsx)(b,{isPending:C.isPending,isSubmitting:A,onCancel:J,pendingLabel:`Creating\\u2026`,submitLabel:`Create Placement Group`}),e[35]=C.isPending,e[36]=A,e[37]=J,e[38]=Y):Y=e[38];let X;e[39]!==H||e[40]!==q||e[41]!==Y||e[42]!==I?(X=(0,S.jsxs)(`form`,{className:`max-w-4xl space-y-6`,onSubmit:I,children:[H,q,Y]}),e[39]=H,e[40]=q,e[41]=Y,e[42]=I,e[43]=X):X=e[43];let Z;return e[44]!==X||e[45]!==F?(Z=(0,S.jsxs)(S.Fragment,{children:[N,P,F,X]}),e[44]=X,e[45]=F,e[46]=Z):Z=e[46],Z}export{C as component};
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./error-banner.js";import{t as r}from"./useNavigate.js";import{t as i}from"./back-link.js";import{a,i as o,n as s,r as c,t as l}from"./select.js";import{r as u}from"./ec2.js";import{o as d}from"./ec22.js";import{A as f}from"./index.js";import{t as p}from"./page-heading.js";import{i as m,n as h,t as g}from"./field.js";import{n as _,r as v,t as y}from"./zod.js";import{t as b}from"./form-actions.js";var x=t(),S=e();function C(){let e=(0,x.c)(47),t=r(),C=d(),w;e[0]===Symbol.for(`react.memo_cache_sentinel`)?(w={resolver:y(u),defaultValues:{groupName:``,strategy:`spread`}},e[0]=w):w=e[0];let{control:T,handleSubmit:E,register:D,formState:O}=v(w),{errors:k,isSubmitting:A}=O,j;e[1]!==C||e[2]!==t?(j=async e=>{t({to:`/ec2/describe-placement-groups/$id`,params:{id:(await C.mutateAsync(e)).PlacementGroup?.GroupId??``}})},e[1]=C,e[2]=t,e[3]=j):j=e[3];let M=j,N,P;e[4]===Symbol.for(`react.memo_cache_sentinel`)?(N=(0,S.jsx)(i,{to:`/ec2/describe-placement-groups`,children:`Back to placement groups`}),P=(0,S.jsx)(p,{title:`Create Placement Group`}),e[4]=N,e[5]=P):(N=e[4],P=e[5]);let F;e[6]===C.error?F=e[7]:(F=C.error&&(0,S.jsx)(n,{error:C.error,msg:`Failed to create placement group`}),e[6]=C.error,e[7]=F);let I;e[8]!==E||e[9]!==M?(I=E(M),e[8]=E,e[9]=M,e[10]=I):I=e[10];let L;e[11]===Symbol.for(`react.memo_cache_sentinel`)?(L=(0,S.jsx)(m,{children:(0,S.jsx)(`label`,{htmlFor:`groupName`,children:`Group Name`})}),e[11]=L):L=e[11];let R=!!k.groupName,z;e[12]===D?z=e[13]:(z=D(`groupName`),e[12]=D,e[13]=z);let B;e[14]!==R||e[15]!==z?(B=(0,S.jsx)(f,{"aria-invalid":R,id:`groupName`,placeholder:`my-placement-group`,...z}),e[14]=R,e[15]=z,e[16]=B):B=e[16];let V;e[17]===k.groupName?V=e[18]:(V=(0,S.jsx)(h,{errors:[k.groupName]}),e[17]=k.groupName,e[18]=V);let H;e[19]!==B||e[20]!==V?(H=(0,S.jsxs)(g,{children:[L,B,V]}),e[19]=B,e[20]=V,e[21]=H):H=e[21];let U;e[22]===Symbol.for(`react.memo_cache_sentinel`)?(U=(0,S.jsx)(m,{children:(0,S.jsx)(`label`,{htmlFor:`strategy`,children:`Strategy`})}),e[22]=U):U=e[22];let W;e[23]===k.strategy?W=e[24]:(W=e=>{let{field:t}=e;return(0,S.jsxs)(l,{onValueChange:e=>t.onChange(e),value:t.value??``,children:[(0,S.jsx)(o,{"aria-invalid":!!k.strategy,className:`w-full`,id:`strategy`,children:(0,S.jsx)(a,{})}),(0,S.jsxs)(s,{children:[(0,S.jsx)(c,{value:`spread`,children:`spread`}),(0,S.jsx)(c,{value:`cluster`,children:`cluster`})]})]})},e[23]=k.strategy,e[24]=W);let G;e[25]!==T||e[26]!==W?(G=(0,S.jsx)(_,{control:T,name:`strategy`,render:W}),e[25]=T,e[26]=W,e[27]=G):G=e[27];let K;e[28]===k.strategy?K=e[29]:(K=(0,S.jsx)(h,{errors:[k.strategy]}),e[28]=k.strategy,e[29]=K);let q;e[30]!==G||e[31]!==K?(q=(0,S.jsxs)(g,{children:[U,G,K]}),e[30]=G,e[31]=K,e[32]=q):q=e[32];let J;e[33]===t?J=e[34]:(J=()=>t({to:`/ec2/describe-placement-groups`}),e[33]=t,e[34]=J);let Y;e[35]!==C.isPending||e[36]!==A||e[37]!==J?(Y=(0,S.jsx)(b,{isPending:C.isPending,isSubmitting:A,onCancel:J,pendingLabel:`Creating\\u2026`,submitLabel:`Create Placement Group`}),e[35]=C.isPending,e[36]=A,e[37]=J,e[38]=Y):Y=e[38];let X;e[39]!==H||e[40]!==q||e[41]!==Y||e[42]!==I?(X=(0,S.jsxs)(`form`,{className:`max-w-4xl space-y-6`,onSubmit:I,children:[H,q,Y]}),e[39]=H,e[40]=q,e[41]=Y,e[42]=I,e[43]=X):X=e[43];let Z;return e[44]!==X||e[45]!==F?(Z=(0,S.jsxs)(S.Fragment,{children:[N,P,F,X]}),e[44]=X,e[45]=F,e[46]=Z):Z=e[46],Z}export{C as component};
@@ -1 +1 @@
import{n as e,t}from"./compiler-runtime.js";import{t as ee}from"./useSuspenseQuery.js";import{t as n}from"./error-banner.js";import{t as r}from"./useNavigate.js";import{t as i}from"./back-link.js";import{a,i as o,n as s,r as c,t as l}from"./select.js";import{s as u}from"./ec2.js";import{_ as d}from"./ec22.js";import{m as f}from"./index.js";import{t as p}from"./page-heading.js";import{i as m,n as te,t as h}from"./field.js";import{t as g}from"./textarea.js";import{n as _,r as v,t as y}from"./zod.js";import{i as b}from"./ec23.js";import{t as ne}from"./form-actions.js";var re=t(),x=e();function S(){let e=(0,re.c)(46),t=r(),{data:c}=ee(d),S=u(),w;e[0]===c.Volumes?w=e[1]:(w=c.Volumes??[],e[0]=c.Volumes,e[1]=w);let T=w,{volumeId:E}=f.useSearch(),D=E??T[0]?.VolumeId??``,O;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(O=y(b),e[2]=O):O=e[2];let k;e[3]===D?k=e[4]:(k={resolver:O,defaultValues:{volumeId:D,description:``}},e[3]=D,e[4]=k);let{control:A,handleSubmit:j,register:M,formState:N}=v(k),{errors:P,isSubmitting:F}=N,I;e[5]!==S||e[6]!==t?(I=async e=>{await S.mutateAsync(e),t({to:`/ec2/describe-snapshots`})},e[5]=S,e[6]=t,e[7]=I):I=e[7];let L=I,R,z;e[8]===Symbol.for(`react.memo_cache_sentinel`)?(R=(0,x.jsx)(i,{to:`/ec2/describe-snapshots`,children:`Back to snapshots`}),z=(0,x.jsx)(p,{title:`Create Snapshot`}),e[8]=R,e[9]=z):(R=e[8],z=e[9]);let B;e[10]===S.error?B=e[11]:(B=S.error&&(0,x.jsx)(n,{error:S.error,msg:`Failed to create snapshot`}),e[10]=S.error,e[11]=B);let V;e[12]!==j||e[13]!==L?(V=j(L),e[12]=j,e[13]=L,e[14]=V):V=e[14];let H;e[15]===Symbol.for(`react.memo_cache_sentinel`)?(H=(0,x.jsx)(m,{children:(0,x.jsx)(`label`,{htmlFor:`volumeId`,children:`Volume`})}),e[15]=H):H=e[15];let U;e[16]!==P.volumeId||e[17]!==T?(U=e=>{let{field:t}=e;return(0,x.jsxs)(l,{onValueChange:e=>t.onChange(e),value:t.value??``,children:[(0,x.jsx)(o,{"aria-invalid":!!P.volumeId,className:`w-full`,id:`volumeId`,children:(0,x.jsx)(a,{})}),(0,x.jsx)(s,{children:T.map(C)})]})},e[16]=P.volumeId,e[17]=T,e[18]=U):U=e[18];let W;e[19]!==A||e[20]!==U?(W=(0,x.jsx)(_,{control:A,name:`volumeId`,render:U}),e[19]=A,e[20]=U,e[21]=W):W=e[21];let G;e[22]===P.volumeId?G=e[23]:(G=(0,x.jsx)(te,{errors:[P.volumeId]}),e[22]=P.volumeId,e[23]=G);let K;e[24]!==W||e[25]!==G?(K=(0,x.jsxs)(h,{children:[H,W,G]}),e[24]=W,e[25]=G,e[26]=K):K=e[26];let q;e[27]===Symbol.for(`react.memo_cache_sentinel`)?(q=(0,x.jsx)(m,{children:(0,x.jsx)(`label`,{htmlFor:`description`,children:`Description (optional)`})}),e[27]=q):q=e[27];let J;e[28]===M?J=e[29]:(J=M(`description`),e[28]=M,e[29]=J);let Y;e[30]===J?Y=e[31]:(Y=(0,x.jsxs)(h,{children:[q,(0,x.jsx)(g,{id:`description`,placeholder:`Snapshot description`,...J})]}),e[30]=J,e[31]=Y);let X;e[32]===t?X=e[33]:(X=()=>t({to:`/ec2/describe-snapshots`}),e[32]=t,e[33]=X);let Z;e[34]!==S.isPending||e[35]!==F||e[36]!==X?(Z=(0,x.jsx)(ne,{isPending:S.isPending,isSubmitting:F,onCancel:X,pendingLabel:`Creating\\u2026`,submitLabel:`Create Snapshot`}),e[34]=S.isPending,e[35]=F,e[36]=X,e[37]=Z):Z=e[37];let Q;e[38]!==K||e[39]!==Y||e[40]!==Z||e[41]!==V?(Q=(0,x.jsxs)(`form`,{className:`max-w-4xl space-y-6`,onSubmit:V,children:[K,Y,Z]}),e[38]=K,e[39]=Y,e[40]=Z,e[41]=V,e[42]=Q):Q=e[42];let $;return e[43]!==Q||e[44]!==B?($=(0,x.jsxs)(x.Fragment,{children:[R,z,B,Q]}),e[43]=Q,e[44]=B,e[45]=$):$=e[45],$}function C(e){return(0,x.jsxs)(c,{value:e.VolumeId??``,children:[e.VolumeId,` (`,e.Size,` GiB)`]},e.VolumeId)}export{S as component};
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{t as r}from"./error-banner.js";import{t as i}from"./useNavigate.js";import{t as a}from"./back-link.js";import{a as o,i as s,n as c,r as l,t as u}from"./select.js";import{i as d}from"./ec2.js";import{s as f}from"./ec22.js";import{_ as p}from"./ec23.js";import{m}from"./index.js";import{t as ee}from"./page-heading.js";import{i as h,n as te,t as g}from"./field.js";import{t as _}from"./textarea.js";import{n as v,r as y,t as b}from"./zod.js";import{t as ne}from"./form-actions.js";var re=t(),x=e();function S(){let e=(0,re.c)(46),t=i(),{data:l}=n(p),S=f(),w;e[0]===l.Volumes?w=e[1]:(w=l.Volumes??[],e[0]=l.Volumes,e[1]=w);let T=w,{volumeId:E}=m.useSearch(),D=E??T[0]?.VolumeId??``,O;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(O=b(d),e[2]=O):O=e[2];let k;e[3]===D?k=e[4]:(k={resolver:O,defaultValues:{volumeId:D,description:``}},e[3]=D,e[4]=k);let{control:A,handleSubmit:j,register:M,formState:N}=y(k),{errors:P,isSubmitting:F}=N,I;e[5]!==S||e[6]!==t?(I=async e=>{await S.mutateAsync(e),t({to:`/ec2/describe-snapshots`})},e[5]=S,e[6]=t,e[7]=I):I=e[7];let L=I,R,z;e[8]===Symbol.for(`react.memo_cache_sentinel`)?(R=(0,x.jsx)(a,{to:`/ec2/describe-snapshots`,children:`Back to snapshots`}),z=(0,x.jsx)(ee,{title:`Create Snapshot`}),e[8]=R,e[9]=z):(R=e[8],z=e[9]);let B;e[10]===S.error?B=e[11]:(B=S.error&&(0,x.jsx)(r,{error:S.error,msg:`Failed to create snapshot`}),e[10]=S.error,e[11]=B);let V;e[12]!==j||e[13]!==L?(V=j(L),e[12]=j,e[13]=L,e[14]=V):V=e[14];let H;e[15]===Symbol.for(`react.memo_cache_sentinel`)?(H=(0,x.jsx)(h,{children:(0,x.jsx)(`label`,{htmlFor:`volumeId`,children:`Volume`})}),e[15]=H):H=e[15];let U;e[16]!==P.volumeId||e[17]!==T?(U=e=>{let{field:t}=e;return(0,x.jsxs)(u,{onValueChange:e=>t.onChange(e),value:t.value??``,children:[(0,x.jsx)(s,{"aria-invalid":!!P.volumeId,className:`w-full`,id:`volumeId`,children:(0,x.jsx)(o,{})}),(0,x.jsx)(c,{children:T.map(C)})]})},e[16]=P.volumeId,e[17]=T,e[18]=U):U=e[18];let W;e[19]!==A||e[20]!==U?(W=(0,x.jsx)(v,{control:A,name:`volumeId`,render:U}),e[19]=A,e[20]=U,e[21]=W):W=e[21];let G;e[22]===P.volumeId?G=e[23]:(G=(0,x.jsx)(te,{errors:[P.volumeId]}),e[22]=P.volumeId,e[23]=G);let K;e[24]!==W||e[25]!==G?(K=(0,x.jsxs)(g,{children:[H,W,G]}),e[24]=W,e[25]=G,e[26]=K):K=e[26];let q;e[27]===Symbol.for(`react.memo_cache_sentinel`)?(q=(0,x.jsx)(h,{children:(0,x.jsx)(`label`,{htmlFor:`description`,children:`Description (optional)`})}),e[27]=q):q=e[27];let J;e[28]===M?J=e[29]:(J=M(`description`),e[28]=M,e[29]=J);let Y;e[30]===J?Y=e[31]:(Y=(0,x.jsxs)(g,{children:[q,(0,x.jsx)(_,{id:`description`,placeholder:`Snapshot description`,...J})]}),e[30]=J,e[31]=Y);let X;e[32]===t?X=e[33]:(X=()=>t({to:`/ec2/describe-snapshots`}),e[32]=t,e[33]=X);let Z;e[34]!==S.isPending||e[35]!==F||e[36]!==X?(Z=(0,x.jsx)(ne,{isPending:S.isPending,isSubmitting:F,onCancel:X,pendingLabel:`Creating\\u2026`,submitLabel:`Create Snapshot`}),e[34]=S.isPending,e[35]=F,e[36]=X,e[37]=Z):Z=e[37];let Q;e[38]!==K||e[39]!==Y||e[40]!==Z||e[41]!==V?(Q=(0,x.jsxs)(`form`,{className:`max-w-4xl space-y-6`,onSubmit:V,children:[K,Y,Z]}),e[38]=K,e[39]=Y,e[40]=Z,e[41]=V,e[42]=Q):Q=e[42];let $;return e[43]!==Q||e[44]!==B?($=(0,x.jsxs)(x.Fragment,{children:[R,z,B,Q]}),e[43]=Q,e[44]=B,e[45]=$):$=e[45],$}function C(e){return(0,x.jsxs)(l,{value:e.VolumeId??``,children:[e.VolumeId,` (`,e.Size,` GiB)`]},e.VolumeId)}export{S as component};
@@ -1 +1 @@
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{t as ee}from"./error-banner.js";import{s as r}from"./utils.js";import{t as te}from"./useNavigate.js";import{t as i}from"./back-link.js";import{a,i as o,n as s,r as c,t as l}from"./select.js";import{c as ne}from"./ec2.js";import{t as re,y as ie}from"./ec22.js";import{A as ae}from"./index.js";import{t as oe}from"./page-heading.js";import{i as u,n as d,t as f}from"./field.js";import{n as p,r as se,t as ce}from"./zod.js";import{a as m}from"./ec23.js";import{t as le}from"./form-actions.js";var ue=t(),h=e();function g(){let e=(0,ue.c)(61),t=te(),{data:r}=n(ie),{data:g}=n(re),_=ne(),v;e[0]===r.Vpcs?v=e[1]:(v=r.Vpcs??[],e[0]=r.Vpcs,e[1]=v);let y=v,b;e[2]===g.AvailabilityZones?b=e[3]:(b=g.AvailabilityZones??[],e[2]=g.AvailabilityZones,e[3]=b);let x=b,S;e[4]===Symbol.for(`react.memo_cache_sentinel`)?(S=ce(m),e[4]=S):S=e[4];let C=y[0]?.VpcId??``,w;e[5]===C?w=e[6]:(w={resolver:S,defaultValues:{vpcId:C,cidrBlock:`10.0.1.0/24`,availabilityZone:``}},e[5]=C,e[6]=w);let{control:T,handleSubmit:E,register:D,formState:pe}=se(w),{errors:O,isSubmitting:k}=pe,A;e[7]!==_||e[8]!==t?(A=async e=>{let n=(await _.mutateAsync(e)).Subnet?.SubnetId;t(n?{to:`/ec2/describe-subnets/$id`,params:{id:n}}:{to:`/ec2/describe-subnets`})},e[7]=_,e[8]=t,e[9]=A):A=e[9];let j=A,M,N;e[10]===Symbol.for(`react.memo_cache_sentinel`)?(M=(0,h.jsx)(i,{to:`/ec2/describe-subnets`,children:`Back to Subnets`}),N=(0,h.jsx)(oe,{title:`Create Subnet`}),e[10]=M,e[11]=N):(M=e[10],N=e[11]);let P;e[12]===_.error?P=e[13]:(P=_.error&&(0,h.jsx)(ee,{error:_.error,msg:`Failed to create subnet`}),e[12]=_.error,e[13]=P);let F;e[14]!==E||e[15]!==j?(F=E(j),e[14]=E,e[15]=j,e[16]=F):F=e[16];let I;e[17]===Symbol.for(`react.memo_cache_sentinel`)?(I=(0,h.jsx)(u,{children:(0,h.jsx)(`label`,{htmlFor:`vpcId`,children:`VPC`})}),e[17]=I):I=e[17];let L;e[18]!==O.vpcId||e[19]!==y?(L=e=>{let{field:t}=e;return(0,h.jsxs)(l,{onValueChange:e=>t.onChange(e),value:t.value??``,children:[(0,h.jsx)(o,{"aria-invalid":!!O.vpcId,className:`w-full`,id:`vpcId`,children:(0,h.jsx)(a,{})}),(0,h.jsx)(s,{children:y.map(fe)})]})},e[18]=O.vpcId,e[19]=y,e[20]=L):L=e[20];let R;e[21]!==T||e[22]!==L?(R=(0,h.jsx)(p,{control:T,name:`vpcId`,render:L}),e[21]=T,e[22]=L,e[23]=R):R=e[23];let z;e[24]===O.vpcId?z=e[25]:(z=(0,h.jsx)(d,{errors:[O.vpcId]}),e[24]=O.vpcId,e[25]=z);let B;e[26]!==R||e[27]!==z?(B=(0,h.jsxs)(f,{children:[I,R,z]}),e[26]=R,e[27]=z,e[28]=B):B=e[28];let V;e[29]===Symbol.for(`react.memo_cache_sentinel`)?(V=(0,h.jsx)(u,{children:(0,h.jsx)(`label`,{htmlFor:`cidrBlock`,children:`CIDR Block`})}),e[29]=V):V=e[29];let H=!!O.cidrBlock,U;e[30]===D?U=e[31]:(U=D(`cidrBlock`),e[30]=D,e[31]=U);let W;e[32]!==H||e[33]!==U?(W=(0,h.jsx)(ae,{"aria-invalid":H,id:`cidrBlock`,placeholder:`10.0.1.0/24`,...U}),e[32]=H,e[33]=U,e[34]=W):W=e[34];let G;e[35]===O.cidrBlock?G=e[36]:(G=(0,h.jsx)(d,{errors:[O.cidrBlock]}),e[35]=O.cidrBlock,e[36]=G);let K;e[37]!==W||e[38]!==G?(K=(0,h.jsxs)(f,{children:[V,W,G]}),e[37]=W,e[38]=G,e[39]=K):K=e[39];let q;e[40]===Symbol.for(`react.memo_cache_sentinel`)?(q=(0,h.jsx)(u,{children:(0,h.jsx)(`label`,{htmlFor:`availabilityZone`,children:`Availability Zone (optional)`})}),e[40]=q):q=e[40];let J;e[41]===x?J=e[42]:(J=e=>{let{field:t}=e;return(0,h.jsxs)(l,{onValueChange:e=>t.onChange(e===`none`?``:e),value:t.value??`none`,children:[(0,h.jsx)(o,{className:`w-full`,id:`availabilityZone`,children:(0,h.jsx)(a,{})}),(0,h.jsxs)(s,{children:[(0,h.jsx)(c,{value:`none`,children:`none`}),x.map(de)]})]})},e[41]=x,e[42]=J);let Y;e[43]!==T||e[44]!==J?(Y=(0,h.jsxs)(f,{children:[q,(0,h.jsx)(p,{control:T,name:`availabilityZone`,render:J})]}),e[43]=T,e[44]=J,e[45]=Y):Y=e[45];let X;e[46]===t?X=e[47]:(X=()=>t({to:`/ec2/describe-subnets`}),e[46]=t,e[47]=X);let Z;e[48]!==_.isPending||e[49]!==k||e[50]!==X?(Z=(0,h.jsx)(le,{isPending:_.isPending,isSubmitting:k,onCancel:X,pendingLabel:`Creating\\u2026`,submitLabel:`Create Subnet`}),e[48]=_.isPending,e[49]=k,e[50]=X,e[51]=Z):Z=e[51];let Q;e[52]!==F||e[53]!==B||e[54]!==K||e[55]!==Y||e[56]!==Z?(Q=(0,h.jsxs)(`form`,{className:`max-w-4xl space-y-6`,onSubmit:F,children:[B,K,Y,Z]}),e[52]=F,e[53]=B,e[54]=K,e[55]=Y,e[56]=Z,e[57]=Q):Q=e[57];let $;return e[58]!==Q||e[59]!==P?($=(0,h.jsxs)(h.Fragment,{children:[M,N,P,Q]}),e[58]=Q,e[59]=P,e[60]=$):$=e[60],$}function de(e){return(0,h.jsx)(c,{value:e.ZoneName??``,children:e.ZoneName},e.ZoneName)}function fe(e){let t=r(e.Tags);return(0,h.jsx)(c,{value:e.VpcId??``,children:t?`${e.VpcId} (${t})`:`${e.VpcId} (${e.CidrBlock})`},e.VpcId)}export{g as component};
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{t as ee}from"./error-banner.js";import{s as r}from"./utils.js";import{t as te}from"./useNavigate.js";import{t as i}from"./back-link.js";import{a,i as o,n as s,r as c,t as l}from"./select.js";import{a as ne}from"./ec2.js";import{c as re}from"./ec22.js";import{t as ie,y as ae}from"./ec23.js";import{A as oe}from"./index.js";import{t as se}from"./page-heading.js";import{i as u,n as d,t as f}from"./field.js";import{n as p,r as ce,t as m}from"./zod.js";import{t as le}from"./form-actions.js";var ue=t(),h=e();function g(){let e=(0,ue.c)(61),t=te(),{data:r}=n(ae),{data:g}=n(ie),_=re(),v;e[0]===r.Vpcs?v=e[1]:(v=r.Vpcs??[],e[0]=r.Vpcs,e[1]=v);let y=v,b;e[2]===g.AvailabilityZones?b=e[3]:(b=g.AvailabilityZones??[],e[2]=g.AvailabilityZones,e[3]=b);let x=b,S;e[4]===Symbol.for(`react.memo_cache_sentinel`)?(S=m(ne),e[4]=S):S=e[4];let C=y[0]?.VpcId??``,w;e[5]===C?w=e[6]:(w={resolver:S,defaultValues:{vpcId:C,cidrBlock:`10.0.1.0/24`,availabilityZone:``}},e[5]=C,e[6]=w);let{control:T,handleSubmit:E,register:D,formState:pe}=ce(w),{errors:O,isSubmitting:k}=pe,A;e[7]!==_||e[8]!==t?(A=async e=>{let n=(await _.mutateAsync(e)).Subnet?.SubnetId;t(n?{to:`/ec2/describe-subnets/$id`,params:{id:n}}:{to:`/ec2/describe-subnets`})},e[7]=_,e[8]=t,e[9]=A):A=e[9];let j=A,M,N;e[10]===Symbol.for(`react.memo_cache_sentinel`)?(M=(0,h.jsx)(i,{to:`/ec2/describe-subnets`,children:`Back to Subnets`}),N=(0,h.jsx)(se,{title:`Create Subnet`}),e[10]=M,e[11]=N):(M=e[10],N=e[11]);let P;e[12]===_.error?P=e[13]:(P=_.error&&(0,h.jsx)(ee,{error:_.error,msg:`Failed to create subnet`}),e[12]=_.error,e[13]=P);let F;e[14]!==E||e[15]!==j?(F=E(j),e[14]=E,e[15]=j,e[16]=F):F=e[16];let I;e[17]===Symbol.for(`react.memo_cache_sentinel`)?(I=(0,h.jsx)(u,{children:(0,h.jsx)(`label`,{htmlFor:`vpcId`,children:`VPC`})}),e[17]=I):I=e[17];let L;e[18]!==O.vpcId||e[19]!==y?(L=e=>{let{field:t}=e;return(0,h.jsxs)(l,{onValueChange:e=>t.onChange(e),value:t.value??``,children:[(0,h.jsx)(o,{"aria-invalid":!!O.vpcId,className:`w-full`,id:`vpcId`,children:(0,h.jsx)(a,{})}),(0,h.jsx)(s,{children:y.map(fe)})]})},e[18]=O.vpcId,e[19]=y,e[20]=L):L=e[20];let R;e[21]!==T||e[22]!==L?(R=(0,h.jsx)(p,{control:T,name:`vpcId`,render:L}),e[21]=T,e[22]=L,e[23]=R):R=e[23];let z;e[24]===O.vpcId?z=e[25]:(z=(0,h.jsx)(d,{errors:[O.vpcId]}),e[24]=O.vpcId,e[25]=z);let B;e[26]!==R||e[27]!==z?(B=(0,h.jsxs)(f,{children:[I,R,z]}),e[26]=R,e[27]=z,e[28]=B):B=e[28];let V;e[29]===Symbol.for(`react.memo_cache_sentinel`)?(V=(0,h.jsx)(u,{children:(0,h.jsx)(`label`,{htmlFor:`cidrBlock`,children:`CIDR Block`})}),e[29]=V):V=e[29];let H=!!O.cidrBlock,U;e[30]===D?U=e[31]:(U=D(`cidrBlock`),e[30]=D,e[31]=U);let W;e[32]!==H||e[33]!==U?(W=(0,h.jsx)(oe,{"aria-invalid":H,id:`cidrBlock`,placeholder:`10.0.1.0/24`,...U}),e[32]=H,e[33]=U,e[34]=W):W=e[34];let G;e[35]===O.cidrBlock?G=e[36]:(G=(0,h.jsx)(d,{errors:[O.cidrBlock]}),e[35]=O.cidrBlock,e[36]=G);let K;e[37]!==W||e[38]!==G?(K=(0,h.jsxs)(f,{children:[V,W,G]}),e[37]=W,e[38]=G,e[39]=K):K=e[39];let q;e[40]===Symbol.for(`react.memo_cache_sentinel`)?(q=(0,h.jsx)(u,{children:(0,h.jsx)(`label`,{htmlFor:`availabilityZone`,children:`Availability Zone (optional)`})}),e[40]=q):q=e[40];let J;e[41]===x?J=e[42]:(J=e=>{let{field:t}=e;return(0,h.jsxs)(l,{onValueChange:e=>t.onChange(e===`none`?``:e),value:t.value??`none`,children:[(0,h.jsx)(o,{className:`w-full`,id:`availabilityZone`,children:(0,h.jsx)(a,{})}),(0,h.jsxs)(s,{children:[(0,h.jsx)(c,{value:`none`,children:`none`}),x.map(de)]})]})},e[41]=x,e[42]=J);let Y;e[43]!==T||e[44]!==J?(Y=(0,h.jsxs)(f,{children:[q,(0,h.jsx)(p,{control:T,name:`availabilityZone`,render:J})]}),e[43]=T,e[44]=J,e[45]=Y):Y=e[45];let X;e[46]===t?X=e[47]:(X=()=>t({to:`/ec2/describe-subnets`}),e[46]=t,e[47]=X);let Z;e[48]!==_.isPending||e[49]!==k||e[50]!==X?(Z=(0,h.jsx)(le,{isPending:_.isPending,isSubmitting:k,onCancel:X,pendingLabel:`Creating\\u2026`,submitLabel:`Create Subnet`}),e[48]=_.isPending,e[49]=k,e[50]=X,e[51]=Z):Z=e[51];let Q;e[52]!==F||e[53]!==B||e[54]!==K||e[55]!==Y||e[56]!==Z?(Q=(0,h.jsxs)(`form`,{className:`max-w-4xl space-y-6`,onSubmit:F,children:[B,K,Y,Z]}),e[52]=F,e[53]=B,e[54]=K,e[55]=Y,e[56]=Z,e[57]=Q):Q=e[57];let $;return e[58]!==Q||e[59]!==P?($=(0,h.jsxs)(h.Fragment,{children:[M,N,P,Q]}),e[58]=Q,e[59]=P,e[60]=$):$=e[60],$}function de(e){return(0,h.jsx)(c,{value:e.ZoneName??``,children:e.ZoneName},e.ZoneName)}function fe(e){let t=r(e.Tags);return(0,h.jsx)(c,{value:e.VpcId??``,children:t?`${e.VpcId} (${t})`:`${e.VpcId} (${e.CidrBlock})`},e.VpcId)}export{g as component};
@@ -1 +1 @@
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{t as r}from"./error-banner.js";import{t as i}from"./useNavigate.js";import{t as a}from"./back-link.js";import{a as o,i as ee,n as s,r as c,t as l}from"./select.js";import{l as u}from"./ec2.js";import{t as d}from"./ec22.js";import{A as f}from"./index.js";import{t as te}from"./page-heading.js";import{i as p,n as m,t as h}from"./field.js";import{n as ne,r as re,t as g}from"./zod.js";import{o as _}from"./ec23.js";import{t as ie}from"./form-actions.js";var v=t(),y=e();function b(){let e=(0,v.c)(52),t=i(),{data:c}=n(d),b=u(),S;e[0]===c.AvailabilityZones?S=e[1]:(S=c.AvailabilityZones??[],e[0]=c.AvailabilityZones,e[1]=S);let C=S,w=C[0]?.ZoneName??``,T;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(T=g(_),e[2]=T):T=e[2];let E;e[3]===w?E=e[4]:(E={resolver:T,defaultValues:{size:1,availabilityZone:w}},e[3]=w,e[4]=E);let{control:D,handleSubmit:O,register:k,formState:A}=re(E),{errors:j,isSubmitting:M}=A,N;e[5]!==b||e[6]!==t?(N=async e=>{await b.mutateAsync(e),t({to:`/ec2/describe-volumes`})},e[5]=b,e[6]=t,e[7]=N):N=e[7];let P=N,F,I;e[8]===Symbol.for(`react.memo_cache_sentinel`)?(F=(0,y.jsx)(a,{to:`/ec2/describe-volumes`,children:`Back to volumes`}),I=(0,y.jsx)(te,{title:`Create Volume`}),e[8]=F,e[9]=I):(F=e[8],I=e[9]);let L;e[10]===b.error?L=e[11]:(L=b.error&&(0,y.jsx)(r,{error:b.error,msg:`Failed to create volume`}),e[10]=b.error,e[11]=L);let R;e[12]!==O||e[13]!==P?(R=O(P),e[12]=O,e[13]=P,e[14]=R):R=e[14];let z;e[15]===Symbol.for(`react.memo_cache_sentinel`)?(z=(0,y.jsx)(p,{children:(0,y.jsx)(`label`,{htmlFor:`size`,children:`Size (GiB)`})}),e[15]=z):z=e[15];let B=!!j.size,V;e[16]===k?V=e[17]:(V=k(`size`,{valueAsNumber:!0}),e[16]=k,e[17]=V);let H;e[18]!==B||e[19]!==V?(H=(0,y.jsx)(f,{"aria-invalid":B,id:`size`,max:16384,min:1,type:`number`,...V}),e[18]=B,e[19]=V,e[20]=H):H=e[20];let U;e[21]===j.size?U=e[22]:(U=(0,y.jsx)(m,{errors:[j.size]}),e[21]=j.size,e[22]=U);let W;e[23]!==H||e[24]!==U?(W=(0,y.jsxs)(h,{children:[z,H,U]}),e[23]=H,e[24]=U,e[25]=W):W=e[25];let G;e[26]===Symbol.for(`react.memo_cache_sentinel`)?(G=(0,y.jsx)(p,{children:(0,y.jsx)(`label`,{htmlFor:`availabilityZone`,children:`Availability Zone`})}),e[26]=G):G=e[26];let K;e[27]!==C||e[28]!==j.availabilityZone?(K=e=>{let{field:t}=e;return(0,y.jsxs)(l,{onValueChange:e=>t.onChange(e),value:t.value??``,children:[(0,y.jsx)(ee,{"aria-invalid":!!j.availabilityZone,className:`w-full`,id:`availabilityZone`,children:(0,y.jsx)(o,{})}),(0,y.jsx)(s,{children:C.map(x)})]})},e[27]=C,e[28]=j.availabilityZone,e[29]=K):K=e[29];let q;e[30]!==D||e[31]!==K?(q=(0,y.jsx)(ne,{control:D,name:`availabilityZone`,render:K}),e[30]=D,e[31]=K,e[32]=q):q=e[32];let J;e[33]===j.availabilityZone?J=e[34]:(J=(0,y.jsx)(m,{errors:[j.availabilityZone]}),e[33]=j.availabilityZone,e[34]=J);let Y;e[35]!==q||e[36]!==J?(Y=(0,y.jsxs)(h,{children:[G,q,J]}),e[35]=q,e[36]=J,e[37]=Y):Y=e[37];let X;e[38]===t?X=e[39]:(X=()=>t({to:`/ec2/describe-volumes`}),e[38]=t,e[39]=X);let Z;e[40]!==b.isPending||e[41]!==M||e[42]!==X?(Z=(0,y.jsx)(ie,{isPending:b.isPending,isSubmitting:M,onCancel:X,pendingLabel:`Creating\\u2026`,submitLabel:`Create Volume`}),e[40]=b.isPending,e[41]=M,e[42]=X,e[43]=Z):Z=e[43];let Q;e[44]!==W||e[45]!==Y||e[46]!==Z||e[47]!==R?(Q=(0,y.jsxs)(`form`,{className:`max-w-4xl space-y-6`,onSubmit:R,children:[W,Y,Z]}),e[44]=W,e[45]=Y,e[46]=Z,e[47]=R,e[48]=Q):Q=e[48];let $;return e[49]!==Q||e[50]!==L?($=(0,y.jsxs)(y.Fragment,{children:[F,I,L,Q]}),e[49]=Q,e[50]=L,e[51]=$):$=e[51],$}function x(e){return(0,y.jsx)(c,{value:e.ZoneName??``,children:e.ZoneName},e.ZoneName)}export{b as component};
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{t as r}from"./error-banner.js";import{t as i}from"./useNavigate.js";import{t as a}from"./back-link.js";import{a as o,i as ee,n as s,r as c,t as l}from"./select.js";import{o as u}from"./ec2.js";import{l as d}from"./ec22.js";import{t as f}from"./ec23.js";import{A as te}from"./index.js";import{t as ne}from"./page-heading.js";import{i as p,n as m,t as h}from"./field.js";import{n as re,r as g,t as _}from"./zod.js";import{t as ie}from"./form-actions.js";var v=t(),y=e();function b(){let e=(0,v.c)(52),t=i(),{data:c}=n(f),b=d(),S;e[0]===c.AvailabilityZones?S=e[1]:(S=c.AvailabilityZones??[],e[0]=c.AvailabilityZones,e[1]=S);let C=S,w=C[0]?.ZoneName??``,T;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(T=_(u),e[2]=T):T=e[2];let E;e[3]===w?E=e[4]:(E={resolver:T,defaultValues:{size:1,availabilityZone:w}},e[3]=w,e[4]=E);let{control:D,handleSubmit:O,register:k,formState:A}=g(E),{errors:j,isSubmitting:M}=A,N;e[5]!==b||e[6]!==t?(N=async e=>{await b.mutateAsync(e),t({to:`/ec2/describe-volumes`})},e[5]=b,e[6]=t,e[7]=N):N=e[7];let P=N,F,I;e[8]===Symbol.for(`react.memo_cache_sentinel`)?(F=(0,y.jsx)(a,{to:`/ec2/describe-volumes`,children:`Back to volumes`}),I=(0,y.jsx)(ne,{title:`Create Volume`}),e[8]=F,e[9]=I):(F=e[8],I=e[9]);let L;e[10]===b.error?L=e[11]:(L=b.error&&(0,y.jsx)(r,{error:b.error,msg:`Failed to create volume`}),e[10]=b.error,e[11]=L);let R;e[12]!==O||e[13]!==P?(R=O(P),e[12]=O,e[13]=P,e[14]=R):R=e[14];let z;e[15]===Symbol.for(`react.memo_cache_sentinel`)?(z=(0,y.jsx)(p,{children:(0,y.jsx)(`label`,{htmlFor:`size`,children:`Size (GiB)`})}),e[15]=z):z=e[15];let B=!!j.size,V;e[16]===k?V=e[17]:(V=k(`size`,{valueAsNumber:!0}),e[16]=k,e[17]=V);let H;e[18]!==B||e[19]!==V?(H=(0,y.jsx)(te,{"aria-invalid":B,id:`size`,max:16384,min:1,type:`number`,...V}),e[18]=B,e[19]=V,e[20]=H):H=e[20];let U;e[21]===j.size?U=e[22]:(U=(0,y.jsx)(m,{errors:[j.size]}),e[21]=j.size,e[22]=U);let W;e[23]!==H||e[24]!==U?(W=(0,y.jsxs)(h,{children:[z,H,U]}),e[23]=H,e[24]=U,e[25]=W):W=e[25];let G;e[26]===Symbol.for(`react.memo_cache_sentinel`)?(G=(0,y.jsx)(p,{children:(0,y.jsx)(`label`,{htmlFor:`availabilityZone`,children:`Availability Zone`})}),e[26]=G):G=e[26];let K;e[27]!==C||e[28]!==j.availabilityZone?(K=e=>{let{field:t}=e;return(0,y.jsxs)(l,{onValueChange:e=>t.onChange(e),value:t.value??``,children:[(0,y.jsx)(ee,{"aria-invalid":!!j.availabilityZone,className:`w-full`,id:`availabilityZone`,children:(0,y.jsx)(o,{})}),(0,y.jsx)(s,{children:C.map(x)})]})},e[27]=C,e[28]=j.availabilityZone,e[29]=K):K=e[29];let q;e[30]!==D||e[31]!==K?(q=(0,y.jsx)(re,{control:D,name:`availabilityZone`,render:K}),e[30]=D,e[31]=K,e[32]=q):q=e[32];let J;e[33]===j.availabilityZone?J=e[34]:(J=(0,y.jsx)(m,{errors:[j.availabilityZone]}),e[33]=j.availabilityZone,e[34]=J);let Y;e[35]!==q||e[36]!==J?(Y=(0,y.jsxs)(h,{children:[G,q,J]}),e[35]=q,e[36]=J,e[37]=Y):Y=e[37];let X;e[38]===t?X=e[39]:(X=()=>t({to:`/ec2/describe-volumes`}),e[38]=t,e[39]=X);let Z;e[40]!==b.isPending||e[41]!==M||e[42]!==X?(Z=(0,y.jsx)(ie,{isPending:b.isPending,isSubmitting:M,onCancel:X,pendingLabel:`Creating\\u2026`,submitLabel:`Create Volume`}),e[40]=b.isPending,e[41]=M,e[42]=X,e[43]=Z):Z=e[43];let Q;e[44]!==W||e[45]!==Y||e[46]!==Z||e[47]!==R?(Q=(0,y.jsxs)(`form`,{className:`max-w-4xl space-y-6`,onSubmit:R,children:[W,Y,Z]}),e[44]=W,e[45]=Y,e[46]=Z,e[47]=R,e[48]=Q):Q=e[48];let $;return e[49]!==Q||e[50]!==L?($=(0,y.jsxs)(y.Fragment,{children:[F,I,L,Q]}),e[49]=Q,e[50]=L,e[51]=$):$=e[51],$}function x(e){return(0,y.jsx)(c,{value:e.ZoneName??``,children:e.ZoneName},e.ZoneName)}export{b as component};
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{r}from"./ec22.js";import{t as i}from"./page-heading.js";import{t as a}from"./state-badge.js";import{t as o}from"./list-card.js";var s=t(),c=e();function l(){let e=(0,s.c)(5),{data:t}=n(r),a;e[0]===t.Images?a=e[1]:(a=t.Images??[],e[0]=t.Images,e[1]=a);let o=a,l;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(l=(0,c.jsx)(i,{title:`EC2 Images`}),e[2]=l):l=e[2];let d;return e[3]===o?d=e[4]:(d=(0,c.jsxs)(c.Fragment,{children:[l,o.length>0?(0,c.jsx)(`div`,{className:`space-y-4`,children:o.map(u)}):(0,c.jsx)(`p`,{className:`text-muted-foreground`,children:`No images found.`})]}),e[3]=o,e[4]=d),d}function u(e){return e.ImageId?(0,c.jsx)(o,{badge:(0,c.jsx)(a,{state:e.State}),params:{id:e.ImageId},subtitle:e.Name,title:e.ImageId,to:`/ec2/describe-images/$id`},e.ImageId):null}export{l as component};
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{r}from"./ec23.js";import{t as i}from"./page-heading.js";import{t as a}from"./state-badge.js";import{t as o}from"./list-card.js";var s=t(),c=e();function l(){let e=(0,s.c)(5),{data:t}=n(r),a;e[0]===t.Images?a=e[1]:(a=t.Images??[],e[0]=t.Images,e[1]=a);let o=a,l;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(l=(0,c.jsx)(i,{title:`EC2 Images`}),e[2]=l):l=e[2];let d;return e[3]===o?d=e[4]:(d=(0,c.jsxs)(c.Fragment,{children:[l,o.length>0?(0,c.jsx)(`div`,{className:`space-y-4`,children:o.map(u)}):(0,c.jsx)(`p`,{className:`text-muted-foreground`,children:`No images found.`})]}),e[3]=o,e[4]=d),d}function u(e){return e.ImageId?(0,c.jsx)(o,{badge:(0,c.jsx)(a,{state:e.State}),params:{id:e.ImageId},subtitle:e.ImageId??``,title:e.Name??e.ImageId??``,to:`/ec2/describe-images/$id`},e.ImageId):null}export{l as component};
@@ -1 +1 @@
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{t as r}from"./link.js";import{t as i}from"./button.js";import{o as a}from"./ec22.js";import{t as o}from"./page-heading.js";import{t as s}from"./state-badge.js";import{t as c}from"./list-card.js";var l=t(),u=e(),d={running:0,pending:1,stopping:2,"shutting-down":3,stopped:4,terminated:5};function f(){let e=(0,l.c)(3),{data:t}=n(a),s;if(e[0]!==t.Reservations){let n=(t.Reservations?.flatMap(h)??[]).toSorted(m),a;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(a=(0,u.jsx)(o,{actions:(0,u.jsx)(r,{to:`/ec2/run-instances`,children:(0,u.jsx)(i,{children:`Run Instances`})}),title:`EC2 Instances`}),e[2]=a):a=e[2],s=(0,u.jsxs)(u.Fragment,{children:[a,n.length>0?(0,u.jsx)(`div`,{className:`space-y-4`,children:n.map(p)}):(0,u.jsx)(`p`,{className:`text-muted-foreground`,children:`No instances found.`})]}),e[0]=t.Reservations,e[1]=s}else s=e[1];return s}function p(e){return e.InstanceId?(0,u.jsx)(c,{badge:(0,u.jsx)(s,{state:e.State?.Name}),params:{id:e.InstanceId},subtitle:`${e.InstanceType} • ${e.ImageId}`,title:e.InstanceId,to:`/ec2/describe-instances/$id`},e.InstanceId):null}function m(e,t){let n=d[e.State?.Name??``]??6,r=d[t.State?.Name??``]??6;return n===r?(e.InstanceId??``).localeCompare(t.InstanceId??``):n-r}function h(e){return e.Instances??[]}export{f as component};
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{t as r}from"./link.js";import{t as i}from"./button.js";import{o as a}from"./ec23.js";import{t as o}from"./page-heading.js";import{t as s}from"./state-badge.js";import{t as c}from"./list-card.js";var l=t(),u=e(),d={running:0,pending:1,stopping:2,"shutting-down":3,stopped:4,terminated:5};function f(){let e=(0,l.c)(3),{data:t}=n(a),s;if(e[0]!==t.Reservations){let n=(t.Reservations?.flatMap(h)??[]).toSorted(m),a;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(a=(0,u.jsx)(o,{actions:(0,u.jsx)(r,{to:`/ec2/run-instances`,children:(0,u.jsx)(i,{children:`Run Instances`})}),title:`EC2 Instances`}),e[2]=a):a=e[2],s=(0,u.jsxs)(u.Fragment,{children:[a,n.length>0?(0,u.jsx)(`div`,{className:`space-y-4`,children:n.map(p)}):(0,u.jsx)(`p`,{className:`text-muted-foreground`,children:`No instances found.`})]}),e[0]=t.Reservations,e[1]=s}else s=e[1];return s}function p(e){return e.InstanceId?(0,u.jsx)(c,{badge:(0,u.jsx)(s,{state:e.State?.Name}),params:{id:e.InstanceId},subtitle:`${e.InstanceType}`,title:e.InstanceId,to:`/ec2/describe-instances/$id`},e.InstanceId):null}function m(e,t){let n=d[e.State?.Name??``]??6,r=d[t.State?.Name??``]??6;return n===r?(e.InstanceId??``).localeCompare(t.InstanceId??``):n-r}function h(e){return e.Instances??[]}export{f as component};
@@ -1 +1 @@
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{t as r}from"./link.js";import{t as i}from"./button.js";import{c as a}from"./ec22.js";import{t as o}from"./page-heading.js";import{t as s}from"./list-card.js";var c=t(),l=e();function u(){let e=(0,c.c)(4),{data:t}=n(a),s;if(e[0]!==t.KeyPairs){let n=(t.KeyPairs??[]).toSorted(f),a;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(a=(0,l.jsx)(r,{to:`/ec2/import-key-pair`,children:(0,l.jsx)(i,{variant:`outline`,children:`Import Key Pair`})}),e[2]=a):a=e[2];let c;e[3]===Symbol.for(`react.memo_cache_sentinel`)?(c=(0,l.jsx)(o,{actions:(0,l.jsxs)(`div`,{className:`flex gap-2`,children:[a,(0,l.jsx)(r,{to:`/ec2/create-key-pair`,children:(0,l.jsx)(i,{children:`Create Key Pair`})})]}),title:`EC2 Key Pairs`}),e[3]=c):c=e[3],s=(0,l.jsxs)(l.Fragment,{children:[c,n.length>0?(0,l.jsx)(`div`,{className:`space-y-4`,children:n.map(d)}):(0,l.jsx)(`p`,{className:`text-muted-foreground`,children:`No key pairs found.`})]}),e[0]=t.KeyPairs,e[1]=s}else s=e[1];return s}function d(e){return e.KeyPairId?(0,l.jsx)(s,{params:{id:e.KeyPairId},subtitle:`${e.KeyPairId} • ${e.KeyType}`,title:e.KeyName??``,to:`/ec2/describe-key-pairs/$id`},e.KeyPairId):null}function f(e,t){let n=e.KeyName?.toLowerCase()??``,r=t.KeyName?.toLowerCase()??``;return n.localeCompare(r)}export{u as component};
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{t as r}from"./link.js";import{t as i}from"./button.js";import{c as a}from"./ec23.js";import{t as o}from"./page-heading.js";import{t as s}from"./list-card.js";var c=t(),l=e();function u(){let e=(0,c.c)(4),{data:t}=n(a),s;if(e[0]!==t.KeyPairs){let n=(t.KeyPairs??[]).toSorted(f),a;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(a=(0,l.jsx)(r,{to:`/ec2/import-key-pair`,children:(0,l.jsx)(i,{variant:`outline`,children:`Import Key Pair`})}),e[2]=a):a=e[2];let c;e[3]===Symbol.for(`react.memo_cache_sentinel`)?(c=(0,l.jsx)(o,{actions:(0,l.jsxs)(`div`,{className:`flex gap-2`,children:[a,(0,l.jsx)(r,{to:`/ec2/create-key-pair`,children:(0,l.jsx)(i,{children:`Create Key Pair`})})]}),title:`EC2 Key Pairs`}),e[3]=c):c=e[3],s=(0,l.jsxs)(l.Fragment,{children:[c,n.length>0?(0,l.jsx)(`div`,{className:`space-y-4`,children:n.map(d)}):(0,l.jsx)(`p`,{className:`text-muted-foreground`,children:`No key pairs found.`})]}),e[0]=t.KeyPairs,e[1]=s}else s=e[1];return s}function d(e){return e.KeyPairId?(0,l.jsx)(s,{params:{id:e.KeyPairId},subtitle:e.KeyPairId??``,title:e.KeyName??``,to:`/ec2/describe-key-pairs/$id`},e.KeyPairId):null}function f(e,t){let n=e.KeyName?.toLowerCase()??``,r=t.KeyName?.toLowerCase()??``;return n.localeCompare(r)}export{u as component};
@@ -1 +1 @@
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{t as r}from"./link.js";import{t as i}from"./button.js";import{u as a}from"./ec22.js";import{t as o}from"./page-heading.js";import{t as s}from"./state-badge.js";import{t as c}from"./list-card.js";var l=t(),u=e();function d(){let e=(0,l.c)(5),{data:t}=n(a),s;e[0]===t.PlacementGroups?s=e[1]:(s=t.PlacementGroups??[],e[0]=t.PlacementGroups,e[1]=s);let c=s,d;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(d=(0,u.jsx)(o,{actions:(0,u.jsx)(r,{to:`/ec2/create-placement-group`,children:(0,u.jsx)(i,{children:`Create Placement Group`})}),title:`EC2 Placement Groups`}),e[2]=d):d=e[2];let p;return e[3]===c?p=e[4]:(p=(0,u.jsxs)(u.Fragment,{children:[d,c.length>0?(0,u.jsx)(`div`,{className:`space-y-4`,children:c.map(f)}):(0,u.jsx)(`p`,{className:`text-muted-foreground`,children:`No placement groups found.`})]}),e[3]=c,e[4]=p),p}function f(e){return e.GroupId?(0,u.jsx)(c,{badge:(0,u.jsx)(s,{state:e.State}),params:{id:e.GroupId},subtitle:`${e.Strategy} \u2022 ${e.GroupId}`,title:e.GroupName??e.GroupId,to:`/ec2/describe-placement-groups/$id`},e.GroupId):null}export{d as component};
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{t as r}from"./link.js";import{t as i}from"./button.js";import{u as a}from"./ec23.js";import{t as o}from"./page-heading.js";import{t as s}from"./state-badge.js";import{t as c}from"./list-card.js";var l=t(),u=e();function d(){let e=(0,l.c)(5),{data:t}=n(a),s;e[0]===t.PlacementGroups?s=e[1]:(s=t.PlacementGroups??[],e[0]=t.PlacementGroups,e[1]=s);let c=s,d;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(d=(0,u.jsx)(o,{actions:(0,u.jsx)(r,{to:`/ec2/create-placement-group`,children:(0,u.jsx)(i,{children:`Create Placement Group`})}),title:`EC2 Placement Groups`}),e[2]=d):d=e[2];let p;return e[3]===c?p=e[4]:(p=(0,u.jsxs)(u.Fragment,{children:[d,c.length>0?(0,u.jsx)(`div`,{className:`space-y-4`,children:c.map(f)}):(0,u.jsx)(`p`,{className:`text-muted-foreground`,children:`No placement groups found.`})]}),e[3]=c,e[4]=p),p}function f(e){return e.GroupId?(0,u.jsx)(c,{badge:(0,u.jsx)(s,{state:e.State}),params:{id:e.GroupId},subtitle:`${e.Strategy} \u2022 ${e.GroupId}`,title:e.GroupName??e.GroupId,to:`/ec2/describe-placement-groups/$id`},e.GroupId):null}export{d as component};
@@ -1 +1 @@
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{t as r}from"./link.js";import{t as i}from"./button.js";import{p as a}from"./ec22.js";import{t as o}from"./page-heading.js";import{t as s}from"./state-badge.js";import{t as c}from"./list-card.js";var l=t(),u=e();function d(){let e=(0,l.c)(5),{data:t}=n(a),s;e[0]===t.Snapshots?s=e[1]:(s=t.Snapshots??[],e[0]=t.Snapshots,e[1]=s);let c=s,d;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(d=(0,u.jsx)(o,{actions:(0,u.jsx)(r,{to:`/ec2/create-snapshot`,children:(0,u.jsx)(i,{children:`Create Snapshot`})}),title:`EC2 Snapshots`}),e[2]=d):d=e[2];let p;return e[3]===c?p=e[4]:(p=(0,u.jsxs)(u.Fragment,{children:[d,c.length>0?(0,u.jsx)(`div`,{className:`space-y-4`,children:c.map(f)}):(0,u.jsx)(`p`,{className:`text-muted-foreground`,children:`No snapshots found.`})]}),e[3]=c,e[4]=p),p}function f(e){return e.SnapshotId?(0,u.jsx)(c,{badge:(0,u.jsx)(s,{state:e.State}),params:{id:e.SnapshotId},subtitle:`${e.VolumeSize} GiB \u2022 ${e.VolumeId}`,title:e.SnapshotId,to:`/ec2/describe-snapshots/$id`},e.SnapshotId):null}export{d as component};
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{t as r}from"./link.js";import{t as i}from"./button.js";import{p as a}from"./ec23.js";import{t as o}from"./page-heading.js";import{t as s}from"./state-badge.js";import{t as c}from"./list-card.js";var l=t(),u=e();function d(){let e=(0,l.c)(5),{data:t}=n(a),s;e[0]===t.Snapshots?s=e[1]:(s=t.Snapshots??[],e[0]=t.Snapshots,e[1]=s);let c=s,d;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(d=(0,u.jsx)(o,{actions:(0,u.jsx)(r,{to:`/ec2/create-snapshot`,children:(0,u.jsx)(i,{children:`Create Snapshot`})}),title:`EC2 Snapshots`}),e[2]=d):d=e[2];let p;return e[3]===c?p=e[4]:(p=(0,u.jsxs)(u.Fragment,{children:[d,c.length>0?(0,u.jsx)(`div`,{className:`space-y-4`,children:c.map(f)}):(0,u.jsx)(`p`,{className:`text-muted-foreground`,children:`No snapshots found.`})]}),e[3]=c,e[4]=p),p}function f(e){return e.SnapshotId?(0,u.jsx)(c,{badge:(0,u.jsx)(s,{state:e.State}),params:{id:e.SnapshotId},subtitle:`${e.VolumeSize} GiB \u2022 ${e.VolumeId}`,title:e.SnapshotId,to:`/ec2/describe-snapshots/$id`},e.SnapshotId):null}export{d as component};
@@ -1 +1 @@
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{s as r}from"./utils.js";import{t as i}from"./link.js";import{t as a}from"./button.js";import{h as o}from"./ec22.js";import{t as s}from"./page-heading.js";import{t as c}from"./state-badge.js";import{t as l}from"./list-card.js";var u=t(),d=e();function f(){let e=(0,u.c)(5),{data:t}=n(o),r;e[0]===t.Subnets?r=e[1]:(r=t.Subnets??[],e[0]=t.Subnets,e[1]=r);let c=r,l;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(l=(0,d.jsx)(s,{actions:(0,d.jsx)(i,{to:`/ec2/create-subnet`,children:(0,d.jsx)(a,{children:`Create Subnet`})}),title:`Subnets`}),e[2]=l):l=e[2];let f;return e[3]===c?f=e[4]:(f=(0,d.jsxs)(d.Fragment,{children:[l,c.length>0?(0,d.jsx)(`div`,{className:`space-y-4`,children:c.map(p)}):(0,d.jsx)(`p`,{className:`text-muted-foreground`,children:`No subnets found.`})]}),e[3]=c,e[4]=f),f}function p(e){if(!e.SubnetId)return null;let t=r(e.Tags);return(0,d.jsx)(l,{badge:(0,d.jsx)(c,{state:e.State}),params:{id:e.SubnetId},subtitle:`${e.CidrBlock??``} \u2022 ${e.AvailabilityZone??``}`,title:t?`${e.SubnetId} (${t})`:e.SubnetId,to:`/ec2/describe-subnets/$id`},e.SubnetId)}export{f as component};
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{s as r}from"./utils.js";import{t as i}from"./link.js";import{t as a}from"./button.js";import{h as o}from"./ec23.js";import{t as s}from"./page-heading.js";import{t as c}from"./state-badge.js";import{t as l}from"./list-card.js";var u=t(),d=e();function f(){let e=(0,u.c)(5),{data:t}=n(o),r;e[0]===t.Subnets?r=e[1]:(r=t.Subnets??[],e[0]=t.Subnets,e[1]=r);let c=r,l;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(l=(0,d.jsx)(s,{actions:(0,d.jsx)(i,{to:`/ec2/create-subnet`,children:(0,d.jsx)(a,{children:`Create Subnet`})}),title:`Subnets`}),e[2]=l):l=e[2];let f;return e[3]===c?f=e[4]:(f=(0,d.jsxs)(d.Fragment,{children:[l,c.length>0?(0,d.jsx)(`div`,{className:`space-y-4`,children:c.map(p)}):(0,d.jsx)(`p`,{className:`text-muted-foreground`,children:`No subnets found.`})]}),e[3]=c,e[4]=f),f}function p(e){if(!e.SubnetId)return null;let t=r(e.Tags);return(0,d.jsx)(l,{badge:(0,d.jsx)(c,{state:e.State}),params:{id:e.SubnetId},subtitle:`${e.CidrBlock??``} \u2022 ${e.AvailabilityZone??``}`,title:t?`${e.SubnetId} (${t})`:e.SubnetId,to:`/ec2/describe-subnets/$id`},e.SubnetId)}export{f as component};
@@ -1 +1 @@
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{t as r}from"./link.js";import{t as i}from"./button.js";import{_ as a}from"./ec22.js";import{t as o}from"./page-heading.js";import{t as s}from"./state-badge.js";import{t as c}from"./list-card.js";var l=t(),u=e();function d(){let e=(0,l.c)(5),{data:t}=n(a),s;e[0]===t.Volumes?s=e[1]:(s=t.Volumes??[],e[0]=t.Volumes,e[1]=s);let c=s,d;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(d=(0,u.jsx)(o,{actions:(0,u.jsx)(r,{to:`/ec2/create-volume`,children:(0,u.jsx)(i,{children:`Create Volume`})}),title:`EC2 Volumes`}),e[2]=d):d=e[2];let p;return e[3]===c?p=e[4]:(p=(0,u.jsxs)(u.Fragment,{children:[d,c.length>0?(0,u.jsx)(`div`,{className:`space-y-4`,children:c.map(f)}):(0,u.jsx)(`p`,{className:`text-muted-foreground`,children:`No volumes found.`})]}),e[3]=c,e[4]=p),p}function f(e){return e.VolumeId?(0,u.jsx)(c,{badge:(0,u.jsx)(s,{state:e.State}),params:{id:e.VolumeId},subtitle:`${e.Size} GiB • ${e.VolumeType}`,title:e.VolumeId,to:`/ec2/describe-volumes/$id`},e.VolumeId):null}export{d as component};
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{t as r}from"./link.js";import{t as i}from"./button.js";import{_ as a}from"./ec23.js";import{t as o}from"./page-heading.js";import{t as s}from"./state-badge.js";import{t as c}from"./list-card.js";var l=t(),u=e();function d(){let e=(0,l.c)(5),{data:t}=n(a),s;e[0]===t.Volumes?s=e[1]:(s=t.Volumes??[],e[0]=t.Volumes,e[1]=s);let c=s,d;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(d=(0,u.jsx)(o,{actions:(0,u.jsx)(r,{to:`/ec2/create-volume`,children:(0,u.jsx)(i,{children:`Create Volume`})}),title:`EC2 Volumes`}),e[2]=d):d=e[2];let p;return e[3]===c?p=e[4]:(p=(0,u.jsxs)(u.Fragment,{children:[d,c.length>0?(0,u.jsx)(`div`,{className:`space-y-4`,children:c.map(f)}):(0,u.jsx)(`p`,{className:`text-muted-foreground`,children:`No volumes found.`})]}),e[3]=c,e[4]=p),p}function f(e){return e.VolumeId?(0,u.jsx)(c,{badge:(0,u.jsx)(s,{state:e.State}),params:{id:e.VolumeId},subtitle:`${e.Size} GiB`,title:e.VolumeId,to:`/ec2/describe-volumes/$id`},e.VolumeId):null}export{d as component};
@@ -1 +1 @@
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{s as r}from"./utils.js";import{t as i}from"./link.js";import{t as a}from"./button.js";import{y as o}from"./ec22.js";import{t as s}from"./page-heading.js";import{t as c}from"./state-badge.js";import{t as l}from"./list-card.js";var u=t(),d=e();function f(){let e=(0,u.c)(5),{data:t}=n(o),r;e[0]===t.Vpcs?r=e[1]:(r=t.Vpcs??[],e[0]=t.Vpcs,e[1]=r);let c=r,l;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(l=(0,d.jsx)(s,{actions:(0,d.jsx)(i,{to:`/ec2/create-vpc`,children:(0,d.jsx)(a,{children:`Create VPC`})}),title:`VPCs`}),e[2]=l):l=e[2];let f;return e[3]===c?f=e[4]:(f=(0,d.jsxs)(d.Fragment,{children:[l,c.length>0?(0,d.jsx)(`div`,{className:`space-y-4`,children:c.map(p)}):(0,d.jsx)(`p`,{className:`text-muted-foreground`,children:`No VPCs found.`})]}),e[3]=c,e[4]=f),f}function p(e){if(!e.VpcId)return null;let t=r(e.Tags);return(0,d.jsx)(l,{badge:(0,d.jsx)(c,{state:e.State}),params:{id:e.VpcId},subtitle:e.CidrBlock??``,title:t?`${e.VpcId} (${t})`:e.VpcId,to:`/ec2/describe-vpcs/$id`},e.VpcId)}export{f as component};
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{s as r}from"./utils.js";import{t as i}from"./link.js";import{t as a}from"./button.js";import{y as o}from"./ec23.js";import{t as s}from"./page-heading.js";import{t as c}from"./state-badge.js";import{t as l}from"./list-card.js";var u=t(),d=e();function f(){let e=(0,u.c)(5),{data:t}=n(o),r;e[0]===t.Vpcs?r=e[1]:(r=t.Vpcs??[],e[0]=t.Vpcs,e[1]=r);let c=r,l;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(l=(0,d.jsx)(s,{actions:(0,d.jsx)(i,{to:`/ec2/create-vpc`,children:(0,d.jsx)(a,{children:`Create VPC`})}),title:`VPCs`}),e[2]=l):l=e[2];let f;return e[3]===c?f=e[4]:(f=(0,d.jsxs)(d.Fragment,{children:[l,c.length>0?(0,d.jsx)(`div`,{className:`space-y-4`,children:c.map(p)}):(0,d.jsx)(`p`,{className:`text-muted-foreground`,children:`No VPCs found.`})]}),e[3]=c,e[4]=f),f}function p(e){if(!e.VpcId)return null;let t=r(e.Tags);return(0,d.jsx)(l,{badge:(0,d.jsx)(c,{state:e.State}),params:{id:e.VpcId},subtitle:e.CidrBlock??``,title:t?`${e.VpcId} (${t})`:e.VpcId,to:`/ec2/describe-vpcs/$id`},e.VpcId)}export{f as component};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1 +1 @@
import{t as e}from"./compiler-runtime.js";import{n as t}from"./QueryClientProvider.js";import{n}from"./error-banner.js";import{A as r,At as i,C as a,D as o,E as s,O as c,Pt as l,R as u,T as d,k as f,r as p,w as m,z as h}from"./awsClient.js";var g=class extends l.classBuilder().ep(h).m(function(e,t,n,r){return[i(n,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`AttachUserPolicy`,{}).n(`IAMClient`,`AttachUserPolicyCommand`).sc(a).build(){},_=class extends l.classBuilder().ep(h).m(function(e,t,n,r){return[i(n,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`CreateAccessKey`,{}).n(`IAMClient`,`CreateAccessKeyCommand`).sc(m).build(){},v=class extends l.classBuilder().ep(h).m(function(e,t,n,r){return[i(n,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`CreatePolicy`,{}).n(`IAMClient`,`CreatePolicyCommand`).sc(d).build(){},y=class extends l.classBuilder().ep(h).m(function(e,t,n,r){return[i(n,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`CreateUser`,{}).n(`IAMClient`,`CreateUserCommand`).sc(s).build(){},b=class extends l.classBuilder().ep(h).m(function(e,t,n,r){return[i(n,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`DeleteAccessKey`,{}).n(`IAMClient`,`DeleteAccessKeyCommand`).sc(o).build(){},x=class extends l.classBuilder().ep(h).m(function(e,t,n,r){return[i(n,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`DeletePolicy`,{}).n(`IAMClient`,`DeletePolicyCommand`).sc(c).build(){},S=class extends l.classBuilder().ep(h).m(function(e,t,n,r){return[i(n,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`DeleteUser`,{}).n(`IAMClient`,`DeleteUserCommand`).sc(f).build(){},C=class extends l.classBuilder().ep(h).m(function(e,t,n,r){return[i(n,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`DetachUserPolicy`,{}).n(`IAMClient`,`DetachUserPolicyCommand`).sc(r).build(){},w=class extends l.classBuilder().ep(h).m(function(e,t,n,r){return[i(n,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`UpdateAccessKey`,{}).n(`IAMClient`,`UpdateAccessKeyCommand`).sc(u).build(){},T=e();function E(){let e=(0,T.c)(2),r=t(),i;return e[0]===r?i=e[1]:(i={mutationFn:D,onSuccess:()=>{r.invalidateQueries({queryKey:[`iam`,`users`]})}},e[0]=r,e[1]=i),n(i)}function D(e){let t=new y({UserName:e.userName,Path:e.path||void 0});return p().send(t)}function O(){let e=(0,T.c)(2),r=t(),i;return e[0]===r?i=e[1]:(i={mutationFn:k,onSuccess:()=>{r.invalidateQueries({queryKey:[`iam`,`users`]})}},e[0]=r,e[1]=i),n(i)}function k(e){let t=new S({UserName:e});return p().send(t)}function A(){let e=(0,T.c)(2),r=t(),i;return e[0]===r?i=e[1]:(i={mutationFn:j,onSuccess:()=>{r.invalidateQueries({queryKey:[`iam`,`access-keys`]})}},e[0]=r,e[1]=i),n(i)}function j(e){let t=new _({UserName:e});return p().send(t)}function M(){let e=(0,T.c)(2),r=t(),i;return e[0]===r?i=e[1]:(i={mutationFn:N,onSuccess:()=>{r.invalidateQueries({queryKey:[`iam`,`access-keys`]})}},e[0]=r,e[1]=i),n(i)}function N(e){let{userName:t,accessKeyId:n}=e,r=new b({UserName:t,AccessKeyId:n});return p().send(r)}function P(){let e=(0,T.c)(2),r=t(),i;return e[0]===r?i=e[1]:(i={mutationFn:F,onSuccess:()=>{r.invalidateQueries({queryKey:[`iam`,`access-keys`]})}},e[0]=r,e[1]=i),n(i)}function F(e){let{userName:t,accessKeyId:n,status:r}=e,i=new w({UserName:t,AccessKeyId:n,Status:r});return p().send(i)}function I(){let e=(0,T.c)(2),r=t(),i;return e[0]===r?i=e[1]:(i={mutationFn:L,onSuccess:()=>{r.invalidateQueries({queryKey:[`iam`,`policies`]})}},e[0]=r,e[1]=i),n(i)}function L(e){let t=new v({PolicyName:e.policyName,Description:e.description||void 0,PolicyDocument:e.policyDocument});return p().send(t)}function R(){let e=(0,T.c)(2),r=t(),i;return e[0]===r?i=e[1]:(i={mutationFn:z,onSuccess:()=>{r.invalidateQueries({queryKey:[`iam`,`policies`]})}},e[0]=r,e[1]=i),n(i)}function z(e){let t=new x({PolicyArn:e});return p().send(t)}function B(){let e=(0,T.c)(2),r=t(),i;return e[0]===r?i=e[1]:(i={mutationFn:V,onSuccess:()=>{r.invalidateQueries({queryKey:[`iam`,`attached-user-policies`]})}},e[0]=r,e[1]=i),n(i)}function V(e){let{userName:t,policyArn:n}=e,r=new g({UserName:t,PolicyArn:n});return p().send(r)}function H(){let e=(0,T.c)(2),r=t(),i;return e[0]===r?i=e[1]:(i={mutationFn:U,onSuccess:()=>{r.invalidateQueries({queryKey:[`iam`,`attached-user-policies`]})}},e[0]=r,e[1]=i),n(i)}function U(e){let{userName:t,policyArn:n}=e,r=new C({UserName:t,PolicyArn:n});return p().send(r)}export{M as a,H as c,E as i,P as l,A as n,R as o,I as r,O as s,B as t};
import{t as e}from"./compiler-runtime.js";import{n as t}from"./QueryClientProvider.js";import{n}from"./error-banner.js";import{A as r,C as i,D as a,E as o,Lt as s,O as c,R as l,T as u,Vt as d,k as f,r as p,w as m,z as h}from"./awsClient.js";var g=class extends d.classBuilder().ep(h).m(function(e,t,n,r){return[s(n,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`AttachUserPolicy`,{}).n(`IAMClient`,`AttachUserPolicyCommand`).sc(i).build(){},_=class extends d.classBuilder().ep(h).m(function(e,t,n,r){return[s(n,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`CreateAccessKey`,{}).n(`IAMClient`,`CreateAccessKeyCommand`).sc(m).build(){},v=class extends d.classBuilder().ep(h).m(function(e,t,n,r){return[s(n,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`CreatePolicy`,{}).n(`IAMClient`,`CreatePolicyCommand`).sc(u).build(){},y=class extends d.classBuilder().ep(h).m(function(e,t,n,r){return[s(n,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`CreateUser`,{}).n(`IAMClient`,`CreateUserCommand`).sc(o).build(){},b=class extends d.classBuilder().ep(h).m(function(e,t,n,r){return[s(n,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`DeleteAccessKey`,{}).n(`IAMClient`,`DeleteAccessKeyCommand`).sc(a).build(){},x=class extends d.classBuilder().ep(h).m(function(e,t,n,r){return[s(n,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`DeletePolicy`,{}).n(`IAMClient`,`DeletePolicyCommand`).sc(c).build(){},S=class extends d.classBuilder().ep(h).m(function(e,t,n,r){return[s(n,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`DeleteUser`,{}).n(`IAMClient`,`DeleteUserCommand`).sc(f).build(){},C=class extends d.classBuilder().ep(h).m(function(e,t,n,r){return[s(n,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`DetachUserPolicy`,{}).n(`IAMClient`,`DetachUserPolicyCommand`).sc(r).build(){},w=class extends d.classBuilder().ep(h).m(function(e,t,n,r){return[s(n,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`UpdateAccessKey`,{}).n(`IAMClient`,`UpdateAccessKeyCommand`).sc(l).build(){},T=e();function E(){let e=(0,T.c)(2),r=t(),i;return e[0]===r?i=e[1]:(i={mutationFn:D,onSuccess:()=>{r.invalidateQueries({queryKey:[`iam`,`users`]})}},e[0]=r,e[1]=i),n(i)}function D(e){let t=new y({UserName:e.userName,Path:e.path||void 0});return p().send(t)}function O(){let e=(0,T.c)(2),r=t(),i;return e[0]===r?i=e[1]:(i={mutationFn:k,onSuccess:()=>{r.invalidateQueries({queryKey:[`iam`,`users`]})}},e[0]=r,e[1]=i),n(i)}function k(e){let t=new S({UserName:e});return p().send(t)}function A(){let e=(0,T.c)(2),r=t(),i;return e[0]===r?i=e[1]:(i={mutationFn:j,onSuccess:()=>{r.invalidateQueries({queryKey:[`iam`,`access-keys`]})}},e[0]=r,e[1]=i),n(i)}function j(e){let t=new _({UserName:e});return p().send(t)}function M(){let e=(0,T.c)(2),r=t(),i;return e[0]===r?i=e[1]:(i={mutationFn:N,onSuccess:()=>{r.invalidateQueries({queryKey:[`iam`,`access-keys`]})}},e[0]=r,e[1]=i),n(i)}function N(e){let{userName:t,accessKeyId:n}=e,r=new b({UserName:t,AccessKeyId:n});return p().send(r)}function P(){let e=(0,T.c)(2),r=t(),i;return e[0]===r?i=e[1]:(i={mutationFn:F,onSuccess:()=>{r.invalidateQueries({queryKey:[`iam`,`access-keys`]})}},e[0]=r,e[1]=i),n(i)}function F(e){let{userName:t,accessKeyId:n,status:r}=e,i=new w({UserName:t,AccessKeyId:n,Status:r});return p().send(i)}function I(){let e=(0,T.c)(2),r=t(),i;return e[0]===r?i=e[1]:(i={mutationFn:L,onSuccess:()=>{r.invalidateQueries({queryKey:[`iam`,`policies`]})}},e[0]=r,e[1]=i),n(i)}function L(e){let t=new v({PolicyName:e.policyName,Description:e.description||void 0,PolicyDocument:e.policyDocument});return p().send(t)}function R(){let e=(0,T.c)(2),r=t(),i;return e[0]===r?i=e[1]:(i={mutationFn:z,onSuccess:()=>{r.invalidateQueries({queryKey:[`iam`,`policies`]})}},e[0]=r,e[1]=i),n(i)}function z(e){let t=new x({PolicyArn:e});return p().send(t)}function B(){let e=(0,T.c)(2),r=t(),i;return e[0]===r?i=e[1]:(i={mutationFn:V,onSuccess:()=>{r.invalidateQueries({queryKey:[`iam`,`attached-user-policies`]})}},e[0]=r,e[1]=i),n(i)}function V(e){let{userName:t,policyArn:n}=e,r=new g({UserName:t,PolicyArn:n});return p().send(r)}function H(){let e=(0,T.c)(2),r=t(),i;return e[0]===r?i=e[1]:(i={mutationFn:U,onSuccess:()=>{r.invalidateQueries({queryKey:[`iam`,`attached-user-policies`]})}},e[0]=r,e[1]=i),n(i)}function U(e){let{userName:t,policyArn:n}=e,r=new C({UserName:t,PolicyArn:n});return p().send(r)}export{M as a,H as c,E as i,P as l,A as n,R as o,I as r,O as s,B as t};
+1 -1
View File
@@ -1 +1 @@
import{t as e}from"./queryOptions.js";import{At as t,F as n,I as r,L as i,M as a,N as o,P as s,Pt as c,j as l,r as u,z as d}from"./awsClient.js";var f=class extends c.classBuilder().ep(d).m(function(e,n,r,i){return[t(r,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`GetPolicy`,{}).n(`IAMClient`,`GetPolicyCommand`).sc(l).build(){},p=class extends c.classBuilder().ep(d).m(function(e,n,r,i){return[t(r,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`GetPolicyVersion`,{}).n(`IAMClient`,`GetPolicyVersionCommand`).sc(a).build(){},m=class extends c.classBuilder().ep(d).m(function(e,n,r,i){return[t(r,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`GetUser`,{}).n(`IAMClient`,`GetUserCommand`).sc(o).build(){},h=class extends c.classBuilder().ep(d).m(function(e,n,r,i){return[t(r,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`ListAccessKeys`,{}).n(`IAMClient`,`ListAccessKeysCommand`).sc(s).build(){},g=class extends c.classBuilder().ep(d).m(function(e,n,r,i){return[t(r,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`ListAttachedUserPolicies`,{}).n(`IAMClient`,`ListAttachedUserPoliciesCommand`).sc(n).build(){},_=class extends c.classBuilder().ep(d).m(function(e,n,r,i){return[t(r,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`ListPolicies`,{}).n(`IAMClient`,`ListPoliciesCommand`).sc(r).build(){},v=class extends c.classBuilder().ep(d).m(function(e,n,r,i){return[t(r,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`ListUsers`,{}).n(`IAMClient`,`ListUsersCommand`).sc(i).build(){},y=e({queryKey:[`iam`,`users`],queryFn:()=>{let e=new v({});return u().send(e)},staleTime:3e5}),b=t=>e({queryKey:[`iam`,`users`,t],queryFn:()=>{let e=new m({UserName:t});return u().send(e)},staleTime:3e5}),x=t=>e({queryKey:[`iam`,`access-keys`,t],queryFn:()=>{let e=new h({UserName:t});return u().send(e)},staleTime:3e5}),S=e({queryKey:[`iam`,`policies`],queryFn:()=>{let e=new _({Scope:`Local`});return u().send(e)},staleTime:3e5}),C=t=>e({queryKey:[`iam`,`policies`,t],queryFn:()=>{let e=new f({PolicyArn:t});return u().send(e)},staleTime:3e5}),w=(t,n)=>e({queryKey:[`iam`,`policy-versions`,t,n],queryFn:()=>{let e=new p({PolicyArn:t,VersionId:n});return u().send(e)},staleTime:3e5}),T=t=>e({queryKey:[`iam`,`attached-user-policies`,t],queryFn:()=>{let e=new g({UserName:t});return u().send(e)},staleTime:3e5});export{w as a,C as i,T as n,b as o,S as r,y as s,x as t};
import{t as e}from"./queryOptions.js";import{F as t,I as n,L as r,Lt as i,M as a,N as o,P as s,Vt as c,j as l,r as u,z as d}from"./awsClient.js";var f=class extends c.classBuilder().ep(d).m(function(e,t,n,r){return[i(n,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`GetPolicy`,{}).n(`IAMClient`,`GetPolicyCommand`).sc(l).build(){},p=class extends c.classBuilder().ep(d).m(function(e,t,n,r){return[i(n,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`GetPolicyVersion`,{}).n(`IAMClient`,`GetPolicyVersionCommand`).sc(a).build(){},m=class extends c.classBuilder().ep(d).m(function(e,t,n,r){return[i(n,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`GetUser`,{}).n(`IAMClient`,`GetUserCommand`).sc(o).build(){},h=class extends c.classBuilder().ep(d).m(function(e,t,n,r){return[i(n,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`ListAccessKeys`,{}).n(`IAMClient`,`ListAccessKeysCommand`).sc(s).build(){},g=class extends c.classBuilder().ep(d).m(function(e,t,n,r){return[i(n,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`ListAttachedUserPolicies`,{}).n(`IAMClient`,`ListAttachedUserPoliciesCommand`).sc(t).build(){},_=class extends c.classBuilder().ep(d).m(function(e,t,n,r){return[i(n,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`ListPolicies`,{}).n(`IAMClient`,`ListPoliciesCommand`).sc(n).build(){},v=class extends c.classBuilder().ep(d).m(function(e,t,n,r){return[i(n,e.getEndpointParameterInstructions())]}).s(`AWSIdentityManagementV20100508`,`ListUsers`,{}).n(`IAMClient`,`ListUsersCommand`).sc(r).build(){},y=e({queryKey:[`iam`,`users`],queryFn:()=>{let e=new v({});return u().send(e)},staleTime:3e5}),b=t=>e({queryKey:[`iam`,`users`,t],queryFn:()=>{let e=new m({UserName:t});return u().send(e)},staleTime:3e5}),x=t=>e({queryKey:[`iam`,`access-keys`,t],queryFn:()=>{let e=new h({UserName:t});return u().send(e)},staleTime:3e5}),S=e({queryKey:[`iam`,`policies`],queryFn:()=>{let e=new _({Scope:`Local`});return u().send(e)},staleTime:3e5}),C=t=>e({queryKey:[`iam`,`policies`,t],queryFn:()=>{let e=new f({PolicyArn:t});return u().send(e)},staleTime:3e5}),w=(t,n)=>e({queryKey:[`iam`,`policy-versions`,t,n],queryFn:()=>{let e=new p({PolicyArn:t,VersionId:n});return u().send(e)},staleTime:3e5}),T=t=>e({queryKey:[`iam`,`attached-user-policies`,t],queryFn:()=>{let e=new g({UserName:t});return u().send(e)},staleTime:3e5});export{w as a,C as i,T as n,b as o,S as r,y as s,x as t};
+1 -1
View File
@@ -1 +1 @@
import{en as e,tn as t}from"./awsClient.js";var n=e({userName:t().min(1,`User name is required`).max(64,`User name must be 64 characters or less`).regex(/^[\w+=,.@-]+$/,`User name contains invalid characters`),path:t().optional()}),r=e({policyName:t().min(1,`Policy name is required`).max(128,`Policy name must be 128 characters or less`),description:t().optional(),policyDocument:t().min(1,`Policy document is required`).refine(e=>{try{return JSON.parse(e),!0}catch{return!1}},{message:`Policy document must be valid JSON`})});export{n,r as t};
import{ln as e,un as t}from"./awsClient.js";var n=e({userName:t().min(1,`User name is required`).max(64,`User name must be 64 characters or less`).regex(/^[\w+=,.@-]+$/,`User name contains invalid characters`),path:t().optional()}),r=e({policyName:t().min(1,`Policy name is required`).max(128,`Policy name must be 128 characters or less`),description:t().optional(),policyDocument:t().min(1,`Policy document is required`).refine(e=>{try{return JSON.parse(e),!0}catch{return!1}},{message:`Policy document must be valid JSON`})});export{n,r as t};
@@ -1 +1 @@
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./error-banner.js";import{t as r}from"./useNavigate.js";import{t as i}from"./back-link.js";import{y as a}from"./ec2.js";import{A as o}from"./index.js";import{t as s}from"./page-heading.js";import{i as c,n as l,t as u}from"./field.js";import{t as d}from"./textarea.js";import{r as f,t as p}from"./zod.js";import{c as m}from"./ec23.js";import{t as h}from"./form-actions.js";var g=t(),_=e();function v(){let e=(0,g.c)(48),t=r(),v=a(),y;e[0]===Symbol.for(`react.memo_cache_sentinel`)?(y={resolver:p(m)},e[0]=y):y=e[0];let{handleSubmit:b,register:x,formState:S}=f(y),{errors:C,isSubmitting:w}=S,T;e[1]!==v||e[2]!==t?(T=async e=>{await v.mutateAsync(e),t({to:`/ec2/describe-key-pairs`})},e[1]=v,e[2]=t,e[3]=T):T=e[3];let E=T,D,O;e[4]===Symbol.for(`react.memo_cache_sentinel`)?(D=(0,_.jsx)(i,{to:`/ec2/describe-key-pairs`,children:`Back to key pairs`}),O=(0,_.jsx)(s,{title:`Import Key Pair`}),e[4]=D,e[5]=O):(D=e[4],O=e[5]);let k;e[6]===v.error?k=e[7]:(k=v.error&&(0,_.jsx)(n,{error:v.error,msg:`Failed to import key pair`}),e[6]=v.error,e[7]=k);let A;e[8]!==b||e[9]!==E?(A=b(E),e[8]=b,e[9]=E,e[10]=A):A=e[10];let j;e[11]===Symbol.for(`react.memo_cache_sentinel`)?(j=(0,_.jsx)(c,{children:(0,_.jsx)(`label`,{htmlFor:`keyName`,children:`Key Pair Name`})}),e[11]=j):j=e[11];let M=!!C.keyName,N;e[12]===x?N=e[13]:(N=x(`keyName`),e[12]=x,e[13]=N);let P;e[14]!==M||e[15]!==N?(P=(0,_.jsx)(o,{"aria-invalid":M,id:`keyName`,placeholder:`my-key-pair…`,...N}),e[14]=M,e[15]=N,e[16]=P):P=e[16];let F;e[17]===C.keyName?F=e[18]:(F=(0,_.jsx)(l,{errors:[C.keyName]}),e[17]=C.keyName,e[18]=F);let I;e[19]!==P||e[20]!==F?(I=(0,_.jsxs)(u,{children:[j,P,F]}),e[19]=P,e[20]=F,e[21]=I):I=e[21];let L,R;e[22]===Symbol.for(`react.memo_cache_sentinel`)?(L=(0,_.jsx)(c,{children:(0,_.jsx)(`label`,{htmlFor:`publicKeyMaterial`,children:`Public Key`})}),R=(0,_.jsx)(`p`,{className:`text-xs text-muted-foreground`,id:`publicKey-description`,children:`Paste your OpenSSH public key (e.g. the contents of id_rsa.pub)`}),e[22]=L,e[23]=R):(L=e[22],R=e[23]);let z=!!C.publicKeyMaterial,B;e[24]===x?B=e[25]:(B=x(`publicKeyMaterial`),e[24]=x,e[25]=B);let V;e[26]!==z||e[27]!==B?(V=(0,_.jsx)(d,{"aria-invalid":z,id:`publicKeyMaterial`,placeholder:`ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC…`,rows:8,...B}),e[26]=z,e[27]=B,e[28]=V):V=e[28];let H;e[29]===C.publicKeyMaterial?H=e[30]:(H=(0,_.jsx)(l,{errors:[C.publicKeyMaterial]}),e[29]=C.publicKeyMaterial,e[30]=H);let U;e[31]!==V||e[32]!==H?(U=(0,_.jsxs)(u,{children:[L,R,V,H]}),e[31]=V,e[32]=H,e[33]=U):U=e[33];let W;e[34]===t?W=e[35]:(W=()=>t({to:`/ec2/describe-key-pairs`}),e[34]=t,e[35]=W);let G;e[36]!==v.isPending||e[37]!==w||e[38]!==W?(G=(0,_.jsx)(h,{isPending:v.isPending,isSubmitting:w,onCancel:W,pendingLabel:`Importing…`,submitLabel:`Import Key Pair`}),e[36]=v.isPending,e[37]=w,e[38]=W,e[39]=G):G=e[39];let K;e[40]!==I||e[41]!==U||e[42]!==G||e[43]!==A?(K=(0,_.jsxs)(`form`,{className:`max-w-4xl space-y-6`,onSubmit:A,children:[I,U,G]}),e[40]=I,e[41]=U,e[42]=G,e[43]=A,e[44]=K):K=e[44];let q;return e[45]!==K||e[46]!==k?(q=(0,_.jsxs)(_.Fragment,{children:[D,O,k,K]}),e[45]=K,e[46]=k,e[47]=q):q=e[47],q}export{v as component};
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./error-banner.js";import{t as r}from"./useNavigate.js";import{t as i}from"./back-link.js";import{c as a}from"./ec2.js";import{b as o}from"./ec22.js";import{A as s}from"./index.js";import{t as c}from"./page-heading.js";import{i as l,n as u,t as d}from"./field.js";import{t as f}from"./textarea.js";import{r as p,t as m}from"./zod.js";import{t as h}from"./form-actions.js";var g=t(),_=e();function v(){let e=(0,g.c)(48),t=r(),v=o(),y;e[0]===Symbol.for(`react.memo_cache_sentinel`)?(y={resolver:m(a)},e[0]=y):y=e[0];let{handleSubmit:b,register:x,formState:S}=p(y),{errors:C,isSubmitting:w}=S,T;e[1]!==v||e[2]!==t?(T=async e=>{await v.mutateAsync(e),t({to:`/ec2/describe-key-pairs`})},e[1]=v,e[2]=t,e[3]=T):T=e[3];let E=T,D,O;e[4]===Symbol.for(`react.memo_cache_sentinel`)?(D=(0,_.jsx)(i,{to:`/ec2/describe-key-pairs`,children:`Back to key pairs`}),O=(0,_.jsx)(c,{title:`Import Key Pair`}),e[4]=D,e[5]=O):(D=e[4],O=e[5]);let k;e[6]===v.error?k=e[7]:(k=v.error&&(0,_.jsx)(n,{error:v.error,msg:`Failed to import key pair`}),e[6]=v.error,e[7]=k);let A;e[8]!==b||e[9]!==E?(A=b(E),e[8]=b,e[9]=E,e[10]=A):A=e[10];let j;e[11]===Symbol.for(`react.memo_cache_sentinel`)?(j=(0,_.jsx)(l,{children:(0,_.jsx)(`label`,{htmlFor:`keyName`,children:`Key Pair Name`})}),e[11]=j):j=e[11];let M=!!C.keyName,N;e[12]===x?N=e[13]:(N=x(`keyName`),e[12]=x,e[13]=N);let P;e[14]!==M||e[15]!==N?(P=(0,_.jsx)(s,{"aria-invalid":M,id:`keyName`,placeholder:`my-key-pair…`,...N}),e[14]=M,e[15]=N,e[16]=P):P=e[16];let F;e[17]===C.keyName?F=e[18]:(F=(0,_.jsx)(u,{errors:[C.keyName]}),e[17]=C.keyName,e[18]=F);let I;e[19]!==P||e[20]!==F?(I=(0,_.jsxs)(d,{children:[j,P,F]}),e[19]=P,e[20]=F,e[21]=I):I=e[21];let L,R;e[22]===Symbol.for(`react.memo_cache_sentinel`)?(L=(0,_.jsx)(l,{children:(0,_.jsx)(`label`,{htmlFor:`publicKeyMaterial`,children:`Public Key`})}),R=(0,_.jsx)(`p`,{className:`text-xs text-muted-foreground`,id:`publicKey-description`,children:`Paste your OpenSSH public key (e.g. the contents of id_rsa.pub)`}),e[22]=L,e[23]=R):(L=e[22],R=e[23]);let z=!!C.publicKeyMaterial,B;e[24]===x?B=e[25]:(B=x(`publicKeyMaterial`),e[24]=x,e[25]=B);let V;e[26]!==z||e[27]!==B?(V=(0,_.jsx)(f,{"aria-invalid":z,id:`publicKeyMaterial`,placeholder:`ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC…`,rows:8,...B}),e[26]=z,e[27]=B,e[28]=V):V=e[28];let H;e[29]===C.publicKeyMaterial?H=e[30]:(H=(0,_.jsx)(u,{errors:[C.publicKeyMaterial]}),e[29]=C.publicKeyMaterial,e[30]=H);let U;e[31]!==V||e[32]!==H?(U=(0,_.jsxs)(d,{children:[L,R,V,H]}),e[31]=V,e[32]=H,e[33]=U):U=e[33];let W;e[34]===t?W=e[35]:(W=()=>t({to:`/ec2/describe-key-pairs`}),e[34]=t,e[35]=W);let G;e[36]!==v.isPending||e[37]!==w||e[38]!==W?(G=(0,_.jsx)(h,{isPending:v.isPending,isSubmitting:w,onCancel:W,pendingLabel:`Importing…`,submitLabel:`Import Key Pair`}),e[36]=v.isPending,e[37]=w,e[38]=W,e[39]=G):G=e[39];let K;e[40]!==I||e[41]!==U||e[42]!==G||e[43]!==A?(K=(0,_.jsxs)(`form`,{className:`max-w-4xl space-y-6`,onSubmit:A,children:[I,U,G]}),e[40]=I,e[41]=U,e[42]=G,e[43]=A,e[44]=K):K=e[44];let q;return e[45]!==K||e[46]!==k?(q=(0,_.jsxs)(_.Fragment,{children:[D,O,k,K]}),e[45]=K,e[46]=k,e[47]=q):q=e[47],q}export{v as component};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{a as r}from"./utils.js";import{t as i}from"./link.js";import{t as a}from"./button.js";import{r as o}from"./iam2.js";import{t as s}from"./page-heading.js";import{t as c}from"./list-card.js";var l=t(),u=e();function d(){let e=(0,l.c)(3),{data:t}=n(o),r;if(e[0]!==t.Policies){let n=(t.Policies??[]).toSorted(p),o;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(o=(0,u.jsx)(s,{actions:(0,u.jsx)(i,{to:`/iam/create-policy`,children:(0,u.jsx)(a,{children:`Create Policy`})}),title:`IAM Policies`}),e[2]=o):o=e[2],r=(0,u.jsxs)(u.Fragment,{children:[o,n.length>0?(0,u.jsx)(`div`,{className:`space-y-4`,children:n.map(f)}):(0,u.jsx)(`p`,{className:`text-muted-foreground`,children:`No IAM policies found.`})]}),e[0]=t.Policies,e[1]=r}else r=e[1];return r}function f(e){return e.Arn?(0,u.jsx)(c,{params:{policyArn:encodeURIComponent(e.Arn)},subtitle:`${e.Arn} • Created ${r(e.CreateDate)}`,title:e.PolicyName??``,to:`/iam/list-policies/$policyArn`},e.Arn):null}function p(e,t){let n=e.PolicyName?.toLowerCase()??``,r=t.PolicyName?.toLowerCase()??``;return n.localeCompare(r)}export{d as component};
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{t as r}from"./link.js";import{t as i}from"./button.js";import{r as a}from"./iam2.js";import{t as o}from"./page-heading.js";import{t as s}from"./list-card.js";var c=t(),l=e();function u(){let e=(0,c.c)(3),{data:t}=n(a),s;if(e[0]!==t.Policies){let n=(t.Policies??[]).toSorted(f),a;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(a=(0,l.jsx)(o,{actions:(0,l.jsx)(r,{to:`/iam/create-policy`,children:(0,l.jsx)(i,{children:`Create Policy`})}),title:`IAM Policies`}),e[2]=a):a=e[2],s=(0,l.jsxs)(l.Fragment,{children:[a,n.length>0?(0,l.jsx)(`div`,{className:`space-y-4`,children:n.map(d)}):(0,l.jsx)(`p`,{className:`text-muted-foreground`,children:`No IAM policies found.`})]}),e[0]=t.Policies,e[1]=s}else s=e[1];return s}function d(e){return e.Arn?(0,l.jsx)(s,{params:{policyArn:encodeURIComponent(e.Arn)},subtitle:e.Arn??``,title:e.PolicyName??``,to:`/iam/list-policies/$policyArn`},e.Arn):null}function f(e,t){let n=e.PolicyName?.toLowerCase()??``,r=t.PolicyName?.toLowerCase()??``;return n.localeCompare(r)}export{u as component};
@@ -1 +1 @@
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{a as r}from"./utils.js";import{t as i}from"./link.js";import{t as a}from"./button.js";import{s as o}from"./iam2.js";import{t as s}from"./page-heading.js";import{t as c}from"./list-card.js";var l=t(),u=e();function d(){let e=(0,l.c)(3),{data:t}=n(o),r;if(e[0]!==t.Users){let n=(t.Users??[]).toSorted(p),o;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(o=(0,u.jsx)(s,{actions:(0,u.jsx)(i,{to:`/iam/create-user`,children:(0,u.jsx)(a,{children:`Create User`})}),title:`IAM Users`}),e[2]=o):o=e[2],r=(0,u.jsxs)(u.Fragment,{children:[o,n.length>0?(0,u.jsx)(`div`,{className:`space-y-4`,children:n.map(f)}):(0,u.jsx)(`p`,{className:`text-muted-foreground`,children:`No IAM users found.`})]}),e[0]=t.Users,e[1]=r}else r=e[1];return r}function f(e){return e.UserName?(0,u.jsx)(c,{params:{userName:e.UserName},subtitle:`${e.UserId} • ${e.Path??`/`} • Created ${r(e.CreateDate)}`,title:e.UserName,to:`/iam/list-users/$userName`},e.UserName):null}function p(e,t){let n=e.UserName?.toLowerCase()??``,r=t.UserName?.toLowerCase()??``;return n.localeCompare(r)}export{d as component};
import{n as e,t}from"./compiler-runtime.js";import{t as n}from"./useSuspenseQuery.js";import{t as r}from"./link.js";import{t as i}from"./button.js";import{s as a}from"./iam2.js";import{t as o}from"./page-heading.js";import{t as s}from"./list-card.js";var c=t(),l=e();function u(){let e=(0,c.c)(3),{data:t}=n(a),s;if(e[0]!==t.Users){let n=(t.Users??[]).toSorted(f),a;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(a=(0,l.jsx)(o,{actions:(0,l.jsx)(r,{to:`/iam/create-user`,children:(0,l.jsx)(i,{children:`Create User`})}),title:`IAM Users`}),e[2]=a):a=e[2],s=(0,l.jsxs)(l.Fragment,{children:[a,n.length>0?(0,l.jsx)(`div`,{className:`space-y-4`,children:n.map(d)}):(0,l.jsx)(`p`,{className:`text-muted-foreground`,children:`No IAM users found.`})]}),e[0]=t.Users,e[1]=s}else s=e[1];return s}function d(e){return e.UserName?(0,l.jsx)(s,{params:{userName:e.UserName},subtitle:e.UserId??``,title:e.UserName,to:`/iam/list-users/$userName`},e.UserName):null}function f(e,t){let n=e.UserName?.toLowerCase()??``,r=t.UserName?.toLowerCase()??``;return n.localeCompare(r)}export{u as component};
+1 -1
View File
@@ -1 +1 @@
import{a as e,n as t,r as n,t as r}from"./compiler-runtime.js";import{n as i}from"./utils.js";import{t as a}from"./useNavigate.js";import{t as o}from"./button.js";import{Jt as s,Xt as c,n as l,qt as u,t as d}from"./awsClient.js";import{t as f}from"./DescribeInstancesCommand.js";import{A as p}from"./index.js";import{i as m,n as h,r as g,t as _}from"./field.js";import{r as v,t as y}from"./zod.js";var b=e(n()),x=r(),S=t();function C(e){let t=(0,x.c)(10),n,r,a;t[0]===e?(n=t[1],r=t[2],a=t[3]):({className:n,size:a,...r}=e,t[0]=e,t[1]=n,t[2]=r,t[3]=a);let o=a===void 0?`default`:a,s;t[4]===n?s=t[5]:(s=i(`group/card flex flex-col gap-4 overflow-hidden rounded-lg bg-card py-4 text-xs/relaxed text-card-foreground ring-1 ring-foreground/10 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 *:[img:first-child]:rounded-t-lg *:[img:last-child]:rounded-b-lg`,n),t[4]=n,t[5]=s);let c;return t[6]!==r||t[7]!==o||t[8]!==s?(c=(0,S.jsx)(`div`,{className:s,"data-size":o,"data-slot":`card`,...r}),t[6]=r,t[7]=o,t[8]=s,t[9]=c):c=t[9],c}function w(e){let t=(0,x.c)(8),n,r;t[0]===e?(n=t[1],r=t[2]):({className:n,...r}=e,t[0]=e,t[1]=n,t[2]=r);let a;t[3]===n?a=t[4]:(a=i(`group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-lg px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3`,n),t[3]=n,t[4]=a);let o;return t[5]!==r||t[6]!==a?(o=(0,S.jsx)(`div`,{className:a,"data-slot":`card-header`,...r}),t[5]=r,t[6]=a,t[7]=o):o=t[7],o}function T(e){let t=(0,x.c)(8),n,r;t[0]===e?(n=t[1],r=t[2]):({className:n,...r}=e,t[0]=e,t[1]=n,t[2]=r);let a;t[3]===n?a=t[4]:(a=i(`text-sm font-medium`,n),t[3]=n,t[4]=a);let o;return t[5]!==r||t[6]!==a?(o=(0,S.jsx)(`div`,{className:a,"data-slot":`card-title`,...r}),t[5]=r,t[6]=a,t[7]=o):o=t[7],o}function E(e){let t=(0,x.c)(8),n,r;t[0]===e?(n=t[1],r=t[2]):({className:n,...r}=e,t[0]=e,t[1]=n,t[2]=r);let a;t[3]===n?a=t[4]:(a=i(`px-4 group-data-[size=sm]/card:px-3`,n),t[3]=n,t[4]=a);let o;return t[5]!==r||t[6]!==a?(o=(0,S.jsx)(`div`,{className:a,"data-slot":`card-content`,...r}),t[5]=r,t[6]=a,t[7]=o):o=t[7],o}function D(){let e=(0,x.c)(44),t=a(),[n,r]=(0,b.useState)(null),i;e[0]===Symbol.for(`react.memo_cache_sentinel`)?(i={resolver:y(u)},e[0]=i):i=e[0];let{register:D,handleSubmit:O,formState:k}=v(i),{errors:A,isSubmitting:j}=k,M;e[1]===t?M=e[2]:(M=async function(e){r(null),d(),c(e);try{await l().send(new f({})),t({to:`/`})}catch{s(),d(),r(`Invalid credentials. Please check your Access Key ID and Secret Access Key.`)}},e[1]=t,e[2]=M);let N=M,P;e[3]===Symbol.for(`react.memo_cache_sentinel`)?(P=(0,S.jsx)(w,{children:(0,S.jsx)(T,{children:`AWS Credentials`})}),e[3]=P):P=e[3];let F;e[4]===n?F=e[5]:(F=n&&(0,S.jsx)(`p`,{className:`mb-4 rounded-md bg-destructive/10 p-3 text-sm text-destructive`,children:n}),e[4]=n,e[5]=F);let I;e[6]!==O||e[7]!==N?(I=O(N),e[6]=O,e[7]=N,e[8]=I):I=e[8];let L;e[9]===Symbol.for(`react.memo_cache_sentinel`)?(L=(0,S.jsx)(m,{children:(0,S.jsx)(`label`,{htmlFor:`accessKeyId`,children:`Access Key ID`})}),e[9]=L):L=e[9];let R=!!A.accessKeyId,z;e[10]===D?z=e[11]:(z=D(`accessKeyId`),e[10]=D,e[11]=z);let B;e[12]!==R||e[13]!==z?(B=(0,S.jsx)(p,{"aria-invalid":R,autoComplete:`username`,id:`accessKeyId`,placeholder:`AKIAIOSFODNN7EXAMPLE`,...z}),e[12]=R,e[13]=z,e[14]=B):B=e[14];let V;e[15]===A.accessKeyId?V=e[16]:(V=(0,S.jsx)(h,{errors:[A.accessKeyId]}),e[15]=A.accessKeyId,e[16]=V);let H;e[17]!==V||e[18]!==B?(H=(0,S.jsxs)(_,{children:[L,B,V]}),e[17]=V,e[18]=B,e[19]=H):H=e[19];let U;e[20]===Symbol.for(`react.memo_cache_sentinel`)?(U=(0,S.jsx)(m,{children:(0,S.jsx)(`label`,{htmlFor:`secretAccessKey`,children:`Secret Access Key`})}),e[20]=U):U=e[20];let W=!!A.secretAccessKey,G;e[21]===D?G=e[22]:(G=D(`secretAccessKey`),e[21]=D,e[22]=G);let K;e[23]!==W||e[24]!==G?(K=(0,S.jsx)(p,{"aria-invalid":W,autoComplete:`current-password`,id:`secretAccessKey`,placeholder:`wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`,type:`password`,...G}),e[23]=W,e[24]=G,e[25]=K):K=e[25];let q;e[26]===A.secretAccessKey?q=e[27]:(q=(0,S.jsx)(h,{errors:[A.secretAccessKey]}),e[26]=A.secretAccessKey,e[27]=q);let J;e[28]!==K||e[29]!==q?(J=(0,S.jsxs)(_,{children:[U,K,q]}),e[28]=K,e[29]=q,e[30]=J):J=e[30];let Y=j?`Signing in...`:`Sign In`,X;e[31]!==j||e[32]!==Y?(X=(0,S.jsx)(o,{className:`w-full`,disabled:j,type:`submit`,children:Y}),e[31]=j,e[32]=Y,e[33]=X):X=e[33];let Z;e[34]!==H||e[35]!==J||e[36]!==X?(Z=(0,S.jsxs)(g,{children:[H,J,X]}),e[34]=H,e[35]=J,e[36]=X,e[37]=Z):Z=e[37];let Q;e[38]!==Z||e[39]!==I?(Q=(0,S.jsx)(`form`,{onSubmit:I,children:Z}),e[38]=Z,e[39]=I,e[40]=Q):Q=e[40];let $;return e[41]!==Q||e[42]!==F?($=(0,S.jsx)(`div`,{className:`flex flex-1 items-center justify-center`,children:(0,S.jsxs)(C,{className:`w-full max-w-sm`,children:[P,(0,S.jsxs)(E,{children:[F,Q]})]})}),e[41]=Q,e[42]=F,e[43]=$):$=e[43],$}export{D as component};
import{a as e,n as t,r as n,t as r}from"./compiler-runtime.js";import{n as i}from"./utils.js";import{t as a}from"./useNavigate.js";import{t as o}from"./button.js";import{en as s,n as c,rn as l,t as u,tn as d}from"./awsClient.js";import{t as f}from"./DescribeInstancesCommand.js";import{A as p}from"./index.js";import{i as m,n as h,r as g,t as _}from"./field.js";import{r as v,t as y}from"./zod.js";var b=e(n()),x=r(),S=t();function C(e){let t=(0,x.c)(10),n,r,a;t[0]===e?(n=t[1],r=t[2],a=t[3]):({className:n,size:a,...r}=e,t[0]=e,t[1]=n,t[2]=r,t[3]=a);let o=a===void 0?`default`:a,s;t[4]===n?s=t[5]:(s=i(`group/card flex flex-col gap-4 overflow-hidden rounded-lg bg-card py-4 text-xs/relaxed text-card-foreground ring-1 ring-foreground/10 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 *:[img:first-child]:rounded-t-lg *:[img:last-child]:rounded-b-lg`,n),t[4]=n,t[5]=s);let c;return t[6]!==r||t[7]!==o||t[8]!==s?(c=(0,S.jsx)(`div`,{className:s,"data-size":o,"data-slot":`card`,...r}),t[6]=r,t[7]=o,t[8]=s,t[9]=c):c=t[9],c}function w(e){let t=(0,x.c)(8),n,r;t[0]===e?(n=t[1],r=t[2]):({className:n,...r}=e,t[0]=e,t[1]=n,t[2]=r);let a;t[3]===n?a=t[4]:(a=i(`group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-lg px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3`,n),t[3]=n,t[4]=a);let o;return t[5]!==r||t[6]!==a?(o=(0,S.jsx)(`div`,{className:a,"data-slot":`card-header`,...r}),t[5]=r,t[6]=a,t[7]=o):o=t[7],o}function T(e){let t=(0,x.c)(8),n,r;t[0]===e?(n=t[1],r=t[2]):({className:n,...r}=e,t[0]=e,t[1]=n,t[2]=r);let a;t[3]===n?a=t[4]:(a=i(`text-sm font-medium`,n),t[3]=n,t[4]=a);let o;return t[5]!==r||t[6]!==a?(o=(0,S.jsx)(`div`,{className:a,"data-slot":`card-title`,...r}),t[5]=r,t[6]=a,t[7]=o):o=t[7],o}function E(e){let t=(0,x.c)(8),n,r;t[0]===e?(n=t[1],r=t[2]):({className:n,...r}=e,t[0]=e,t[1]=n,t[2]=r);let a;t[3]===n?a=t[4]:(a=i(`px-4 group-data-[size=sm]/card:px-3`,n),t[3]=n,t[4]=a);let o;return t[5]!==r||t[6]!==a?(o=(0,S.jsx)(`div`,{className:a,"data-slot":`card-content`,...r}),t[5]=r,t[6]=a,t[7]=o):o=t[7],o}function D(){let e=(0,x.c)(44),t=a(),[n,r]=(0,b.useState)(null),i;e[0]===Symbol.for(`react.memo_cache_sentinel`)?(i={resolver:y(s)},e[0]=i):i=e[0];let{register:D,handleSubmit:O,formState:k}=v(i),{errors:A,isSubmitting:j}=k,M;e[1]===t?M=e[2]:(M=async function(e){r(null),u(),l(e);try{await c().send(new f({})),t({to:`/`})}catch{d(),u(),r(`Invalid credentials. Please check your Access Key ID and Secret Access Key.`)}},e[1]=t,e[2]=M);let N=M,P;e[3]===Symbol.for(`react.memo_cache_sentinel`)?(P=(0,S.jsx)(w,{children:(0,S.jsx)(T,{children:`AWS Credentials`})}),e[3]=P):P=e[3];let F;e[4]===n?F=e[5]:(F=n&&(0,S.jsx)(`p`,{className:`mb-4 rounded-md bg-destructive/10 p-3 text-sm text-destructive`,children:n}),e[4]=n,e[5]=F);let I;e[6]!==O||e[7]!==N?(I=O(N),e[6]=O,e[7]=N,e[8]=I):I=e[8];let L;e[9]===Symbol.for(`react.memo_cache_sentinel`)?(L=(0,S.jsx)(m,{children:(0,S.jsx)(`label`,{htmlFor:`accessKeyId`,children:`Access Key ID`})}),e[9]=L):L=e[9];let R=!!A.accessKeyId,z;e[10]===D?z=e[11]:(z=D(`accessKeyId`),e[10]=D,e[11]=z);let B;e[12]!==R||e[13]!==z?(B=(0,S.jsx)(p,{"aria-invalid":R,autoComplete:`username`,id:`accessKeyId`,placeholder:`AKIAIOSFODNN7EXAMPLE`,...z}),e[12]=R,e[13]=z,e[14]=B):B=e[14];let V;e[15]===A.accessKeyId?V=e[16]:(V=(0,S.jsx)(h,{errors:[A.accessKeyId]}),e[15]=A.accessKeyId,e[16]=V);let H;e[17]!==V||e[18]!==B?(H=(0,S.jsxs)(_,{children:[L,B,V]}),e[17]=V,e[18]=B,e[19]=H):H=e[19];let U;e[20]===Symbol.for(`react.memo_cache_sentinel`)?(U=(0,S.jsx)(m,{children:(0,S.jsx)(`label`,{htmlFor:`secretAccessKey`,children:`Secret Access Key`})}),e[20]=U):U=e[20];let W=!!A.secretAccessKey,G;e[21]===D?G=e[22]:(G=D(`secretAccessKey`),e[21]=D,e[22]=G);let K;e[23]!==W||e[24]!==G?(K=(0,S.jsx)(p,{"aria-invalid":W,autoComplete:`current-password`,id:`secretAccessKey`,placeholder:`wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`,type:`password`,...G}),e[23]=W,e[24]=G,e[25]=K):K=e[25];let q;e[26]===A.secretAccessKey?q=e[27]:(q=(0,S.jsx)(h,{errors:[A.secretAccessKey]}),e[26]=A.secretAccessKey,e[27]=q);let J;e[28]!==K||e[29]!==q?(J=(0,S.jsxs)(_,{children:[U,K,q]}),e[28]=K,e[29]=q,e[30]=J):J=e[30];let Y=j?`Signing in...`:`Sign In`,X;e[31]!==j||e[32]!==Y?(X=(0,S.jsx)(o,{className:`w-full`,disabled:j,type:`submit`,children:Y}),e[31]=j,e[32]=Y,e[33]=X):X=e[33];let Z;e[34]!==H||e[35]!==J||e[36]!==X?(Z=(0,S.jsxs)(g,{children:[H,J,X]}),e[34]=H,e[35]=J,e[36]=X,e[37]=Z):Z=e[37];let Q;e[38]!==Z||e[39]!==I?(Q=(0,S.jsx)(`form`,{onSubmit:I,children:Z}),e[38]=Z,e[39]=I,e[40]=Q):Q=e[40];let $;return e[41]!==Q||e[42]!==F?($=(0,S.jsx)(`div`,{className:`flex flex-1 items-center justify-center`,children:(0,S.jsxs)(C,{className:`w-full max-w-sm`,children:[P,(0,S.jsxs)(E,{children:[F,Q]})]})}),e[41]=Q,e[42]=F,e[43]=$):$=e[43],$}export{D as component};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1 +1 @@
import{t as e}from"./queryOptions.js";import{At as t,Pt as n,_ as r,d as i,f as a,g as o,i as s}from"./awsClient.js";var c=class extends n.classBuilder().ep(o).m(function(e,n,i,a){return[t(i,e.getEndpointParameterInstructions()),r(i)]}).s(`AmazonS3`,`ListBuckets`,{}).n(`S3Client`,`ListBucketsCommand`).sc(i).build(){},l=class extends n.classBuilder().ep({...o,Bucket:{type:`contextParams`,name:`Bucket`},Prefix:{type:`contextParams`,name:`Prefix`}}).m(function(e,n,i,a){return[t(i,e.getEndpointParameterInstructions()),r(i)]}).s(`AmazonS3`,`ListObjectsV2`,{}).n(`S3Client`,`ListObjectsV2Command`).sc(a).build(){},u=e({queryKey:[`s3`,`buckets`],queryFn:()=>{let e=new c({});return s().send(e)}}),d=(t,n)=>e({queryKey:[`s3`,`buckets`,t,`objects`,n??``],queryFn:()=>{let e=new l({Bucket:t,Prefix:n,Delimiter:`/`});return s().send(e)}});export{u as n,d as t};
import{t as e}from"./queryOptions.js";import{Lt as t,Vt as n,_ as r,d as i,f as a,g as o,i as s}from"./awsClient.js";var c=class extends n.classBuilder().ep(o).m(function(e,n,i,a){return[t(i,e.getEndpointParameterInstructions()),r(i)]}).s(`AmazonS3`,`ListBuckets`,{}).n(`S3Client`,`ListBucketsCommand`).sc(i).build(){},l=class extends n.classBuilder().ep({...o,Bucket:{type:`contextParams`,name:`Bucket`},Prefix:{type:`contextParams`,name:`Prefix`}}).m(function(e,n,i,a){return[t(i,e.getEndpointParameterInstructions()),r(i)]}).s(`AmazonS3`,`ListObjectsV2`,{}).n(`S3Client`,`ListObjectsV2Command`).sc(a).build(){},u=e({queryKey:[`s3`,`buckets`],queryFn:()=>{let e=new c({});return s().send(e)}}),d=(t,n)=>e({queryKey:[`s3`,`buckets`,t,`objects`,n??``],queryFn:()=>{let e=new l({Bucket:t,Prefix:n,Delimiter:`/`});return s().send(e)}});export{u as n,d as t};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -12,7 +12,7 @@
<link rel="modulepreload" crossorigin href="/assets/awsClient.js">
<link rel="modulepreload" crossorigin href="/assets/DescribeInstancesCommand.js">
<link rel="modulepreload" crossorigin href="/assets/queryOptions.js">
<link rel="modulepreload" crossorigin href="/assets/ec22.js">
<link rel="modulepreload" crossorigin href="/assets/ec23.js">
<link rel="modulepreload" crossorigin href="/assets/iam2.js">
<link rel="modulepreload" crossorigin href="/assets/s32.js">
<link rel="modulepreload" crossorigin href="/assets/utils.js">
@@ -0,0 +1,64 @@
import { ChevronDown, ChevronRight } from "lucide-react"
import { useState } from "react"
import type { UseFormReturn } from "react-hook-form"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import type { CreateVpcWizardFormData } from "@/types/ec2"
interface SubnetCidrInputsProps {
form: UseFormReturn<CreateVpcWizardFormData>
type: "public" | "private"
count: number
defaults: string[]
}
export function SubnetCidrInputs({
form,
type,
count,
defaults,
}: SubnetCidrInputsProps) {
const [expanded, setExpanded] = useState(false)
const fieldName =
type === "public" ? "publicSubnetCidrs" : "privateSubnetCidrs"
if (count === 0) {
return null
}
return (
<div className="mt-2">
<Button
className="gap-1 px-0 text-xs text-muted-foreground"
onClick={() => setExpanded(!expanded)}
type="button"
variant="link"
>
{expanded ? (
<ChevronDown className="size-3" />
) : (
<ChevronRight className="size-3" />
)}
Customize {type} subnet CIDR blocks
</Button>
{expanded && (
<div className="mt-2 space-y-2">
{Array.from({ length: count }, (_, i) => (
<div className="flex items-center gap-2" key={i}>
<span className="w-32 text-xs text-muted-foreground">
{type === "public" ? "Public" : "Private"} subnet {i + 1}
</span>
<Input
defaultValue={defaults[i]}
placeholder={defaults[i]}
{...form.register(`${fieldName}.${i}`)}
/>
</div>
))}
</div>
)}
</div>
)
}
@@ -0,0 +1,52 @@
import { Plus, Trash2 } from "lucide-react"
import type { UseFormReturn } from "react-hook-form"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import type { CreateVpcWizardFormData } from "@/types/ec2"
interface TagEditorProps {
form: UseFormReturn<CreateVpcWizardFormData>
}
export function TagEditor({ form }: TagEditorProps) {
const tags = form.watch("tags")
function addTag() {
form.setValue("tags", [...tags, { key: "", value: "" }])
}
function removeTag(index: number) {
form.setValue(
"tags",
tags.filter((_, i) => i !== index),
)
}
return (
<div className="space-y-2">
{tags.map((_, index) => (
// oxlint-disable-next-line react/no-array-index-key -- form array with no stable id
<div className="flex items-center gap-2" key={index}>
<Input placeholder="Key" {...form.register(`tags.${index}.key`)} />
<Input
placeholder="Value"
{...form.register(`tags.${index}.value`)}
/>
<Button
onClick={() => removeTag(index)}
size="icon"
type="button"
variant="ghost"
>
<Trash2 className="size-3.5" />
</Button>
</div>
))}
<Button onClick={addTag} size="sm" type="button" variant="outline">
<Plus className="size-3.5" />
Add tag
</Button>
</div>
)
}
@@ -0,0 +1,131 @@
import type { SubnetCidr } from "@/lib/subnet-calculator"
interface VpcPreviewProps {
mode: "vpc-only" | "vpc-and-more"
vpcCidr: string
publicSubnets: SubnetCidr[]
privateSubnets: SubnetCidr[]
hasIgw: boolean
}
function SubnetCard({
label,
cidr,
variant,
}: {
label: string
cidr: string
variant: "public" | "private"
}) {
return (
<div
className={`rounded-md border px-3 py-2 text-xs ${
variant === "public"
? "border-emerald-500/30 bg-emerald-500/10"
: "border-blue-500/30 bg-blue-500/10"
}`}
>
<div className="font-medium">{label}</div>
<div className="text-muted-foreground">{cidr}</div>
</div>
)
}
export function VpcPreview({
mode,
vpcCidr,
publicSubnets,
privateSubnets,
hasIgw,
}: VpcPreviewProps) {
return (
<div className="rounded-lg border bg-muted/30 p-4">
<h3 className="mb-3 text-xs font-semibold tracking-wider text-muted-foreground uppercase">
Preview
</h3>
{/* VPC box */}
<div className="rounded-lg border-2 border-dashed border-foreground/20 p-4">
<div className="mb-3 text-xs font-medium">
VPC <span className="text-muted-foreground">({vpcCidr})</span>
</div>
{mode === "vpc-and-more" && (
<div className="grid gap-4 md:grid-cols-3">
{/* Subnets column */}
<div className="space-y-2">
<div className="text-xs font-medium text-muted-foreground">
Subnets
</div>
{publicSubnets.map((s) => (
<SubnetCard
cidr={s.cidr}
key={s.cidr}
label={s.label}
variant="public"
/>
))}
{privateSubnets.map((s) => (
<SubnetCard
cidr={s.cidr}
key={s.cidr}
label={s.label}
variant="private"
/>
))}
{publicSubnets.length === 0 && privateSubnets.length === 0 && (
<div className="text-xs text-muted-foreground">No subnets</div>
)}
</div>
{/* Route Tables column */}
<div className="space-y-2">
<div className="text-xs font-medium text-muted-foreground">
Route Tables
</div>
{publicSubnets.length > 0 && (
<div className="rounded-md border border-foreground/10 bg-background px-3 py-2 text-xs">
<div className="font-medium">Public Route Table</div>
<div className="mt-1 text-muted-foreground">
0.0.0.0/0 → IGW
</div>
<div className="text-muted-foreground">local</div>
</div>
)}
{privateSubnets.length > 0 && (
<div className="rounded-md border border-foreground/10 bg-background px-3 py-2 text-xs">
<div className="font-medium">Private Route Table</div>
<div className="mt-1 text-muted-foreground">local</div>
</div>
)}
</div>
{/* Network Connections column */}
<div className="space-y-2">
<div className="text-xs font-medium text-muted-foreground">
Network Connections
</div>
{hasIgw && (
<div className="rounded-md border border-amber-500/30 bg-amber-500/10 px-3 py-2 text-xs">
<div className="font-medium">Internet Gateway</div>
<div className="text-muted-foreground">Attached to VPC</div>
</div>
)}
{!hasIgw && (
<div className="text-xs text-muted-foreground">
No internet gateway
</div>
)}
</div>
</div>
)}
{mode === "vpc-only" && (
<div className="text-xs text-muted-foreground">
VPC only — no additional resources will be created.
</div>
)}
</div>
</div>
)
}
@@ -196,6 +196,34 @@ export function SidebarLayout() {
</SidebarMenuButton>
</Link>
</SidebarMenuItem>
{/* uncomment when route pages are created
<SidebarMenuItem>
<Link to="/ec2/describe-route-tables">
<SidebarMenuButton
isActive={pathname.startsWith("/ec2/describe-route-tables")}
tooltip="Route Tables"
>
<Route className="size-4" />
<span>Route Tables</span>
</SidebarMenuButton>
</Link>
</SidebarMenuItem>
<SidebarMenuItem>
<Link to="/ec2/describe-internet-gateways">
<SidebarMenuButton
isActive={pathname.startsWith(
"/ec2/describe-internet-gateways",
)}
tooltip="Internet Gateways"
>
<Globe className="size-4" />
<span>Internet Gateways</span>
</SidebarMenuButton>
</Link>
</SidebarMenuItem>
*/}
</SidebarMenu>
</SidebarGroup>
@@ -0,0 +1,141 @@
import { describe, expect, it } from "vitest"
import {
calculateSubnetCidrs,
cidrContains,
cidrsOverlap,
isValidCidr,
numberToIp,
parseCidr,
subnetPrefix,
} from "./subnet-calculator"
describe("parseCidr", () => {
it("parses a /16 CIDR", () => {
const result = parseCidr("10.0.0.0/16")
expect(result.network).toBe(0x0a_00_00_00)
expect(result.prefix).toBe(16)
})
it("normalises non-aligned addresses", () => {
const result = parseCidr("10.0.1.5/16")
expect(result.network).toBe(0x0a_00_00_00)
expect(result.prefix).toBe(16)
})
it("parses a /24 CIDR", () => {
const result = parseCidr("192.168.1.0/24")
expect(result.network).toBe(0xc0_a8_01_00)
expect(result.prefix).toBe(24)
})
})
describe("numberToIp", () => {
it("converts 0x0A000000 to 10.0.0.0", () => {
expect(numberToIp(0x0a_00_00_00)).toBe("10.0.0.0")
})
it("converts 0xC0A80100 to 192.168.1.0", () => {
expect(numberToIp(0xc0_a8_01_00)).toBe("192.168.1.0")
})
})
describe("subnetPrefix", () => {
it("returns /20 for a /16 VPC", () => {
expect(subnetPrefix(16)).toBe(20)
})
it("returns /28 (max) for a /24 VPC", () => {
expect(subnetPrefix(24)).toBe(28)
})
})
describe("calculateSubnetCidrs", () => {
it("calculates correct CIDRs for 1 public + 1 private in a /16", () => {
const result = calculateSubnetCidrs("10.0.0.0/16", 1, 1)
expect(result.publicSubnets).toHaveLength(1)
expect(result.privateSubnets).toHaveLength(1)
expect(result.publicSubnets[0]?.cidr).toBe("10.0.0.0/20")
expect(result.privateSubnets[0]?.cidr).toBe("10.0.128.0/20")
})
it("calculates correct CIDRs for 2 public + 2 private", () => {
const result = calculateSubnetCidrs("10.0.0.0/16", 2, 2)
expect(result.publicSubnets[0]?.cidr).toBe("10.0.0.0/20")
expect(result.publicSubnets[1]?.cidr).toBe("10.0.16.0/20")
expect(result.privateSubnets[0]?.cidr).toBe("10.0.128.0/20")
expect(result.privateSubnets[1]?.cidr).toBe("10.0.144.0/20")
})
it("returns empty arrays for 0 counts", () => {
const result = calculateSubnetCidrs("10.0.0.0/16", 0, 0)
expect(result.publicSubnets).toHaveLength(0)
expect(result.privateSubnets).toHaveLength(0)
})
it("handles 4 public + 4 private", () => {
const result = calculateSubnetCidrs("10.0.0.0/16", 4, 4)
expect(result.publicSubnets).toHaveLength(4)
expect(result.privateSubnets).toHaveLength(4)
})
it("sets correct labels", () => {
const result = calculateSubnetCidrs("10.0.0.0/16", 1, 1)
expect(result.publicSubnets[0]?.label).toBe("Public subnet 1")
expect(result.privateSubnets[0]?.label).toBe("Private subnet 1")
})
})
describe("cidrsOverlap", () => {
it("detects overlapping CIDRs", () => {
expect(cidrsOverlap("10.0.0.0/20", "10.0.8.0/24")).toBe(true)
})
it("returns false for non-overlapping CIDRs", () => {
expect(cidrsOverlap("10.0.0.0/20", "10.0.128.0/20")).toBe(false)
})
it("detects identical CIDRs as overlapping", () => {
expect(cidrsOverlap("10.0.0.0/20", "10.0.0.0/20")).toBe(true)
})
})
describe("cidrContains", () => {
it("returns true when subnet fits inside VPC", () => {
expect(cidrContains("10.0.0.0/16", "10.0.0.0/20")).toBe(true)
})
it("returns false when subnet exceeds VPC range", () => {
expect(cidrContains("10.0.0.0/16", "10.1.0.0/20")).toBe(false)
})
it("returns true for VPC containing itself", () => {
expect(cidrContains("10.0.0.0/16", "10.0.0.0/16")).toBe(true)
})
})
describe("isValidCidr", () => {
it("accepts valid /16 CIDR", () => {
expect(isValidCidr("10.0.0.0/16")).toBe(true)
})
it("accepts valid /28 CIDR", () => {
expect(isValidCidr("10.0.0.0/28")).toBe(true)
})
it("rejects /15 (too large)", () => {
expect(isValidCidr("10.0.0.0/15")).toBe(false)
})
it("rejects /29 (too small)", () => {
expect(isValidCidr("10.0.0.0/29")).toBe(false)
})
it("rejects invalid format", () => {
expect(isValidCidr("not-a-cidr")).toBe(false)
})
it("rejects octets > 255", () => {
expect(isValidCidr("256.0.0.0/16")).toBe(false)
})
})
@@ -0,0 +1,134 @@
// oxlint-disable no-bitwise
// oxlint-disable unicorn/prefer-math-trunc
// oxlint-disable no-plusplus
/**
* Subnet CIDR auto-calculation from a VPC CIDR block.
*
* Strategy: public subnets start from the beginning of the VPC range,
* private subnets start from the midpoint. Each subnet gets a /20 within
* a /16 VPC (adjusted proportionally for other prefix lengths).
*/
/** Parse a CIDR string into its network address (as a 32-bit number) and prefix length. */
export function parseCidr(cidr: string): { network: number; prefix: number } {
const parts = cidr.split("/")
const ip = parts[0] ?? ""
const prefixStr = parts[1] ?? "0"
const prefix = Number.parseInt(prefixStr, 10)
const octets = ip.split(".").map((o) => Number.parseInt(o, 10))
const o0 = octets[0] ?? 0
const o1 = octets[1] ?? 0
const o2 = octets[2] ?? 0
const o3 = octets[3] ?? 0
const network = ((o0 << 24) | (o1 << 16) | (o2 << 8) | o3) >>> 0
// Mask to the prefix length to normalise
const mask = prefix === 0 ? 0 : (0xff_ff_ff_ff << (32 - prefix)) >>> 0
return { network: (network & mask) >>> 0, prefix }
}
/** Convert a 32-bit number back to dotted-quad notation. */
export function numberToIp(n: number): string {
return `${(n >>> 24) & 0xff}.${(n >>> 16) & 0xff}.${(n >>> 8) & 0xff}.${n & 0xff}`
}
/** Return the number of host addresses in a CIDR block. */
export function cidrSize(prefix: number): number {
return 2 ** (32 - prefix)
}
/**
* Calculate subnet prefix length given the VPC prefix and total number of
* subnets (public + private). Each half of the address space is divided among
* its subnet type, with each subnet getting a /20 for a /16 VPC. The prefix
* is capped so subnets never exceed /28.
*/
export function subnetPrefix(vpcPrefix: number): number {
// Each subnet gets a /20 in a /16 VPC -> offset of 4 bits from VPC prefix
const sub = vpcPrefix + 4
return Math.min(sub, 28)
}
export interface SubnetCidr {
cidr: string
label: string
}
/**
* Calculate default subnet CIDRs for a VPC.
*
* Public subnets occupy the first half of the VPC address space,
* private subnets occupy the second half.
*/
export function calculateSubnetCidrs(
vpcCidr: string,
publicCount: number,
privateCount: number,
): { publicSubnets: SubnetCidr[]; privateSubnets: SubnetCidr[] } {
const { network, prefix: vpcPrefix } = parseCidr(vpcCidr)
const subPrefix = subnetPrefix(vpcPrefix)
const subSize = cidrSize(subPrefix)
const halfOffset = cidrSize(vpcPrefix) / 2
const publicSubnets: SubnetCidr[] = []
for (let i = 0; i < publicCount; i++) {
const addr = (network + i * subSize) >>> 0
publicSubnets.push({
cidr: `${numberToIp(addr)}/${subPrefix}`,
label: `Public Subnet ${i + 1}`,
})
}
const privateSubnets: SubnetCidr[] = []
for (let i = 0; i < privateCount; i++) {
const addr = (network + halfOffset + i * subSize) >>> 0
privateSubnets.push({
cidr: `${numberToIp(addr)}/${subPrefix}`,
label: `Private Subnet ${i + 1}`,
})
}
return { publicSubnets, privateSubnets }
}
/** Check whether two CIDR blocks overlap. */
export function cidrsOverlap(a: string, b: string): boolean {
const cidrA = parseCidr(a)
const cidrB = parseCidr(b)
const endA = (cidrA.network + cidrSize(cidrA.prefix) - 1) >>> 0
const endB = (cidrB.network + cidrSize(cidrB.prefix) - 1) >>> 0
return cidrA.network <= endB && cidrB.network <= endA
}
/** Check that a subnet CIDR fits entirely within a VPC CIDR. */
export function cidrContains(vpcCidr: string, subnetCidr: string): boolean {
const vpc = parseCidr(vpcCidr)
const sub = parseCidr(subnetCidr)
const vpcEnd = (vpc.network + cidrSize(vpc.prefix) - 1) >>> 0
const subEnd = (sub.network + cidrSize(sub.prefix) - 1) >>> 0
return sub.network >= vpc.network && subEnd <= vpcEnd
}
/** Validate a CIDR string for basic format and prefix range. */
export function isValidCidr(
cidr: string,
minPrefix = 16,
maxPrefix = 28,
): boolean {
const match = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\/(\d{1,2})$/.exec(
cidr,
)
if (!match) {
return false
}
const octets = [
Number.parseInt(match[1] ?? "0", 10),
Number.parseInt(match[2] ?? "0", 10),
Number.parseInt(match[3] ?? "0", 10),
Number.parseInt(match[4] ?? "0", 10),
]
if (octets.some((o) => o > 255)) {
return false
}
const prefix = Number.parseInt(match[5] ?? "0", 10)
return prefix >= minPrefix && prefix <= maxPrefix
}
@@ -20,6 +20,7 @@ import {
useCreateSubnet,
useCreateVolume,
useCreateVpc,
useCreateVpcWizard,
useDeleteKeyPair,
useDeletePlacementGroup,
useDeleteSnapshot,
@@ -37,6 +38,8 @@ import {
useTerminateInstance,
} from "./ec2"
import type { CreateVpcWizardFormData } from "@/types/ec2"
let queryClient: QueryClient
function wrapper({ children }: { children: ReactNode }) {
@@ -613,3 +616,209 @@ describe("useDeletePlacementGroup", () => {
})
})
})
describe("useCreateVpcWizard", () => {
const baseParams: CreateVpcWizardFormData = {
mode: "vpc-only",
namePrefix: "test",
autoGenerateNames: true,
cidrBlock: "10.0.0.0/16",
tenancy: "default",
publicSubnetCount: 0,
privateSubnetCount: 0,
publicSubnetCidrs: [],
privateSubnetCidrs: [],
tags: [],
}
it("sends only CreateVpcCommand in vpc-only mode", async () => {
createQueryClient()
mockSend.mockResolvedValueOnce({
Vpc: { VpcId: "vpc-111" },
})
const { result } = renderHook(() => useCreateVpcWizard(), { wrapper })
result.current.mutate(baseParams)
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(mockSend).toHaveBeenCalledOnce()
expect(mockSend.mock.calls[0]?.[0].input.CidrBlock).toBe("10.0.0.0/16")
expect(result.current.data?.vpcId).toBe("vpc-111")
expect(result.current.data?.created).toHaveLength(1)
})
it("includes TagSpecifications with auto-generated name", async () => {
createQueryClient()
mockSend.mockResolvedValueOnce({
Vpc: { VpcId: "vpc-111" },
})
const { result } = renderHook(() => useCreateVpcWizard(), { wrapper })
result.current.mutate({
...baseParams,
namePrefix: "proj",
autoGenerateNames: true,
})
await waitFor(() => expect(result.current.isSuccess).toBe(true))
const tags = mockSend.mock.calls[0]?.[0].input.TagSpecifications
expect(tags?.[0]?.Tags).toContainEqual({
Key: "Name",
Value: "proj-vpc",
})
})
it("sends correct command sequence for vpc-and-more with 1 public + 1 private", async () => {
createQueryClient()
mockSend
.mockResolvedValueOnce({ Vpc: { VpcId: "vpc-111" } })
.mockResolvedValueOnce({ Subnet: { SubnetId: "subnet-pub-1" } })
.mockResolvedValueOnce({ Subnet: { SubnetId: "subnet-priv-1" } })
.mockResolvedValueOnce({
InternetGateway: { InternetGatewayId: "igw-111" },
})
.mockResolvedValueOnce({}) // AttachInternetGateway
.mockResolvedValueOnce({
RouteTable: { RouteTableId: "rtb-pub-1" },
})
.mockResolvedValueOnce({}) // CreateRoute
.mockResolvedValueOnce({}) // AssociateRouteTable (public)
.mockResolvedValueOnce({
RouteTable: { RouteTableId: "rtb-priv-1" },
})
.mockResolvedValueOnce({}) // AssociateRouteTable (private)
const { result } = renderHook(() => useCreateVpcWizard(), { wrapper })
result.current.mutate({
...baseParams,
mode: "vpc-and-more",
publicSubnetCount: 1,
privateSubnetCount: 1,
})
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(mockSend).toHaveBeenCalledTimes(10)
expect(result.current.data?.vpcId).toBe("vpc-111")
expect(result.current.data?.created).toHaveLength(6)
expect(result.current.data?.error).toBeUndefined()
})
it("skips IGW and public route table when publicSubnetCount is 0", async () => {
createQueryClient()
mockSend
.mockResolvedValueOnce({ Vpc: { VpcId: "vpc-111" } })
.mockResolvedValueOnce({ Subnet: { SubnetId: "subnet-priv-1" } })
.mockResolvedValueOnce({
RouteTable: { RouteTableId: "rtb-priv-1" },
})
.mockResolvedValueOnce({}) // AssociateRouteTable
const { result } = renderHook(() => useCreateVpcWizard(), { wrapper })
result.current.mutate({
...baseParams,
mode: "vpc-and-more",
publicSubnetCount: 0,
privateSubnetCount: 1,
})
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(mockSend).toHaveBeenCalledTimes(4)
const types = result.current.data?.created.map((r) => r.type)
expect(types).not.toContain("Internet Gateway")
expect(types).not.toContain("Public Route Table")
})
it("returns partial result with failedStep on error mid-orchestration", async () => {
createQueryClient()
mockSend
.mockResolvedValueOnce({ Vpc: { VpcId: "vpc-111" } })
.mockResolvedValueOnce({ Subnet: { SubnetId: "subnet-pub-1" } })
.mockRejectedValueOnce(new Error("CIDR conflict"))
const { result } = renderHook(() => useCreateVpcWizard(), { wrapper })
result.current.mutate({
...baseParams,
mode: "vpc-and-more",
publicSubnetCount: 1,
privateSubnetCount: 1,
})
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(result.current.data?.error?.message).toBe("CIDR conflict")
expect(result.current.data?.failedStep).toBe(
"Failed while creating private subnets",
)
expect(result.current.data?.vpcId).toBe("vpc-111")
expect(result.current.data?.created).toHaveLength(2)
})
it("returns error when VPC creation fails", async () => {
createQueryClient()
mockSend.mockRejectedValueOnce(new Error("Access denied"))
const { result } = renderHook(() => useCreateVpcWizard(), { wrapper })
result.current.mutate(baseParams)
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(result.current.data?.error?.message).toBe("Access denied")
expect(result.current.data?.failedStep).toBe(
"Failed while creating VPC",
)
expect(result.current.data?.vpcId).toBeUndefined()
expect(result.current.data?.created).toHaveLength(0)
})
it("returns error when VPC is created but no ID returned", async () => {
createQueryClient()
mockSend.mockResolvedValueOnce({ Vpc: {} })
const { result } = renderHook(() => useCreateVpcWizard(), { wrapper })
result.current.mutate(baseParams)
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(result.current.data?.error?.message).toContain(
"no VPC ID was returned",
)
expect(result.current.data?.failedStep).toBe(
"Failed while creating VPC",
)
})
it("invalidates related queries on success", async () => {
createQueryClient()
const spy = vi.spyOn(queryClient, "invalidateQueries")
mockSend.mockResolvedValueOnce({ Vpc: { VpcId: "vpc-111" } })
const { result } = renderHook(() => useCreateVpcWizard(), { wrapper })
result.current.mutate(baseParams)
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(spy).toHaveBeenCalledWith({ queryKey: ["ec2", "vpcs"] })
expect(spy).toHaveBeenCalledWith({ queryKey: ["ec2", "subnets"] })
expect(spy).toHaveBeenCalledWith({
queryKey: ["ec2", "internetGateways"],
})
expect(spy).toHaveBeenCalledWith({ queryKey: ["ec2", "routeTables"] })
})
it("propagates extra tags to all resources", async () => {
createQueryClient()
mockSend.mockResolvedValueOnce({ Vpc: { VpcId: "vpc-111" } })
const { result } = renderHook(() => useCreateVpcWizard(), { wrapper })
result.current.mutate({
...baseParams,
tags: [{ key: "Env", value: "prod" }],
})
await waitFor(() => expect(result.current.isSuccess).toBe(true))
const tags = mockSend.mock.calls[0]?.[0].input.TagSpecifications?.[0]?.Tags
expect(tags).toContainEqual({ Key: "Env", Value: "prod" })
})
})
@@ -1,11 +1,19 @@
import {
type _InstanceType,
type PlacementStrategy,
type Tag,
type TagSpecification,
type Tenancy,
AssociateRouteTableCommand,
AttachInternetGatewayCommand,
AttachVolumeCommand,
CopySnapshotCommand,
CreateImageCommand,
CreateInternetGatewayCommand,
CreateKeyPairCommand,
CreatePlacementGroupCommand,
CreateRouteCommand,
CreateRouteTableCommand,
CreateSnapshotCommand,
CreateSubnetCommand,
CreateVolumeCommand,
@@ -22,6 +30,7 @@ import {
ModifyInstanceAttributeCommand,
ModifyVolumeCommand,
RebootInstancesCommand,
ResourceType,
RunInstancesCommand,
StartInstancesCommand,
StopInstancesCommand,
@@ -30,6 +39,7 @@ import {
import { useMutation, useQueryClient } from "@tanstack/react-query"
import { getEc2Client } from "@/lib/awsClient"
import { calculateSubnetCidrs } from "@/lib/subnet-calculator"
import { ec2KeyPairsQueryOptions } from "@/queries/ec2"
import type {
AttachVolumeFormData,
@@ -42,6 +52,7 @@ import type {
CreateSubnetFormData,
CreateVolumeFormData,
CreateVpcFormData,
CreateVpcWizardFormData,
DetachVolumeFormData,
ImportKeyPairData,
ModifyInstanceTypeFormData,
@@ -472,3 +483,272 @@ export function useDeletePlacementGroup() {
},
})
}
function buildTags(name: string | undefined, extraTags: Tag[]): Tag[] {
const tags: Tag[] = []
if (name) {
tags.push({ Key: "Name", Value: name })
}
tags.push(...extraTags)
return tags
}
function buildTagSpec(
resourceType: ResourceType,
name: string | undefined,
extraTags: Tag[],
): TagSpecification[] | undefined {
const tags = buildTags(name, extraTags)
if (tags.length === 0) {
return undefined
}
return [{ ResourceType: resourceType, Tags: tags }]
}
export interface WizardCreatedResource {
type: string
id: string | undefined
}
export interface WizardResult {
vpcId: string | undefined
created: WizardCreatedResource[]
error?: Error
failedStep?: string
}
export function useCreateVpcWizard() {
const queryClient = useQueryClient()
return useMutation({
mutationFn: async (
params: CreateVpcWizardFormData,
): Promise<WizardResult> => {
const client = getEc2Client()
const created: WizardCreatedResource[] = []
const prefix = params.autoGenerateNames ? params.namePrefix : undefined
const extraTags: Tag[] = params.tags.map((t) => ({
Key: t.key,
Value: t.value,
}))
let currentStep = "creating VPC"
try {
// Step 1: Create VPC
const vpcName = prefix ? `${prefix}-vpc` : params.namePrefix
// oxlint-disable-next-line typescript/no-unsafe-type-assertion -- AWS SDK expects Tenancy enum
const tenancy = params.tenancy as Tenancy
const vpcResult = await client.send(
new CreateVpcCommand({
CidrBlock: params.cidrBlock,
InstanceTenancy: tenancy,
TagSpecifications: buildTagSpec(
ResourceType.vpc,
vpcName,
extraTags,
),
}),
)
const vpcId = vpcResult.Vpc?.VpcId
if (!vpcId) {
throw new Error(
"VPC was created but no VPC ID was returned by the API",
)
}
created.push({ type: "VPC", id: vpcId })
if (params.mode === "vpc-only") {
return { vpcId, created }
}
// Compute subnet CIDRs (use custom values if provided, else auto-calculate)
const defaults = calculateSubnetCidrs(
params.cidrBlock,
params.publicSubnetCount,
params.privateSubnetCount,
)
const publicCidrs =
params.publicSubnetCidrs.length > 0
? params.publicSubnetCidrs
: defaults.publicSubnets.map((s) => s.cidr)
const privateCidrs =
params.privateSubnetCidrs.length > 0
? params.privateSubnetCidrs
: defaults.privateSubnets.map((s) => s.cidr)
// Step 2: Create public subnets
currentStep = "creating public subnets"
const publicSubnetIds: string[] = []
for (let i = 0; i < params.publicSubnetCount; i += 1) {
const name = prefix ? `${prefix}-subnet-public-${i + 1}` : undefined
const result = await client.send(
new CreateSubnetCommand({
VpcId: vpcId,
CidrBlock: publicCidrs[i],
TagSpecifications: buildTagSpec(
ResourceType.subnet,
name,
extraTags,
),
}),
)
const subnetId = result.Subnet?.SubnetId
if (!subnetId) {
throw new Error(
`Public subnet ${i + 1} was created but no subnet ID was returned`,
)
}
publicSubnetIds.push(subnetId)
created.push({ type: "Public Subnet", id: subnetId })
}
// Step 3: Create private subnets
currentStep = "creating private subnets"
const privateSubnetIds: string[] = []
for (let i = 0; i < params.privateSubnetCount; i += 1) {
const name = prefix ? `${prefix}-subnet-private-${i + 1}` : undefined
const result = await client.send(
new CreateSubnetCommand({
VpcId: vpcId,
CidrBlock: privateCidrs[i],
TagSpecifications: buildTagSpec(
ResourceType.subnet,
name,
extraTags,
),
}),
)
const subnetId = result.Subnet?.SubnetId
if (!subnetId) {
throw new Error(
`Private subnet ${i + 1} was created but no subnet ID was returned`,
)
}
privateSubnetIds.push(subnetId)
created.push({ type: "Private Subnet", id: subnetId })
}
// Step 4: Create and attach internet gateway (if public subnets > 0)
if (params.publicSubnetCount > 0) {
currentStep = "creating internet gateway"
const igwName = prefix ? `${prefix}-igw` : undefined
const igwResult = await client.send(
new CreateInternetGatewayCommand({
TagSpecifications: buildTagSpec(
ResourceType.internet_gateway,
igwName,
extraTags,
),
}),
)
const igwId = igwResult.InternetGateway?.InternetGatewayId
if (!igwId) {
throw new Error(
"Internet gateway was created but no ID was returned",
)
}
created.push({ type: "Internet Gateway", id: igwId })
// Step 5: Attach IGW to VPC
currentStep = "attaching internet gateway to VPC"
await client.send(
new AttachInternetGatewayCommand({
InternetGatewayId: igwId,
VpcId: vpcId,
}),
)
// Step 6: Create public route table
currentStep = "creating public route table"
const rtbPubName = prefix ? `${prefix}-rtb-public` : undefined
const rtbPubResult = await client.send(
new CreateRouteTableCommand({
VpcId: vpcId,
TagSpecifications: buildTagSpec(
ResourceType.route_table,
rtbPubName,
extraTags,
),
}),
)
const pubRtbId = rtbPubResult.RouteTable?.RouteTableId
if (!pubRtbId) {
throw new Error(
"Public route table was created but no ID was returned",
)
}
created.push({ type: "Public Route Table", id: pubRtbId })
// Step 7: Add default route to IGW
currentStep = "creating default route to internet gateway"
await client.send(
new CreateRouteCommand({
RouteTableId: pubRtbId,
DestinationCidrBlock: "0.0.0.0/0",
GatewayId: igwId,
}),
)
// Step 8: Associate public subnets with public route table
currentStep = "associating public subnets with route table"
for (const subnetId of publicSubnetIds) {
await client.send(
new AssociateRouteTableCommand({
RouteTableId: pubRtbId,
SubnetId: subnetId,
}),
)
}
}
// Step 9: Create private route table (if private subnets > 0)
if (params.privateSubnetCount > 0) {
currentStep = "creating private route table"
const rtbPrivName = prefix ? `${prefix}-rtb-private` : undefined
const rtbPrivResult = await client.send(
new CreateRouteTableCommand({
VpcId: vpcId,
TagSpecifications: buildTagSpec(
ResourceType.route_table,
rtbPrivName,
extraTags,
),
}),
)
const privRtbId = rtbPrivResult.RouteTable?.RouteTableId
if (!privRtbId) {
throw new Error(
"Private route table was created but no ID was returned",
)
}
created.push({ type: "Private Route Table", id: privRtbId })
// Step 10: Associate private subnets with private route table
currentStep = "associating private subnets with route table"
for (const subnetId of privateSubnetIds) {
await client.send(
new AssociateRouteTableCommand({
RouteTableId: privRtbId,
SubnetId: subnetId,
}),
)
}
}
return { vpcId, created }
} catch (error) {
return {
vpcId: created.find((r) => r.type === "VPC")?.id,
created,
error: error instanceof Error ? error : new Error(String(error)),
failedStep: `Failed while ${currentStep}`,
}
}
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["ec2", "vpcs"] })
queryClient.invalidateQueries({ queryKey: ["ec2", "subnets"] })
queryClient.invalidateQueries({ queryKey: ["ec2", "internetGateways"] })
queryClient.invalidateQueries({ queryKey: ["ec2", "routeTables"] })
},
})
}
@@ -3,9 +3,11 @@ import {
DescribeImagesCommand,
DescribeInstancesCommand,
DescribeInstanceTypesCommand,
DescribeInternetGatewaysCommand,
DescribeKeyPairsCommand,
DescribePlacementGroupsCommand,
DescribeRegionsCommand,
DescribeRouteTablesCommand,
DescribeSnapshotsCommand,
DescribeSubnetsCommand,
DescribeVolumesCommand,
@@ -151,6 +153,22 @@ export const ec2SnapshotQueryOptions = (snapshotId: string) =>
refetchInterval: 5000,
})
export const ec2InternetGatewaysQueryOptions = queryOptions({
queryKey: ["ec2", "internetGateways"],
queryFn: () => {
const command = new DescribeInternetGatewaysCommand({})
return getEc2Client().send(command)
},
})
export const ec2RouteTablesQueryOptions = queryOptions({
queryKey: ["ec2", "routeTables"],
queryFn: () => {
const command = new DescribeRouteTablesCommand({})
return getEc2Client().send(command)
},
})
export const ec2VpcsQueryOptions = queryOptions({
queryKey: ["ec2", "vpcs"],
queryFn: () => {
@@ -41,8 +41,8 @@ function Images() {
badge={<StateBadge state={image.State} />}
key={image.ImageId}
params={{ id: image.ImageId }}
subtitle={image.Name}
title={image.ImageId}
subtitle={image.ImageId ?? ""}
title={image.Name ?? image.ImageId ?? ""}
to="/ec2/describe-images/$id"
/>
)
@@ -71,7 +71,7 @@ function Ec2() {
badge={<StateBadge state={instance.State?.Name} />}
key={instance.InstanceId}
params={{ id: instance.InstanceId }}
subtitle={`${instance.InstanceType} • ${instance.ImageId}`}
subtitle={`${instance.InstanceType}`}
title={instance.InstanceId}
to="/ec2/describe-instances/$id"
/>
@@ -90,8 +90,8 @@ function KeyPairDetail() {
<DetailCard>
<DetailCard.Header>Key Pair Information</DetailCard.Header>
<DetailCard.Content>
<DetailRow label="Key Name" value={keyPair.KeyName} />
<DetailRow label="Key Pair ID" value={keyPair.KeyPairId} />
<DetailRow label="Key Name" value={keyPair.KeyName} />
<DetailRow label="Key Type" value={keyPair.KeyType} />
<DetailRow label="Key Fingerprint" value={keyPair.KeyFingerprint} />
<DetailRow label="Creation Date" value={createTime} />
@@ -56,7 +56,7 @@ function KeyPairs() {
<ListCard
key={keyPair.KeyPairId}
params={{ id: keyPair.KeyPairId }}
subtitle={`${keyPair.KeyPairId} • ${keyPair.KeyType}`}
subtitle={keyPair.KeyPairId ?? ""}
title={keyPair.KeyName ?? ""}
to="/ec2/describe-key-pairs/$id"
/>
@@ -49,7 +49,7 @@ function Volumes() {
badge={<StateBadge state={volume.State} />}
key={volume.VolumeId}
params={{ id: volume.VolumeId }}
subtitle={`${volume.Size} GiB • ${volume.VolumeType}`}
subtitle={`${volume.Size} GiB`}
title={volume.VolumeId}
to="/ec2/describe-volumes/$id"
/>
@@ -1,15 +1,34 @@
import { zodResolver } from "@hookform/resolvers/zod"
import { createFileRoute, useNavigate } from "@tanstack/react-router"
import { useForm } from "react-hook-form"
import { useState } from "react"
import { Controller, useForm } from "react-hook-form"
import { BackLink } from "@/components/back-link"
import { ErrorBanner } from "@/components/error-banner"
import { FormActions } from "@/components/form-actions"
import { PageHeading } from "@/components/page-heading"
import { Button } from "@/components/ui/button"
import { Field, FieldError, FieldTitle } from "@/components/ui/field"
import { Input } from "@/components/ui/input"
import { useCreateVpc } from "@/mutations/ec2"
import { type CreateVpcFormData, createVpcSchema } from "@/types/ec2"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
import { SubnetCidrInputs } from "@/components/vpc-wizard/subnet-cidr-inputs"
import { VpcPreview } from "@/components/vpc-wizard/vpc-preview"
import { calculateSubnetCidrs } from "@/lib/subnet-calculator"
import {
type WizardResult,
useCreateVpc,
useCreateVpcWizard,
} from "@/mutations/ec2"
import {
type CreateVpcWizardFormData,
createVpcWizardSchema,
} from "@/types/ec2"
export const Route = createFileRoute("/_auth/ec2/(vpc)/create-vpc")({
head: () => ({
@@ -22,71 +41,315 @@ export const Route = createFileRoute("/_auth/ec2/(vpc)/create-vpc")({
component: CreateVpc,
})
const PUBLIC_SUBNET_COUNTS = [0, 1] as const
const PRIVATE_SUBNET_COUNTS = [0, 1, 2] as const
function CreateVpc() {
const navigate = useNavigate()
const createMutation = useCreateVpc()
const createVpcMutation = useCreateVpc()
const wizardMutation = useCreateVpcWizard()
const [wizardResult, setWizardResult] = useState<WizardResult | null>(null)
const form = useForm<CreateVpcWizardFormData>({
resolver: zodResolver(createVpcWizardSchema),
defaultValues: {
mode: "vpc-only",
namePrefix: "",
autoGenerateNames: true,
cidrBlock: "10.0.0.0/16",
tenancy: "default",
publicSubnetCount: 1,
privateSubnetCount: 1,
publicSubnetCidrs: [],
privateSubnetCidrs: [],
tags: [],
},
})
const {
handleSubmit,
register,
watch,
control,
formState: { errors, isSubmitting },
} = useForm<CreateVpcFormData>({
resolver: zodResolver(createVpcSchema),
defaultValues: {
cidrBlock: "10.0.0.0/16",
name: "",
},
})
} = form
const onSubmit = async (data: CreateVpcFormData) => {
const result = await createMutation.mutateAsync(data)
const vpcId = result.Vpc?.VpcId
if (vpcId) {
navigate({ to: "/ec2/describe-vpcs/$id", params: { id: vpcId } })
} else {
navigate({ to: "/ec2/describe-vpcs" })
const mode = watch("mode")
const cidrBlock = watch("cidrBlock")
const publicSubnetCount = watch("publicSubnetCount")
const privateSubnetCount = watch("privateSubnetCount")
// Compute preview subnet CIDRs
const subnetCidrs = calculateSubnetCidrs(
cidrBlock || "10.0.0.0/16",
mode === "vpc-and-more" ? publicSubnetCount : 0,
mode === "vpc-and-more" ? privateSubnetCount : 0,
)
const [progressMessage, setProgressMessage] = useState("")
const onSubmit = async (data: CreateVpcWizardFormData) => {
setWizardResult(null)
if (data.mode === "vpc-only") {
const name =
data.autoGenerateNames && data.namePrefix
? `${data.namePrefix}-vpc`
: data.namePrefix
const result = await createVpcMutation.mutateAsync({
cidrBlock: data.cidrBlock,
// oxlint-disable-next-line typescript/prefer-nullish-coalescing
name: name || undefined,
})
const vpcId = result.Vpc?.VpcId
if (vpcId) {
navigate({ to: "/ec2/describe-vpcs/$id", params: { id: vpcId } })
} else {
navigate({ to: "/ec2/describe-vpcs" })
}
return
}
// VPC and more mode
setProgressMessage("Creating VPC and resources...")
const result = await wizardMutation.mutateAsync(data)
setWizardResult(result)
if (!result.error && result.vpcId) {
navigate({ to: "/ec2/describe-vpcs/$id", params: { id: result.vpcId } })
}
setProgressMessage("")
}
const mutationError = createVpcMutation.error ?? wizardMutation.error
const isPending = createVpcMutation.isPending || wizardMutation.isPending
return (
<>
<BackLink to="/ec2/describe-vpcs">Back to VPCs</BackLink>
<PageHeading title="Create VPC" />
{createMutation.error && (
<ErrorBanner error={createMutation.error} msg="Failed to create VPC" />
{mutationError && (
<ErrorBanner error={mutationError} msg="Failed to create VPC" />
)}
<form className="max-w-4xl space-y-6" onSubmit={handleSubmit(onSubmit)}>
<Field>
<FieldTitle>
<label htmlFor="cidrBlock">CIDR Block</label>
</FieldTitle>
<Input
aria-invalid={!!errors.cidrBlock}
id="cidrBlock"
placeholder="10.0.0.0/16"
{...register("cidrBlock")}
{wizardResult?.error && (
<div className="mb-6 max-w-4xl rounded-md border border-destructive bg-destructive/10 p-4">
<h2 className="text-sm font-medium text-destructive">
Wizard failed: {wizardResult.failedStep}
</h2>
<p className="mt-1 text-sm text-destructive">
{wizardResult.error.message}
</p>
{wizardResult.created.length > 0 && (
<div className="mt-3">
<p className="text-xs font-medium text-destructive">
Successfully created resources:
</p>
<ul className="mt-1 list-inside list-disc text-xs text-destructive">
{wizardResult.created.map((r, i) => (
// oxlint-disable-next-line react/no-array-index-key -- error list with no stable id
<li key={i}>
{r.type}: {r.id}
</li>
))}
</ul>
</div>
)}
</div>
)}
{progressMessage && (
<div className="mb-4 max-w-4xl text-sm text-muted-foreground">
{progressMessage}
</div>
)}
<div className="flex max-w-6xl gap-8">
{/* Left column: Form */}
<form
className="min-w-0 flex-1 space-y-6"
onSubmit={handleSubmit(onSubmit)}
>
{/* Section 1: Resources to create */}
<Field>
<FieldTitle>Resources to create</FieldTitle>
<Controller
control={control}
name="mode"
render={({ field }) => (
<div className="flex gap-4">
<label className="flex items-center gap-2 text-xs">
<input
checked={field.value === "vpc-only"}
name="mode"
onChange={() => field.onChange("vpc-only")}
type="radio"
/>
VPC only
</label>
<label className="flex items-center gap-2 text-xs">
<input
checked={field.value === "vpc-and-more"}
name="mode"
onChange={() => field.onChange("vpc-and-more")}
type="radio"
/>
VPC and more
</label>
</div>
)}
/>
</Field>
{/* Section 2: Name tag auto-generation */}
<Field>
<FieldTitle>
<label htmlFor="namePrefix">Name tag auto-generation</label>
</FieldTitle>
<div className="flex items-center gap-3">
<Input
id="namePrefix"
placeholder="project"
{...register("namePrefix")}
/>
<Controller
control={control}
name="autoGenerateNames"
render={({ field }) => (
<label className="flex shrink-0 items-center gap-2 text-xs">
<input
checked={field.value}
onChange={(e) => field.onChange(e.target.checked)}
type="checkbox"
/>
Auto-generate
</label>
)}
/>
</div>
</Field>
{/* Section 3: CIDR Block */}
<Field>
<FieldTitle>
<label htmlFor="cidrBlock">IPv4 CIDR block</label>
</FieldTitle>
<Input
aria-invalid={!!errors.cidrBlock}
id="cidrBlock"
placeholder="10.0.0.0/16"
{...register("cidrBlock")}
/>
<FieldError errors={[errors.cidrBlock]} />
</Field>
{/* Section 4: Tenancy */}
<Field>
<FieldTitle>Tenancy</FieldTitle>
<Controller
control={control}
name="tenancy"
render={({ field }) => (
<Select onValueChange={field.onChange} value={field.value}>
<SelectTrigger id="tenancy">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="default">default</SelectItem>
<SelectItem value="dedicated">dedicated</SelectItem>
</SelectContent>
</Select>
)}
/>
</Field>
{/* VPC and more sections */}
{mode === "vpc-and-more" && (
<>
{/* Section 5: Public Subnets */}
<Field>
<FieldTitle>Number of public subnets</FieldTitle>
<Controller
control={control}
name="publicSubnetCount"
render={({ field }) => (
<div className="flex gap-1">
{PUBLIC_SUBNET_COUNTS.map((n) => (
<Button
key={n}
onClick={() => field.onChange(n)}
size="sm"
type="button"
variant={field.value === n ? "default" : "outline"}
>
{n}
</Button>
))}
</div>
)}
/>
<SubnetCidrInputs
count={publicSubnetCount}
defaults={subnetCidrs.publicSubnets.map((s) => s.cidr)}
form={form}
type="public"
/>
</Field>
{/* Section 6: Private Subnets */}
<Field>
<FieldTitle>Number of private subnets</FieldTitle>
<Controller
control={control}
name="privateSubnetCount"
render={({ field }) => (
<div className="flex gap-1">
{PRIVATE_SUBNET_COUNTS.map((n) => (
<Button
key={n}
onClick={() => field.onChange(n)}
size="sm"
type="button"
variant={field.value === n ? "default" : "outline"}
>
{n}
</Button>
))}
</div>
)}
/>
<SubnetCidrInputs
count={privateSubnetCount}
defaults={subnetCidrs.privateSubnets.map((s) => s.cidr)}
form={form}
type="private"
/>
</Field>
</>
)}
<FormActions
isPending={isPending}
isSubmitting={isSubmitting}
onCancel={() => navigate({ to: "/ec2/describe-vpcs" })}
pendingLabel="Creating\u2026"
submitLabel="Create VPC"
/>
<FieldError errors={[errors.cidrBlock]} />
</Field>
</form>
<Field>
<FieldTitle>
<label htmlFor="name">Name (optional)</label>
</FieldTitle>
<Input id="name" placeholder="my-vpc" {...register("name")} />
</Field>
<FormActions
isPending={createMutation.isPending}
isSubmitting={isSubmitting}
onCancel={() => navigate({ to: "/ec2/describe-vpcs" })}
pendingLabel="Creating\u2026"
submitLabel="Create VPC"
/>
</form>
{/* Right column: Preview */}
<div className="hidden min-w-0 flex-1 lg:block">
<VpcPreview
hasIgw={mode === "vpc-and-more" && publicSubnetCount > 0}
mode={mode}
privateSubnets={subnetCidrs.privateSubnets}
publicSubnets={subnetCidrs.publicSubnets}
vpcCidr={cidrBlock || "10.0.0.0/16"}
/>
</div>
</div>
</>
)
}
@@ -5,7 +5,6 @@ import { createFileRoute, Link } from "@tanstack/react-router"
import { ListCard } from "@/components/list-card"
import { PageHeading } from "@/components/page-heading"
import { Button } from "@/components/ui/button"
import { formatDateTime } from "@/lib/utils"
import { iamPoliciesQueryOptions } from "@/queries/iam"
export const Route = createFileRoute("/_auth/iam/(policies)/list-policies/")({
@@ -48,7 +47,7 @@ function Policies() {
<ListCard
key={policy.Arn}
params={{ policyArn: encodeURIComponent(policy.Arn) }}
subtitle={`${policy.Arn} • Created ${formatDateTime(policy.CreateDate)}`}
subtitle={policy.Arn ?? ""}
title={policy.PolicyName ?? ""}
to="/iam/list-policies/$policyArn"
/>
@@ -5,7 +5,6 @@ import { createFileRoute, Link } from "@tanstack/react-router"
import { ListCard } from "@/components/list-card"
import { PageHeading } from "@/components/page-heading"
import { Button } from "@/components/ui/button"
import { formatDateTime } from "@/lib/utils"
import { iamUsersQueryOptions } from "@/queries/iam"
export const Route = createFileRoute("/_auth/iam/(users)/list-users/")({
@@ -48,7 +47,7 @@ function Users() {
<ListCard
key={user.UserName}
params={{ userName: user.UserName }}
subtitle={`${user.UserId} • ${user.Path ?? "/"} • Created ${formatDateTime(user.CreateDate)}`}
subtitle={user.UserId ?? ""}
title={user.UserName}
to="/iam/list-users/$userName"
/>
@@ -10,6 +10,8 @@ import {
createSubnetSchema,
createVolumeSchema,
createVpcSchema,
createVpcWizardSchema,
formTagSchema,
importKeyPairSchema,
modifyVolumeSchema,
} from "./ec2"
@@ -323,3 +325,203 @@ describe("createPlacementGroupSchema", () => {
expect(result.success).toBe(false)
})
})
describe("formTagSchema", () => {
it("accepts valid tag with key and value", () => {
const result = formTagSchema.safeParse({ key: "Env", value: "prod" })
expect(result.success).toBe(true)
})
it("accepts tag with empty value", () => {
const result = formTagSchema.safeParse({ key: "Env", value: "" })
expect(result.success).toBe(true)
})
it("rejects tag with empty key", () => {
const result = formTagSchema.safeParse({ key: "", value: "prod" })
expect(result.success).toBe(false)
})
})
describe("createVpcWizardSchema", () => {
const validBase = {
mode: "vpc-only" as const,
namePrefix: "test",
autoGenerateNames: true,
cidrBlock: "10.0.0.0/16",
tenancy: "default" as const,
publicSubnetCount: 0,
privateSubnetCount: 0,
publicSubnetCidrs: [],
privateSubnetCidrs: [],
tags: [],
}
it("accepts valid vpc-only mode with minimal fields", () => {
const result = createVpcWizardSchema.safeParse(validBase)
expect(result.success).toBe(true)
})
it("accepts valid vpc-and-more mode", () => {
const result = createVpcWizardSchema.safeParse({
...validBase,
mode: "vpc-and-more",
publicSubnetCount: 1,
privateSubnetCount: 1,
})
expect(result.success).toBe(true)
})
it("rejects invalid mode", () => {
const result = createVpcWizardSchema.safeParse({
...validBase,
mode: "invalid",
})
expect(result.success).toBe(false)
})
it("rejects empty CIDR block", () => {
const result = createVpcWizardSchema.safeParse({
...validBase,
cidrBlock: "",
})
expect(result.success).toBe(false)
})
it("rejects invalid CIDR format", () => {
const result = createVpcWizardSchema.safeParse({
...validBase,
cidrBlock: "not-a-cidr",
})
expect(result.success).toBe(false)
})
it("rejects CIDR with out-of-range octets", () => {
const result = createVpcWizardSchema.safeParse({
...validBase,
cidrBlock: "999.0.0.0/16",
})
expect(result.success).toBe(false)
})
it("rejects CIDR with prefix out of /16-/28 range", () => {
const result = createVpcWizardSchema.safeParse({
...validBase,
cidrBlock: "10.0.0.0/8",
})
expect(result.success).toBe(false)
})
it("rejects invalid tenancy", () => {
const result = createVpcWizardSchema.safeParse({
...validBase,
tenancy: "shared",
})
expect(result.success).toBe(false)
})
it("rejects publicSubnetCount above 4", () => {
const result = createVpcWizardSchema.safeParse({
...validBase,
publicSubnetCount: 5,
})
expect(result.success).toBe(false)
})
it("rejects negative privateSubnetCount", () => {
const result = createVpcWizardSchema.safeParse({
...validBase,
privateSubnetCount: -1,
})
expect(result.success).toBe(false)
})
it("rejects fractional subnet count", () => {
const result = createVpcWizardSchema.safeParse({
...validBase,
publicSubnetCount: 1.5,
})
expect(result.success).toBe(false)
})
it("rejects invalid custom subnet CIDR in vpc-and-more mode", () => {
const result = createVpcWizardSchema.safeParse({
...validBase,
mode: "vpc-and-more",
publicSubnetCount: 1,
publicSubnetCidrs: ["not-a-cidr"],
})
expect(result.success).toBe(false)
})
it("rejects subnet CIDR outside VPC range", () => {
const result = createVpcWizardSchema.safeParse({
...validBase,
mode: "vpc-and-more",
publicSubnetCount: 1,
publicSubnetCidrs: ["192.168.0.0/20"],
})
expect(result.success).toBe(false)
if (!result.success) {
const issue = result.error.issues.find(
(i) => i.path[0] === "publicSubnetCidrs",
)
expect(issue?.message).toContain("within the VPC CIDR")
}
})
it("rejects overlapping subnet CIDRs", () => {
const result = createVpcWizardSchema.safeParse({
...validBase,
mode: "vpc-and-more",
publicSubnetCount: 1,
privateSubnetCount: 1,
publicSubnetCidrs: ["10.0.0.0/20"],
privateSubnetCidrs: ["10.0.0.0/20"],
})
expect(result.success).toBe(false)
if (!result.success) {
const issue = result.error.issues.find((i) =>
i.message.includes("overlap"),
)
expect(issue).toBeDefined()
}
})
it("accepts valid custom subnet CIDRs within VPC range", () => {
const result = createVpcWizardSchema.safeParse({
...validBase,
mode: "vpc-and-more",
publicSubnetCount: 1,
privateSubnetCount: 1,
publicSubnetCidrs: ["10.0.0.0/20"],
privateSubnetCidrs: ["10.0.128.0/20"],
})
expect(result.success).toBe(true)
})
it("skips subnet CIDR validation in vpc-only mode", () => {
const result = createVpcWizardSchema.safeParse({
...validBase,
mode: "vpc-only",
publicSubnetCidrs: ["not-a-cidr"],
})
expect(result.success).toBe(true)
})
it("accepts valid tags", () => {
const result = createVpcWizardSchema.safeParse({
...validBase,
tags: [{ key: "Env", value: "prod" }],
})
expect(result.success).toBe(true)
})
it("rejects tags with empty key", () => {
const result = createVpcWizardSchema.safeParse({
...validBase,
tags: [{ key: "", value: "prod" }],
})
expect(result.success).toBe(false)
})
})
@@ -1,5 +1,11 @@
import { z } from "zod"
import {
cidrContains,
cidrsOverlap,
isValidCidr,
} from "@/lib/subnet-calculator"
const CIDR_REGEX = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2}$/
const keyNameField = z
@@ -133,6 +139,93 @@ export const createVpcSchema = z.object({
export type CreateVpcFormData = z.infer<typeof createVpcSchema>
export const formTagSchema = z.object({
key: z.string().min(1, "Key is required"),
value: z.string(),
})
export type FormTag = z.infer<typeof formTagSchema>
export const createVpcWizardSchema = z
.object({
mode: z.enum(["vpc-only", "vpc-and-more"]),
namePrefix: z.string().optional(),
autoGenerateNames: z.boolean(),
cidrBlock: z
.string()
.min(1, "CIDR block is required")
.regex(CIDR_REGEX, "Must be a valid CIDR block (e.g. 10.0.0.0/16)")
.refine(
(cidr) => isValidCidr(cidr),
"CIDR has invalid octets or prefix length (must be /16 to /28)",
),
tenancy: z.enum(["default", "dedicated"]),
publicSubnetCount: z.number().int().min(0).max(1),
privateSubnetCount: z.number().int().min(0).max(2),
publicSubnetCidrs: z.array(z.string()),
privateSubnetCidrs: z.array(z.string()),
tags: z.array(formTagSchema),
})
.superRefine((data, ctx) => {
if (data.mode !== "vpc-and-more") return
const allCidrs: { cidr: string; field: string; index: number }[] = []
for (const [i, cidr] of data.publicSubnetCidrs.entries()) {
if (!isValidCidr(cidr, 16, 28)) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "Invalid subnet CIDR format or prefix length",
path: ["publicSubnetCidrs", i],
})
} else {
if (!cidrContains(data.cidrBlock, cidr)) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "Subnet CIDR must be within the VPC CIDR range",
path: ["publicSubnetCidrs", i],
})
}
allCidrs.push({ cidr, field: "publicSubnetCidrs", index: i })
}
}
for (const [i, cidr] of data.privateSubnetCidrs.entries()) {
if (!isValidCidr(cidr, 16, 28)) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "Invalid subnet CIDR format or prefix length",
path: ["privateSubnetCidrs", i],
})
} else {
if (!cidrContains(data.cidrBlock, cidr)) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "Subnet CIDR must be within the VPC CIDR range",
path: ["privateSubnetCidrs", i],
})
}
allCidrs.push({ cidr, field: "privateSubnetCidrs", index: i })
}
}
for (let i = 0; i < allCidrs.length; i++) {
for (let j = i + 1; j < allCidrs.length; j++) {
const a = allCidrs[i]
const b = allCidrs[j]
if (a && b && cidrsOverlap(a.cidr, b.cidr)) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "Subnet CIDRs must not overlap",
path: [b.field, b.index],
})
}
}
}
})
export type CreateVpcWizardFormData = z.infer<typeof createVpcWizardSchema>
export const createPlacementGroupSchema = z.object({
groupName: z
.string()