Files
floci-ui/packages/frontend/src/api/api.ts
T
2026-09-22 16:13:21 -04:00

966 lines
34 KiB
TypeScript

import { EndpointRegistry, HttpClient } from "./HttpClient";
import { ACCOUNT_HEADER, getAccountId } from "@/lib/accountStore";
export class AuthenticationRequiredError extends Error {
constructor() {
super("Authentication is required before calling the API.");
this.name = "AuthenticationRequiredError";
}
}
export const apiEndpointKeys = {
clouds: {
list: "clouds.list",
services: "clouds.services.list",
status: "clouds.status.get",
serviceStatus: "clouds.services.status.get",
schema: "clouds.services.schema.get",
resources: {
list: "clouds.services.resources.list",
get: "clouds.services.resources.get",
create: "clouds.services.resources.create",
update: "clouds.services.resources.update",
delete: "clouds.services.resources.delete",
invoke: "clouds.services.resources.invoke",
encrypt: "clouds.services.resources.encrypt",
decrypt: "clouds.services.resources.decrypt",
createApiGatewayRoute: "clouds.services.resources.apigateway.route.create",
},
storage: {
objects: {
list: "clouds.services.storage.objects.list",
upload: "clouds.services.storage.objects.upload",
download: "clouds.services.storage.objects.download",
delete: "clouds.services.storage.objects.delete",
copy: "clouds.services.storage.objects.copy",
},
},
nosql: {
cosmos: {
containers: {
list: "clouds.services.nosql.cosmos.containers.list",
create: "clouds.services.nosql.cosmos.containers.create",
delete: "clouds.services.nosql.cosmos.containers.delete",
},
items: {
list: "clouds.services.nosql.cosmos.items.list",
upsert: "clouds.services.nosql.cosmos.items.upsert",
delete: "clouds.services.nosql.cosmos.items.delete",
query: "clouds.services.nosql.cosmos.items.query",
},
},
items: {
list: "clouds.services.nosql.items.list",
put: "clouds.services.nosql.items.put",
},
},
database: {
sql: {
databases: "clouds.services.database.sql.databases.list",
tables: "clouds.services.database.sql.tables.list",
query: "clouds.services.database.sql.query",
},
snapshots: {
list: "clouds.services.database.snapshots.list",
create: "clouds.services.database.snapshots.create",
},
orderableClasses: {
list: "clouds.services.database.orderable-classes.list",
},
},
logs: {
query: "clouds.services.logs.query",
},
k8s: {
nodegroups: {
list: "clouds.services.k8s.nodegroups.list",
create: "clouds.services.k8s.nodegroups.create",
delete: "clouds.services.k8s.nodegroups.delete",
},
fargateProfiles: {
list: "clouds.services.k8s.fargate-profiles.list",
create: "clouds.services.k8s.fargate-profiles.create",
delete: "clouds.services.k8s.fargate-profiles.delete",
},
},
email: {
inbox: {
clear: "clouds.services.email.inbox.clear",
},
},
childCollections: {
list: "clouds.services.childCollections.list",
items: {
list: "clouds.services.childCollections.items.list",
},
},
configuration: {
environments: {
list: "clouds.services.configuration.environments.list",
create: "clouds.services.configuration.environments.create",
delete: "clouds.services.configuration.environments.delete",
deployments: {
start: "clouds.services.configuration.environments.deployments.start",
get: "clouds.services.configuration.environments.deployments.get",
},
},
configurationProfiles: {
list: "clouds.services.configuration.profiles.list",
create: "clouds.services.configuration.profiles.create",
delete: "clouds.services.configuration.profiles.delete",
hostedVersions: {
list: "clouds.services.configuration.profiles.hosted-versions.list",
get: "clouds.services.configuration.profiles.hosted-versions.get",
create: "clouds.services.configuration.profiles.hosted-versions.create",
delete: "clouds.services.configuration.profiles.hosted-versions.delete",
},
},
deploymentStrategies: {
list: "clouds.services.configuration.deployment-strategies.list",
create: "clouds.services.configuration.deployment-strategies.create",
delete: "clouds.services.configuration.deployment-strategies.delete",
},
},
},
aws: {
eks: {
clusters: {
list: "aws.eks.clusters.list",
describe: "aws.eks.clusters.describe",
},
nodegroups: {
list: "aws.eks.nodegroups.list",
describe: "aws.eks.nodegroups.describe",
create: "aws.eks.nodegroups.create",
delete: "aws.eks.nodegroups.delete",
},
fargateProfiles: {
list: "aws.eks.fargate-profiles.list",
describe: "aws.eks.fargate-profiles.describe",
create: "aws.eks.fargate-profiles.create",
delete: "aws.eks.fargate-profiles.delete",
},
},
secretsmanager: {
secrets: {
list: "aws.secretsmanager.secrets.list",
create: "aws.secretsmanager.secrets.create",
describe: "aws.secretsmanager.secrets.describe",
delete: "aws.secretsmanager.secrets.delete",
value: {
get: "aws.secretsmanager.secrets.value.get",
put: "aws.secretsmanager.secrets.value.put",
},
},
},
ec2: {
instances: {
list: "aws.ec2.instances.list",
describe: "aws.ec2.instances.describe",
create: "aws.ec2.instances.create",
start: "aws.ec2.instances.start",
stop: "aws.ec2.instances.stop",
reboot: "aws.ec2.instances.reboot",
terminate: "aws.ec2.instances.terminate",
tags: "aws.ec2.instances.tags",
createImage: "aws.ec2.instances.create-image",
console: "aws.ec2.instances.console",
},
amis: {
list: "aws.ec2.amis.list",
deregister: "aws.ec2.amis.deregister",
},
keyPairs: {
list: "aws.ec2.key-pairs.list",
create: "aws.ec2.key-pairs.create",
delete: "aws.ec2.key-pairs.delete",
},
securityGroups: {
list: "aws.ec2.security-groups.list",
create: "aws.ec2.security-groups.create",
delete: "aws.ec2.security-groups.delete",
authorize: "aws.ec2.security-groups.authorize",
revoke: "aws.ec2.security-groups.revoke",
authorizeEgress: "aws.ec2.security-groups.authorize-egress",
revokeEgress: "aws.ec2.security-groups.revoke-egress",
},
vpcs: {
list: "aws.ec2.vpcs.list",
create: "aws.ec2.vpcs.create",
delete: "aws.ec2.vpcs.delete",
getAttributes: "aws.ec2.vpcs.get-attributes",
modifyAttribute: "aws.ec2.vpcs.modify-attribute",
},
subnets: {
list: "aws.ec2.subnets.list",
create: "aws.ec2.subnets.create",
delete: "aws.ec2.subnets.delete",
modifyAttribute: "aws.ec2.subnets.modify-attribute",
},
internetGateways: {
list: "aws.ec2.igw.list",
create: "aws.ec2.igw.create",
attach: "aws.ec2.igw.attach",
detach: "aws.ec2.igw.detach",
delete: "aws.ec2.igw.delete",
},
natGateways: {
list: "aws.ec2.nat.list",
create: "aws.ec2.nat.create",
delete: "aws.ec2.nat.delete",
},
routeTables: {
list: "aws.ec2.rtb.list",
create: "aws.ec2.rtb.create",
delete: "aws.ec2.rtb.delete",
createRoute: "aws.ec2.rtb.route.create",
deleteRoute: "aws.ec2.rtb.route.delete",
associate: "aws.ec2.rtb.associate",
disassociate: "aws.ec2.rtb.disassociate",
},
elasticIps: {
list: "aws.ec2.eip.list",
create: "aws.ec2.eip.create",
release: "aws.ec2.eip.release",
associate: "aws.ec2.eip.associate",
disassociate: "aws.ec2.eip.disassociate",
},
availabilityZones: "aws.ec2.availability-zones",
instanceTypes: "aws.ec2.instance-types",
vpcWizard: "aws.ec2.vpc-wizard",
},
},
} as const;
export const API_BASE_URL = import.meta.env.VITE_API_BASE_URL ?? "/api";
export const endpointRegistry: EndpointRegistry = new Map([
// Cloud Proxy
[
apiEndpointKeys.clouds.list,
{
path: "/clouds",
method: "GET",
telemetry: { provider: "system", service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.services,
{
path: "/clouds/:cloud/services",
method: "GET",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.status,
{
path: "/clouds/:cloud/status",
method: "GET",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.serviceStatus,
{
path: "/clouds/:cloud/services/:service/status",
method: "GET",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.schema,
{
path: "/clouds/:cloud/services/:service/schema",
method: "GET",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.resources.list,
{
path: "/clouds/:cloud/services/:service/resources",
method: "GET",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.resources.invoke,
{
path: "/clouds/:cloud/services/:service/resources/:id/invoke",
method: "POST",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.resources.createApiGatewayRoute,
{
path: "/clouds/:cloud/services/apigateway/resources/:id/routes",
method: "POST",
telemetry: { service: "apigateway" },
},
],
[
apiEndpointKeys.clouds.resources.get,
{
path: "/clouds/:cloud/services/:service/resources/:id",
method: "GET",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.resources.encrypt,
{
path: "/clouds/:cloud/services/kms/resources/:id/encrypt",
method: "POST",
telemetry: { service: "kms" },
},
],
[
apiEndpointKeys.clouds.resources.decrypt,
{
path: "/clouds/:cloud/services/kms/resources/:id/decrypt",
method: "POST",
telemetry: { service: "kms" },
},
],
[
apiEndpointKeys.clouds.resources.create,
{
path: "/clouds/:cloud/services/:service/resources",
method: "POST",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.resources.update,
{
path: "/clouds/:cloud/services/:service/resources/:id",
method: "PATCH",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.resources.delete,
{
path: "/clouds/:cloud/services/:service/resources/:id",
method: "DELETE",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.resources.invoke,
{
path: "/clouds/:cloud/services/:service/resources/:id/invoke",
method: "POST",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.storage.objects.list,
{
path: "/clouds/:cloud/services/storage/resources/:id/objects",
method: "GET",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.storage.objects.upload,
{
path: "/clouds/:cloud/services/storage/resources/:id/object",
method: "PUT",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.storage.objects.download,
{
path: "/clouds/:cloud/services/storage/resources/:id/object",
method: "GET",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.storage.objects.delete,
{
path: "/clouds/:cloud/services/storage/resources/:id/object",
method: "DELETE",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.storage.objects.copy,
{
path: "/clouds/:cloud/services/storage/resources/:id/object/copy",
method: "POST",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.nosql.cosmos.containers.list,
{
path: "/clouds/:cloud/services/nosql/resources/:id/containers",
method: "GET",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.nosql.cosmos.containers.create,
{
path: "/clouds/:cloud/services/nosql/resources/:id/containers",
method: "POST",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.nosql.cosmos.containers.delete,
{
path: "/clouds/:cloud/services/nosql/resources/:id/containers/:containerId",
method: "DELETE",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.nosql.cosmos.items.list,
{
path: "/clouds/:cloud/services/nosql/resources/:id/containers/:containerId/items",
method: "GET",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.nosql.cosmos.items.upsert,
{
path: "/clouds/:cloud/services/nosql/resources/:id/containers/:containerId/items",
method: "POST",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.nosql.cosmos.items.delete,
{
path: "/clouds/:cloud/services/nosql/resources/:id/containers/:containerId/items/:itemId",
method: "DELETE",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.nosql.cosmos.items.query,
{
path: "/clouds/:cloud/services/nosql/resources/:id/containers/:containerId/query",
method: "POST",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.database.sql.databases,
{
path: "/clouds/:cloud/services/database/resources/:id/sql/databases",
method: "POST",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.database.sql.tables,
{
path: "/clouds/:cloud/services/database/resources/:id/sql/tables",
method: "POST",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.database.sql.query,
{
path: "/clouds/:cloud/services/database/resources/:id/sql/query",
method: "POST",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.logs.query,
{
path: "/clouds/:cloud/services/logs/resources/:id/query",
method: "POST",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.database.snapshots.list,
{
path: "/clouds/:cloud/services/database/snapshots",
method: "GET",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.database.snapshots.create,
{
path: "/clouds/:cloud/services/database/snapshots",
method: "POST",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.database.orderableClasses.list,
{
path: "/clouds/:cloud/services/database/orderable-classes",
method: "GET",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.nosql.items.list,
{
path: "/clouds/:cloud/services/nosql/resources/:id/items",
method: "GET",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.nosql.items.put,
{
path: "/clouds/:cloud/services/nosql/resources/:id/items",
method: "POST",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.k8s.nodegroups.list,
{
path: "/clouds/:cloud/services/k8s/resources/:id/nodegroups",
method: "GET",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.k8s.nodegroups.create,
{
path: "/clouds/:cloud/services/k8s/resources/:id/nodegroups",
method: "POST",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.k8s.nodegroups.delete,
{
path: "/clouds/:cloud/services/k8s/resources/:id/nodegroups/:nodegroupId",
method: "DELETE",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.k8s.fargateProfiles.list,
{
path: "/clouds/:cloud/services/k8s/resources/:id/fargate-profiles",
method: "GET",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.k8s.fargateProfiles.create,
{
path: "/clouds/:cloud/services/k8s/resources/:id/fargate-profiles",
method: "POST",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.k8s.fargateProfiles.delete,
{
path: "/clouds/:cloud/services/k8s/resources/:id/fargate-profiles/:profileId",
method: "DELETE",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.email.inbox.clear,
{
path: "/clouds/:cloud/services/email/inbox",
method: "DELETE",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.configuration.environments.list,
{
path: "/clouds/:cloud/services/configuration/resources/:id/environments",
method: "GET",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.configuration.environments.create,
{
path: "/clouds/:cloud/services/configuration/resources/:id/environments",
method: "POST",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.configuration.environments.delete,
{
path: "/clouds/:cloud/services/configuration/resources/:id/environments/:environmentId",
method: "DELETE",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.configuration.environments.deployments.start,
{
path: "/clouds/:cloud/services/configuration/resources/:id/environments/:environmentId/deployments",
method: "POST",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.configuration.environments.deployments.get,
{
path: "/clouds/:cloud/services/configuration/resources/:id/environments/:environmentId/deployments/:deploymentNumber",
method: "GET",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.configuration.configurationProfiles.list,
{
path: "/clouds/:cloud/services/configuration/resources/:id/configuration-profiles",
method: "GET",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.configuration.configurationProfiles.create,
{
path: "/clouds/:cloud/services/configuration/resources/:id/configuration-profiles",
method: "POST",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.configuration.configurationProfiles.delete,
{
path: "/clouds/:cloud/services/configuration/resources/:id/configuration-profiles/:profileId",
method: "DELETE",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.configuration.configurationProfiles.hostedVersions.list,
{
path: "/clouds/:cloud/services/configuration/resources/:id/configuration-profiles/:profileId/hosted-configuration-versions",
method: "GET",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.configuration.configurationProfiles.hostedVersions.get,
{
path: "/clouds/:cloud/services/configuration/resources/:id/configuration-profiles/:profileId/hosted-configuration-versions/:versionNumber",
method: "GET",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.configuration.configurationProfiles.hostedVersions.create,
{
path: "/clouds/:cloud/services/configuration/resources/:id/configuration-profiles/:profileId/hosted-configuration-versions",
method: "POST",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.configuration.configurationProfiles.hostedVersions.delete,
{
path: "/clouds/:cloud/services/configuration/resources/:id/configuration-profiles/:profileId/hosted-configuration-versions/:versionNumber",
method: "DELETE",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.configuration.deploymentStrategies.list,
{
path: "/clouds/:cloud/services/configuration/deployment-strategies",
method: "GET",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.configuration.deploymentStrategies.create,
{
path: "/clouds/:cloud/services/configuration/deployment-strategies",
method: "POST",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.configuration.deploymentStrategies.delete,
{
path: "/clouds/:cloud/services/configuration/deployment-strategies/:strategyId",
method: "DELETE",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.childCollections.list,
{
path: "/clouds/:cloud/services/:service/resources/:id/collections",
method: "GET",
telemetry: { service: "cloud-proxy" },
},
],
[
apiEndpointKeys.clouds.childCollections.items.list,
{
path: "/clouds/:cloud/services/:service/resources/:id/collections/:cid/items",
method: "GET",
telemetry: { service: "cloud-proxy" },
},
],
// AWS EKS
[
apiEndpointKeys.aws.eks.clusters.list,
{
path: "/eks/clusters",
method: "GET",
telemetry: { provider: "aws", service: "eks" },
},
],
[
apiEndpointKeys.aws.eks.clusters.describe,
{
path: "/eks/clusters/:name",
method: "GET",
telemetry: { provider: "aws", service: "eks" },
},
],
[
apiEndpointKeys.aws.eks.nodegroups.list,
{
path: "/eks/clusters/:name/nodegroups",
method: "GET",
telemetry: { provider: "aws", service: "eks" },
},
],
[
apiEndpointKeys.aws.eks.nodegroups.describe,
{
path: "/eks/clusters/:name/nodegroups/:nodegroup",
method: "GET",
telemetry: { provider: "aws", service: "eks" },
},
],
[
apiEndpointKeys.aws.eks.nodegroups.create,
{
path: "/eks/clusters/:name/nodegroups",
method: "POST",
telemetry: { provider: "aws", service: "eks" },
},
],
[
apiEndpointKeys.aws.eks.nodegroups.delete,
{
path: "/eks/clusters/:name/nodegroups/:nodegroup",
method: "DELETE",
telemetry: { provider: "aws", service: "eks" },
},
],
[
apiEndpointKeys.aws.eks.fargateProfiles.list,
{
path: "/eks/clusters/:name/fargate-profiles",
method: "GET",
telemetry: { provider: "aws", service: "eks" },
},
],
[
apiEndpointKeys.aws.eks.fargateProfiles.describe,
{
path: "/eks/clusters/:name/fargate-profiles/:profile",
method: "GET",
telemetry: { provider: "aws", service: "eks" },
},
],
[
apiEndpointKeys.aws.eks.fargateProfiles.create,
{
path: "/eks/clusters/:name/fargate-profiles",
method: "POST",
telemetry: { provider: "aws", service: "eks" },
},
],
[
apiEndpointKeys.aws.eks.fargateProfiles.delete,
{
path: "/eks/clusters/:name/fargate-profiles/:profile",
method: "DELETE",
telemetry: { provider: "aws", service: "eks" },
},
],
// AWS Secrets Manager
[
apiEndpointKeys.aws.secretsmanager.secrets.list,
{
path: "/secretsmanager/secrets",
method: "GET",
telemetry: { provider: "aws", service: "secretsmanager" },
},
],
[
apiEndpointKeys.aws.secretsmanager.secrets.create,
{
path: "/secretsmanager/secrets",
method: "POST",
telemetry: { provider: "aws", service: "secretsmanager" },
},
],
[
apiEndpointKeys.aws.secretsmanager.secrets.describe,
{
path: "/secretsmanager/secret",
method: "GET",
telemetry: { provider: "aws", service: "secretsmanager" },
},
],
[
apiEndpointKeys.aws.secretsmanager.secrets.delete,
{
path: "/secretsmanager/secret",
method: "DELETE",
telemetry: { provider: "aws", service: "secretsmanager" },
},
],
[
apiEndpointKeys.aws.secretsmanager.secrets.value.get,
{
path: "/secretsmanager/secret/value",
method: "GET",
telemetry: { provider: "aws", service: "secretsmanager" },
},
],
[
apiEndpointKeys.aws.secretsmanager.secrets.value.put,
{
path: "/secretsmanager/secret/value",
method: "PUT",
telemetry: { provider: "aws", service: "secretsmanager" },
},
],
// AWS EC2
[apiEndpointKeys.aws.ec2.instances.list, { path: "/ec2/instances", method: "GET", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.instances.describe, { path: "/ec2/instances/:instanceId", method: "GET", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.instances.create, { path: "/ec2/instances", method: "POST", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.instances.start, { path: "/ec2/instances/:instanceId/start", method: "POST", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.instances.stop, { path: "/ec2/instances/:instanceId/stop", method: "POST", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.instances.reboot, { path: "/ec2/instances/:instanceId/reboot", method: "POST", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.instances.terminate,{ path: "/ec2/instances/:instanceId/terminate", method: "POST", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.instances.tags, { path: "/ec2/instances/:instanceId/tags", method: "PUT", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.instances.createImage, { path: "/ec2/instances/:instanceId/image", method: "POST", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.instances.console, { path: "/ec2/instances/:instanceId/console", method: "GET", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.amis.list, { path: "/ec2/amis", method: "GET", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.amis.deregister, { path: "/ec2/amis/:imageId/deregister", method: "POST", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.keyPairs.list, { path: "/ec2/key-pairs", method: "GET", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.keyPairs.create, { path: "/ec2/key-pairs", method: "POST", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.keyPairs.delete, { path: "/ec2/key-pairs/:name", method: "DELETE", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.securityGroups.list, { path: "/ec2/security-groups", method: "GET", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.securityGroups.create, { path: "/ec2/security-groups", method: "POST", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.securityGroups.delete, { path: "/ec2/security-groups/:groupId", method: "DELETE", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.securityGroups.authorize, { path: "/ec2/security-groups/:groupId/ingress", method: "POST", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.securityGroups.revoke, { path: "/ec2/security-groups/:groupId/ingress", method: "DELETE", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.securityGroups.authorizeEgress, { path: "/ec2/security-groups/:groupId/egress", method: "POST", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.securityGroups.revokeEgress, { path: "/ec2/security-groups/:groupId/egress", method: "DELETE", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.vpcs.list, { path: "/ec2/vpcs", method: "GET", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.vpcs.create, { path: "/ec2/vpcs", method: "POST", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.vpcs.delete, { path: "/ec2/vpcs/:vpcId", method: "DELETE", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.vpcs.getAttributes, { path: "/ec2/vpcs/:vpcId/attributes", method: "GET", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.vpcs.modifyAttribute, { path: "/ec2/vpcs/:vpcId/attributes", method: "PUT", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.subnets.list, { path: "/ec2/subnets", method: "GET", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.subnets.create, { path: "/ec2/subnets", method: "POST", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.subnets.delete, { path: "/ec2/subnets/:subnetId", method: "DELETE", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.subnets.modifyAttribute, { path: "/ec2/subnets/:subnetId/attributes", method: "PUT", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.internetGateways.list, { path: "/ec2/internet-gateways", method: "GET", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.internetGateways.create, { path: "/ec2/internet-gateways", method: "POST", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.internetGateways.attach, { path: "/ec2/internet-gateways/:igwId/attach", method: "POST", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.internetGateways.detach, { path: "/ec2/internet-gateways/:igwId/detach", method: "POST", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.internetGateways.delete, { path: "/ec2/internet-gateways/:igwId", method: "DELETE", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.natGateways.list, { path: "/ec2/nat-gateways", method: "GET", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.natGateways.create, { path: "/ec2/nat-gateways", method: "POST", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.natGateways.delete, { path: "/ec2/nat-gateways/:natId", method: "DELETE", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.routeTables.list, { path: "/ec2/route-tables", method: "GET", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.routeTables.create, { path: "/ec2/route-tables", method: "POST", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.routeTables.delete, { path: "/ec2/route-tables/:rtbId", method: "DELETE", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.routeTables.createRoute, { path: "/ec2/route-tables/:rtbId/routes", method: "POST", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.routeTables.deleteRoute, { path: "/ec2/route-tables/:rtbId/routes", method: "DELETE", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.routeTables.associate, { path: "/ec2/route-tables/:rtbId/associations", method: "POST", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.routeTables.disassociate,{ path: "/ec2/route-table-associations/:associationId", method: "DELETE", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.elasticIps.list, { path: "/ec2/elastic-ips", method: "GET", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.elasticIps.create, { path: "/ec2/elastic-ips", method: "POST", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.elasticIps.release, { path: "/ec2/elastic-ips/:allocationId/release", method: "POST", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.elasticIps.associate, { path: "/ec2/elastic-ips/:allocationId/associate", method: "POST", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.elasticIps.disassociate, { path: "/ec2/elastic-ips/:allocationId/disassociate", method: "POST", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.availabilityZones, { path: "/ec2/availability-zones", method: "GET", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.instanceTypes, { path: "/ec2/instance-types", method: "GET", telemetry: { provider: "aws", service: "ec2" } }],
[apiEndpointKeys.aws.ec2.vpcWizard, { path: "/ec2/vpc-wizard", method: "POST", telemetry: { provider: "aws", service: "ec2" } }],
]);
// ─── Client Factory ───────────────────────────────────────────────────────────
export function createApiClient(
getToken?: () => string | null | Promise<string | null>,
) {
const client = new HttpClient(
{
baseUrl: API_BASE_URL,
defaultHeaders: { Accept: "application/json" },
timeout: 10_000,
},
endpointRegistry,
);
// Account scope — every request carries the active AWS account so Floci can
// isolate resources per account (the API maps this header to its SDK creds).
client.addRequestInterceptor((url, init) => {
const headers = (init.headers ?? {}) as Record<string, string>;
headers[ACCOUNT_HEADER] = getAccountId();
init.headers = headers;
return { url, init };
});
// Auth interceptor — attaches Bearer token if available
if (getToken) {
client.addRequestInterceptor(async (url, init) => {
const token = await getToken();
if (token) {
(init.headers as Record<string, string>)["Authorization"] =
`Bearer ${token}`;
}
return { url, init };
});
}
// Logging interceptor (dev only)
if (import.meta.env.DEV) {
client.addResponseInterceptor((res) => {
console.debug(`[HTTP] ${res.status} ${res.url}`);
return res;
});
}
// client.addResponseInterceptor((res) => {
// if (res.status === 401) {
// handleUnauthorizedApiResponse();
// }
// return res;
// });
return client;
}
export const apiClient = createApiClient();