feat: ElastiCache

This commit is contained in:
Zakaria
2026-10-05 16:03:05 -04:00
parent c0d3e5f402
commit c86b4554c0
27 changed files with 2454 additions and 5 deletions
@@ -0,0 +1,85 @@
import {apiClient} from './api'
import {HttpError} from './HttpClient'
export interface RedisCredentials {
username?: string
password?: string
}
export interface RedisTarget {
resourceId: string
resourceType: 'replication-group' | 'cache-cluster'
engine: 'redis' | 'valkey'
endpoint: {address: string; port: number; kind: 'configuration' | 'primary' | 'node'}
}
export interface RedisExplorerRequest {
resourceId: string
credentials?: RedisCredentials
}
export interface RedisKeyDetails {
key: string
type: string
ttlSeconds: number
value: unknown
}
export type ElastiCacheUser = { UserId?: string; UserName?: string; Engine?: string; AccessString?: string; Authentication?: { Type?: string } }
export type ElastiCacheSubnetGroup = { CacheSubnetGroupName?: string; CacheSubnetGroupDescription?: string; Subnets?: Array<{ SubnetIdentifier?: string }> }
export type ElastiCacheParameterGroup = { CacheParameterGroupName?: string; CacheParameterGroupFamily?: string; Description?: string }
export type ElastiCacheParameter = { ParameterName?: string; ParameterValue?: string; IsModifiable?: boolean; Description?: string; DataType?: string }
export type ElastiCacheUserInput = { userId: string; userName: string; engine: 'redis' | 'valkey'; accessString: string; authenticationMode: 'password' | 'no-password-required' | 'iam'; passwords?: string[] }
export type CacheSubnetGroupInput = { cacheSubnetGroupName: string; cacheSubnetGroupDescription: string; subnetIds: string[] }
export type CacheParameterGroupInput = { cacheParameterGroupName: string; cacheParameterGroupFamily: string; description: string }
export async function connectRedis(input: RedisExplorerRequest): Promise<{target: RedisTarget; ping: string}> {
return request('/elasticache/connect', input)
}
export async function scanRedisKeys(input: RedisExplorerRequest & {cursor?: string; count?: number; match?: string}): Promise<{cursor: string; keys: string[]}> {
return request('/elasticache/keys/scan', input)
}
export async function getRedisKeyDetails(input: RedisExplorerRequest & {key: string}): Promise<RedisKeyDetails | null> {
return request('/elasticache/keys/details', input)
}
export async function setRedisString(input: RedisExplorerRequest & {key: string; value: string; ttlSeconds?: number}): Promise<{ok: true}> {
return request('/elasticache/keys/set', input)
}
export async function deleteRedisKey(input: RedisExplorerRequest & {key: string}): Promise<{deleted: boolean}> {
return request('/elasticache/keys/delete', input)
}
export async function listElastiCacheUsers(): Promise<ElastiCacheUser[]> { return get('/elasticache/users') }
export async function createElastiCacheUser(input: ElastiCacheUserInput): Promise<unknown> { return request('/elasticache/users', input) }
export async function modifyElastiCacheUser(userId: string, input: Omit<ElastiCacheUserInput, 'userId' | 'userName' | 'engine'>): Promise<unknown> { return patch(`/elasticache/users/${encodeURIComponent(userId)}`, input) }
export async function deleteElastiCacheUser(userId: string): Promise<unknown> { return remove(`/elasticache/users/${encodeURIComponent(userId)}`) }
export async function listCacheSubnetGroups(): Promise<ElastiCacheSubnetGroup[]> { return get('/elasticache/subnet-groups') }
export async function createCacheSubnetGroup(input: CacheSubnetGroupInput): Promise<unknown> { return request('/elasticache/subnet-groups', input) }
export async function modifyCacheSubnetGroup(name: string, input: Omit<CacheSubnetGroupInput, 'cacheSubnetGroupName'>): Promise<unknown> { return patch(`/elasticache/subnet-groups/${encodeURIComponent(name)}`, input) }
export async function deleteCacheSubnetGroup(name: string): Promise<unknown> { return remove(`/elasticache/subnet-groups/${encodeURIComponent(name)}`) }
export async function listCacheParameterGroups(): Promise<ElastiCacheParameterGroup[]> { return get('/elasticache/parameter-groups') }
export async function createCacheParameterGroup(input: CacheParameterGroupInput): Promise<unknown> { return request('/elasticache/parameter-groups', input) }
export async function deleteCacheParameterGroup(name: string): Promise<unknown> { return remove(`/elasticache/parameter-groups/${encodeURIComponent(name)}`) }
export async function listCacheParameters(name: string): Promise<ElastiCacheParameter[]> { return get(`/elasticache/parameter-groups/${encodeURIComponent(name)}/parameters`) }
export async function setCacheParameters(name: string, parameters: Array<{parameterName: string; parameterValue: string}>): Promise<unknown> { return put(`/elasticache/parameter-groups/${encodeURIComponent(name)}/parameters`, {parameters}) }
async function request<TResponse, TBody>(path: string, body: TBody): Promise<TResponse> {
try {
return (await apiClient.post<TResponse, TBody>(path, body)).data
} catch (error) {
if (error instanceof HttpError) {
const apiError = error.body as {error?: {code?: unknown; message?: unknown}}
if (typeof apiError.error?.message === 'string') throw Object.assign(new Error(apiError.error.message), {cause: error})
}
throw error
}
}
async function get<T>(path: string): Promise<T> { return (await apiClient.get<T>(path)).data }
async function patch<T, B>(path: string, body: B): Promise<T> { return (await apiClient.patch<T, B>(path, body)).data }
async function put<T, B>(path: string, body: B): Promise<T> { return (await apiClient.put<T, B>(path, body)).data }
async function remove<T>(path: string): Promise<T> { return (await apiClient.delete<T>(path)).data }