mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-15 17:11:30 +00:00
refactor(ui): type the form values the CLI panels read (#860)
This commit is contained in:
+34
-60
@@ -4,7 +4,12 @@ import { useQuery, useSuspenseQuery } from "@tanstack/react-query"
|
||||
import { useNavigate } from "@tanstack/react-router"
|
||||
import { ChevronDown } from "lucide-react"
|
||||
import { useEffect } from "react"
|
||||
import { Controller, useForm, useWatch } from "react-hook-form"
|
||||
import {
|
||||
Controller,
|
||||
useForm,
|
||||
type UseFormWatch,
|
||||
useWatch,
|
||||
} from "react-hook-form"
|
||||
|
||||
import { BackLink } from "@/components/back-link"
|
||||
import {
|
||||
@@ -935,21 +940,13 @@ function resolveTemplateVersion(
|
||||
}
|
||||
|
||||
function buildRunInstancesCommands(
|
||||
watch: (name?: string) => unknown,
|
||||
watch: UseFormWatch<CreateInstanceFormData>,
|
||||
vpcId: string | undefined,
|
||||
): CliCommand[] {
|
||||
const rawLaunchTemplateId = watch("launchTemplateId")
|
||||
const launchTemplateId =
|
||||
typeof rawLaunchTemplateId === "string" ? rawLaunchTemplateId : ""
|
||||
const launchTemplateId = watch("launchTemplateId") ?? ""
|
||||
if (launchTemplateId) {
|
||||
const rawTemplateVersion = watch("launchTemplateVersion")
|
||||
const templateVersion =
|
||||
typeof rawTemplateVersion === "string" && rawTemplateVersion
|
||||
? rawTemplateVersion
|
||||
: "$Default"
|
||||
const rawTemplateCount = watch("count")
|
||||
const templateCount =
|
||||
typeof rawTemplateCount === "number" ? rawTemplateCount : 0
|
||||
const templateVersion = watch("launchTemplateVersion") || "$Default"
|
||||
const templateCount = watch("count") ?? 0
|
||||
return [
|
||||
{
|
||||
label: "Run Instances",
|
||||
@@ -970,34 +967,16 @@ function buildRunInstancesCommands(
|
||||
]
|
||||
}
|
||||
|
||||
const rawImageId = watch("imageId")
|
||||
const imageId = typeof rawImageId === "string" ? rawImageId : ""
|
||||
const rawInstanceType = watch("instanceType")
|
||||
const instanceType =
|
||||
typeof rawInstanceType === "string" ? rawInstanceType : ""
|
||||
const rawKeyName = watch("keyName")
|
||||
const keyName = typeof rawKeyName === "string" ? rawKeyName : ""
|
||||
const rawSubnetId = watch("subnetId")
|
||||
const subnetId = typeof rawSubnetId === "string" ? rawSubnetId : ""
|
||||
const rawPlacementGroupName = watch("placementGroupName")
|
||||
const placementGroupName =
|
||||
typeof rawPlacementGroupName === "string" ? rawPlacementGroupName : ""
|
||||
const rawCount = watch("count")
|
||||
const count = typeof rawCount === "number" ? rawCount : 0
|
||||
const rawRootDeviceName = watch("rootDeviceName")
|
||||
const rootDeviceName =
|
||||
typeof rawRootDeviceName === "string" ? rawRootDeviceName : ""
|
||||
const rawRootVolumeSize = watch("rootVolumeSize")
|
||||
const rootVolumeSize =
|
||||
typeof rawRootVolumeSize === "number" ? rawRootVolumeSize : undefined
|
||||
const rawRootVolumeType = watch("rootVolumeType")
|
||||
const rootVolumeType =
|
||||
typeof rawRootVolumeType === "string" ? rawRootVolumeType : ""
|
||||
const rawRootDeleteOnTermination = watch("rootDeleteOnTermination")
|
||||
const rootDeleteOnTermination =
|
||||
typeof rawRootDeleteOnTermination === "boolean"
|
||||
? rawRootDeleteOnTermination
|
||||
: true
|
||||
const imageId = watch("imageId") ?? ""
|
||||
const instanceType = watch("instanceType") ?? ""
|
||||
const keyName = watch("keyName") ?? ""
|
||||
const subnetId = watch("subnetId") ?? ""
|
||||
const placementGroupName = watch("placementGroupName") ?? ""
|
||||
const count = watch("count") ?? 0
|
||||
const rootDeviceName = watch("rootDeviceName") ?? ""
|
||||
const rootVolumeSize = watch("rootVolumeSize")
|
||||
const rootVolumeType = watch("rootVolumeType")
|
||||
const rootDeleteOnTermination = watch("rootDeleteOnTermination")
|
||||
|
||||
const parts = [
|
||||
{
|
||||
@@ -1033,17 +1012,11 @@ function buildRunInstancesCommands(
|
||||
|
||||
// Security groups — create-new emits create + authorize commands and feeds
|
||||
// $SG_ID into run-instances; select-existing passes the chosen IDs.
|
||||
const rawSgMode = watch("securityGroupMode")
|
||||
const sgMode = typeof rawSgMode === "string" ? rawSgMode : "create"
|
||||
const rawNewSgName = watch("newSgName")
|
||||
const sgName = typeof rawNewSgName === "string" ? rawNewSgName : ""
|
||||
const rawNewSgDesc = watch("newSgDescription")
|
||||
const sgDesc = typeof rawNewSgDesc === "string" ? rawNewSgDesc : ""
|
||||
const rawRuleSource = watch("ruleSource")
|
||||
const ruleSource =
|
||||
typeof rawRuleSource === "string" ? rawRuleSource : "anywhere"
|
||||
const rawCustomCidr = watch("customCidr")
|
||||
const customCidr = typeof rawCustomCidr === "string" ? rawCustomCidr : ""
|
||||
const sgMode = watch("securityGroupMode") || "create"
|
||||
const sgName = watch("newSgName") ?? ""
|
||||
const sgDesc = watch("newSgDescription") ?? ""
|
||||
const ruleSource = watch("ruleSource") || "anywhere"
|
||||
const customCidr = watch("customCidr") ?? ""
|
||||
const sgCommands: CliCommand[] = []
|
||||
if (sgMode === "create") {
|
||||
sgCommands.push({
|
||||
@@ -1103,10 +1076,7 @@ function buildRunInstancesCommands(
|
||||
{ type: "value" as const, value: " $SG_ID" },
|
||||
)
|
||||
} else {
|
||||
const rawSgIds = watch("securityGroupIds")
|
||||
const sgIds = Array.isArray(rawSgIds)
|
||||
? rawSgIds.filter((id): id is string => typeof id === "string")
|
||||
: []
|
||||
const sgIds = watch("securityGroupIds") ?? []
|
||||
if (sgIds.length > 0) {
|
||||
parts.push(
|
||||
{ type: "flag" as const, value: " \\\n --security-group-ids" },
|
||||
@@ -1117,17 +1087,21 @@ function buildRunInstancesCommands(
|
||||
|
||||
const hasStorageOverride =
|
||||
rootVolumeSize !== undefined ||
|
||||
rawRootVolumeType !== undefined ||
|
||||
rawRootDeleteOnTermination !== undefined
|
||||
rootVolumeType !== undefined ||
|
||||
rootDeleteOnTermination !== undefined
|
||||
if (hasStorageOverride) {
|
||||
const ebs: Record<string, unknown> = {}
|
||||
const ebs: {
|
||||
VolumeSize?: number
|
||||
VolumeType?: string
|
||||
DeleteOnTermination?: boolean
|
||||
} = {}
|
||||
if (rootVolumeSize !== undefined) {
|
||||
ebs.VolumeSize = rootVolumeSize
|
||||
}
|
||||
if (rootVolumeType) {
|
||||
ebs.VolumeType = rootVolumeType
|
||||
}
|
||||
if (rawRootDeleteOnTermination !== undefined) {
|
||||
if (rootDeleteOnTermination !== undefined) {
|
||||
ebs.DeleteOnTermination = rootDeleteOnTermination
|
||||
}
|
||||
const bdm = JSON.stringify([
|
||||
|
||||
+10
-8
@@ -1,7 +1,12 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { useNavigate } from "@tanstack/react-router"
|
||||
import { useState } from "react"
|
||||
import { Controller, useForm, useWatch } from "react-hook-form"
|
||||
import {
|
||||
Controller,
|
||||
type DeepPartialSkipArrayKey,
|
||||
useForm,
|
||||
useWatch,
|
||||
} from "react-hook-form"
|
||||
|
||||
import { BackLink } from "@/components/back-link"
|
||||
import {
|
||||
@@ -51,8 +56,6 @@ export function CreateKeyPairPage() {
|
||||
})
|
||||
|
||||
const values = useWatch({ control })
|
||||
const cliWatch = (name?: string): unknown =>
|
||||
name ? (values as Record<string, unknown>)[name] : undefined
|
||||
|
||||
const onSubmit = async (data: CreateKeyPairData) => {
|
||||
const response = await createMutation.mutateAsync(data)
|
||||
@@ -127,7 +130,7 @@ export function CreateKeyPairPage() {
|
||||
<FieldError errors={[errors.keyType]} />
|
||||
</Field>
|
||||
|
||||
<CliCommandPanel commands={buildCreateKeyPairCommands(cliWatch)} />
|
||||
<CliCommandPanel commands={buildCreateKeyPairCommands(values)} />
|
||||
|
||||
{/* Actions */}
|
||||
<FormActions
|
||||
@@ -154,11 +157,10 @@ export function CreateKeyPairPage() {
|
||||
}
|
||||
|
||||
function buildCreateKeyPairCommands(
|
||||
watch: (name?: string) => unknown,
|
||||
values: DeepPartialSkipArrayKey<CreateKeyPairData>,
|
||||
): CliCommand[] {
|
||||
const rawKeyName = watch("keyName")
|
||||
const keyName = typeof rawKeyName === "string" ? rawKeyName : ""
|
||||
const rawKeyType = watch("keyType")
|
||||
const keyName = values.keyName ?? ""
|
||||
const rawKeyType = values.keyType
|
||||
const keyType = typeof rawKeyType === "string" ? rawKeyType : "rsa"
|
||||
|
||||
return [
|
||||
|
||||
+8
-7
@@ -1,6 +1,10 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { createFileRoute, useNavigate } from "@tanstack/react-router"
|
||||
import { useForm, useWatch } from "react-hook-form"
|
||||
import {
|
||||
type DeepPartialSkipArrayKey,
|
||||
useForm,
|
||||
useWatch,
|
||||
} from "react-hook-form"
|
||||
|
||||
import { BackLink } from "@/components/back-link"
|
||||
import {
|
||||
@@ -41,8 +45,6 @@ function ImportKeyPair() {
|
||||
})
|
||||
|
||||
const values = useWatch({ control })
|
||||
const cliWatch = (name?: string): unknown =>
|
||||
name ? (values as Record<string, unknown>)[name] : undefined
|
||||
|
||||
const onSubmit = async (data: ImportKeyPairData) => {
|
||||
await importMutation.mutateAsync(data)
|
||||
@@ -98,7 +100,7 @@ function ImportKeyPair() {
|
||||
<FieldError errors={[errors.publicKeyMaterial]} />
|
||||
</Field>
|
||||
|
||||
<CliCommandPanel commands={buildImportKeyPairCommands(cliWatch)} />
|
||||
<CliCommandPanel commands={buildImportKeyPairCommands(values)} />
|
||||
|
||||
{/* Actions */}
|
||||
<FormActions
|
||||
@@ -116,10 +118,9 @@ function ImportKeyPair() {
|
||||
}
|
||||
|
||||
function buildImportKeyPairCommands(
|
||||
watch: (name?: string) => unknown,
|
||||
values: DeepPartialSkipArrayKey<ImportKeyPairData>,
|
||||
): CliCommand[] {
|
||||
const rawKeyName = watch("keyName")
|
||||
const keyName = typeof rawKeyName === "string" ? rawKeyName : ""
|
||||
const keyName = values.keyName ?? ""
|
||||
|
||||
return [
|
||||
{
|
||||
|
||||
+23
-42
@@ -3,7 +3,12 @@ import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { useSuspenseQuery } from "@tanstack/react-query"
|
||||
import { useNavigate } from "@tanstack/react-router"
|
||||
import { useState } from "react"
|
||||
import { Controller, useForm, useWatch } from "react-hook-form"
|
||||
import {
|
||||
Controller,
|
||||
useForm,
|
||||
type UseFormWatch,
|
||||
useWatch,
|
||||
} from "react-hook-form"
|
||||
|
||||
import { BackLink } from "@/components/back-link"
|
||||
import {
|
||||
@@ -790,35 +795,20 @@ export function CreateLoadBalancerPage() {
|
||||
}
|
||||
|
||||
function buildCreateLbCommands(
|
||||
watch: (name?: string) => unknown,
|
||||
tgWatch: (name?: string) => unknown,
|
||||
watch: UseFormWatch<CreateLoadBalancerFormData>,
|
||||
tgWatch: UseFormWatch<CreateTargetGroupFormData>,
|
||||
): CliCommand[] {
|
||||
const asString = (key: string): string => {
|
||||
const raw = watch(key)
|
||||
return typeof raw === "string" ? raw : ""
|
||||
}
|
||||
const asStringArray = (key: string): string[] => {
|
||||
const raw = watch(key)
|
||||
return Array.isArray(raw)
|
||||
? raw.filter((v): v is string => typeof v === "string")
|
||||
: []
|
||||
}
|
||||
const asNumber = (key: string): number | undefined => {
|
||||
const raw = watch(key)
|
||||
return typeof raw === "number" && Number.isFinite(raw) ? raw : undefined
|
||||
}
|
||||
|
||||
const name = asString("name") || "<Name>"
|
||||
const lbTypeValue = asString("type") || "application"
|
||||
const scheme = asString("scheme") || "internet-facing"
|
||||
const subnets = asStringArray("subnetIds")
|
||||
const sgs = asStringArray("securityGroupIds")
|
||||
const listenerProtocol = asString("listener.protocol") || "HTTP"
|
||||
const listenerPort = asNumber("listener.port") ?? 80
|
||||
const certificateArn = asString("listener.certificateArn")
|
||||
const sslPolicy = asString("listener.sslPolicy")
|
||||
const tgMode = asString("listener.targetGroupMode")
|
||||
const existingTgArn = asString("listener.existingTargetGroupArn")
|
||||
const name = watch("name") || "<Name>"
|
||||
const lbTypeValue = watch("type") || "application"
|
||||
const scheme = watch("scheme") || "internet-facing"
|
||||
const subnets = watch("subnetIds")
|
||||
const sgs = watch("securityGroupIds")
|
||||
const listenerProtocol = watch("listener.protocol") || "HTTP"
|
||||
const listenerPort = watch("listener.port") ?? 80
|
||||
const certificateArn = watch("listener.certificateArn")
|
||||
const sslPolicy = watch("listener.sslPolicy")
|
||||
const tgMode = watch("listener.targetGroupMode")
|
||||
const existingTgArn = watch("listener.existingTargetGroupArn")
|
||||
|
||||
const commands: CliCommand[] = []
|
||||
const comment: CommandPart = {
|
||||
@@ -829,21 +819,12 @@ function buildCreateLbCommands(
|
||||
: "# Create ALB with listener and default target group\n\n",
|
||||
}
|
||||
|
||||
const tgAsString = (key: string): string => {
|
||||
const raw = tgWatch(key)
|
||||
return typeof raw === "string" ? raw : ""
|
||||
}
|
||||
const tgAsNumber = (key: string): number | undefined => {
|
||||
const raw = tgWatch(key)
|
||||
return typeof raw === "number" && Number.isFinite(raw) ? raw : undefined
|
||||
}
|
||||
|
||||
// Either a create-target-group step (mode=new) or just a TG_ARN= assignment
|
||||
if (tgMode === "new") {
|
||||
const tgName = tgAsString("name") || "<TG-Name>"
|
||||
const tgPort = tgAsNumber("port") ?? 80
|
||||
const tgVpc = tgAsString("vpcId")
|
||||
const tgProtocol = tgAsString("protocol") || "HTTP"
|
||||
const tgName = tgWatch("name") || "<TG-Name>"
|
||||
const tgPort = tgWatch("port") ?? 80
|
||||
const tgVpc = tgWatch("vpcId")
|
||||
const tgProtocol = tgWatch("protocol") || "HTTP"
|
||||
commands.push({
|
||||
label: "Create Target Group",
|
||||
parts: [
|
||||
|
||||
+11
-10
@@ -1,7 +1,12 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { useSuspenseQuery } from "@tanstack/react-query"
|
||||
import { createFileRoute, Link, useNavigate } from "@tanstack/react-router"
|
||||
import { Controller, useForm, useWatch } from "react-hook-form"
|
||||
import {
|
||||
Controller,
|
||||
type DeepPartialSkipArrayKey,
|
||||
useForm,
|
||||
useWatch,
|
||||
} from "react-hook-form"
|
||||
|
||||
import { BackLink } from "@/components/back-link"
|
||||
import {
|
||||
@@ -78,8 +83,6 @@ function CreateNatGateway() {
|
||||
})
|
||||
|
||||
const values = useWatch({ control })
|
||||
const cliWatch = (name?: string): unknown =>
|
||||
name ? (values as Record<string, unknown>)[name] : undefined
|
||||
|
||||
const onSubmit = async (data: CreateNatGatewayFormData) => {
|
||||
const result = await createMutation.mutateAsync({
|
||||
@@ -207,7 +210,7 @@ function CreateNatGateway() {
|
||||
<FieldError errors={[errors.allocationId]} />
|
||||
</Field>
|
||||
|
||||
<CliCommandPanel commands={buildCreateNatGatewayCommands(cliWatch)} />
|
||||
<CliCommandPanel commands={buildCreateNatGatewayCommands(values)} />
|
||||
|
||||
<FormActions
|
||||
isPending={createMutation.isPending}
|
||||
@@ -224,15 +227,13 @@ function CreateNatGateway() {
|
||||
}
|
||||
|
||||
function buildCreateNatGatewayCommands(
|
||||
watch: (name?: string) => unknown,
|
||||
values: DeepPartialSkipArrayKey<CreateNatGatewayFormData>,
|
||||
): CliCommand[] {
|
||||
const rawSubnetId = watch("subnetId")
|
||||
const subnetId = typeof rawSubnetId === "string" ? rawSubnetId : ""
|
||||
const rawAllocationId = watch("allocationId")
|
||||
const subnetId = values.subnetId ?? ""
|
||||
const rawAllocationId = values.allocationId
|
||||
const allocationId =
|
||||
typeof rawAllocationId === "string" ? rawAllocationId : ""
|
||||
const rawName = watch("name")
|
||||
const name = typeof rawName === "string" ? rawName : ""
|
||||
const name = values.name ?? ""
|
||||
|
||||
const parts = [
|
||||
{
|
||||
|
||||
+10
-11
@@ -1,6 +1,11 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { createFileRoute, useNavigate } from "@tanstack/react-router"
|
||||
import { Controller, useForm, useWatch } from "react-hook-form"
|
||||
import {
|
||||
Controller,
|
||||
type DeepPartialSkipArrayKey,
|
||||
useForm,
|
||||
useWatch,
|
||||
} from "react-hook-form"
|
||||
|
||||
import { BackLink } from "@/components/back-link"
|
||||
import {
|
||||
@@ -56,8 +61,6 @@ function CreatePlacementGroup() {
|
||||
})
|
||||
|
||||
const values = useWatch({ control })
|
||||
const cliWatch = (name?: string): unknown =>
|
||||
name ? (values as Record<string, unknown>)[name] : undefined
|
||||
|
||||
const onSubmit = async (data: CreatePlacementGroupFormData) => {
|
||||
const result = await createMutation.mutateAsync(data)
|
||||
@@ -125,9 +128,7 @@ function CreatePlacementGroup() {
|
||||
<FieldError errors={[errors.strategy]} />
|
||||
</Field>
|
||||
|
||||
<CliCommandPanel
|
||||
commands={buildCreatePlacementGroupCommands(cliWatch)}
|
||||
/>
|
||||
<CliCommandPanel commands={buildCreatePlacementGroupCommands(values)} />
|
||||
|
||||
<FormActions
|
||||
isPending={createMutation.isPending}
|
||||
@@ -148,12 +149,10 @@ function shellSingleQuote(value: string): string {
|
||||
}
|
||||
|
||||
function buildCreatePlacementGroupCommands(
|
||||
watch: (name?: string) => unknown,
|
||||
values: DeepPartialSkipArrayKey<CreatePlacementGroupFormData>,
|
||||
): CliCommand[] {
|
||||
const rawName = watch("groupName")
|
||||
const name = typeof rawName === "string" ? rawName : ""
|
||||
const rawStrategy = watch("strategy")
|
||||
const strategy = typeof rawStrategy === "string" ? rawStrategy : ""
|
||||
const name = values.groupName ?? ""
|
||||
const strategy = values.strategy ?? ""
|
||||
const nameValue = name ? shellSingleQuote(name) : "<GroupName>"
|
||||
|
||||
return [
|
||||
|
||||
+11
-13
@@ -1,7 +1,12 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { useSuspenseQuery } from "@tanstack/react-query"
|
||||
import { createFileRoute, useNavigate } from "@tanstack/react-router"
|
||||
import { Controller, useForm, useWatch } from "react-hook-form"
|
||||
import {
|
||||
Controller,
|
||||
type DeepPartialSkipArrayKey,
|
||||
useForm,
|
||||
useWatch,
|
||||
} from "react-hook-form"
|
||||
|
||||
import { BackLink } from "@/components/back-link"
|
||||
import {
|
||||
@@ -66,8 +71,6 @@ function CreateSecurityGroup() {
|
||||
})
|
||||
|
||||
const values = useWatch({ control })
|
||||
const cliWatch = (name?: string): unknown =>
|
||||
name ? (values as Record<string, unknown>)[name] : undefined
|
||||
|
||||
const onSubmit = async (data: CreateSecurityGroupFormData) => {
|
||||
const result = await createMutation.mutateAsync(data)
|
||||
@@ -161,9 +164,7 @@ function CreateSecurityGroup() {
|
||||
<FieldError errors={[errors.vpcId]} />
|
||||
</Field>
|
||||
|
||||
<CliCommandPanel
|
||||
commands={buildCreateSecurityGroupCommands(cliWatch)}
|
||||
/>
|
||||
<CliCommandPanel commands={buildCreateSecurityGroupCommands(values)} />
|
||||
|
||||
<FormActions
|
||||
isPending={createMutation.isPending}
|
||||
@@ -180,14 +181,11 @@ function CreateSecurityGroup() {
|
||||
}
|
||||
|
||||
function buildCreateSecurityGroupCommands(
|
||||
watch: (name?: string) => unknown,
|
||||
values: DeepPartialSkipArrayKey<CreateSecurityGroupFormData>,
|
||||
): CliCommand[] {
|
||||
const rawName = watch("groupName")
|
||||
const name = typeof rawName === "string" ? rawName : ""
|
||||
const rawDesc = watch("description")
|
||||
const desc = typeof rawDesc === "string" ? rawDesc : ""
|
||||
const rawVpcId = watch("vpcId")
|
||||
const vpcId = typeof rawVpcId === "string" ? rawVpcId : ""
|
||||
const name = values.groupName ?? ""
|
||||
const desc = values.description ?? ""
|
||||
const vpcId = values.vpcId ?? ""
|
||||
|
||||
const parts = [
|
||||
{
|
||||
|
||||
+10
-9
@@ -1,7 +1,12 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { useSuspenseQuery } from "@tanstack/react-query"
|
||||
import { createFileRoute, useNavigate } from "@tanstack/react-router"
|
||||
import { Controller, useForm, useWatch } from "react-hook-form"
|
||||
import {
|
||||
Controller,
|
||||
type DeepPartialSkipArrayKey,
|
||||
useForm,
|
||||
useWatch,
|
||||
} from "react-hook-form"
|
||||
import { z } from "zod"
|
||||
|
||||
import { BackLink } from "@/components/back-link"
|
||||
@@ -69,8 +74,6 @@ function CreateSnapshot() {
|
||||
})
|
||||
|
||||
const values = useWatch({ control })
|
||||
const cliWatch = (name?: string): unknown =>
|
||||
name ? (values as Record<string, unknown>)[name] : undefined
|
||||
|
||||
const onSubmit = async (data: CreateSnapshotFormData) => {
|
||||
await createMutation.mutateAsync(data)
|
||||
@@ -137,7 +140,7 @@ function CreateSnapshot() {
|
||||
/>
|
||||
</Field>
|
||||
|
||||
<CliCommandPanel commands={buildCreateSnapshotCommands(cliWatch)} />
|
||||
<CliCommandPanel commands={buildCreateSnapshotCommands(values)} />
|
||||
|
||||
<FormActions
|
||||
isPending={createMutation.isPending}
|
||||
@@ -154,12 +157,10 @@ function CreateSnapshot() {
|
||||
}
|
||||
|
||||
function buildCreateSnapshotCommands(
|
||||
watch: (name?: string) => unknown,
|
||||
values: DeepPartialSkipArrayKey<CreateSnapshotFormData>,
|
||||
): CliCommand[] {
|
||||
const rawVolumeId = watch("volumeId")
|
||||
const volumeId = typeof rawVolumeId === "string" ? rawVolumeId : ""
|
||||
const rawDescription = watch("description")
|
||||
const description = typeof rawDescription === "string" ? rawDescription : ""
|
||||
const volumeId = values.volumeId ?? ""
|
||||
const description = values.description ?? ""
|
||||
|
||||
const parts = [
|
||||
{
|
||||
|
||||
+12
-12
@@ -1,7 +1,12 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { useSuspenseQuery } from "@tanstack/react-query"
|
||||
import { createFileRoute, useNavigate } from "@tanstack/react-router"
|
||||
import { Controller, useForm, useWatch } from "react-hook-form"
|
||||
import {
|
||||
Controller,
|
||||
type DeepPartialSkipArrayKey,
|
||||
useForm,
|
||||
useWatch,
|
||||
} from "react-hook-form"
|
||||
|
||||
import { BackLink } from "@/components/back-link"
|
||||
import {
|
||||
@@ -70,8 +75,6 @@ function CreateSubnet() {
|
||||
})
|
||||
|
||||
const values = useWatch({ control })
|
||||
const cliWatch = (name?: string): unknown =>
|
||||
name ? (values as Record<string, unknown>)[name] : undefined
|
||||
|
||||
const onSubmit = async (data: CreateSubnetFormData) => {
|
||||
const result = await createMutation.mutateAsync(data)
|
||||
@@ -201,7 +204,7 @@ function CreateSubnet() {
|
||||
/>
|
||||
</Field>
|
||||
|
||||
<CliCommandPanel commands={buildCreateSubnetCommands(cliWatch)} />
|
||||
<CliCommandPanel commands={buildCreateSubnetCommands(values)} />
|
||||
|
||||
<FormActions
|
||||
isPending={createMutation.isPending}
|
||||
@@ -216,14 +219,11 @@ function CreateSubnet() {
|
||||
}
|
||||
|
||||
function buildCreateSubnetCommands(
|
||||
watch: (name?: string) => unknown,
|
||||
values: DeepPartialSkipArrayKey<CreateSubnetFormData>,
|
||||
): CliCommand[] {
|
||||
const rawVpcId = watch("vpcId")
|
||||
const vpcId = typeof rawVpcId === "string" ? rawVpcId : ""
|
||||
const rawCidr = watch("cidrBlock")
|
||||
const cidr = typeof rawCidr === "string" ? rawCidr : ""
|
||||
const rawAz = watch("availabilityZone")
|
||||
const az = typeof rawAz === "string" ? rawAz : ""
|
||||
const vpcId = values.vpcId ?? ""
|
||||
const cidr = values.cidrBlock ?? ""
|
||||
const az = values.availabilityZone ?? ""
|
||||
|
||||
const parts = [
|
||||
{
|
||||
@@ -245,7 +245,7 @@ function buildCreateSubnetCommands(
|
||||
|
||||
const commands: CliCommand[] = [{ label: "Create Subnet", parts }]
|
||||
|
||||
if (watch("mapPublicIpOnLaunch") === true) {
|
||||
if (values.mapPublicIpOnLaunch === true) {
|
||||
commands.push({
|
||||
label: "Enable auto-assign public IPv4",
|
||||
parts: [
|
||||
|
||||
+14
-23
@@ -1,7 +1,7 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { useSuspenseQuery } from "@tanstack/react-query"
|
||||
import { useNavigate } from "@tanstack/react-router"
|
||||
import { useForm } from "react-hook-form"
|
||||
import { useForm, type UseFormWatch } from "react-hook-form"
|
||||
|
||||
import { BackLink } from "@/components/back-link"
|
||||
import {
|
||||
@@ -106,29 +106,20 @@ export function CreateTargetGroupPage() {
|
||||
}
|
||||
|
||||
function buildCreateTargetGroupCommands(
|
||||
watch: (name?: string) => unknown,
|
||||
watch: UseFormWatch<CreateTargetGroupFormData>,
|
||||
): CliCommand[] {
|
||||
const asString = (key: string): string => {
|
||||
const raw = watch(key)
|
||||
return typeof raw === "string" ? raw : ""
|
||||
}
|
||||
const asNumber = (key: string): number | undefined => {
|
||||
const raw = watch(key)
|
||||
return typeof raw === "number" && Number.isFinite(raw) ? raw : undefined
|
||||
}
|
||||
|
||||
const name = asString("name")
|
||||
const protocol = asString("protocol") || "HTTP"
|
||||
const port = asNumber("port")
|
||||
const vpcId = asString("vpcId")
|
||||
const hcProtocol = asString("healthCheck.protocol") || "HTTP"
|
||||
const hcPath = asString("healthCheck.path") || "/"
|
||||
const hcPort = asString("healthCheck.port") || "traffic-port"
|
||||
const hcInterval = asNumber("healthCheck.intervalSeconds")
|
||||
const hcTimeout = asNumber("healthCheck.timeoutSeconds")
|
||||
const hcHealthy = asNumber("healthCheck.healthyThresholdCount")
|
||||
const hcUnhealthy = asNumber("healthCheck.unhealthyThresholdCount")
|
||||
const hcMatcher = asString("healthCheck.matcher") || "200"
|
||||
const name = watch("name")
|
||||
const protocol = watch("protocol") || "HTTP"
|
||||
const port = watch("port")
|
||||
const vpcId = watch("vpcId")
|
||||
const hcProtocol = watch("healthCheck.protocol") || "HTTP"
|
||||
const hcPath = watch("healthCheck.path") || "/"
|
||||
const hcPort = watch("healthCheck.port") || "traffic-port"
|
||||
const hcInterval = watch("healthCheck.intervalSeconds")
|
||||
const hcTimeout = watch("healthCheck.timeoutSeconds")
|
||||
const hcHealthy = watch("healthCheck.healthyThresholdCount")
|
||||
const hcUnhealthy = watch("healthCheck.unhealthyThresholdCount")
|
||||
const hcMatcher = watch("healthCheck.matcher") || "200"
|
||||
|
||||
const parts: CommandPart[] = [
|
||||
{
|
||||
|
||||
+4
-6
@@ -1,7 +1,7 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { useSuspenseQuery } from "@tanstack/react-query"
|
||||
import { createFileRoute, useNavigate } from "@tanstack/react-router"
|
||||
import { Controller, useForm } from "react-hook-form"
|
||||
import { Controller, useForm, type UseFormWatch } from "react-hook-form"
|
||||
|
||||
import { BackLink } from "@/components/back-link"
|
||||
import {
|
||||
@@ -141,12 +141,10 @@ function CreateVolume() {
|
||||
}
|
||||
|
||||
function buildCreateVolumeCommands(
|
||||
watch: (name?: string) => unknown,
|
||||
watch: UseFormWatch<CreateVolumeFormData>,
|
||||
): CliCommand[] {
|
||||
const rawSize = watch("size")
|
||||
const size = typeof rawSize === "number" ? rawSize : 0
|
||||
const rawAz = watch("availabilityZone")
|
||||
const az = typeof rawAz === "string" ? rawAz : ""
|
||||
const size = watch("size")
|
||||
const az = watch("availabilityZone")
|
||||
|
||||
return [
|
||||
{
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { createFileRoute, useNavigate } from "@tanstack/react-router"
|
||||
import { useState } from "react"
|
||||
import { Controller, useForm, useWatch } from "react-hook-form"
|
||||
import {
|
||||
Controller,
|
||||
useForm,
|
||||
type UseFormWatch,
|
||||
useWatch,
|
||||
} from "react-hook-form"
|
||||
|
||||
import { BackLink } from "@/components/back-link"
|
||||
import {
|
||||
@@ -398,20 +403,16 @@ function CreateVpc() {
|
||||
}
|
||||
|
||||
function buildCreateVpcCommands(
|
||||
watch: (name?: string) => unknown,
|
||||
watch: UseFormWatch<CreateVpcWizardFormData>,
|
||||
subnetCidrs: {
|
||||
publicSubnets: { cidr: string }[]
|
||||
privateSubnets: { cidr: string }[]
|
||||
},
|
||||
): CliCommand[] {
|
||||
const rawMode = watch("mode")
|
||||
const mode = typeof rawMode === "string" ? rawMode : ""
|
||||
const rawCidr = watch("cidrBlock")
|
||||
const cidr = typeof rawCidr === "string" ? rawCidr : ""
|
||||
const rawTenancy = watch("tenancy")
|
||||
const tenancy = typeof rawTenancy === "string" ? rawTenancy : ""
|
||||
const rawNat = watch("natGateway")
|
||||
const natGateway = typeof rawNat === "string" ? rawNat : ""
|
||||
const mode = watch("mode")
|
||||
const cidr = watch("cidrBlock")
|
||||
const tenancy = watch("tenancy")
|
||||
const natGateway = watch("natGateway")
|
||||
|
||||
if (mode === "vpc-only") {
|
||||
const parts: CommandPart[] = [
|
||||
|
||||
+9
-9
@@ -1,6 +1,10 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { createFileRoute, useNavigate } from "@tanstack/react-router"
|
||||
import { useForm, useWatch } from "react-hook-form"
|
||||
import {
|
||||
type DeepPartialSkipArrayKey,
|
||||
useForm,
|
||||
useWatch,
|
||||
} from "react-hook-form"
|
||||
|
||||
import { BackLink } from "@/components/back-link"
|
||||
import {
|
||||
@@ -36,8 +40,6 @@ function CreateGroup() {
|
||||
})
|
||||
|
||||
const values = useWatch({ control })
|
||||
const cliWatch = (name?: string): unknown =>
|
||||
name ? (values as Record<string, unknown>)[name] : undefined
|
||||
|
||||
const onSubmit = async (data: CreateGroupFormData) => {
|
||||
await createMutation.mutateAsync(data)
|
||||
@@ -78,7 +80,7 @@ function CreateGroup() {
|
||||
<FieldError errors={[errors.path]} />
|
||||
</Field>
|
||||
|
||||
<CliCommandPanel commands={buildCreateGroupCommands(cliWatch)} />
|
||||
<CliCommandPanel commands={buildCreateGroupCommands(values)} />
|
||||
|
||||
<FormActions
|
||||
isPending={createMutation.isPending}
|
||||
@@ -93,12 +95,10 @@ function CreateGroup() {
|
||||
}
|
||||
|
||||
function buildCreateGroupCommands(
|
||||
watch: (name?: string) => unknown,
|
||||
values: DeepPartialSkipArrayKey<CreateGroupFormData>,
|
||||
): CliCommand[] {
|
||||
const rawGroupName = watch("groupName")
|
||||
const groupName = typeof rawGroupName === "string" ? rawGroupName : ""
|
||||
const rawPath = watch("path")
|
||||
const path = typeof rawPath === "string" ? rawPath : ""
|
||||
const groupName = values.groupName ?? ""
|
||||
const path = values.path ?? ""
|
||||
|
||||
const parts = [
|
||||
{
|
||||
|
||||
+9
-9
@@ -1,6 +1,10 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { createFileRoute, useNavigate } from "@tanstack/react-router"
|
||||
import { useForm, useWatch } from "react-hook-form"
|
||||
import {
|
||||
type DeepPartialSkipArrayKey,
|
||||
useForm,
|
||||
useWatch,
|
||||
} from "react-hook-form"
|
||||
|
||||
import { BackLink } from "@/components/back-link"
|
||||
import {
|
||||
@@ -41,8 +45,6 @@ function CreateInstanceProfile() {
|
||||
})
|
||||
|
||||
const values = useWatch({ control })
|
||||
const cliWatch = (name?: string): unknown =>
|
||||
name ? (values as Record<string, unknown>)[name] : undefined
|
||||
|
||||
const onSubmit = async (data: CreateInstanceProfileFormData) => {
|
||||
await createMutation.mutateAsync(data)
|
||||
@@ -86,7 +88,7 @@ function CreateInstanceProfile() {
|
||||
</Field>
|
||||
|
||||
<CliCommandPanel
|
||||
commands={buildCreateInstanceProfileCommands(cliWatch)}
|
||||
commands={buildCreateInstanceProfileCommands(values)}
|
||||
/>
|
||||
|
||||
<FormActions
|
||||
@@ -104,12 +106,10 @@ function CreateInstanceProfile() {
|
||||
}
|
||||
|
||||
function buildCreateInstanceProfileCommands(
|
||||
watch: (name?: string) => unknown,
|
||||
values: DeepPartialSkipArrayKey<CreateInstanceProfileFormData>,
|
||||
): CliCommand[] {
|
||||
const rawName = watch("instanceProfileName")
|
||||
const name = typeof rawName === "string" ? rawName : ""
|
||||
const rawPath = watch("path")
|
||||
const path = typeof rawPath === "string" ? rawPath : ""
|
||||
const name = values.instanceProfileName ?? ""
|
||||
const path = values.path ?? ""
|
||||
|
||||
const parts = [
|
||||
{
|
||||
|
||||
+11
-11
@@ -1,6 +1,11 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { createFileRoute, useNavigate } from "@tanstack/react-router"
|
||||
import { Controller, useForm, useWatch } from "react-hook-form"
|
||||
import {
|
||||
Controller,
|
||||
type DeepPartialSkipArrayKey,
|
||||
useForm,
|
||||
useWatch,
|
||||
} from "react-hook-form"
|
||||
|
||||
import { BackLink } from "@/components/back-link"
|
||||
import {
|
||||
@@ -55,8 +60,6 @@ function CreatePolicy() {
|
||||
})
|
||||
|
||||
const values = useWatch({ control })
|
||||
const cliWatch = (name?: string): unknown =>
|
||||
name ? (values as Record<string, unknown>)[name] : undefined
|
||||
|
||||
const onSubmit = async (data: CreatePolicyFormData) => {
|
||||
await createMutation.mutateAsync(data)
|
||||
@@ -123,7 +126,7 @@ function CreatePolicy() {
|
||||
<FieldError errors={[errors.policyDocument]} />
|
||||
</Field>
|
||||
|
||||
<CliCommandPanel commands={buildCreatePolicyCommands(cliWatch)} />
|
||||
<CliCommandPanel commands={buildCreatePolicyCommands(values)} />
|
||||
|
||||
<FormActions
|
||||
isPending={createMutation.isPending}
|
||||
@@ -138,14 +141,11 @@ function CreatePolicy() {
|
||||
}
|
||||
|
||||
function buildCreatePolicyCommands(
|
||||
watch: (name?: string) => unknown,
|
||||
values: DeepPartialSkipArrayKey<CreatePolicyFormData>,
|
||||
): CliCommand[] {
|
||||
const rawName = watch("policyName")
|
||||
const name = typeof rawName === "string" ? rawName : ""
|
||||
const rawDesc = watch("description")
|
||||
const desc = typeof rawDesc === "string" ? rawDesc : ""
|
||||
const rawDoc = watch("policyDocument")
|
||||
const doc = typeof rawDoc === "string" ? rawDoc : ""
|
||||
const name = values.policyName ?? ""
|
||||
const desc = values.description ?? ""
|
||||
const doc = values.policyDocument ?? ""
|
||||
|
||||
const parts = [
|
||||
{
|
||||
|
||||
+11
-11
@@ -1,6 +1,11 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { createFileRoute, useNavigate } from "@tanstack/react-router"
|
||||
import { Controller, useForm, useWatch } from "react-hook-form"
|
||||
import {
|
||||
Controller,
|
||||
type DeepPartialSkipArrayKey,
|
||||
useForm,
|
||||
useWatch,
|
||||
} from "react-hook-form"
|
||||
|
||||
import { BackLink } from "@/components/back-link"
|
||||
import {
|
||||
@@ -44,8 +49,6 @@ function CreateRole() {
|
||||
})
|
||||
|
||||
const values = useWatch({ control })
|
||||
const cliWatch = (name?: string): unknown =>
|
||||
name ? (values as Record<string, unknown>)[name] : undefined
|
||||
|
||||
const onSubmit = async (data: CreateRoleFormData) => {
|
||||
await createMutation.mutateAsync(data)
|
||||
@@ -111,7 +114,7 @@ function CreateRole() {
|
||||
<FieldError errors={[errors.assumeRolePolicyDocument]} />
|
||||
</Field>
|
||||
|
||||
<CliCommandPanel commands={buildCreateRoleCommands(cliWatch)} />
|
||||
<CliCommandPanel commands={buildCreateRoleCommands(values)} />
|
||||
|
||||
<FormActions
|
||||
isPending={createMutation.isPending}
|
||||
@@ -126,14 +129,11 @@ function CreateRole() {
|
||||
}
|
||||
|
||||
function buildCreateRoleCommands(
|
||||
watch: (name?: string) => unknown,
|
||||
values: DeepPartialSkipArrayKey<CreateRoleFormData>,
|
||||
): CliCommand[] {
|
||||
const rawName = watch("roleName")
|
||||
const name = typeof rawName === "string" ? rawName : ""
|
||||
const rawDesc = watch("description")
|
||||
const desc = typeof rawDesc === "string" ? rawDesc : ""
|
||||
const rawDoc = watch("assumeRolePolicyDocument")
|
||||
const doc = typeof rawDoc === "string" ? rawDoc : ""
|
||||
const name = values.roleName ?? ""
|
||||
const desc = values.description ?? ""
|
||||
const doc = values.assumeRolePolicyDocument ?? ""
|
||||
|
||||
const parts = [
|
||||
{
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { createFileRoute, useNavigate } from "@tanstack/react-router"
|
||||
import { useForm, useWatch } from "react-hook-form"
|
||||
import {
|
||||
type DeepPartialSkipArrayKey,
|
||||
useForm,
|
||||
useWatch,
|
||||
} from "react-hook-form"
|
||||
|
||||
import { BackLink } from "@/components/back-link"
|
||||
import {
|
||||
@@ -36,8 +40,6 @@ function CreateUser() {
|
||||
})
|
||||
|
||||
const values = useWatch({ control })
|
||||
const cliWatch = (name?: string): unknown =>
|
||||
name ? (values as Record<string, unknown>)[name] : undefined
|
||||
|
||||
const onSubmit = async (data: CreateUserFormData) => {
|
||||
await createMutation.mutateAsync(data)
|
||||
@@ -75,7 +77,7 @@ function CreateUser() {
|
||||
<FieldError errors={[errors.path]} />
|
||||
</Field>
|
||||
|
||||
<CliCommandPanel commands={buildCreateUserCommands(cliWatch)} />
|
||||
<CliCommandPanel commands={buildCreateUserCommands(values)} />
|
||||
|
||||
<FormActions
|
||||
isPending={createMutation.isPending}
|
||||
@@ -90,12 +92,10 @@ function CreateUser() {
|
||||
}
|
||||
|
||||
function buildCreateUserCommands(
|
||||
watch: (name?: string) => unknown,
|
||||
values: DeepPartialSkipArrayKey<CreateUserFormData>,
|
||||
): CliCommand[] {
|
||||
const rawUserName = watch("userName")
|
||||
const userName = typeof rawUserName === "string" ? rawUserName : ""
|
||||
const rawPath = watch("path")
|
||||
const path = typeof rawPath === "string" ? rawPath : ""
|
||||
const userName = values.userName ?? ""
|
||||
const path = values.path ?? ""
|
||||
|
||||
const parts = [
|
||||
{ type: "bin" as const, value: "AWS_PROFILE=spinifex aws iam create-user" },
|
||||
|
||||
+8
-7
@@ -1,6 +1,10 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { createFileRoute, useNavigate } from "@tanstack/react-router"
|
||||
import { useForm, useWatch } from "react-hook-form"
|
||||
import {
|
||||
type DeepPartialSkipArrayKey,
|
||||
useForm,
|
||||
useWatch,
|
||||
} from "react-hook-form"
|
||||
|
||||
import { BackLink } from "@/components/back-link"
|
||||
import {
|
||||
@@ -40,8 +44,6 @@ function CreateBucket() {
|
||||
})
|
||||
|
||||
const values = useWatch({ control })
|
||||
const cliWatch = (name?: string): unknown =>
|
||||
name ? (values as Record<string, unknown>)[name] : undefined
|
||||
|
||||
const onSubmit = async (data: CreateBucketFormData) => {
|
||||
await createMutation.mutateAsync(data)
|
||||
@@ -76,7 +78,7 @@ function CreateBucket() {
|
||||
<FieldError errors={[errors.bucketName]} />
|
||||
</Field>
|
||||
|
||||
<CliCommandPanel commands={buildCreateBucketCommands(cliWatch)} />
|
||||
<CliCommandPanel commands={buildCreateBucketCommands(values)} />
|
||||
|
||||
<FormActions
|
||||
isPending={createMutation.isPending}
|
||||
@@ -91,10 +93,9 @@ function CreateBucket() {
|
||||
}
|
||||
|
||||
function buildCreateBucketCommands(
|
||||
watch: (name?: string) => unknown,
|
||||
values: DeepPartialSkipArrayKey<CreateBucketFormData>,
|
||||
): CliCommand[] {
|
||||
const rawBucket = watch("bucketName")
|
||||
const bucket = typeof rawBucket === "string" ? rawBucket : ""
|
||||
const bucket = values.bucketName ?? ""
|
||||
|
||||
return [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user