first commit

This commit is contained in:
Zakaria
2026-09-22 16:13:21 -04:00
commit 7e49be27f1
297 changed files with 63162 additions and 0 deletions
@@ -0,0 +1,104 @@
import {useEffect, useState} from 'react'
import {Link2, Loader2, Rocket} from 'lucide-react'
import {useMutation, useQuery} from '@tanstack/react-query'
import {createApiGatewayLambdaRoute, listCloudResources} from '@/api/cloudProxyClient'
import type {CloudProvider} from '@/types/cloud'
import type {CloudResource} from '@/types/resource'
interface ApiGatewayRoutePanelProps {
cloud: CloudProvider
resource?: CloudResource
runtimeReachable: boolean
}
export function ApiGatewayRoutePanel({cloud, resource, runtimeReachable}: ApiGatewayRoutePanelProps) {
const [path, setPath] = useState('/hello')
const [method, setMethod] = useState('GET')
const [stage, setStage] = useState('dev')
const [functionName, setFunctionName] = useState('')
const functionsQuery = useQuery({
queryKey: ['cloud-resources', cloud, 'serverless'],
queryFn: ({signal}) => listCloudResources(cloud, 'serverless', undefined, signal),
enabled: cloud === 'aws' && Boolean(resource) && runtimeReachable,
})
useEffect(() => {
setPath('/hello')
setMethod('GET')
setStage('dev')
setFunctionName('')
}, [resource?.id])
const routeMutation = useMutation({
mutationFn: () => createApiGatewayLambdaRoute(cloud, resource!.id, {path, method, stage, functionName}),
})
if (!resource || resource.service !== 'apigateway') {
return (
<section className="table-panel">
<div className="empty compact">
<h3>Select a REST API</h3>
<p>Select an API Gateway REST API to connect a route to a Lambda function.</p>
</div>
</section>
)
}
const functions = functionsQuery.data?.filter((item) => item.type === 'lambda') ?? []
const canCreate = cloud === 'aws' && runtimeReachable && Boolean(functionName) && !routeMutation.isPending
return (
<section className="table-panel">
<div className="dynamic-stage-header">
<div>
<p className="eyebrow">REST API Route</p>
<h3><Link2 size={15}/> Connect Lambda</h3>
<p className="muted compact-text">Creates and deploys one Lambda proxy route to the selected REST API.</p>
</div>
</div>
<div className="resource-create-inline">
<form className="inspector-action-form apigateway-route-form" onSubmit={(event) => {
event.preventDefault()
if (canCreate) routeMutation.mutate()
}}>
<label className="dynamic-field">
<span>Route path</span>
<input className="input" value={path} onChange={(event) => setPath(event.target.value)} placeholder="/orders" required/>
<small>One path segment, for example <code>/qrcode</code>.</small>
</label>
<label className="dynamic-field">
<span>Method</span>
<select className="input" value={method} onChange={(event) => setMethod(event.target.value)}>
{['GET', 'POST', 'PUT', 'DELETE'].map((value) => <option key={value} value={value}>{value}</option>)}
</select>
<small>Lambda proxy method.</small>
</label>
<label className="dynamic-field">
<span>Lambda function</span>
<select className="input" value={functionName} onChange={(event) => setFunctionName(event.target.value)} required>
<option value="">Select a Lambda function</option>
{functions.map((fn) => <option key={fn.id} value={fn.name}>{fn.name}</option>)}
</select>
<small>{functionsQuery.isLoading ? 'Loading functions...' : functions.length === 0 ? 'Create a Lambda function before adding a route.' : 'Receives this route\'s proxy event.'}</small>
</label>
<label className="dynamic-field">
<span>Stage</span>
<input className="input" value={stage} onChange={(event) => setStage(event.target.value)} placeholder="dev" required/>
<small>Deployment stage name.</small>
</label>
<button className="button primary apigateway-route-submit" type="submit" disabled={!canCreate}>
{routeMutation.isPending ? <Loader2 size={13}/> : <Rocket size={13}/>}
{routeMutation.isPending ? 'Deploying' : 'Create and deploy route'}
</button>
</form>
{routeMutation.isError && <p className="error-text compact-text">{routeMutation.error instanceof Error ? routeMutation.error.message : 'Unable to create API route.'}</p>}
{routeMutation.data && (
<div className="apigateway-route-result">
<strong>Route deployed</strong>
<a href={routeMutation.data.invokeUrl} target="_blank" rel="noreferrer">{routeMutation.data.invokeUrl}</a>
</div>
)}
</div>
</section>
)
}