chore: import upstream snapshot with attribution
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import { z } from 'zod'
|
||||
import { genericToolResponseSchema } from '@/lib/api/contracts/tools/shared'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { RawFileInputSchema } from '@/lib/uploads/utils/file-schemas'
|
||||
|
||||
const a2aBaseBodySchema = z.object({
|
||||
agentUrl: z.string().url('Agent URL must be a valid URL').max(2048),
|
||||
apiKey: z.string().optional(),
|
||||
})
|
||||
|
||||
export const a2aSendMessageBodySchema = a2aBaseBodySchema.extend({
|
||||
message: z.string().min(1, 'Message is required'),
|
||||
data: z.union([z.string(), z.record(z.string(), z.unknown())]).optional(),
|
||||
files: z.array(RawFileInputSchema).max(20).optional(),
|
||||
taskId: z.string().optional(),
|
||||
contextId: z.string().optional(),
|
||||
})
|
||||
|
||||
export const a2aGetTaskBodySchema = a2aBaseBodySchema.extend({
|
||||
taskId: z.string().min(1, 'Task ID is required'),
|
||||
historyLength: z
|
||||
.number()
|
||||
.int()
|
||||
.positive()
|
||||
.max(1000, 'History length cannot exceed 1000')
|
||||
.optional(),
|
||||
})
|
||||
|
||||
export const a2aCancelTaskBodySchema = a2aBaseBodySchema.extend({
|
||||
taskId: z.string().min(1, 'Task ID is required'),
|
||||
})
|
||||
|
||||
export const a2aGetAgentCardContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/a2a/get-agent-card',
|
||||
body: a2aBaseBodySchema,
|
||||
response: { mode: 'json', schema: genericToolResponseSchema },
|
||||
})
|
||||
|
||||
export const a2aSendMessageContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/a2a/send-message',
|
||||
body: a2aSendMessageBodySchema,
|
||||
response: { mode: 'json', schema: genericToolResponseSchema },
|
||||
})
|
||||
|
||||
export const a2aGetTaskContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/a2a/get-task',
|
||||
body: a2aGetTaskBodySchema,
|
||||
response: { mode: 'json', schema: genericToolResponseSchema },
|
||||
})
|
||||
|
||||
export const a2aCancelTaskContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/a2a/cancel-task',
|
||||
body: a2aCancelTaskBodySchema,
|
||||
response: { mode: 'json', schema: genericToolResponseSchema },
|
||||
})
|
||||
@@ -0,0 +1,396 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { FileInputSchema } from '@/lib/uploads/utils/file-schemas'
|
||||
|
||||
const agiloftFileOutputSchema = z.object({
|
||||
name: z.string(),
|
||||
mimeType: z.string(),
|
||||
data: z.string(),
|
||||
size: z.number(),
|
||||
})
|
||||
|
||||
export const agiloftRetrieveResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
file: agiloftFileOutputSchema,
|
||||
}),
|
||||
})
|
||||
|
||||
export const agiloftAttachResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
recordId: z.string(),
|
||||
fieldName: z.string(),
|
||||
fileName: z.string(),
|
||||
totalAttachments: z.number(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const agiloftRetrieveBodySchema = z.object({
|
||||
instanceUrl: z.string().min(1, 'Instance URL is required'),
|
||||
knowledgeBase: z.string().min(1, 'Knowledge base is required'),
|
||||
login: z.string().min(1, 'Login is required'),
|
||||
password: z.string().min(1, 'Password is required'),
|
||||
table: z.string().min(1, 'Table is required'),
|
||||
recordId: z.string().min(1, 'Record ID is required'),
|
||||
fieldName: z.string().min(1, 'Field name is required'),
|
||||
position: z.string().min(1, 'Position is required'),
|
||||
})
|
||||
|
||||
export const agiloftAttachBodySchema = z.object({
|
||||
instanceUrl: z.string().min(1, 'Instance URL is required'),
|
||||
knowledgeBase: z.string().min(1, 'Knowledge base is required'),
|
||||
login: z.string().min(1, 'Login is required'),
|
||||
password: z.string().min(1, 'Password is required'),
|
||||
table: z.string().min(1, 'Table is required'),
|
||||
recordId: z.string().min(1, 'Record ID is required'),
|
||||
fieldName: z.string().min(1, 'Field name is required'),
|
||||
file: FileInputSchema.optional(),
|
||||
fileName: z.string().optional(),
|
||||
})
|
||||
|
||||
export const agiloftRetrieveContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/agiloft/retrieve',
|
||||
body: agiloftRetrieveBodySchema,
|
||||
response: { mode: 'json', schema: agiloftRetrieveResponseSchema },
|
||||
})
|
||||
|
||||
export const agiloftAttachContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/agiloft/attach',
|
||||
body: agiloftAttachBodySchema,
|
||||
response: { mode: 'json', schema: agiloftAttachResponseSchema },
|
||||
})
|
||||
|
||||
export type AgiloftRetrieveBody = ContractBody<typeof agiloftRetrieveContract>
|
||||
export type AgiloftRetrieveBodyInput = ContractBodyInput<typeof agiloftRetrieveContract>
|
||||
export type AgiloftRetrieveResponse = ContractJsonResponse<typeof agiloftRetrieveContract>
|
||||
export type AgiloftAttachBody = ContractBody<typeof agiloftAttachContract>
|
||||
export type AgiloftAttachBodyInput = ContractBodyInput<typeof agiloftAttachContract>
|
||||
export type AgiloftAttachResponse = ContractJsonResponse<typeof agiloftAttachContract>
|
||||
|
||||
const agiloftBaseFields = {
|
||||
instanceUrl: z.string().min(1, 'Instance URL is required'),
|
||||
knowledgeBase: z.string().min(1, 'Knowledge base is required'),
|
||||
login: z.string().min(1, 'Login is required'),
|
||||
password: z.string().min(1, 'Password is required'),
|
||||
table: z.string().min(1, 'Table is required'),
|
||||
} as const
|
||||
|
||||
export const agiloftCreateRecordBodySchema = z.object({
|
||||
...agiloftBaseFields,
|
||||
data: z.string().min(1, 'Data is required'),
|
||||
})
|
||||
|
||||
export const agiloftCreateRecordResponseSchema = z.object({
|
||||
success: z.boolean(),
|
||||
output: z.object({
|
||||
id: z.string().nullable(),
|
||||
fields: z.record(z.string(), z.unknown()),
|
||||
}),
|
||||
error: z.string().optional(),
|
||||
})
|
||||
|
||||
export const agiloftCreateRecordContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/agiloft/create_record',
|
||||
body: agiloftCreateRecordBodySchema,
|
||||
response: { mode: 'json', schema: agiloftCreateRecordResponseSchema },
|
||||
})
|
||||
|
||||
export type AgiloftCreateRecordBody = ContractBody<typeof agiloftCreateRecordContract>
|
||||
export type AgiloftCreateRecordBodyInput = ContractBodyInput<typeof agiloftCreateRecordContract>
|
||||
export type AgiloftCreateRecordResponse = ContractJsonResponse<typeof agiloftCreateRecordContract>
|
||||
|
||||
export const agiloftReadRecordBodySchema = z.object({
|
||||
...agiloftBaseFields,
|
||||
recordId: z.string().min(1, 'Record ID is required'),
|
||||
fields: z.string().optional(),
|
||||
})
|
||||
|
||||
export const agiloftReadRecordResponseSchema = z.object({
|
||||
success: z.boolean(),
|
||||
output: z.object({
|
||||
id: z.string().nullable(),
|
||||
fields: z.record(z.string(), z.unknown()),
|
||||
}),
|
||||
error: z.string().optional(),
|
||||
})
|
||||
|
||||
export const agiloftReadRecordContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/agiloft/read_record',
|
||||
body: agiloftReadRecordBodySchema,
|
||||
response: { mode: 'json', schema: agiloftReadRecordResponseSchema },
|
||||
})
|
||||
|
||||
export type AgiloftReadRecordBody = ContractBody<typeof agiloftReadRecordContract>
|
||||
export type AgiloftReadRecordBodyInput = ContractBodyInput<typeof agiloftReadRecordContract>
|
||||
export type AgiloftReadRecordResponse = ContractJsonResponse<typeof agiloftReadRecordContract>
|
||||
|
||||
export const agiloftUpdateRecordBodySchema = z.object({
|
||||
...agiloftBaseFields,
|
||||
recordId: z.string().min(1, 'Record ID is required'),
|
||||
data: z.string().min(1, 'Data is required'),
|
||||
})
|
||||
|
||||
export const agiloftUpdateRecordResponseSchema = z.object({
|
||||
success: z.boolean(),
|
||||
output: z.object({
|
||||
id: z.string().nullable(),
|
||||
fields: z.record(z.string(), z.unknown()),
|
||||
}),
|
||||
error: z.string().optional(),
|
||||
})
|
||||
|
||||
export const agiloftUpdateRecordContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/agiloft/update_record',
|
||||
body: agiloftUpdateRecordBodySchema,
|
||||
response: { mode: 'json', schema: agiloftUpdateRecordResponseSchema },
|
||||
})
|
||||
|
||||
export type AgiloftUpdateRecordBody = ContractBody<typeof agiloftUpdateRecordContract>
|
||||
export type AgiloftUpdateRecordBodyInput = ContractBodyInput<typeof agiloftUpdateRecordContract>
|
||||
export type AgiloftUpdateRecordResponse = ContractJsonResponse<typeof agiloftUpdateRecordContract>
|
||||
|
||||
export const agiloftDeleteRecordBodySchema = z.object({
|
||||
...agiloftBaseFields,
|
||||
recordId: z.string().min(1, 'Record ID is required'),
|
||||
})
|
||||
|
||||
export const agiloftDeleteRecordResponseSchema = z.object({
|
||||
success: z.boolean(),
|
||||
output: z.object({
|
||||
id: z.string(),
|
||||
deleted: z.boolean(),
|
||||
}),
|
||||
error: z.string().optional(),
|
||||
})
|
||||
|
||||
export const agiloftDeleteRecordContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/agiloft/delete_record',
|
||||
body: agiloftDeleteRecordBodySchema,
|
||||
response: { mode: 'json', schema: agiloftDeleteRecordResponseSchema },
|
||||
})
|
||||
|
||||
export type AgiloftDeleteRecordBody = ContractBody<typeof agiloftDeleteRecordContract>
|
||||
export type AgiloftDeleteRecordBodyInput = ContractBodyInput<typeof agiloftDeleteRecordContract>
|
||||
export type AgiloftDeleteRecordResponse = ContractJsonResponse<typeof agiloftDeleteRecordContract>
|
||||
|
||||
export const agiloftLockRecordBodySchema = z.object({
|
||||
...agiloftBaseFields,
|
||||
recordId: z.string().min(1, 'Record ID is required'),
|
||||
lockAction: z.enum(['lock', 'unlock', 'check'], {
|
||||
message: 'Lock action must be "lock", "unlock", or "check"',
|
||||
}),
|
||||
})
|
||||
|
||||
export const agiloftLockRecordResponseSchema = z.object({
|
||||
success: z.boolean(),
|
||||
output: z.object({
|
||||
id: z.string(),
|
||||
lockStatus: z.string(),
|
||||
lockedBy: z.string().nullable(),
|
||||
lockExpiresInMinutes: z.number().nullable(),
|
||||
}),
|
||||
error: z.string().optional(),
|
||||
})
|
||||
|
||||
export const agiloftLockRecordContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/agiloft/lock_record',
|
||||
body: agiloftLockRecordBodySchema,
|
||||
response: { mode: 'json', schema: agiloftLockRecordResponseSchema },
|
||||
})
|
||||
|
||||
export type AgiloftLockRecordBody = ContractBody<typeof agiloftLockRecordContract>
|
||||
export type AgiloftLockRecordBodyInput = ContractBodyInput<typeof agiloftLockRecordContract>
|
||||
export type AgiloftLockRecordResponse = ContractJsonResponse<typeof agiloftLockRecordContract>
|
||||
|
||||
export const agiloftSearchRecordsBodySchema = z.object({
|
||||
...agiloftBaseFields,
|
||||
query: z.string().min(1, 'Query is required'),
|
||||
fields: z.string().optional(),
|
||||
page: z.string().optional(),
|
||||
limit: z.string().optional(),
|
||||
})
|
||||
|
||||
export const agiloftSearchRecordsResponseSchema = z.object({
|
||||
success: z.boolean(),
|
||||
output: z.object({
|
||||
records: z.array(z.record(z.string(), z.unknown())),
|
||||
totalCount: z.number(),
|
||||
page: z.number(),
|
||||
limit: z.number(),
|
||||
}),
|
||||
error: z.string().optional(),
|
||||
})
|
||||
|
||||
export const agiloftSearchRecordsContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/agiloft/search_records',
|
||||
body: agiloftSearchRecordsBodySchema,
|
||||
response: { mode: 'json', schema: agiloftSearchRecordsResponseSchema },
|
||||
})
|
||||
|
||||
export type AgiloftSearchRecordsBody = ContractBody<typeof agiloftSearchRecordsContract>
|
||||
export type AgiloftSearchRecordsBodyInput = ContractBodyInput<typeof agiloftSearchRecordsContract>
|
||||
export type AgiloftSearchRecordsResponse = ContractJsonResponse<typeof agiloftSearchRecordsContract>
|
||||
|
||||
export const agiloftSelectRecordsBodySchema = z.object({
|
||||
...agiloftBaseFields,
|
||||
where: z.string().min(1, 'Where clause is required'),
|
||||
})
|
||||
|
||||
export const agiloftSelectRecordsResponseSchema = z.object({
|
||||
success: z.boolean(),
|
||||
output: z.object({
|
||||
recordIds: z.array(z.string()),
|
||||
totalCount: z.number(),
|
||||
}),
|
||||
error: z.string().optional(),
|
||||
})
|
||||
|
||||
export const agiloftSelectRecordsContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/agiloft/select_records',
|
||||
body: agiloftSelectRecordsBodySchema,
|
||||
response: { mode: 'json', schema: agiloftSelectRecordsResponseSchema },
|
||||
})
|
||||
|
||||
export type AgiloftSelectRecordsBody = ContractBody<typeof agiloftSelectRecordsContract>
|
||||
export type AgiloftSelectRecordsBodyInput = ContractBodyInput<typeof agiloftSelectRecordsContract>
|
||||
export type AgiloftSelectRecordsResponse = ContractJsonResponse<typeof agiloftSelectRecordsContract>
|
||||
|
||||
export const agiloftSavedSearchBodySchema = z.object({
|
||||
...agiloftBaseFields,
|
||||
})
|
||||
|
||||
export const agiloftSavedSearchResponseSchema = z.object({
|
||||
success: z.boolean(),
|
||||
output: z.object({
|
||||
searches: z.array(
|
||||
z.object({
|
||||
name: z.string(),
|
||||
label: z.string(),
|
||||
id: z.union([z.string(), z.number()]),
|
||||
description: z.string().nullable(),
|
||||
})
|
||||
),
|
||||
}),
|
||||
error: z.string().optional(),
|
||||
})
|
||||
|
||||
export const agiloftSavedSearchContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/agiloft/saved_search',
|
||||
body: agiloftSavedSearchBodySchema,
|
||||
response: { mode: 'json', schema: agiloftSavedSearchResponseSchema },
|
||||
})
|
||||
|
||||
export type AgiloftSavedSearchBody = ContractBody<typeof agiloftSavedSearchContract>
|
||||
export type AgiloftSavedSearchBodyInput = ContractBodyInput<typeof agiloftSavedSearchContract>
|
||||
export type AgiloftSavedSearchResponse = ContractJsonResponse<typeof agiloftSavedSearchContract>
|
||||
|
||||
export const agiloftAttachmentInfoBodySchema = z.object({
|
||||
...agiloftBaseFields,
|
||||
recordId: z.string().min(1, 'Record ID is required'),
|
||||
fieldName: z.string().min(1, 'Field name is required'),
|
||||
})
|
||||
|
||||
export const agiloftAttachmentInfoResponseSchema = z.object({
|
||||
success: z.boolean(),
|
||||
output: z.object({
|
||||
attachments: z.array(
|
||||
z.object({
|
||||
position: z.number(),
|
||||
name: z.string(),
|
||||
size: z.number(),
|
||||
})
|
||||
),
|
||||
totalCount: z.number(),
|
||||
}),
|
||||
error: z.string().optional(),
|
||||
})
|
||||
|
||||
export const agiloftAttachmentInfoContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/agiloft/attachment_info',
|
||||
body: agiloftAttachmentInfoBodySchema,
|
||||
response: { mode: 'json', schema: agiloftAttachmentInfoResponseSchema },
|
||||
})
|
||||
|
||||
export type AgiloftAttachmentInfoBody = ContractBody<typeof agiloftAttachmentInfoContract>
|
||||
export type AgiloftAttachmentInfoBodyInput = ContractBodyInput<typeof agiloftAttachmentInfoContract>
|
||||
export type AgiloftAttachmentInfoResponse = ContractJsonResponse<
|
||||
typeof agiloftAttachmentInfoContract
|
||||
>
|
||||
|
||||
export const agiloftRemoveAttachmentBodySchema = z.object({
|
||||
...agiloftBaseFields,
|
||||
recordId: z.string().min(1, 'Record ID is required'),
|
||||
fieldName: z.string().min(1, 'Field name is required'),
|
||||
position: z.string().min(1, 'Position is required'),
|
||||
})
|
||||
|
||||
export const agiloftRemoveAttachmentResponseSchema = z.object({
|
||||
success: z.boolean(),
|
||||
output: z.object({
|
||||
recordId: z.string(),
|
||||
fieldName: z.string(),
|
||||
remainingAttachments: z.number(),
|
||||
}),
|
||||
error: z.string().optional(),
|
||||
})
|
||||
|
||||
export const agiloftRemoveAttachmentContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/agiloft/remove_attachment',
|
||||
body: agiloftRemoveAttachmentBodySchema,
|
||||
response: { mode: 'json', schema: agiloftRemoveAttachmentResponseSchema },
|
||||
})
|
||||
|
||||
export type AgiloftRemoveAttachmentBody = ContractBody<typeof agiloftRemoveAttachmentContract>
|
||||
export type AgiloftRemoveAttachmentBodyInput = ContractBodyInput<
|
||||
typeof agiloftRemoveAttachmentContract
|
||||
>
|
||||
export type AgiloftRemoveAttachmentResponse = ContractJsonResponse<
|
||||
typeof agiloftRemoveAttachmentContract
|
||||
>
|
||||
|
||||
export const agiloftGetChoiceLineIdBodySchema = z.object({
|
||||
...agiloftBaseFields,
|
||||
fieldName: z.string().min(1, 'Field name is required'),
|
||||
value: z.string().min(1, 'Value is required'),
|
||||
})
|
||||
|
||||
export const agiloftGetChoiceLineIdResponseSchema = z.object({
|
||||
success: z.boolean(),
|
||||
output: z.object({
|
||||
choiceLineId: z.number().nullable(),
|
||||
}),
|
||||
error: z.string().optional(),
|
||||
})
|
||||
|
||||
export const agiloftGetChoiceLineIdContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/agiloft/get_choice_line_id',
|
||||
body: agiloftGetChoiceLineIdBodySchema,
|
||||
response: { mode: 'json', schema: agiloftGetChoiceLineIdResponseSchema },
|
||||
})
|
||||
|
||||
export type AgiloftGetChoiceLineIdBody = ContractBody<typeof agiloftGetChoiceLineIdContract>
|
||||
export type AgiloftGetChoiceLineIdBodyInput = ContractBodyInput<
|
||||
typeof agiloftGetChoiceLineIdContract
|
||||
>
|
||||
export type AgiloftGetChoiceLineIdResponse = ContractJsonResponse<
|
||||
typeof agiloftGetChoiceLineIdContract
|
||||
>
|
||||
@@ -0,0 +1,376 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const asanaUserSummarySchema = z.object({
|
||||
gid: z.string(),
|
||||
name: z.string(),
|
||||
})
|
||||
|
||||
const asanaCreatedBySchema = asanaUserSummarySchema.extend({
|
||||
resource_type: z.string().optional(),
|
||||
})
|
||||
|
||||
const asanaTaskSchema = z.object({
|
||||
gid: z.string(),
|
||||
resource_type: z.string().optional(),
|
||||
resource_subtype: z.string().optional(),
|
||||
name: z.string(),
|
||||
notes: z.string(),
|
||||
completed: z.boolean(),
|
||||
assignee: asanaUserSummarySchema.optional(),
|
||||
created_by: asanaCreatedBySchema.optional(),
|
||||
due_on: z.string().optional(),
|
||||
created_at: z.string().optional(),
|
||||
modified_at: z.string().optional(),
|
||||
})
|
||||
|
||||
const asanaTaskMutationResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
ts: z.string(),
|
||||
gid: z.string(),
|
||||
name: z.string(),
|
||||
notes: z.string(),
|
||||
completed: z.boolean(),
|
||||
created_at: z.string().optional(),
|
||||
modified_at: z.string().optional(),
|
||||
permalink_url: z.string().optional(),
|
||||
})
|
||||
|
||||
const asanaTasksResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
ts: z.string(),
|
||||
tasks: z.array(asanaTaskSchema),
|
||||
next_page: z.unknown().optional(),
|
||||
})
|
||||
|
||||
const asanaSingleTaskResponseSchema = asanaTaskSchema.extend({
|
||||
success: z.literal(true),
|
||||
ts: z.string(),
|
||||
})
|
||||
|
||||
const asanaProjectSchema = z.object({
|
||||
gid: z.string(),
|
||||
name: z.string(),
|
||||
resource_type: z.string(),
|
||||
})
|
||||
|
||||
const asanaProjectsResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
ts: z.string(),
|
||||
projects: z.array(asanaProjectSchema),
|
||||
})
|
||||
|
||||
const asanaCommentResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
ts: z.string(),
|
||||
gid: z.string(),
|
||||
text: z.string(),
|
||||
created_at: z.string().optional(),
|
||||
created_by: asanaUserSummarySchema.optional(),
|
||||
})
|
||||
|
||||
const asanaGetTaskResponseSchema = z.union([
|
||||
asanaSingleTaskResponseSchema,
|
||||
asanaTasksResponseSchema,
|
||||
])
|
||||
|
||||
const asanaProjectRecordResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
ts: z.string(),
|
||||
gid: z.string(),
|
||||
name: z.string(),
|
||||
notes: z.string(),
|
||||
archived: z.boolean().optional(),
|
||||
color: z.string().nullable().optional(),
|
||||
created_at: z.string().optional(),
|
||||
modified_at: z.string().optional(),
|
||||
permalink_url: z.string().optional(),
|
||||
})
|
||||
|
||||
const asanaWorkspaceSchema = z.object({
|
||||
gid: z.string(),
|
||||
name: z.string(),
|
||||
resource_type: z.string().optional(),
|
||||
})
|
||||
|
||||
const asanaListWorkspacesResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
ts: z.string(),
|
||||
workspaces: z.array(asanaWorkspaceSchema),
|
||||
})
|
||||
|
||||
const asanaDeleteTaskResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
ts: z.string(),
|
||||
gid: z.string(),
|
||||
deleted: z.literal(true),
|
||||
})
|
||||
|
||||
const asanaAddFollowersResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
ts: z.string(),
|
||||
gid: z.string(),
|
||||
name: z.string(),
|
||||
followers: z.array(asanaUserSummarySchema),
|
||||
})
|
||||
|
||||
const asanaSectionSchema = z.object({
|
||||
gid: z.string(),
|
||||
name: z.string(),
|
||||
resource_type: z.string().optional(),
|
||||
})
|
||||
|
||||
const asanaSectionResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
ts: z.string(),
|
||||
gid: z.string(),
|
||||
name: z.string(),
|
||||
created_at: z.string().optional(),
|
||||
})
|
||||
|
||||
const asanaListSectionsResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
ts: z.string(),
|
||||
sections: z.array(asanaSectionSchema),
|
||||
})
|
||||
|
||||
export const asanaAddCommentBodySchema = z.object({
|
||||
accessToken: z.string().min(1, 'Access token is required'),
|
||||
taskGid: z.string().min(1, 'Task GID is required'),
|
||||
text: z.string().min(1, 'Comment text is required'),
|
||||
})
|
||||
|
||||
export const asanaCreateTaskBodySchema = z.object({
|
||||
accessToken: z.string().min(1, 'Access token is required'),
|
||||
name: z.string().min(1, 'Task name is required'),
|
||||
workspace: z.string().min(1, 'Workspace GID is required'),
|
||||
notes: z.string().nullish(),
|
||||
assignee: z.string().nullish(),
|
||||
due_on: z.string().nullish(),
|
||||
})
|
||||
|
||||
export const asanaGetProjectsBodySchema = z.object({
|
||||
accessToken: z.string().min(1, 'Access token is required'),
|
||||
workspace: z.string().min(1, 'Workspace is required'),
|
||||
})
|
||||
|
||||
export const asanaGetTaskBodySchema = z.object({
|
||||
accessToken: z.string().min(1, 'Access token is required'),
|
||||
taskGid: z.string().nullish(),
|
||||
workspace: z.string().nullish(),
|
||||
project: z.string().nullish(),
|
||||
limit: z.union([z.string(), z.number()]).nullish(),
|
||||
})
|
||||
|
||||
export const asanaSearchTasksBodySchema = z.object({
|
||||
accessToken: z.string().min(1, 'Access token is required'),
|
||||
workspace: z.string().min(1, 'Workspace is required'),
|
||||
text: z.string().nullish(),
|
||||
assignee: z.string().nullish(),
|
||||
projects: z.array(z.string()).nullish(),
|
||||
completed: z.boolean().nullish(),
|
||||
})
|
||||
|
||||
export const asanaUpdateTaskBodySchema = z.object({
|
||||
accessToken: z.string().min(1, 'Access token is required'),
|
||||
taskGid: z.string().min(1, 'Task GID is required'),
|
||||
name: z.string().nullish(),
|
||||
notes: z.string().nullish(),
|
||||
assignee: z.string().nullish(),
|
||||
completed: z.boolean().nullish(),
|
||||
due_on: z.string().nullish(),
|
||||
})
|
||||
|
||||
export const asanaCreateProjectBodySchema = z.object({
|
||||
accessToken: z.string().min(1, 'Access token is required'),
|
||||
workspace: z.string().min(1, 'Workspace GID is required'),
|
||||
name: z.string().min(1, 'Project name is required'),
|
||||
notes: z.string().nullish(),
|
||||
})
|
||||
|
||||
export const asanaGetProjectBodySchema = z.object({
|
||||
accessToken: z.string().min(1, 'Access token is required'),
|
||||
projectGid: z.string().min(1, 'Project GID is required'),
|
||||
})
|
||||
|
||||
export const asanaListWorkspacesBodySchema = z.object({
|
||||
accessToken: z.string().min(1, 'Access token is required'),
|
||||
})
|
||||
|
||||
export const asanaCreateSubtaskBodySchema = z.object({
|
||||
accessToken: z.string().min(1, 'Access token is required'),
|
||||
taskGid: z.string().min(1, 'Parent task GID is required'),
|
||||
name: z.string().min(1, 'Subtask name is required'),
|
||||
notes: z.string().nullish(),
|
||||
assignee: z.string().nullish(),
|
||||
due_on: z.string().nullish(),
|
||||
})
|
||||
|
||||
export const asanaDeleteTaskBodySchema = z.object({
|
||||
accessToken: z.string().min(1, 'Access token is required'),
|
||||
taskGid: z.string().min(1, 'Task GID is required'),
|
||||
})
|
||||
|
||||
export const asanaAddFollowersBodySchema = z.object({
|
||||
accessToken: z.string().min(1, 'Access token is required'),
|
||||
taskGid: z.string().min(1, 'Task GID is required'),
|
||||
followers: z.array(z.string().min(1)).min(1, 'At least one follower GID is required'),
|
||||
})
|
||||
|
||||
export const asanaCreateSectionBodySchema = z.object({
|
||||
accessToken: z.string().min(1, 'Access token is required'),
|
||||
projectGid: z.string().min(1, 'Project GID is required'),
|
||||
name: z.string().min(1, 'Section name is required'),
|
||||
})
|
||||
|
||||
export const asanaListSectionsBodySchema = z.object({
|
||||
accessToken: z.string().min(1, 'Access token is required'),
|
||||
projectGid: z.string().min(1, 'Project GID is required'),
|
||||
})
|
||||
|
||||
export const asanaAddCommentContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/asana/add-comment',
|
||||
body: asanaAddCommentBodySchema,
|
||||
response: { mode: 'json', schema: asanaCommentResponseSchema },
|
||||
})
|
||||
|
||||
export const asanaCreateTaskContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/asana/create-task',
|
||||
body: asanaCreateTaskBodySchema,
|
||||
response: { mode: 'json', schema: asanaTaskMutationResponseSchema },
|
||||
})
|
||||
|
||||
export const asanaGetProjectsContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/asana/get-projects',
|
||||
body: asanaGetProjectsBodySchema,
|
||||
response: { mode: 'json', schema: asanaProjectsResponseSchema },
|
||||
})
|
||||
|
||||
export const asanaGetTaskContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/asana/get-task',
|
||||
body: asanaGetTaskBodySchema,
|
||||
response: { mode: 'json', schema: asanaGetTaskResponseSchema },
|
||||
})
|
||||
|
||||
export const asanaSearchTasksContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/asana/search-tasks',
|
||||
body: asanaSearchTasksBodySchema,
|
||||
response: { mode: 'json', schema: asanaTasksResponseSchema },
|
||||
})
|
||||
|
||||
export const asanaUpdateTaskContract = defineRouteContract({
|
||||
method: 'PUT',
|
||||
path: '/api/tools/asana/update-task',
|
||||
body: asanaUpdateTaskBodySchema,
|
||||
response: { mode: 'json', schema: asanaTaskMutationResponseSchema },
|
||||
})
|
||||
|
||||
export const asanaCreateProjectContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/asana/create-project',
|
||||
body: asanaCreateProjectBodySchema,
|
||||
response: { mode: 'json', schema: asanaProjectRecordResponseSchema },
|
||||
})
|
||||
|
||||
export const asanaGetProjectContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/asana/get-project',
|
||||
body: asanaGetProjectBodySchema,
|
||||
response: { mode: 'json', schema: asanaProjectRecordResponseSchema },
|
||||
})
|
||||
|
||||
export const asanaListWorkspacesContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/asana/list-workspaces',
|
||||
body: asanaListWorkspacesBodySchema,
|
||||
response: { mode: 'json', schema: asanaListWorkspacesResponseSchema },
|
||||
})
|
||||
|
||||
export const asanaCreateSubtaskContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/asana/create-subtask',
|
||||
body: asanaCreateSubtaskBodySchema,
|
||||
response: { mode: 'json', schema: asanaTaskMutationResponseSchema },
|
||||
})
|
||||
|
||||
export const asanaDeleteTaskContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/asana/delete-task',
|
||||
body: asanaDeleteTaskBodySchema,
|
||||
response: { mode: 'json', schema: asanaDeleteTaskResponseSchema },
|
||||
})
|
||||
|
||||
export const asanaAddFollowersContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/asana/add-followers',
|
||||
body: asanaAddFollowersBodySchema,
|
||||
response: { mode: 'json', schema: asanaAddFollowersResponseSchema },
|
||||
})
|
||||
|
||||
export const asanaCreateSectionContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/asana/create-section',
|
||||
body: asanaCreateSectionBodySchema,
|
||||
response: { mode: 'json', schema: asanaSectionResponseSchema },
|
||||
})
|
||||
|
||||
export const asanaListSectionsContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/asana/list-sections',
|
||||
body: asanaListSectionsBodySchema,
|
||||
response: { mode: 'json', schema: asanaListSectionsResponseSchema },
|
||||
})
|
||||
|
||||
export type AsanaCreateProjectBody = ContractBody<typeof asanaCreateProjectContract>
|
||||
export type AsanaCreateProjectBodyInput = ContractBodyInput<typeof asanaCreateProjectContract>
|
||||
export type AsanaCreateProjectResponse = ContractJsonResponse<typeof asanaCreateProjectContract>
|
||||
export type AsanaGetProjectBody = ContractBody<typeof asanaGetProjectContract>
|
||||
export type AsanaGetProjectBodyInput = ContractBodyInput<typeof asanaGetProjectContract>
|
||||
export type AsanaGetProjectResponse = ContractJsonResponse<typeof asanaGetProjectContract>
|
||||
export type AsanaListWorkspacesBody = ContractBody<typeof asanaListWorkspacesContract>
|
||||
export type AsanaListWorkspacesBodyInput = ContractBodyInput<typeof asanaListWorkspacesContract>
|
||||
export type AsanaListWorkspacesResponse = ContractJsonResponse<typeof asanaListWorkspacesContract>
|
||||
export type AsanaCreateSubtaskBody = ContractBody<typeof asanaCreateSubtaskContract>
|
||||
export type AsanaCreateSubtaskBodyInput = ContractBodyInput<typeof asanaCreateSubtaskContract>
|
||||
export type AsanaCreateSubtaskResponse = ContractJsonResponse<typeof asanaCreateSubtaskContract>
|
||||
export type AsanaDeleteTaskBody = ContractBody<typeof asanaDeleteTaskContract>
|
||||
export type AsanaDeleteTaskBodyInput = ContractBodyInput<typeof asanaDeleteTaskContract>
|
||||
export type AsanaDeleteTaskResponse = ContractJsonResponse<typeof asanaDeleteTaskContract>
|
||||
export type AsanaAddFollowersBody = ContractBody<typeof asanaAddFollowersContract>
|
||||
export type AsanaAddFollowersBodyInput = ContractBodyInput<typeof asanaAddFollowersContract>
|
||||
export type AsanaAddFollowersResponse = ContractJsonResponse<typeof asanaAddFollowersContract>
|
||||
export type AsanaCreateSectionBody = ContractBody<typeof asanaCreateSectionContract>
|
||||
export type AsanaCreateSectionBodyInput = ContractBodyInput<typeof asanaCreateSectionContract>
|
||||
export type AsanaCreateSectionResponse = ContractJsonResponse<typeof asanaCreateSectionContract>
|
||||
export type AsanaListSectionsBody = ContractBody<typeof asanaListSectionsContract>
|
||||
export type AsanaListSectionsBodyInput = ContractBodyInput<typeof asanaListSectionsContract>
|
||||
export type AsanaListSectionsResponse = ContractJsonResponse<typeof asanaListSectionsContract>
|
||||
|
||||
export type AsanaAddCommentBody = ContractBody<typeof asanaAddCommentContract>
|
||||
export type AsanaAddCommentBodyInput = ContractBodyInput<typeof asanaAddCommentContract>
|
||||
export type AsanaAddCommentResponse = ContractJsonResponse<typeof asanaAddCommentContract>
|
||||
export type AsanaCreateTaskBody = ContractBody<typeof asanaCreateTaskContract>
|
||||
export type AsanaCreateTaskBodyInput = ContractBodyInput<typeof asanaCreateTaskContract>
|
||||
export type AsanaCreateTaskResponse = ContractJsonResponse<typeof asanaCreateTaskContract>
|
||||
export type AsanaGetProjectsBody = ContractBody<typeof asanaGetProjectsContract>
|
||||
export type AsanaGetProjectsBodyInput = ContractBodyInput<typeof asanaGetProjectsContract>
|
||||
export type AsanaGetProjectsResponse = ContractJsonResponse<typeof asanaGetProjectsContract>
|
||||
export type AsanaGetTaskBody = ContractBody<typeof asanaGetTaskContract>
|
||||
export type AsanaGetTaskBodyInput = ContractBodyInput<typeof asanaGetTaskContract>
|
||||
export type AsanaGetTaskResponse = ContractJsonResponse<typeof asanaGetTaskContract>
|
||||
export type AsanaSearchTasksBody = ContractBody<typeof asanaSearchTasksContract>
|
||||
export type AsanaSearchTasksBodyInput = ContractBodyInput<typeof asanaSearchTasksContract>
|
||||
export type AsanaSearchTasksResponse = ContractJsonResponse<typeof asanaSearchTasksContract>
|
||||
export type AsanaUpdateTaskBody = ContractBody<typeof asanaUpdateTaskContract>
|
||||
export type AsanaUpdateTaskBodyInput = ContractBodyInput<typeof asanaUpdateTaskContract>
|
||||
export type AsanaUpdateTaskResponse = ContractJsonResponse<typeof asanaUpdateTaskContract>
|
||||
@@ -0,0 +1,38 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const CreateApplicationSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
name: z.string().min(1, 'Application name is required').max(64),
|
||||
description: z.string().max(1024).nullish(),
|
||||
})
|
||||
|
||||
const CreateApplicationResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
description: z.string().nullable(),
|
||||
})
|
||||
|
||||
export const awsAppConfigCreateApplicationContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/appconfig/create-application',
|
||||
body: CreateApplicationSchema,
|
||||
response: { mode: 'json', schema: CreateApplicationResponseSchema },
|
||||
})
|
||||
export type AwsAppConfigCreateApplicationRequest = ContractBodyInput<
|
||||
typeof awsAppConfigCreateApplicationContract
|
||||
>
|
||||
export type AwsAppConfigCreateApplicationBody = ContractBody<
|
||||
typeof awsAppConfigCreateApplicationContract
|
||||
>
|
||||
export type AwsAppConfigCreateApplicationResponse = ContractJsonResponse<
|
||||
typeof awsAppConfigCreateApplicationContract
|
||||
>
|
||||
@@ -0,0 +1,44 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const CreateConfigurationProfileSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
applicationId: z.string().min(1, 'Application ID is required'),
|
||||
name: z.string().min(1, 'Configuration profile name is required').max(128),
|
||||
locationUri: z.string().min(1, 'Location URI is required').max(2048),
|
||||
description: z.string().max(1024).nullish(),
|
||||
retrievalRoleArn: z.string().nullish(),
|
||||
type: z.string().nullish(),
|
||||
})
|
||||
|
||||
const CreateConfigurationProfileResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
applicationId: z.string(),
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
locationUri: z.string().nullable(),
|
||||
type: z.string().nullable(),
|
||||
})
|
||||
|
||||
export const awsAppConfigCreateConfigurationProfileContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/appconfig/create-configuration-profile',
|
||||
body: CreateConfigurationProfileSchema,
|
||||
response: { mode: 'json', schema: CreateConfigurationProfileResponseSchema },
|
||||
})
|
||||
export type AwsAppConfigCreateConfigurationProfileRequest = ContractBodyInput<
|
||||
typeof awsAppConfigCreateConfigurationProfileContract
|
||||
>
|
||||
export type AwsAppConfigCreateConfigurationProfileBody = ContractBody<
|
||||
typeof awsAppConfigCreateConfigurationProfileContract
|
||||
>
|
||||
export type AwsAppConfigCreateConfigurationProfileResponse = ContractJsonResponse<
|
||||
typeof awsAppConfigCreateConfigurationProfileContract
|
||||
>
|
||||
@@ -0,0 +1,40 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const CreateEnvironmentSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
applicationId: z.string().min(1, 'Application ID is required'),
|
||||
name: z.string().min(1, 'Environment name is required').max(64),
|
||||
description: z.string().max(1024).nullish(),
|
||||
})
|
||||
|
||||
const CreateEnvironmentResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
applicationId: z.string(),
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
state: z.string().nullable(),
|
||||
})
|
||||
|
||||
export const awsAppConfigCreateEnvironmentContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/appconfig/create-environment',
|
||||
body: CreateEnvironmentSchema,
|
||||
response: { mode: 'json', schema: CreateEnvironmentResponseSchema },
|
||||
})
|
||||
export type AwsAppConfigCreateEnvironmentRequest = ContractBodyInput<
|
||||
typeof awsAppConfigCreateEnvironmentContract
|
||||
>
|
||||
export type AwsAppConfigCreateEnvironmentBody = ContractBody<
|
||||
typeof awsAppConfigCreateEnvironmentContract
|
||||
>
|
||||
export type AwsAppConfigCreateEnvironmentResponse = ContractJsonResponse<
|
||||
typeof awsAppConfigCreateEnvironmentContract
|
||||
>
|
||||
@@ -0,0 +1,45 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const CreateHostedConfigurationVersionSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
applicationId: z.string().min(1, 'Application ID is required'),
|
||||
configurationProfileId: z.string().min(1, 'Configuration profile ID is required'),
|
||||
content: z.string().min(1, 'Content is required'),
|
||||
contentType: z.string().min(1, 'Content type is required').max(255),
|
||||
description: z.string().max(1024).nullish(),
|
||||
latestVersionNumber: z.number().int().min(0).nullish(),
|
||||
versionLabel: z.string().max(64).nullish(),
|
||||
})
|
||||
|
||||
const CreateHostedConfigurationVersionResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
applicationId: z.string(),
|
||||
configurationProfileId: z.string(),
|
||||
versionNumber: z.number().nullable(),
|
||||
contentType: z.string().nullable(),
|
||||
versionLabel: z.string().nullable(),
|
||||
})
|
||||
|
||||
export const awsAppConfigCreateHostedConfigurationVersionContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/appconfig/create-hosted-configuration-version',
|
||||
body: CreateHostedConfigurationVersionSchema,
|
||||
response: { mode: 'json', schema: CreateHostedConfigurationVersionResponseSchema },
|
||||
})
|
||||
export type AwsAppConfigCreateHostedConfigurationVersionRequest = ContractBodyInput<
|
||||
typeof awsAppConfigCreateHostedConfigurationVersionContract
|
||||
>
|
||||
export type AwsAppConfigCreateHostedConfigurationVersionBody = ContractBody<
|
||||
typeof awsAppConfigCreateHostedConfigurationVersionContract
|
||||
>
|
||||
export type AwsAppConfigCreateHostedConfigurationVersionResponse = ContractJsonResponse<
|
||||
typeof awsAppConfigCreateHostedConfigurationVersionContract
|
||||
>
|
||||
@@ -0,0 +1,35 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const DeleteApplicationSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
applicationId: z.string().min(1, 'Application ID is required'),
|
||||
})
|
||||
|
||||
const DeleteApplicationResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
id: z.string(),
|
||||
})
|
||||
|
||||
export const awsAppConfigDeleteApplicationContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/appconfig/delete-application',
|
||||
body: DeleteApplicationSchema,
|
||||
response: { mode: 'json', schema: DeleteApplicationResponseSchema },
|
||||
})
|
||||
export type AwsAppConfigDeleteApplicationRequest = ContractBodyInput<
|
||||
typeof awsAppConfigDeleteApplicationContract
|
||||
>
|
||||
export type AwsAppConfigDeleteApplicationBody = ContractBody<
|
||||
typeof awsAppConfigDeleteApplicationContract
|
||||
>
|
||||
export type AwsAppConfigDeleteApplicationResponse = ContractJsonResponse<
|
||||
typeof awsAppConfigDeleteApplicationContract
|
||||
>
|
||||
@@ -0,0 +1,37 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const DeleteConfigurationProfileSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
applicationId: z.string().min(1, 'Application ID is required'),
|
||||
configurationProfileId: z.string().min(1, 'Configuration profile ID is required'),
|
||||
})
|
||||
|
||||
const DeleteConfigurationProfileResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
applicationId: z.string(),
|
||||
id: z.string(),
|
||||
})
|
||||
|
||||
export const awsAppConfigDeleteConfigurationProfileContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/appconfig/delete-configuration-profile',
|
||||
body: DeleteConfigurationProfileSchema,
|
||||
response: { mode: 'json', schema: DeleteConfigurationProfileResponseSchema },
|
||||
})
|
||||
export type AwsAppConfigDeleteConfigurationProfileRequest = ContractBodyInput<
|
||||
typeof awsAppConfigDeleteConfigurationProfileContract
|
||||
>
|
||||
export type AwsAppConfigDeleteConfigurationProfileBody = ContractBody<
|
||||
typeof awsAppConfigDeleteConfigurationProfileContract
|
||||
>
|
||||
export type AwsAppConfigDeleteConfigurationProfileResponse = ContractJsonResponse<
|
||||
typeof awsAppConfigDeleteConfigurationProfileContract
|
||||
>
|
||||
@@ -0,0 +1,37 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const DeleteEnvironmentSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
applicationId: z.string().min(1, 'Application ID is required'),
|
||||
environmentId: z.string().min(1, 'Environment ID is required'),
|
||||
})
|
||||
|
||||
const DeleteEnvironmentResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
applicationId: z.string(),
|
||||
id: z.string(),
|
||||
})
|
||||
|
||||
export const awsAppConfigDeleteEnvironmentContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/appconfig/delete-environment',
|
||||
body: DeleteEnvironmentSchema,
|
||||
response: { mode: 'json', schema: DeleteEnvironmentResponseSchema },
|
||||
})
|
||||
export type AwsAppConfigDeleteEnvironmentRequest = ContractBodyInput<
|
||||
typeof awsAppConfigDeleteEnvironmentContract
|
||||
>
|
||||
export type AwsAppConfigDeleteEnvironmentBody = ContractBody<
|
||||
typeof awsAppConfigDeleteEnvironmentContract
|
||||
>
|
||||
export type AwsAppConfigDeleteEnvironmentResponse = ContractJsonResponse<
|
||||
typeof awsAppConfigDeleteEnvironmentContract
|
||||
>
|
||||
@@ -0,0 +1,39 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const DeleteHostedConfigurationVersionSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
applicationId: z.string().min(1, 'Application ID is required'),
|
||||
configurationProfileId: z.string().min(1, 'Configuration profile ID is required'),
|
||||
versionNumber: z.number().int().min(1, 'Version number is required'),
|
||||
})
|
||||
|
||||
const DeleteHostedConfigurationVersionResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
applicationId: z.string(),
|
||||
configurationProfileId: z.string(),
|
||||
versionNumber: z.number(),
|
||||
})
|
||||
|
||||
export const awsAppConfigDeleteHostedConfigurationVersionContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/appconfig/delete-hosted-configuration-version',
|
||||
body: DeleteHostedConfigurationVersionSchema,
|
||||
response: { mode: 'json', schema: DeleteHostedConfigurationVersionResponseSchema },
|
||||
})
|
||||
export type AwsAppConfigDeleteHostedConfigurationVersionRequest = ContractBodyInput<
|
||||
typeof awsAppConfigDeleteHostedConfigurationVersionContract
|
||||
>
|
||||
export type AwsAppConfigDeleteHostedConfigurationVersionBody = ContractBody<
|
||||
typeof awsAppConfigDeleteHostedConfigurationVersionContract
|
||||
>
|
||||
export type AwsAppConfigDeleteHostedConfigurationVersionResponse = ContractJsonResponse<
|
||||
typeof awsAppConfigDeleteHostedConfigurationVersionContract
|
||||
>
|
||||
@@ -0,0 +1,34 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const GetApplicationSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
applicationId: z.string().min(1, 'Application ID is required'),
|
||||
})
|
||||
|
||||
const GetApplicationResponseSchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
description: z.string().nullable(),
|
||||
})
|
||||
|
||||
export const awsAppConfigGetApplicationContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/appconfig/get-application',
|
||||
body: GetApplicationSchema,
|
||||
response: { mode: 'json', schema: GetApplicationResponseSchema },
|
||||
})
|
||||
export type AwsAppConfigGetApplicationRequest = ContractBodyInput<
|
||||
typeof awsAppConfigGetApplicationContract
|
||||
>
|
||||
export type AwsAppConfigGetApplicationBody = ContractBody<typeof awsAppConfigGetApplicationContract>
|
||||
export type AwsAppConfigGetApplicationResponse = ContractJsonResponse<
|
||||
typeof awsAppConfigGetApplicationContract
|
||||
>
|
||||
@@ -0,0 +1,42 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const GetConfigurationProfileSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
applicationId: z.string().min(1, 'Application ID is required'),
|
||||
configurationProfileId: z.string().min(1, 'Configuration profile ID is required'),
|
||||
})
|
||||
|
||||
const GetConfigurationProfileResponseSchema = z.object({
|
||||
applicationId: z.string(),
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
description: z.string().nullable(),
|
||||
locationUri: z.string().nullable(),
|
||||
retrievalRoleArn: z.string().nullable(),
|
||||
type: z.string().nullable(),
|
||||
validators: z.array(z.object({ type: z.string() })),
|
||||
})
|
||||
|
||||
export const awsAppConfigGetConfigurationProfileContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/appconfig/get-configuration-profile',
|
||||
body: GetConfigurationProfileSchema,
|
||||
response: { mode: 'json', schema: GetConfigurationProfileResponseSchema },
|
||||
})
|
||||
export type AwsAppConfigGetConfigurationProfileRequest = ContractBodyInput<
|
||||
typeof awsAppConfigGetConfigurationProfileContract
|
||||
>
|
||||
export type AwsAppConfigGetConfigurationProfileBody = ContractBody<
|
||||
typeof awsAppConfigGetConfigurationProfileContract
|
||||
>
|
||||
export type AwsAppConfigGetConfigurationProfileResponse = ContractJsonResponse<
|
||||
typeof awsAppConfigGetConfigurationProfileContract
|
||||
>
|
||||
@@ -0,0 +1,38 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const GetConfigurationSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
applicationId: z.string().min(1, 'Application ID or name is required'),
|
||||
environmentId: z.string().min(1, 'Environment ID or name is required'),
|
||||
configurationProfileId: z.string().min(1, 'Configuration profile ID or name is required'),
|
||||
})
|
||||
|
||||
const GetConfigurationResponseSchema = z.object({
|
||||
configuration: z.string(),
|
||||
contentType: z.string().nullable(),
|
||||
versionLabel: z.string().nullable(),
|
||||
})
|
||||
|
||||
export const awsAppConfigGetConfigurationContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/appconfig/get-configuration',
|
||||
body: GetConfigurationSchema,
|
||||
response: { mode: 'json', schema: GetConfigurationResponseSchema },
|
||||
})
|
||||
export type AwsAppConfigGetConfigurationRequest = ContractBodyInput<
|
||||
typeof awsAppConfigGetConfigurationContract
|
||||
>
|
||||
export type AwsAppConfigGetConfigurationBody = ContractBody<
|
||||
typeof awsAppConfigGetConfigurationContract
|
||||
>
|
||||
export type AwsAppConfigGetConfigurationResponse = ContractJsonResponse<
|
||||
typeof awsAppConfigGetConfigurationContract
|
||||
>
|
||||
@@ -0,0 +1,45 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const GetDeploymentSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
applicationId: z.string().min(1, 'Application ID is required'),
|
||||
environmentId: z.string().min(1, 'Environment ID is required'),
|
||||
deploymentNumber: z.number().int().min(1, 'Deployment number is required'),
|
||||
})
|
||||
|
||||
const GetDeploymentResponseSchema = z.object({
|
||||
applicationId: z.string(),
|
||||
environmentId: z.string(),
|
||||
deploymentStrategyId: z.string(),
|
||||
configurationProfileId: z.string(),
|
||||
deploymentNumber: z.number().nullable(),
|
||||
configurationName: z.string().nullable(),
|
||||
configurationVersion: z.string().nullable(),
|
||||
description: z.string().nullable(),
|
||||
state: z.string().nullable(),
|
||||
percentageComplete: z.number().nullable(),
|
||||
startedAt: z.string().nullable(),
|
||||
completedAt: z.string().nullable(),
|
||||
})
|
||||
|
||||
export const awsAppConfigGetDeploymentContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/appconfig/get-deployment',
|
||||
body: GetDeploymentSchema,
|
||||
response: { mode: 'json', schema: GetDeploymentResponseSchema },
|
||||
})
|
||||
export type AwsAppConfigGetDeploymentRequest = ContractBodyInput<
|
||||
typeof awsAppConfigGetDeploymentContract
|
||||
>
|
||||
export type AwsAppConfigGetDeploymentBody = ContractBody<typeof awsAppConfigGetDeploymentContract>
|
||||
export type AwsAppConfigGetDeploymentResponse = ContractJsonResponse<
|
||||
typeof awsAppConfigGetDeploymentContract
|
||||
>
|
||||
@@ -0,0 +1,43 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const GetEnvironmentSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
applicationId: z.string().min(1, 'Application ID is required'),
|
||||
environmentId: z.string().min(1, 'Environment ID is required'),
|
||||
})
|
||||
|
||||
const GetEnvironmentResponseSchema = z.object({
|
||||
applicationId: z.string(),
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
description: z.string().nullable(),
|
||||
state: z.string().nullable(),
|
||||
monitors: z.array(
|
||||
z.object({
|
||||
alarmArn: z.string(),
|
||||
alarmRoleArn: z.string().nullable(),
|
||||
})
|
||||
),
|
||||
})
|
||||
|
||||
export const awsAppConfigGetEnvironmentContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/appconfig/get-environment',
|
||||
body: GetEnvironmentSchema,
|
||||
response: { mode: 'json', schema: GetEnvironmentResponseSchema },
|
||||
})
|
||||
export type AwsAppConfigGetEnvironmentRequest = ContractBodyInput<
|
||||
typeof awsAppConfigGetEnvironmentContract
|
||||
>
|
||||
export type AwsAppConfigGetEnvironmentBody = ContractBody<typeof awsAppConfigGetEnvironmentContract>
|
||||
export type AwsAppConfigGetEnvironmentResponse = ContractJsonResponse<
|
||||
typeof awsAppConfigGetEnvironmentContract
|
||||
>
|
||||
@@ -0,0 +1,42 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const GetHostedConfigurationVersionSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
applicationId: z.string().min(1, 'Application ID is required'),
|
||||
configurationProfileId: z.string().min(1, 'Configuration profile ID is required'),
|
||||
versionNumber: z.number().int().min(1, 'Version number is required'),
|
||||
})
|
||||
|
||||
const GetHostedConfigurationVersionResponseSchema = z.object({
|
||||
applicationId: z.string(),
|
||||
configurationProfileId: z.string(),
|
||||
versionNumber: z.number().nullable(),
|
||||
description: z.string().nullable(),
|
||||
content: z.string(),
|
||||
contentType: z.string().nullable(),
|
||||
versionLabel: z.string().nullable(),
|
||||
})
|
||||
|
||||
export const awsAppConfigGetHostedConfigurationVersionContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/appconfig/get-hosted-configuration-version',
|
||||
body: GetHostedConfigurationVersionSchema,
|
||||
response: { mode: 'json', schema: GetHostedConfigurationVersionResponseSchema },
|
||||
})
|
||||
export type AwsAppConfigGetHostedConfigurationVersionRequest = ContractBodyInput<
|
||||
typeof awsAppConfigGetHostedConfigurationVersionContract
|
||||
>
|
||||
export type AwsAppConfigGetHostedConfigurationVersionBody = ContractBody<
|
||||
typeof awsAppConfigGetHostedConfigurationVersionContract
|
||||
>
|
||||
export type AwsAppConfigGetHostedConfigurationVersionResponse = ContractJsonResponse<
|
||||
typeof awsAppConfigGetHostedConfigurationVersionContract
|
||||
>
|
||||
@@ -0,0 +1,43 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const ListApplicationsSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
maxResults: z.number().int().min(1).max(50).nullish(),
|
||||
nextToken: z.string().nullish(),
|
||||
})
|
||||
|
||||
const ApplicationSchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
description: z.string().nullable(),
|
||||
})
|
||||
|
||||
const ListApplicationsResponseSchema = z.object({
|
||||
applications: z.array(ApplicationSchema),
|
||||
nextToken: z.string().nullable(),
|
||||
count: z.number(),
|
||||
})
|
||||
|
||||
export const awsAppConfigListApplicationsContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/appconfig/list-applications',
|
||||
body: ListApplicationsSchema,
|
||||
response: { mode: 'json', schema: ListApplicationsResponseSchema },
|
||||
})
|
||||
export type AwsAppConfigListApplicationsRequest = ContractBodyInput<
|
||||
typeof awsAppConfigListApplicationsContract
|
||||
>
|
||||
export type AwsAppConfigListApplicationsBody = ContractBody<
|
||||
typeof awsAppConfigListApplicationsContract
|
||||
>
|
||||
export type AwsAppConfigListApplicationsResponse = ContractJsonResponse<
|
||||
typeof awsAppConfigListApplicationsContract
|
||||
>
|
||||
@@ -0,0 +1,49 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const ListConfigurationProfilesSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
applicationId: z.string().min(1, 'Application ID is required'),
|
||||
maxResults: z.number().int().min(1).max(50).nullish(),
|
||||
nextToken: z.string().nullish(),
|
||||
})
|
||||
|
||||
const ConfigurationProfileSchema = z.object({
|
||||
applicationId: z.string(),
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
description: z.string().nullable(),
|
||||
locationUri: z.string().nullable(),
|
||||
retrievalRoleArn: z.string().nullable(),
|
||||
type: z.string().nullable(),
|
||||
validatorTypes: z.array(z.string()),
|
||||
})
|
||||
|
||||
const ListConfigurationProfilesResponseSchema = z.object({
|
||||
configurationProfiles: z.array(ConfigurationProfileSchema),
|
||||
nextToken: z.string().nullable(),
|
||||
count: z.number(),
|
||||
})
|
||||
|
||||
export const awsAppConfigListConfigurationProfilesContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/appconfig/list-configuration-profiles',
|
||||
body: ListConfigurationProfilesSchema,
|
||||
response: { mode: 'json', schema: ListConfigurationProfilesResponseSchema },
|
||||
})
|
||||
export type AwsAppConfigListConfigurationProfilesRequest = ContractBodyInput<
|
||||
typeof awsAppConfigListConfigurationProfilesContract
|
||||
>
|
||||
export type AwsAppConfigListConfigurationProfilesBody = ContractBody<
|
||||
typeof awsAppConfigListConfigurationProfilesContract
|
||||
>
|
||||
export type AwsAppConfigListConfigurationProfilesResponse = ContractJsonResponse<
|
||||
typeof awsAppConfigListConfigurationProfilesContract
|
||||
>
|
||||
@@ -0,0 +1,48 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const ListDeploymentStrategiesSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
maxResults: z.number().int().min(1).max(50).nullish(),
|
||||
nextToken: z.string().nullish(),
|
||||
})
|
||||
|
||||
const DeploymentStrategySchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
description: z.string().nullable(),
|
||||
deploymentDurationInMinutes: z.number().nullable(),
|
||||
growthType: z.string().nullable(),
|
||||
growthFactor: z.number().nullable(),
|
||||
finalBakeTimeInMinutes: z.number().nullable(),
|
||||
replicateTo: z.string().nullable(),
|
||||
})
|
||||
|
||||
const ListDeploymentStrategiesResponseSchema = z.object({
|
||||
deploymentStrategies: z.array(DeploymentStrategySchema),
|
||||
nextToken: z.string().nullable(),
|
||||
count: z.number(),
|
||||
})
|
||||
|
||||
export const awsAppConfigListDeploymentStrategiesContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/appconfig/list-deployment-strategies',
|
||||
body: ListDeploymentStrategiesSchema,
|
||||
response: { mode: 'json', schema: ListDeploymentStrategiesResponseSchema },
|
||||
})
|
||||
export type AwsAppConfigListDeploymentStrategiesRequest = ContractBodyInput<
|
||||
typeof awsAppConfigListDeploymentStrategiesContract
|
||||
>
|
||||
export type AwsAppConfigListDeploymentStrategiesBody = ContractBody<
|
||||
typeof awsAppConfigListDeploymentStrategiesContract
|
||||
>
|
||||
export type AwsAppConfigListDeploymentStrategiesResponse = ContractJsonResponse<
|
||||
typeof awsAppConfigListDeploymentStrategiesContract
|
||||
>
|
||||
@@ -0,0 +1,54 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const ListDeploymentsSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
applicationId: z.string().min(1, 'Application ID is required'),
|
||||
environmentId: z.string().min(1, 'Environment ID is required'),
|
||||
maxResults: z.number().int().min(1).max(50).nullish(),
|
||||
nextToken: z.string().nullish(),
|
||||
})
|
||||
|
||||
const DeploymentSummarySchema = z.object({
|
||||
deploymentNumber: z.number().nullable(),
|
||||
configurationName: z.string().nullable(),
|
||||
configurationVersion: z.string().nullable(),
|
||||
deploymentDurationInMinutes: z.number().nullable(),
|
||||
growthType: z.string().nullable(),
|
||||
growthFactor: z.number().nullable(),
|
||||
finalBakeTimeInMinutes: z.number().nullable(),
|
||||
state: z.string().nullable(),
|
||||
percentageComplete: z.number().nullable(),
|
||||
startedAt: z.string().nullable(),
|
||||
completedAt: z.string().nullable(),
|
||||
versionLabel: z.string().nullable(),
|
||||
})
|
||||
|
||||
const ListDeploymentsResponseSchema = z.object({
|
||||
deployments: z.array(DeploymentSummarySchema),
|
||||
nextToken: z.string().nullable(),
|
||||
count: z.number(),
|
||||
})
|
||||
|
||||
export const awsAppConfigListDeploymentsContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/appconfig/list-deployments',
|
||||
body: ListDeploymentsSchema,
|
||||
response: { mode: 'json', schema: ListDeploymentsResponseSchema },
|
||||
})
|
||||
export type AwsAppConfigListDeploymentsRequest = ContractBodyInput<
|
||||
typeof awsAppConfigListDeploymentsContract
|
||||
>
|
||||
export type AwsAppConfigListDeploymentsBody = ContractBody<
|
||||
typeof awsAppConfigListDeploymentsContract
|
||||
>
|
||||
export type AwsAppConfigListDeploymentsResponse = ContractJsonResponse<
|
||||
typeof awsAppConfigListDeploymentsContract
|
||||
>
|
||||
@@ -0,0 +1,46 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const ListEnvironmentsSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
applicationId: z.string().min(1, 'Application ID is required'),
|
||||
maxResults: z.number().int().min(1).max(50).nullish(),
|
||||
nextToken: z.string().nullish(),
|
||||
})
|
||||
|
||||
const EnvironmentSchema = z.object({
|
||||
applicationId: z.string(),
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
description: z.string().nullable(),
|
||||
state: z.string().nullable(),
|
||||
})
|
||||
|
||||
const ListEnvironmentsResponseSchema = z.object({
|
||||
environments: z.array(EnvironmentSchema),
|
||||
nextToken: z.string().nullable(),
|
||||
count: z.number(),
|
||||
})
|
||||
|
||||
export const awsAppConfigListEnvironmentsContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/appconfig/list-environments',
|
||||
body: ListEnvironmentsSchema,
|
||||
response: { mode: 'json', schema: ListEnvironmentsResponseSchema },
|
||||
})
|
||||
export type AwsAppConfigListEnvironmentsRequest = ContractBodyInput<
|
||||
typeof awsAppConfigListEnvironmentsContract
|
||||
>
|
||||
export type AwsAppConfigListEnvironmentsBody = ContractBody<
|
||||
typeof awsAppConfigListEnvironmentsContract
|
||||
>
|
||||
export type AwsAppConfigListEnvironmentsResponse = ContractJsonResponse<
|
||||
typeof awsAppConfigListEnvironmentsContract
|
||||
>
|
||||
@@ -0,0 +1,48 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const ListHostedConfigurationVersionsSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
applicationId: z.string().min(1, 'Application ID is required'),
|
||||
configurationProfileId: z.string().min(1, 'Configuration profile ID is required'),
|
||||
maxResults: z.number().int().min(1).max(50).nullish(),
|
||||
nextToken: z.string().nullish(),
|
||||
})
|
||||
|
||||
const HostedConfigurationVersionSummarySchema = z.object({
|
||||
applicationId: z.string().nullable(),
|
||||
configurationProfileId: z.string().nullable(),
|
||||
versionNumber: z.number().nullable(),
|
||||
description: z.string().nullable(),
|
||||
contentType: z.string().nullable(),
|
||||
versionLabel: z.string().nullable(),
|
||||
})
|
||||
|
||||
const ListHostedConfigurationVersionsResponseSchema = z.object({
|
||||
versions: z.array(HostedConfigurationVersionSummarySchema),
|
||||
nextToken: z.string().nullable(),
|
||||
count: z.number(),
|
||||
})
|
||||
|
||||
export const awsAppConfigListHostedConfigurationVersionsContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/appconfig/list-hosted-configuration-versions',
|
||||
body: ListHostedConfigurationVersionsSchema,
|
||||
response: { mode: 'json', schema: ListHostedConfigurationVersionsResponseSchema },
|
||||
})
|
||||
export type AwsAppConfigListHostedConfigurationVersionsRequest = ContractBodyInput<
|
||||
typeof awsAppConfigListHostedConfigurationVersionsContract
|
||||
>
|
||||
export type AwsAppConfigListHostedConfigurationVersionsBody = ContractBody<
|
||||
typeof awsAppConfigListHostedConfigurationVersionsContract
|
||||
>
|
||||
export type AwsAppConfigListHostedConfigurationVersionsResponse = ContractJsonResponse<
|
||||
typeof awsAppConfigListHostedConfigurationVersionsContract
|
||||
>
|
||||
@@ -0,0 +1,42 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const StartDeploymentSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
applicationId: z.string().min(1, 'Application ID is required'),
|
||||
environmentId: z.string().min(1, 'Environment ID is required'),
|
||||
deploymentStrategyId: z.string().min(1, 'Deployment strategy ID is required'),
|
||||
configurationProfileId: z.string().min(1, 'Configuration profile ID is required'),
|
||||
configurationVersion: z.string().min(1, 'Configuration version is required'),
|
||||
description: z.string().max(1024).nullish(),
|
||||
})
|
||||
|
||||
const StartDeploymentResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
deploymentNumber: z.number().nullable(),
|
||||
state: z.string().nullable(),
|
||||
percentageComplete: z.number().nullable(),
|
||||
})
|
||||
|
||||
export const awsAppConfigStartDeploymentContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/appconfig/start-deployment',
|
||||
body: StartDeploymentSchema,
|
||||
response: { mode: 'json', schema: StartDeploymentResponseSchema },
|
||||
})
|
||||
export type AwsAppConfigStartDeploymentRequest = ContractBodyInput<
|
||||
typeof awsAppConfigStartDeploymentContract
|
||||
>
|
||||
export type AwsAppConfigStartDeploymentBody = ContractBody<
|
||||
typeof awsAppConfigStartDeploymentContract
|
||||
>
|
||||
export type AwsAppConfigStartDeploymentResponse = ContractJsonResponse<
|
||||
typeof awsAppConfigStartDeploymentContract
|
||||
>
|
||||
@@ -0,0 +1,36 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const StopDeploymentSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
applicationId: z.string().min(1, 'Application ID is required'),
|
||||
environmentId: z.string().min(1, 'Environment ID is required'),
|
||||
deploymentNumber: z.number().int().min(1, 'Deployment number is required'),
|
||||
})
|
||||
|
||||
const StopDeploymentResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
deploymentNumber: z.number().nullable(),
|
||||
state: z.string().nullable(),
|
||||
})
|
||||
|
||||
export const awsAppConfigStopDeploymentContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/appconfig/stop-deployment',
|
||||
body: StopDeploymentSchema,
|
||||
response: { mode: 'json', schema: StopDeploymentResponseSchema },
|
||||
})
|
||||
export type AwsAppConfigStopDeploymentRequest = ContractBodyInput<
|
||||
typeof awsAppConfigStopDeploymentContract
|
||||
>
|
||||
export type AwsAppConfigStopDeploymentBody = ContractBody<typeof awsAppConfigStopDeploymentContract>
|
||||
export type AwsAppConfigStopDeploymentResponse = ContractJsonResponse<
|
||||
typeof awsAppConfigStopDeploymentContract
|
||||
>
|
||||
@@ -0,0 +1,39 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const UpdateApplicationSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
applicationId: z.string().min(1, 'Application ID is required'),
|
||||
name: z.string().min(1).max(64).nullish(),
|
||||
description: z.string().max(1024).nullish(),
|
||||
})
|
||||
|
||||
const UpdateApplicationResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
description: z.string().nullable(),
|
||||
})
|
||||
|
||||
export const awsAppConfigUpdateApplicationContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/appconfig/update-application',
|
||||
body: UpdateApplicationSchema,
|
||||
response: { mode: 'json', schema: UpdateApplicationResponseSchema },
|
||||
})
|
||||
export type AwsAppConfigUpdateApplicationRequest = ContractBodyInput<
|
||||
typeof awsAppConfigUpdateApplicationContract
|
||||
>
|
||||
export type AwsAppConfigUpdateApplicationBody = ContractBody<
|
||||
typeof awsAppConfigUpdateApplicationContract
|
||||
>
|
||||
export type AwsAppConfigUpdateApplicationResponse = ContractJsonResponse<
|
||||
typeof awsAppConfigUpdateApplicationContract
|
||||
>
|
||||
@@ -0,0 +1,43 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const UpdateConfigurationProfileSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
applicationId: z.string().min(1, 'Application ID is required'),
|
||||
configurationProfileId: z.string().min(1, 'Configuration profile ID is required'),
|
||||
name: z.string().min(1).max(128).nullish(),
|
||||
description: z.string().max(1024).nullish(),
|
||||
retrievalRoleArn: z.string().nullish(),
|
||||
})
|
||||
|
||||
const UpdateConfigurationProfileResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
applicationId: z.string(),
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
description: z.string().nullable(),
|
||||
type: z.string().nullable(),
|
||||
})
|
||||
|
||||
export const awsAppConfigUpdateConfigurationProfileContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/appconfig/update-configuration-profile',
|
||||
body: UpdateConfigurationProfileSchema,
|
||||
response: { mode: 'json', schema: UpdateConfigurationProfileResponseSchema },
|
||||
})
|
||||
export type AwsAppConfigUpdateConfigurationProfileRequest = ContractBodyInput<
|
||||
typeof awsAppConfigUpdateConfigurationProfileContract
|
||||
>
|
||||
export type AwsAppConfigUpdateConfigurationProfileBody = ContractBody<
|
||||
typeof awsAppConfigUpdateConfigurationProfileContract
|
||||
>
|
||||
export type AwsAppConfigUpdateConfigurationProfileResponse = ContractJsonResponse<
|
||||
typeof awsAppConfigUpdateConfigurationProfileContract
|
||||
>
|
||||
@@ -0,0 +1,41 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const UpdateEnvironmentSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
applicationId: z.string().min(1, 'Application ID is required'),
|
||||
environmentId: z.string().min(1, 'Environment ID is required'),
|
||||
name: z.string().min(1).max(64).nullish(),
|
||||
description: z.string().max(1024).nullish(),
|
||||
})
|
||||
|
||||
const UpdateEnvironmentResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
applicationId: z.string(),
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
state: z.string().nullable(),
|
||||
})
|
||||
|
||||
export const awsAppConfigUpdateEnvironmentContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/appconfig/update-environment',
|
||||
body: UpdateEnvironmentSchema,
|
||||
response: { mode: 'json', schema: UpdateEnvironmentResponseSchema },
|
||||
})
|
||||
export type AwsAppConfigUpdateEnvironmentRequest = ContractBodyInput<
|
||||
typeof awsAppConfigUpdateEnvironmentContract
|
||||
>
|
||||
export type AwsAppConfigUpdateEnvironmentBody = ContractBody<
|
||||
typeof awsAppConfigUpdateEnvironmentContract
|
||||
>
|
||||
export type AwsAppConfigUpdateEnvironmentResponse = ContractJsonResponse<
|
||||
typeof awsAppConfigUpdateEnvironmentContract
|
||||
>
|
||||
@@ -0,0 +1,72 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const BatchGetQueryExecutionSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
queryExecutionIds: z
|
||||
.array(z.string().trim().min(1))
|
||||
.min(1, 'At least one query execution ID is required')
|
||||
.max(50, 'A maximum of 50 query execution IDs can be requested at once'),
|
||||
})
|
||||
|
||||
const BatchGetQueryExecutionResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
queryExecutions: z.array(
|
||||
z.object({
|
||||
queryExecutionId: z.string(),
|
||||
query: z.string().nullable(),
|
||||
state: z.string().nullable(),
|
||||
stateChangeReason: z.string().nullable(),
|
||||
statementType: z.string().nullable(),
|
||||
database: z.string().nullable(),
|
||||
catalog: z.string().nullable(),
|
||||
workGroup: z.string().nullable(),
|
||||
submissionDateTime: z.number().nullable(),
|
||||
completionDateTime: z.number().nullable(),
|
||||
dataScannedInBytes: z.number().nullable(),
|
||||
engineExecutionTimeInMillis: z.number().nullable(),
|
||||
queryPlanningTimeInMillis: z.number().nullable(),
|
||||
queryQueueTimeInMillis: z.number().nullable(),
|
||||
totalExecutionTimeInMillis: z.number().nullable(),
|
||||
outputLocation: z.string().nullable(),
|
||||
})
|
||||
),
|
||||
unprocessedQueryExecutionIds: z.array(
|
||||
z.object({
|
||||
queryExecutionId: z.string().nullable(),
|
||||
errorCode: z.string().nullable(),
|
||||
errorMessage: z.string().nullable(),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsAthenaBatchGetQueryExecutionContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/athena/batch-get-query-execution',
|
||||
body: BatchGetQueryExecutionSchema,
|
||||
response: { mode: 'json', schema: BatchGetQueryExecutionResponseSchema },
|
||||
})
|
||||
export type AwsAthenaBatchGetQueryExecutionRequest = ContractBodyInput<
|
||||
typeof awsAthenaBatchGetQueryExecutionContract
|
||||
>
|
||||
export type AwsAthenaBatchGetQueryExecutionBody = ContractBody<
|
||||
typeof awsAthenaBatchGetQueryExecutionContract
|
||||
>
|
||||
export type AwsAthenaBatchGetQueryExecutionResponse = ContractJsonResponse<
|
||||
typeof awsAthenaBatchGetQueryExecutionContract
|
||||
>
|
||||
@@ -0,0 +1,39 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const CreateNamedQuerySchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
name: z.string().min(1, 'Query name is required'),
|
||||
database: z.string().min(1, 'Database is required'),
|
||||
queryString: z.string().min(1, 'Query string is required'),
|
||||
description: z.string().optional(),
|
||||
workGroup: z.string().optional(),
|
||||
})
|
||||
|
||||
const CreateNamedQueryResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
namedQueryId: z.string(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsAthenaCreateNamedQueryContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/athena/create-named-query',
|
||||
body: CreateNamedQuerySchema,
|
||||
response: { mode: 'json', schema: CreateNamedQueryResponseSchema },
|
||||
})
|
||||
export type AwsAthenaCreateNamedQueryRequest = ContractBodyInput<
|
||||
typeof awsAthenaCreateNamedQueryContract
|
||||
>
|
||||
export type AwsAthenaCreateNamedQueryBody = ContractBody<typeof awsAthenaCreateNamedQueryContract>
|
||||
export type AwsAthenaCreateNamedQueryResponse = ContractJsonResponse<
|
||||
typeof awsAthenaCreateNamedQueryContract
|
||||
>
|
||||
@@ -0,0 +1,41 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const DeleteNamedQuerySchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
namedQueryId: z.string().trim().min(1, 'Named query ID is required'),
|
||||
})
|
||||
|
||||
const DeleteNamedQueryResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
success: z.literal(true),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsAthenaDeleteNamedQueryContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/athena/delete-named-query',
|
||||
body: DeleteNamedQuerySchema,
|
||||
response: { mode: 'json', schema: DeleteNamedQueryResponseSchema },
|
||||
})
|
||||
export type AwsAthenaDeleteNamedQueryRequest = ContractBodyInput<
|
||||
typeof awsAthenaDeleteNamedQueryContract
|
||||
>
|
||||
export type AwsAthenaDeleteNamedQueryBody = ContractBody<typeof awsAthenaDeleteNamedQueryContract>
|
||||
export type AwsAthenaDeleteNamedQueryResponse = ContractJsonResponse<
|
||||
typeof awsAthenaDeleteNamedQueryContract
|
||||
>
|
||||
@@ -0,0 +1,38 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const GetNamedQuerySchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
namedQueryId: z.string().trim().min(1, 'Named query ID is required'),
|
||||
})
|
||||
|
||||
const GetNamedQueryResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
namedQueryId: z.string(),
|
||||
name: z.string(),
|
||||
description: z.string().nullable(),
|
||||
database: z.string(),
|
||||
queryString: z.string(),
|
||||
workGroup: z.string().nullable(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsAthenaGetNamedQueryContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/athena/get-named-query',
|
||||
body: GetNamedQuerySchema,
|
||||
response: { mode: 'json', schema: GetNamedQueryResponseSchema },
|
||||
})
|
||||
export type AwsAthenaGetNamedQueryRequest = ContractBodyInput<typeof awsAthenaGetNamedQueryContract>
|
||||
export type AwsAthenaGetNamedQueryBody = ContractBody<typeof awsAthenaGetNamedQueryContract>
|
||||
export type AwsAthenaGetNamedQueryResponse = ContractJsonResponse<
|
||||
typeof awsAthenaGetNamedQueryContract
|
||||
>
|
||||
@@ -0,0 +1,50 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const GetQueryExecutionSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
queryExecutionId: z.string().trim().min(1, 'Query execution ID is required'),
|
||||
})
|
||||
|
||||
const GetQueryExecutionResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
queryExecutionId: z.string(),
|
||||
query: z.string(),
|
||||
state: z.string(),
|
||||
stateChangeReason: z.string().nullable(),
|
||||
statementType: z.string().nullable(),
|
||||
database: z.string().nullable(),
|
||||
catalog: z.string().nullable(),
|
||||
workGroup: z.string().nullable(),
|
||||
submissionDateTime: z.number().nullable(),
|
||||
completionDateTime: z.number().nullable(),
|
||||
dataScannedInBytes: z.number().nullable(),
|
||||
engineExecutionTimeInMillis: z.number().nullable(),
|
||||
queryPlanningTimeInMillis: z.number().nullable(),
|
||||
queryQueueTimeInMillis: z.number().nullable(),
|
||||
totalExecutionTimeInMillis: z.number().nullable(),
|
||||
outputLocation: z.string().nullable(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsAthenaGetQueryExecutionContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/athena/get-query-execution',
|
||||
body: GetQueryExecutionSchema,
|
||||
response: { mode: 'json', schema: GetQueryExecutionResponseSchema },
|
||||
})
|
||||
export type AwsAthenaGetQueryExecutionRequest = ContractBodyInput<
|
||||
typeof awsAthenaGetQueryExecutionContract
|
||||
>
|
||||
export type AwsAthenaGetQueryExecutionBody = ContractBody<typeof awsAthenaGetQueryExecutionContract>
|
||||
export type AwsAthenaGetQueryExecutionResponse = ContractJsonResponse<
|
||||
typeof awsAthenaGetQueryExecutionContract
|
||||
>
|
||||
@@ -0,0 +1,48 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const GetQueryResultsSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
queryExecutionId: z.string().trim().min(1, 'Query execution ID is required'),
|
||||
maxResults: z.preprocess(
|
||||
(v) => (v === '' || v === undefined || v === null ? undefined : v),
|
||||
z.coerce.number().int().positive().max(999).optional()
|
||||
),
|
||||
nextToken: z.string().optional(),
|
||||
})
|
||||
|
||||
const GetQueryResultsResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
columns: z.array(
|
||||
z.object({
|
||||
name: z.string(),
|
||||
type: z.string(),
|
||||
})
|
||||
),
|
||||
rows: z.array(z.record(z.string(), z.string())),
|
||||
nextToken: z.string().nullable(),
|
||||
updateCount: z.number().nullable(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsAthenaGetQueryResultsContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/athena/get-query-results',
|
||||
body: GetQueryResultsSchema,
|
||||
response: { mode: 'json', schema: GetQueryResultsResponseSchema },
|
||||
})
|
||||
export type AwsAthenaGetQueryResultsRequest = ContractBodyInput<
|
||||
typeof awsAthenaGetQueryResultsContract
|
||||
>
|
||||
export type AwsAthenaGetQueryResultsBody = ContractBody<typeof awsAthenaGetQueryResultsContract>
|
||||
export type AwsAthenaGetQueryResultsResponse = ContractJsonResponse<
|
||||
typeof awsAthenaGetQueryResultsContract
|
||||
>
|
||||
@@ -0,0 +1,51 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const ListDatabasesSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
catalogName: z.string().trim().min(1, 'Data catalog name is required'),
|
||||
workGroup: z.string().optional(),
|
||||
maxResults: z.preprocess(
|
||||
(v) => (v === '' || v === undefined || v === null ? undefined : v),
|
||||
z.coerce.number().int().min(1).max(50).optional()
|
||||
),
|
||||
nextToken: z.string().optional(),
|
||||
})
|
||||
|
||||
const ListDatabasesResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
databases: z.array(
|
||||
z.object({
|
||||
name: z.string(),
|
||||
description: z.string().nullable(),
|
||||
})
|
||||
),
|
||||
nextToken: z.string().nullable(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsAthenaListDatabasesContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/athena/list-databases',
|
||||
body: ListDatabasesSchema,
|
||||
response: { mode: 'json', schema: ListDatabasesResponseSchema },
|
||||
})
|
||||
export type AwsAthenaListDatabasesRequest = ContractBodyInput<typeof awsAthenaListDatabasesContract>
|
||||
export type AwsAthenaListDatabasesBody = ContractBody<typeof awsAthenaListDatabasesContract>
|
||||
export type AwsAthenaListDatabasesResponse = ContractJsonResponse<
|
||||
typeof awsAthenaListDatabasesContract
|
||||
>
|
||||
@@ -0,0 +1,41 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const ListNamedQueriesSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
workGroup: z.string().optional(),
|
||||
maxResults: z.preprocess(
|
||||
(v) => (v === '' || v === undefined || v === null ? undefined : v),
|
||||
z.coerce.number().int().min(0).max(50).optional()
|
||||
),
|
||||
nextToken: z.string().optional(),
|
||||
})
|
||||
|
||||
const ListNamedQueriesResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
namedQueryIds: z.array(z.string()),
|
||||
nextToken: z.string().nullable(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsAthenaListNamedQueriesContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/athena/list-named-queries',
|
||||
body: ListNamedQueriesSchema,
|
||||
response: { mode: 'json', schema: ListNamedQueriesResponseSchema },
|
||||
})
|
||||
export type AwsAthenaListNamedQueriesRequest = ContractBodyInput<
|
||||
typeof awsAthenaListNamedQueriesContract
|
||||
>
|
||||
export type AwsAthenaListNamedQueriesBody = ContractBody<typeof awsAthenaListNamedQueriesContract>
|
||||
export type AwsAthenaListNamedQueriesResponse = ContractJsonResponse<
|
||||
typeof awsAthenaListNamedQueriesContract
|
||||
>
|
||||
@@ -0,0 +1,43 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const ListQueryExecutionsSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
workGroup: z.string().optional(),
|
||||
maxResults: z.preprocess(
|
||||
(v) => (v === '' || v === undefined || v === null ? undefined : v),
|
||||
z.coerce.number().int().min(0).max(50).optional()
|
||||
),
|
||||
nextToken: z.string().optional(),
|
||||
})
|
||||
|
||||
const ListQueryExecutionsResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
queryExecutionIds: z.array(z.string()),
|
||||
nextToken: z.string().nullable(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsAthenaListQueryExecutionsContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/athena/list-query-executions',
|
||||
body: ListQueryExecutionsSchema,
|
||||
response: { mode: 'json', schema: ListQueryExecutionsResponseSchema },
|
||||
})
|
||||
export type AwsAthenaListQueryExecutionsRequest = ContractBodyInput<
|
||||
typeof awsAthenaListQueryExecutionsContract
|
||||
>
|
||||
export type AwsAthenaListQueryExecutionsBody = ContractBody<
|
||||
typeof awsAthenaListQueryExecutionsContract
|
||||
>
|
||||
export type AwsAthenaListQueryExecutionsResponse = ContractJsonResponse<
|
||||
typeof awsAthenaListQueryExecutionsContract
|
||||
>
|
||||
@@ -0,0 +1,65 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const ColumnSchema = z.object({
|
||||
name: z.string(),
|
||||
type: z.string().nullable(),
|
||||
comment: z.string().nullable(),
|
||||
})
|
||||
|
||||
const ListTableMetadataSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
catalogName: z.string().trim().min(1, 'Data catalog name is required'),
|
||||
databaseName: z.string().trim().min(1, 'Database name is required'),
|
||||
expression: z.string().optional(),
|
||||
workGroup: z.string().optional(),
|
||||
maxResults: z.preprocess(
|
||||
(v) => (v === '' || v === undefined || v === null ? undefined : v),
|
||||
z.coerce.number().int().min(1).max(50).optional()
|
||||
),
|
||||
nextToken: z.string().optional(),
|
||||
})
|
||||
|
||||
const ListTableMetadataResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
tables: z.array(
|
||||
z.object({
|
||||
name: z.string(),
|
||||
tableType: z.string().nullable(),
|
||||
createTime: z.number().nullable(),
|
||||
lastAccessTime: z.number().nullable(),
|
||||
columns: z.array(ColumnSchema),
|
||||
partitionKeys: z.array(ColumnSchema),
|
||||
})
|
||||
),
|
||||
nextToken: z.string().nullable(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsAthenaListTableMetadataContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/athena/list-table-metadata',
|
||||
body: ListTableMetadataSchema,
|
||||
response: { mode: 'json', schema: ListTableMetadataResponseSchema },
|
||||
})
|
||||
export type AwsAthenaListTableMetadataRequest = ContractBodyInput<
|
||||
typeof awsAthenaListTableMetadataContract
|
||||
>
|
||||
export type AwsAthenaListTableMetadataBody = ContractBody<typeof awsAthenaListTableMetadataContract>
|
||||
export type AwsAthenaListTableMetadataResponse = ContractJsonResponse<
|
||||
typeof awsAthenaListTableMetadataContract
|
||||
>
|
||||
@@ -0,0 +1,35 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const StartQuerySchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
queryString: z.string().min(1, 'Query string is required'),
|
||||
database: z.string().optional(),
|
||||
catalog: z.string().optional(),
|
||||
outputLocation: z.string().optional(),
|
||||
workGroup: z.string().optional(),
|
||||
})
|
||||
|
||||
const StartQueryResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
queryExecutionId: z.string(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsAthenaStartQueryContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/athena/start-query',
|
||||
body: StartQuerySchema,
|
||||
response: { mode: 'json', schema: StartQueryResponseSchema },
|
||||
})
|
||||
export type AwsAthenaStartQueryRequest = ContractBodyInput<typeof awsAthenaStartQueryContract>
|
||||
export type AwsAthenaStartQueryBody = ContractBody<typeof awsAthenaStartQueryContract>
|
||||
export type AwsAthenaStartQueryResponse = ContractJsonResponse<typeof awsAthenaStartQueryContract>
|
||||
@@ -0,0 +1,31 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const StopQuerySchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
queryExecutionId: z.string().trim().min(1, 'Query execution ID is required'),
|
||||
})
|
||||
|
||||
const StopQueryResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
success: z.literal(true),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsAthenaStopQueryContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/athena/stop-query',
|
||||
body: StopQuerySchema,
|
||||
response: { mode: 'json', schema: StopQueryResponseSchema },
|
||||
})
|
||||
export type AwsAthenaStopQueryRequest = ContractBodyInput<typeof awsAthenaStopQueryContract>
|
||||
export type AwsAthenaStopQueryBody = ContractBody<typeof awsAthenaStopQueryContract>
|
||||
export type AwsAthenaStopQueryResponse = ContractJsonResponse<typeof awsAthenaStopQueryContract>
|
||||
@@ -0,0 +1,43 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const CancelUpdateStackSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
stackName: z.string().min(1, 'Stack name is required'),
|
||||
})
|
||||
|
||||
const CancelUpdateStackResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
message: z.string(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudformationCancelUpdateStackContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudformation/cancel-update-stack',
|
||||
body: CancelUpdateStackSchema,
|
||||
response: { mode: 'json', schema: CancelUpdateStackResponseSchema },
|
||||
})
|
||||
export type AwsCloudformationCancelUpdateStackRequest = ContractBodyInput<
|
||||
typeof awsCloudformationCancelUpdateStackContract
|
||||
>
|
||||
export type AwsCloudformationCancelUpdateStackBody = ContractBody<
|
||||
typeof awsCloudformationCancelUpdateStackContract
|
||||
>
|
||||
export type AwsCloudformationCancelUpdateStackResponse = ContractJsonResponse<
|
||||
typeof awsCloudformationCancelUpdateStackContract
|
||||
>
|
||||
@@ -0,0 +1,86 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const CreateChangeSetSchema = z
|
||||
.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
stackName: z.string().min(1, 'Stack name is required'),
|
||||
changeSetName: z.string().min(1, 'Change set name is required'),
|
||||
templateBody: z.string().optional(),
|
||||
usePreviousTemplate: z.boolean().optional(),
|
||||
parameters: z
|
||||
.array(
|
||||
z.object({
|
||||
parameterKey: z.string().min(1, 'Parameter key is required'),
|
||||
parameterValue: z.string().optional(),
|
||||
usePreviousValue: z.boolean().optional(),
|
||||
})
|
||||
)
|
||||
.optional(),
|
||||
capabilities: z
|
||||
.string()
|
||||
.optional()
|
||||
.refine(
|
||||
(v) =>
|
||||
!v ||
|
||||
v
|
||||
.split(',')
|
||||
.map((c) => c.trim())
|
||||
.filter(Boolean)
|
||||
.every((c) =>
|
||||
['CAPABILITY_IAM', 'CAPABILITY_NAMED_IAM', 'CAPABILITY_AUTO_EXPAND'].includes(c)
|
||||
),
|
||||
{
|
||||
message:
|
||||
'capabilities must be a comma-separated list of CAPABILITY_IAM, CAPABILITY_NAMED_IAM, CAPABILITY_AUTO_EXPAND',
|
||||
}
|
||||
),
|
||||
changeSetType: z.enum(['CREATE', 'UPDATE', 'IMPORT']).optional(),
|
||||
description: z.string().max(1024, 'Description must be at most 1024 characters').optional(),
|
||||
})
|
||||
.superRefine((data, ctx) => {
|
||||
if (!data.templateBody && !data.usePreviousTemplate) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: 'Either templateBody must be provided or usePreviousTemplate must be true',
|
||||
path: ['templateBody'],
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const CreateChangeSetResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
changeSetId: z.string(),
|
||||
stackId: z.string(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudformationCreateChangeSetContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudformation/create-change-set',
|
||||
body: CreateChangeSetSchema,
|
||||
response: { mode: 'json', schema: CreateChangeSetResponseSchema },
|
||||
})
|
||||
export type AwsCloudformationCreateChangeSetRequest = ContractBodyInput<
|
||||
typeof awsCloudformationCreateChangeSetContract
|
||||
>
|
||||
export type AwsCloudformationCreateChangeSetBody = ContractBody<
|
||||
typeof awsCloudformationCreateChangeSetContract
|
||||
>
|
||||
export type AwsCloudformationCreateChangeSetResponse = ContractJsonResponse<
|
||||
typeof awsCloudformationCreateChangeSetContract
|
||||
>
|
||||
@@ -0,0 +1,84 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const CreateStackSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
stackName: z.string().min(1, 'Stack name is required'),
|
||||
templateBody: z.string().min(1, 'Template body is required'),
|
||||
parameters: z
|
||||
.array(
|
||||
z.object({
|
||||
parameterKey: z.string().min(1, 'Parameter key is required'),
|
||||
parameterValue: z.string().optional(),
|
||||
usePreviousValue: z.boolean().optional(),
|
||||
})
|
||||
)
|
||||
.optional(),
|
||||
capabilities: z
|
||||
.string()
|
||||
.optional()
|
||||
.refine(
|
||||
(v) =>
|
||||
!v ||
|
||||
v
|
||||
.split(',')
|
||||
.map((c) => c.trim())
|
||||
.filter(Boolean)
|
||||
.every((c) =>
|
||||
['CAPABILITY_IAM', 'CAPABILITY_NAMED_IAM', 'CAPABILITY_AUTO_EXPAND'].includes(c)
|
||||
),
|
||||
{
|
||||
message:
|
||||
'capabilities must be a comma-separated list of CAPABILITY_IAM, CAPABILITY_NAMED_IAM, CAPABILITY_AUTO_EXPAND',
|
||||
}
|
||||
),
|
||||
tags: z
|
||||
.array(
|
||||
z.object({
|
||||
key: z
|
||||
.string()
|
||||
.min(1, 'Tag key is required')
|
||||
.max(128, 'Tag key must be at most 128 characters'),
|
||||
value: z.string().max(256, 'Tag value must be at most 256 characters'),
|
||||
})
|
||||
)
|
||||
.optional(),
|
||||
onFailure: z.enum(['ROLLBACK', 'DELETE', 'DO_NOTHING']).optional(),
|
||||
timeoutInMinutes: z.coerce.number().int().positive().optional(),
|
||||
})
|
||||
|
||||
const CreateStackResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
stackId: z.string(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudformationCreateStackContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudformation/create-stack',
|
||||
body: CreateStackSchema,
|
||||
response: { mode: 'json', schema: CreateStackResponseSchema },
|
||||
})
|
||||
export type AwsCloudformationCreateStackRequest = ContractBodyInput<
|
||||
typeof awsCloudformationCreateStackContract
|
||||
>
|
||||
export type AwsCloudformationCreateStackBody = ContractBody<
|
||||
typeof awsCloudformationCreateStackContract
|
||||
>
|
||||
export type AwsCloudformationCreateStackResponse = ContractJsonResponse<
|
||||
typeof awsCloudformationCreateStackContract
|
||||
>
|
||||
@@ -0,0 +1,44 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const DeleteStackSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
stackName: z.string().min(1, 'Stack name is required'),
|
||||
retainResources: z.string().optional(),
|
||||
})
|
||||
|
||||
const DeleteStackResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
message: z.string(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudformationDeleteStackContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudformation/delete-stack',
|
||||
body: DeleteStackSchema,
|
||||
response: { mode: 'json', schema: DeleteStackResponseSchema },
|
||||
})
|
||||
export type AwsCloudformationDeleteStackRequest = ContractBodyInput<
|
||||
typeof awsCloudformationDeleteStackContract
|
||||
>
|
||||
export type AwsCloudformationDeleteStackBody = ContractBody<
|
||||
typeof awsCloudformationDeleteStackContract
|
||||
>
|
||||
export type AwsCloudformationDeleteStackResponse = ContractJsonResponse<
|
||||
typeof awsCloudformationDeleteStackContract
|
||||
>
|
||||
@@ -0,0 +1,62 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const DescribeChangeSetSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
changeSetName: z.string().min(1, 'Change set name is required'),
|
||||
stackName: z.string().optional(),
|
||||
})
|
||||
|
||||
const DescribeChangeSetResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
changeSetName: z.string().optional(),
|
||||
changeSetId: z.string().optional(),
|
||||
stackId: z.string().optional(),
|
||||
stackName: z.string().optional(),
|
||||
description: z.string().optional(),
|
||||
executionStatus: z.string().optional(),
|
||||
status: z.string().optional(),
|
||||
statusReason: z.string().optional(),
|
||||
creationTime: z.number().optional(),
|
||||
capabilities: z.array(z.string()),
|
||||
changes: z.array(
|
||||
z.object({
|
||||
action: z.string().optional(),
|
||||
logicalResourceId: z.string().optional(),
|
||||
physicalResourceId: z.string().optional(),
|
||||
resourceType: z.string().optional(),
|
||||
replacement: z.string().optional(),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudformationDescribeChangeSetContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudformation/describe-change-set',
|
||||
body: DescribeChangeSetSchema,
|
||||
response: { mode: 'json', schema: DescribeChangeSetResponseSchema },
|
||||
})
|
||||
export type AwsCloudformationDescribeChangeSetRequest = ContractBodyInput<
|
||||
typeof awsCloudformationDescribeChangeSetContract
|
||||
>
|
||||
export type AwsCloudformationDescribeChangeSetBody = ContractBody<
|
||||
typeof awsCloudformationDescribeChangeSetContract
|
||||
>
|
||||
export type AwsCloudformationDescribeChangeSetResponse = ContractJsonResponse<
|
||||
typeof awsCloudformationDescribeChangeSetContract
|
||||
>
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const DescribeStackDriftDetectionStatusSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
stackDriftDetectionId: z.string().min(1, 'Stack drift detection ID is required'),
|
||||
})
|
||||
|
||||
const DescribeStackDriftDetectionStatusResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
stackId: z.string(),
|
||||
stackDriftDetectionId: z.string(),
|
||||
stackDriftStatus: z.string().optional(),
|
||||
detectionStatus: z.string(),
|
||||
detectionStatusReason: z.string().optional(),
|
||||
driftedStackResourceCount: z.number().optional(),
|
||||
timestamp: z.number().optional(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudformationDescribeStackDriftDetectionStatusContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudformation/describe-stack-drift-detection-status',
|
||||
body: DescribeStackDriftDetectionStatusSchema,
|
||||
response: { mode: 'json', schema: DescribeStackDriftDetectionStatusResponseSchema },
|
||||
})
|
||||
export type AwsCloudformationDescribeStackDriftDetectionStatusRequest = ContractBodyInput<
|
||||
typeof awsCloudformationDescribeStackDriftDetectionStatusContract
|
||||
>
|
||||
export type AwsCloudformationDescribeStackDriftDetectionStatusBody = ContractBody<
|
||||
typeof awsCloudformationDescribeStackDriftDetectionStatusContract
|
||||
>
|
||||
export type AwsCloudformationDescribeStackDriftDetectionStatusResponse = ContractJsonResponse<
|
||||
typeof awsCloudformationDescribeStackDriftDetectionStatusContract
|
||||
>
|
||||
@@ -0,0 +1,53 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const DescribeStackEventsSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
stackName: z.string().min(1, 'Stack name is required'),
|
||||
limit: z.preprocess(
|
||||
(v) => (v === '' || v === undefined || v === null ? undefined : v),
|
||||
z.coerce.number().int().positive().optional()
|
||||
),
|
||||
})
|
||||
|
||||
const DescribeStackEventsResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
events: z.array(
|
||||
z.object({
|
||||
stackId: z.string(),
|
||||
eventId: z.string(),
|
||||
stackName: z.string(),
|
||||
logicalResourceId: z.string().optional(),
|
||||
physicalResourceId: z.string().optional(),
|
||||
resourceType: z.string().optional(),
|
||||
resourceStatus: z.string().optional(),
|
||||
resourceStatusReason: z.string().optional(),
|
||||
timestamp: z.number().optional(),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudformationDescribeStackEventsContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudformation/describe-stack-events',
|
||||
body: DescribeStackEventsSchema,
|
||||
response: { mode: 'json', schema: DescribeStackEventsResponseSchema },
|
||||
})
|
||||
export type AwsCloudformationDescribeStackEventsRequest = ContractBodyInput<
|
||||
typeof awsCloudformationDescribeStackEventsContract
|
||||
>
|
||||
export type AwsCloudformationDescribeStackEventsBody = ContractBody<
|
||||
typeof awsCloudformationDescribeStackEventsContract
|
||||
>
|
||||
export type AwsCloudformationDescribeStackEventsResponse = ContractJsonResponse<
|
||||
typeof awsCloudformationDescribeStackEventsContract
|
||||
>
|
||||
@@ -0,0 +1,67 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const DescribeStacksSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
stackName: z.string().optional(),
|
||||
})
|
||||
|
||||
const DescribeStacksResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
stacks: z.array(
|
||||
z.object({
|
||||
stackName: z.string(),
|
||||
stackId: z.string(),
|
||||
stackStatus: z.string(),
|
||||
stackStatusReason: z.string().optional(),
|
||||
creationTime: z.number().optional(),
|
||||
lastUpdatedTime: z.number().optional(),
|
||||
description: z.string().optional(),
|
||||
enableTerminationProtection: z.boolean().optional(),
|
||||
driftInformation: z
|
||||
.object({
|
||||
stackDriftStatus: z.string().optional(),
|
||||
lastCheckTimestamp: z.number().optional(),
|
||||
})
|
||||
.nullable(),
|
||||
outputs: z.array(
|
||||
z.object({
|
||||
outputKey: z.string(),
|
||||
outputValue: z.string(),
|
||||
description: z.string().optional(),
|
||||
})
|
||||
),
|
||||
tags: z.array(
|
||||
z.object({
|
||||
key: z.string(),
|
||||
value: z.string(),
|
||||
})
|
||||
),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudformationDescribeStacksContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudformation/describe-stacks',
|
||||
body: DescribeStacksSchema,
|
||||
response: { mode: 'json', schema: DescribeStacksResponseSchema },
|
||||
})
|
||||
export type AwsCloudformationDescribeStacksRequest = ContractBodyInput<
|
||||
typeof awsCloudformationDescribeStacksContract
|
||||
>
|
||||
export type AwsCloudformationDescribeStacksBody = ContractBody<
|
||||
typeof awsCloudformationDescribeStacksContract
|
||||
>
|
||||
export type AwsCloudformationDescribeStacksResponse = ContractJsonResponse<
|
||||
typeof awsCloudformationDescribeStacksContract
|
||||
>
|
||||
@@ -0,0 +1,37 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const DetectStackDriftSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
stackName: z.string().min(1, 'Stack name is required'),
|
||||
})
|
||||
|
||||
const DetectStackDriftResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
stackDriftDetectionId: z.string(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudformationDetectStackDriftContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudformation/detect-stack-drift',
|
||||
body: DetectStackDriftSchema,
|
||||
response: { mode: 'json', schema: DetectStackDriftResponseSchema },
|
||||
})
|
||||
export type AwsCloudformationDetectStackDriftRequest = ContractBodyInput<
|
||||
typeof awsCloudformationDetectStackDriftContract
|
||||
>
|
||||
export type AwsCloudformationDetectStackDriftBody = ContractBody<
|
||||
typeof awsCloudformationDetectStackDriftContract
|
||||
>
|
||||
export type AwsCloudformationDetectStackDriftResponse = ContractJsonResponse<
|
||||
typeof awsCloudformationDetectStackDriftContract
|
||||
>
|
||||
@@ -0,0 +1,44 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const ExecuteChangeSetSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
changeSetName: z.string().min(1, 'Change set name is required'),
|
||||
stackName: z.string().optional(),
|
||||
})
|
||||
|
||||
const ExecuteChangeSetResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
message: z.string(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudformationExecuteChangeSetContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudformation/execute-change-set',
|
||||
body: ExecuteChangeSetSchema,
|
||||
response: { mode: 'json', schema: ExecuteChangeSetResponseSchema },
|
||||
})
|
||||
export type AwsCloudformationExecuteChangeSetRequest = ContractBodyInput<
|
||||
typeof awsCloudformationExecuteChangeSetContract
|
||||
>
|
||||
export type AwsCloudformationExecuteChangeSetBody = ContractBody<
|
||||
typeof awsCloudformationExecuteChangeSetContract
|
||||
>
|
||||
export type AwsCloudformationExecuteChangeSetResponse = ContractJsonResponse<
|
||||
typeof awsCloudformationExecuteChangeSetContract
|
||||
>
|
||||
@@ -0,0 +1,68 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const GetTemplateSummarySchema = z
|
||||
.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
templateBody: z.string().optional(),
|
||||
stackName: z.string().optional(),
|
||||
})
|
||||
.superRefine((data, ctx) => {
|
||||
if (!data.templateBody && !data.stackName) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: 'Either templateBody or stackName is required',
|
||||
path: ['templateBody'],
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const GetTemplateSummaryResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
description: z.string().optional(),
|
||||
parameters: z.array(
|
||||
z.object({
|
||||
parameterKey: z.string().optional(),
|
||||
defaultValue: z.string().optional(),
|
||||
parameterType: z.string().optional(),
|
||||
noEcho: z.boolean().optional(),
|
||||
description: z.string().optional(),
|
||||
})
|
||||
),
|
||||
capabilities: z.array(z.string()),
|
||||
capabilitiesReason: z.string().optional(),
|
||||
resourceTypes: z.array(z.string()),
|
||||
version: z.string().optional(),
|
||||
declaredTransforms: z.array(z.string()),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudformationGetTemplateSummaryContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudformation/get-template-summary',
|
||||
body: GetTemplateSummarySchema,
|
||||
response: { mode: 'json', schema: GetTemplateSummaryResponseSchema },
|
||||
})
|
||||
export type AwsCloudformationGetTemplateSummaryRequest = ContractBodyInput<
|
||||
typeof awsCloudformationGetTemplateSummaryContract
|
||||
>
|
||||
export type AwsCloudformationGetTemplateSummaryBody = ContractBody<
|
||||
typeof awsCloudformationGetTemplateSummaryContract
|
||||
>
|
||||
export type AwsCloudformationGetTemplateSummaryResponse = ContractJsonResponse<
|
||||
typeof awsCloudformationGetTemplateSummaryContract
|
||||
>
|
||||
@@ -0,0 +1,39 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const GetTemplateSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
stackName: z.string().min(1, 'Stack name is required'),
|
||||
templateStage: z.enum(['Original', 'Processed']).optional(),
|
||||
})
|
||||
|
||||
const GetTemplateResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
templateBody: z.string(),
|
||||
stagesAvailable: z.array(z.string()),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudformationGetTemplateContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudformation/get-template',
|
||||
body: GetTemplateSchema,
|
||||
response: { mode: 'json', schema: GetTemplateResponseSchema },
|
||||
})
|
||||
export type AwsCloudformationGetTemplateRequest = ContractBodyInput<
|
||||
typeof awsCloudformationGetTemplateContract
|
||||
>
|
||||
export type AwsCloudformationGetTemplateBody = ContractBody<
|
||||
typeof awsCloudformationGetTemplateContract
|
||||
>
|
||||
export type AwsCloudformationGetTemplateResponse = ContractJsonResponse<
|
||||
typeof awsCloudformationGetTemplateContract
|
||||
>
|
||||
@@ -0,0 +1,52 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const ListStackResourcesSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
stackName: z.string().min(1, 'Stack name is required'),
|
||||
})
|
||||
|
||||
const ListStackResourcesResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
resources: z.array(
|
||||
z.object({
|
||||
logicalResourceId: z.string(),
|
||||
physicalResourceId: z.string().optional(),
|
||||
resourceType: z.string(),
|
||||
resourceStatus: z.string(),
|
||||
resourceStatusReason: z.string().optional(),
|
||||
lastUpdatedTimestamp: z.number().optional(),
|
||||
driftInformation: z
|
||||
.object({
|
||||
stackResourceDriftStatus: z.string().optional(),
|
||||
lastCheckTimestamp: z.number().optional(),
|
||||
})
|
||||
.nullable(),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudformationListStackResourcesContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudformation/list-stack-resources',
|
||||
body: ListStackResourcesSchema,
|
||||
response: { mode: 'json', schema: ListStackResourcesResponseSchema },
|
||||
})
|
||||
export type AwsCloudformationListStackResourcesRequest = ContractBodyInput<
|
||||
typeof awsCloudformationListStackResourcesContract
|
||||
>
|
||||
export type AwsCloudformationListStackResourcesBody = ContractBody<
|
||||
typeof awsCloudformationListStackResourcesContract
|
||||
>
|
||||
export type AwsCloudformationListStackResourcesResponse = ContractJsonResponse<
|
||||
typeof awsCloudformationListStackResourcesContract
|
||||
>
|
||||
@@ -0,0 +1,93 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const UpdateStackSchema = z
|
||||
.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
stackName: z.string().min(1, 'Stack name is required'),
|
||||
templateBody: z.string().optional(),
|
||||
usePreviousTemplate: z.boolean().optional(),
|
||||
parameters: z
|
||||
.array(
|
||||
z.object({
|
||||
parameterKey: z.string().min(1, 'Parameter key is required'),
|
||||
parameterValue: z.string().optional(),
|
||||
usePreviousValue: z.boolean().optional(),
|
||||
})
|
||||
)
|
||||
.optional(),
|
||||
capabilities: z
|
||||
.string()
|
||||
.optional()
|
||||
.refine(
|
||||
(v) =>
|
||||
!v ||
|
||||
v
|
||||
.split(',')
|
||||
.map((c) => c.trim())
|
||||
.filter(Boolean)
|
||||
.every((c) =>
|
||||
['CAPABILITY_IAM', 'CAPABILITY_NAMED_IAM', 'CAPABILITY_AUTO_EXPAND'].includes(c)
|
||||
),
|
||||
{
|
||||
message:
|
||||
'capabilities must be a comma-separated list of CAPABILITY_IAM, CAPABILITY_NAMED_IAM, CAPABILITY_AUTO_EXPAND',
|
||||
}
|
||||
),
|
||||
tags: z
|
||||
.array(
|
||||
z.object({
|
||||
key: z
|
||||
.string()
|
||||
.min(1, 'Tag key is required')
|
||||
.max(128, 'Tag key must be at most 128 characters'),
|
||||
value: z.string().max(256, 'Tag value must be at most 256 characters'),
|
||||
})
|
||||
)
|
||||
.optional(),
|
||||
})
|
||||
.superRefine((data, ctx) => {
|
||||
if (!data.templateBody && !data.usePreviousTemplate) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: 'Either templateBody must be provided or usePreviousTemplate must be true',
|
||||
path: ['templateBody'],
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const UpdateStackResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
stackId: z.string(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudformationUpdateStackContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudformation/update-stack',
|
||||
body: UpdateStackSchema,
|
||||
response: { mode: 'json', schema: UpdateStackResponseSchema },
|
||||
})
|
||||
export type AwsCloudformationUpdateStackRequest = ContractBodyInput<
|
||||
typeof awsCloudformationUpdateStackContract
|
||||
>
|
||||
export type AwsCloudformationUpdateStackBody = ContractBody<
|
||||
typeof awsCloudformationUpdateStackContract
|
||||
>
|
||||
export type AwsCloudformationUpdateStackResponse = ContractJsonResponse<
|
||||
typeof awsCloudformationUpdateStackContract
|
||||
>
|
||||
@@ -0,0 +1,48 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
const ValidateTemplateSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
templateBody: z.string().min(1, 'Template body is required'),
|
||||
})
|
||||
|
||||
const ValidateTemplateResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
description: z.string().optional(),
|
||||
parameters: z.array(
|
||||
z.object({
|
||||
parameterKey: z.string().optional(),
|
||||
defaultValue: z.string().optional(),
|
||||
noEcho: z.boolean().optional(),
|
||||
description: z.string().optional(),
|
||||
})
|
||||
),
|
||||
capabilities: z.array(z.string()),
|
||||
capabilitiesReason: z.string().optional(),
|
||||
declaredTransforms: z.array(z.string()),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudformationValidateTemplateContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudformation/validate-template',
|
||||
body: ValidateTemplateSchema,
|
||||
response: { mode: 'json', schema: ValidateTemplateResponseSchema },
|
||||
})
|
||||
export type AwsCloudformationValidateTemplateRequest = ContractBodyInput<
|
||||
typeof awsCloudformationValidateTemplateContract
|
||||
>
|
||||
export type AwsCloudformationValidateTemplateBody = ContractBody<
|
||||
typeof awsCloudformationValidateTemplateContract
|
||||
>
|
||||
export type AwsCloudformationValidateTemplateResponse = ContractJsonResponse<
|
||||
typeof awsCloudformationValidateTemplateContract
|
||||
>
|
||||
@@ -0,0 +1,73 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const DescribeAlarmHistorySchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
alarmName: z.string().optional(),
|
||||
historyItemType: z.preprocess(
|
||||
(v) => (v === '' ? undefined : v),
|
||||
z
|
||||
.enum([
|
||||
'ConfigurationUpdate',
|
||||
'StateUpdate',
|
||||
'Action',
|
||||
'AlarmContributorStateUpdate',
|
||||
'AlarmContributorAction',
|
||||
])
|
||||
.optional()
|
||||
),
|
||||
startDate: z.coerce.number().int().optional(),
|
||||
endDate: z.coerce.number().int().optional(),
|
||||
scanBy: z.preprocess(
|
||||
(v) => (v === '' ? undefined : v),
|
||||
z.enum(['TimestampDescending', 'TimestampAscending']).optional()
|
||||
),
|
||||
limit: z.preprocess(
|
||||
(v) => (v === '' || v === undefined || v === null ? undefined : v),
|
||||
z.coerce.number().int().positive().optional()
|
||||
),
|
||||
})
|
||||
|
||||
const DescribeAlarmHistoryResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
alarmHistoryItems: z.array(
|
||||
z.object({
|
||||
alarmName: z.string().optional(),
|
||||
alarmType: z.string().optional(),
|
||||
timestamp: z.number().optional(),
|
||||
historyItemType: z.string().optional(),
|
||||
historySummary: z.string().optional(),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudwatchDescribeAlarmHistoryContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudwatch/describe-alarm-history',
|
||||
body: DescribeAlarmHistorySchema,
|
||||
response: { mode: 'json', schema: DescribeAlarmHistoryResponseSchema },
|
||||
})
|
||||
export type AwsCloudwatchDescribeAlarmHistoryRequest = ContractBodyInput<
|
||||
typeof awsCloudwatchDescribeAlarmHistoryContract
|
||||
>
|
||||
export type AwsCloudwatchDescribeAlarmHistoryBody = ContractBody<
|
||||
typeof awsCloudwatchDescribeAlarmHistoryContract
|
||||
>
|
||||
export type AwsCloudwatchDescribeAlarmHistoryResponse = ContractJsonResponse<
|
||||
typeof awsCloudwatchDescribeAlarmHistoryContract
|
||||
>
|
||||
@@ -0,0 +1,73 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const DescribeAlarmsSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
alarmNamePrefix: z.string().optional(),
|
||||
stateValue: z.preprocess(
|
||||
(v) => (v === '' ? undefined : v),
|
||||
z.enum(['OK', 'ALARM', 'INSUFFICIENT_DATA']).optional()
|
||||
),
|
||||
alarmType: z.preprocess(
|
||||
(v) => (v === '' ? undefined : v),
|
||||
z.enum(['MetricAlarm', 'CompositeAlarm']).optional()
|
||||
),
|
||||
limit: z.preprocess(
|
||||
(v) => (v === '' || v === undefined || v === null ? undefined : v),
|
||||
z.coerce
|
||||
.number()
|
||||
.int()
|
||||
.positive()
|
||||
.max(100, 'limit must be at most 100 (CloudWatch DescribeAlarms limit)')
|
||||
.optional()
|
||||
),
|
||||
})
|
||||
|
||||
const DescribeAlarmsResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
alarms: z.array(
|
||||
z.object({
|
||||
alarmName: z.string(),
|
||||
alarmArn: z.string(),
|
||||
stateValue: z.string(),
|
||||
stateReason: z.string(),
|
||||
metricName: z.string().optional(),
|
||||
namespace: z.string().optional(),
|
||||
comparisonOperator: z.string().optional(),
|
||||
threshold: z.number().optional(),
|
||||
evaluationPeriods: z.number().optional(),
|
||||
stateUpdatedTimestamp: z.number().optional(),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudwatchDescribeAlarmsContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudwatch/describe-alarms',
|
||||
body: DescribeAlarmsSchema,
|
||||
response: { mode: 'json', schema: DescribeAlarmsResponseSchema },
|
||||
})
|
||||
export type AwsCloudwatchDescribeAlarmsRequest = ContractBodyInput<
|
||||
typeof awsCloudwatchDescribeAlarmsContract
|
||||
>
|
||||
export type AwsCloudwatchDescribeAlarmsBody = ContractBody<
|
||||
typeof awsCloudwatchDescribeAlarmsContract
|
||||
>
|
||||
export type AwsCloudwatchDescribeAlarmsResponse = ContractJsonResponse<
|
||||
typeof awsCloudwatchDescribeAlarmsContract
|
||||
>
|
||||
@@ -0,0 +1,59 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const FilterLogEventsSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
logGroupName: z.string().min(1, 'Log group name is required'),
|
||||
filterPattern: z.string().max(1024).optional(),
|
||||
logStreamNamePrefix: z.string().optional(),
|
||||
startTime: z.coerce.number().int().optional(),
|
||||
endTime: z.coerce.number().int().optional(),
|
||||
startFromHead: z.boolean().optional(),
|
||||
limit: z.preprocess(
|
||||
(v) => (v === '' || v === undefined || v === null ? undefined : v),
|
||||
z.coerce.number().int().positive().optional()
|
||||
),
|
||||
})
|
||||
|
||||
const FilterLogEventsResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
events: z.array(
|
||||
z.object({
|
||||
logStreamName: z.string().optional(),
|
||||
timestamp: z.number().optional(),
|
||||
message: z.string().optional(),
|
||||
ingestionTime: z.number().optional(),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudwatchFilterLogEventsContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudwatch/filter-log-events',
|
||||
body: FilterLogEventsSchema,
|
||||
response: { mode: 'json', schema: FilterLogEventsResponseSchema },
|
||||
})
|
||||
export type AwsCloudwatchFilterLogEventsRequest = ContractBodyInput<
|
||||
typeof awsCloudwatchFilterLogEventsContract
|
||||
>
|
||||
export type AwsCloudwatchFilterLogEventsBody = ContractBody<
|
||||
typeof awsCloudwatchFilterLogEventsContract
|
||||
>
|
||||
export type AwsCloudwatchFilterLogEventsResponse = ContractJsonResponse<
|
||||
typeof awsCloudwatchFilterLogEventsContract
|
||||
>
|
||||
@@ -0,0 +1,59 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const GetLogEventsSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
logGroupName: z.string().min(1, 'Log group name is required'),
|
||||
logStreamName: z.string().min(1, 'Log stream name is required'),
|
||||
startTime: z.coerce.number().int().optional(),
|
||||
endTime: z.coerce.number().int().optional(),
|
||||
limit: z.preprocess(
|
||||
(v) => (v === '' || v === undefined || v === null ? undefined : v),
|
||||
z.coerce
|
||||
.number()
|
||||
.int()
|
||||
.positive()
|
||||
.max(10000, 'limit must be at most 10000 (CloudWatch Logs GetLogEvents limit)')
|
||||
.optional()
|
||||
),
|
||||
})
|
||||
|
||||
const GetLogEventsResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
events: z.array(
|
||||
z.object({
|
||||
timestamp: z.number().optional(),
|
||||
message: z.string().optional(),
|
||||
ingestionTime: z.number().optional(),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudwatchGetLogEventsContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudwatch/get-log-events',
|
||||
body: GetLogEventsSchema,
|
||||
response: { mode: 'json', schema: GetLogEventsResponseSchema },
|
||||
})
|
||||
export type AwsCloudwatchGetLogEventsRequest = ContractBodyInput<
|
||||
typeof awsCloudwatchGetLogEventsContract
|
||||
>
|
||||
export type AwsCloudwatchGetLogEventsBody = ContractBody<typeof awsCloudwatchGetLogEventsContract>
|
||||
export type AwsCloudwatchGetLogEventsResponse = ContractJsonResponse<
|
||||
typeof awsCloudwatchGetLogEventsContract
|
||||
>
|
||||
@@ -0,0 +1,63 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const GetMetricStatisticsSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
namespace: z.string().min(1, 'Namespace is required'),
|
||||
metricName: z.string().min(1, 'Metric name is required'),
|
||||
startTime: z.coerce.number().int(),
|
||||
endTime: z.coerce.number().int(),
|
||||
period: z.coerce.number().int().min(1),
|
||||
statistics: z
|
||||
.array(z.enum(['Average', 'Sum', 'Minimum', 'Maximum', 'SampleCount']))
|
||||
.min(1, 'At least one statistic is required')
|
||||
.max(5, 'At most 5 statistics are allowed per GetMetricStatistics call'),
|
||||
dimensions: z.string().optional(),
|
||||
})
|
||||
|
||||
const GetMetricStatisticsResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
label: z.string(),
|
||||
datapoints: z.array(
|
||||
z.object({
|
||||
timestamp: z.number(),
|
||||
average: z.number().optional(),
|
||||
sum: z.number().optional(),
|
||||
minimum: z.number().optional(),
|
||||
maximum: z.number().optional(),
|
||||
sampleCount: z.number().optional(),
|
||||
unit: z.string().optional(),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudwatchGetMetricStatisticsContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudwatch/get-metric-statistics',
|
||||
body: GetMetricStatisticsSchema,
|
||||
response: { mode: 'json', schema: GetMetricStatisticsResponseSchema },
|
||||
})
|
||||
export type AwsCloudwatchGetMetricStatisticsRequest = ContractBodyInput<
|
||||
typeof awsCloudwatchGetMetricStatisticsContract
|
||||
>
|
||||
export type AwsCloudwatchGetMetricStatisticsBody = ContractBody<
|
||||
typeof awsCloudwatchGetMetricStatisticsContract
|
||||
>
|
||||
export type AwsCloudwatchGetMetricStatisticsResponse = ContractJsonResponse<
|
||||
typeof awsCloudwatchGetMetricStatisticsContract
|
||||
>
|
||||
@@ -0,0 +1,58 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const ListMetricsSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
namespace: z.string().optional(),
|
||||
metricName: z.string().optional(),
|
||||
recentlyActive: z.boolean().optional(),
|
||||
limit: z.preprocess(
|
||||
(v) => (v === '' || v === undefined || v === null ? undefined : v),
|
||||
z.coerce.number().int().positive().optional()
|
||||
),
|
||||
})
|
||||
|
||||
const ListMetricsResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
metrics: z.array(
|
||||
z.object({
|
||||
namespace: z.string(),
|
||||
metricName: z.string(),
|
||||
dimensions: z.array(
|
||||
z.object({
|
||||
name: z.string(),
|
||||
value: z.string(),
|
||||
})
|
||||
),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudwatchListMetricsContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudwatch/list-metrics',
|
||||
body: ListMetricsSchema,
|
||||
response: { mode: 'json', schema: ListMetricsResponseSchema },
|
||||
})
|
||||
export type AwsCloudwatchListMetricsRequest = ContractBodyInput<
|
||||
typeof awsCloudwatchListMetricsContract
|
||||
>
|
||||
export type AwsCloudwatchListMetricsBody = ContractBody<typeof awsCloudwatchListMetricsContract>
|
||||
export type AwsCloudwatchListMetricsResponse = ContractJsonResponse<
|
||||
typeof awsCloudwatchListMetricsContract
|
||||
>
|
||||
@@ -0,0 +1,75 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const MAX_MUTE_MINUTES = 15 * 24 * 60
|
||||
|
||||
const MuteAlarmSchema = z
|
||||
.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
muteRuleName: z
|
||||
.string()
|
||||
.min(1, 'muteRuleName cannot be empty')
|
||||
.max(255, 'muteRuleName must be at most 255 characters'),
|
||||
alarmNames: z
|
||||
.array(z.string().min(1, 'Alarm name cannot be empty').max(255))
|
||||
.min(1, 'At least one alarm name is required')
|
||||
.max(100, 'At most 100 alarm names are allowed per mute rule'),
|
||||
durationValue: z
|
||||
.number()
|
||||
.int('durationValue must be an integer')
|
||||
.min(1, 'durationValue must be at least 1'),
|
||||
durationUnit: z.enum(['minutes', 'hours', 'days']),
|
||||
description: z.string().max(1024).optional(),
|
||||
startDate: z
|
||||
.number()
|
||||
.int('startDate must be an integer')
|
||||
.min(0, 'startDate must be a non-negative Unix epoch in seconds')
|
||||
.optional(),
|
||||
})
|
||||
.superRefine((data, ctx) => {
|
||||
const minutesPerUnit = { minutes: 1, hours: 60, days: 1440 } as const
|
||||
const totalMinutes = data.durationValue * minutesPerUnit[data.durationUnit]
|
||||
if (totalMinutes > MAX_MUTE_MINUTES) {
|
||||
ctx.addIssue({
|
||||
code: 'custom',
|
||||
message: 'duration must be at most 15 days (CloudWatch mute rule limit)',
|
||||
path: ['durationValue'],
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const MuteAlarmResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
success: z.literal(true),
|
||||
muteRuleName: z.string(),
|
||||
alarmNames: z.array(z.string()),
|
||||
expression: z.string(),
|
||||
duration: z.string(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudwatchMuteAlarmContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudwatch/mute-alarm',
|
||||
body: MuteAlarmSchema,
|
||||
response: { mode: 'json', schema: MuteAlarmResponseSchema },
|
||||
})
|
||||
export type AwsCloudwatchMuteAlarmRequest = ContractBodyInput<typeof awsCloudwatchMuteAlarmContract>
|
||||
export type AwsCloudwatchMuteAlarmBody = ContractBody<typeof awsCloudwatchMuteAlarmContract>
|
||||
export type AwsCloudwatchMuteAlarmResponse = ContractJsonResponse<
|
||||
typeof awsCloudwatchMuteAlarmContract
|
||||
>
|
||||
@@ -0,0 +1,60 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
/** Only these values are accepted by CloudWatch Logs PutRetentionPolicy. */
|
||||
const VALID_RETENTION_DAYS = [
|
||||
1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1096, 1827, 2192, 2557, 2922, 3288,
|
||||
3653,
|
||||
] as const
|
||||
|
||||
const PutLogGroupRetentionSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
logGroupName: z.string().min(1, 'Log group name is required'),
|
||||
retentionInDays: z.preprocess(
|
||||
(v) => (v === '' || v === undefined || v === null ? undefined : v),
|
||||
z.coerce
|
||||
.number()
|
||||
.refine((v) => (VALID_RETENTION_DAYS as readonly number[]).includes(v), {
|
||||
message: `retentionInDays must be one of ${VALID_RETENTION_DAYS.join(', ')}`,
|
||||
})
|
||||
.optional()
|
||||
),
|
||||
})
|
||||
|
||||
const PutLogGroupRetentionResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
success: z.literal(true),
|
||||
logGroupName: z.string(),
|
||||
retentionInDays: z.number().nullable(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudwatchPutLogGroupRetentionContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudwatch/put-log-group-retention',
|
||||
body: PutLogGroupRetentionSchema,
|
||||
response: { mode: 'json', schema: PutLogGroupRetentionResponseSchema },
|
||||
})
|
||||
export type AwsCloudwatchPutLogGroupRetentionRequest = ContractBodyInput<
|
||||
typeof awsCloudwatchPutLogGroupRetentionContract
|
||||
>
|
||||
export type AwsCloudwatchPutLogGroupRetentionBody = ContractBody<
|
||||
typeof awsCloudwatchPutLogGroupRetentionContract
|
||||
>
|
||||
export type AwsCloudwatchPutLogGroupRetentionResponse = ContractJsonResponse<
|
||||
typeof awsCloudwatchPutLogGroupRetentionContract
|
||||
>
|
||||
@@ -0,0 +1,97 @@
|
||||
import { isRecordLike } from '@sim/utils/object'
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const VALID_UNITS = [
|
||||
'Seconds',
|
||||
'Microseconds',
|
||||
'Milliseconds',
|
||||
'Bytes',
|
||||
'Kilobytes',
|
||||
'Megabytes',
|
||||
'Gigabytes',
|
||||
'Terabytes',
|
||||
'Bits',
|
||||
'Kilobits',
|
||||
'Megabits',
|
||||
'Gigabits',
|
||||
'Terabits',
|
||||
'Percent',
|
||||
'Count',
|
||||
'Bytes/Second',
|
||||
'Kilobytes/Second',
|
||||
'Megabytes/Second',
|
||||
'Gigabytes/Second',
|
||||
'Terabytes/Second',
|
||||
'Bits/Second',
|
||||
'Kilobits/Second',
|
||||
'Megabits/Second',
|
||||
'Gigabits/Second',
|
||||
'Terabits/Second',
|
||||
'Count/Second',
|
||||
'None',
|
||||
] as const
|
||||
|
||||
const PutMetricDataSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
namespace: z.string().min(1, 'Namespace is required'),
|
||||
metricName: z.string().min(1, 'Metric name is required'),
|
||||
value: z.coerce.number().refine((v) => Number.isFinite(v), {
|
||||
message: 'Metric value must be a finite number',
|
||||
}),
|
||||
unit: z.enum(VALID_UNITS).optional(),
|
||||
dimensions: z
|
||||
.string()
|
||||
.optional()
|
||||
.refine(
|
||||
(val) => {
|
||||
if (!val) return true
|
||||
try {
|
||||
const parsed = JSON.parse(val)
|
||||
return isRecordLike(parsed)
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
},
|
||||
{ message: 'dimensions must be a valid JSON object string' }
|
||||
),
|
||||
})
|
||||
|
||||
const PutMetricDataResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
success: z.literal(true),
|
||||
namespace: z.string(),
|
||||
metricName: z.string(),
|
||||
value: z.number(),
|
||||
unit: z.string(),
|
||||
timestamp: z.string(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudwatchPutMetricDataContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudwatch/put-metric-data',
|
||||
body: PutMetricDataSchema,
|
||||
response: { mode: 'json', schema: PutMetricDataResponseSchema },
|
||||
})
|
||||
export type AwsCloudwatchPutMetricDataRequest = ContractBodyInput<
|
||||
typeof awsCloudwatchPutMetricDataContract
|
||||
>
|
||||
export type AwsCloudwatchPutMetricDataBody = ContractBody<typeof awsCloudwatchPutMetricDataContract>
|
||||
export type AwsCloudwatchPutMetricDataResponse = ContractJsonResponse<
|
||||
typeof awsCloudwatchPutMetricDataContract
|
||||
>
|
||||
@@ -0,0 +1,52 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const QueryLogsSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
logGroupNames: z.array(z.string().min(1)).min(1, 'At least one log group name is required'),
|
||||
queryString: z.string().min(1, 'Query string is required'),
|
||||
startTime: z.coerce.number().int(),
|
||||
endTime: z.coerce.number().int(),
|
||||
limit: z.preprocess(
|
||||
(v) => (v === '' || v === undefined || v === null ? undefined : v),
|
||||
z.coerce.number().int().positive().optional()
|
||||
),
|
||||
})
|
||||
|
||||
const QueryLogsResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
results: z.array(z.record(z.string(), z.string())),
|
||||
statistics: z.object({
|
||||
bytesScanned: z.number(),
|
||||
recordsMatched: z.number(),
|
||||
recordsScanned: z.number(),
|
||||
}),
|
||||
status: z.string(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudwatchQueryLogsContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudwatch/query-logs',
|
||||
body: QueryLogsSchema,
|
||||
response: { mode: 'json', schema: QueryLogsResponseSchema },
|
||||
})
|
||||
export type AwsCloudwatchQueryLogsRequest = ContractBodyInput<typeof awsCloudwatchQueryLogsContract>
|
||||
export type AwsCloudwatchQueryLogsBody = ContractBody<typeof awsCloudwatchQueryLogsContract>
|
||||
export type AwsCloudwatchQueryLogsResponse = ContractJsonResponse<
|
||||
typeof awsCloudwatchQueryLogsContract
|
||||
>
|
||||
@@ -0,0 +1,45 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const UnmuteAlarmSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
muteRuleName: z
|
||||
.string()
|
||||
.min(1, 'muteRuleName cannot be empty')
|
||||
.max(255, 'muteRuleName must be at most 255 characters'),
|
||||
})
|
||||
|
||||
const UnmuteAlarmResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
success: z.literal(true),
|
||||
muteRuleName: z.string(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCloudwatchUnmuteAlarmContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/cloudwatch/unmute-alarm',
|
||||
body: UnmuteAlarmSchema,
|
||||
response: { mode: 'json', schema: UnmuteAlarmResponseSchema },
|
||||
})
|
||||
export type AwsCloudwatchUnmuteAlarmRequest = ContractBodyInput<
|
||||
typeof awsCloudwatchUnmuteAlarmContract
|
||||
>
|
||||
export type AwsCloudwatchUnmuteAlarmBody = ContractBody<typeof awsCloudwatchUnmuteAlarmContract>
|
||||
export type AwsCloudwatchUnmuteAlarmResponse = ContractJsonResponse<
|
||||
typeof awsCloudwatchUnmuteAlarmContract
|
||||
>
|
||||
@@ -0,0 +1,54 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const DisableStageTransitionSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
pipelineName: z
|
||||
.string()
|
||||
.min(1, 'Pipeline name is required')
|
||||
.max(100, 'Pipeline name must be at most 100 characters'),
|
||||
stageName: z
|
||||
.string()
|
||||
.min(1, 'Stage name is required')
|
||||
.max(100, 'Stage name must be at most 100 characters'),
|
||||
transitionType: z.enum(['Inbound', 'Outbound']),
|
||||
reason: z.string().min(1, 'Reason is required').max(300, 'Reason must be at most 300 characters'),
|
||||
})
|
||||
|
||||
const DisableStageTransitionResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
pipelineName: z.string(),
|
||||
stageName: z.string(),
|
||||
transitionType: z.enum(['Inbound', 'Outbound']),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCodepipelineDisableStageTransitionContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/codepipeline/disable-stage-transition',
|
||||
body: DisableStageTransitionSchema,
|
||||
response: { mode: 'json', schema: DisableStageTransitionResponseSchema },
|
||||
})
|
||||
export type AwsCodepipelineDisableStageTransitionRequest = ContractBodyInput<
|
||||
typeof awsCodepipelineDisableStageTransitionContract
|
||||
>
|
||||
export type AwsCodepipelineDisableStageTransitionBody = ContractBody<
|
||||
typeof awsCodepipelineDisableStageTransitionContract
|
||||
>
|
||||
export type AwsCodepipelineDisableStageTransitionResponse = ContractJsonResponse<
|
||||
typeof awsCodepipelineDisableStageTransitionContract
|
||||
>
|
||||
@@ -0,0 +1,53 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const EnableStageTransitionSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
pipelineName: z
|
||||
.string()
|
||||
.min(1, 'Pipeline name is required')
|
||||
.max(100, 'Pipeline name must be at most 100 characters'),
|
||||
stageName: z
|
||||
.string()
|
||||
.min(1, 'Stage name is required')
|
||||
.max(100, 'Stage name must be at most 100 characters'),
|
||||
transitionType: z.enum(['Inbound', 'Outbound']),
|
||||
})
|
||||
|
||||
const EnableStageTransitionResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
pipelineName: z.string(),
|
||||
stageName: z.string(),
|
||||
transitionType: z.enum(['Inbound', 'Outbound']),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCodepipelineEnableStageTransitionContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/codepipeline/enable-stage-transition',
|
||||
body: EnableStageTransitionSchema,
|
||||
response: { mode: 'json', schema: EnableStageTransitionResponseSchema },
|
||||
})
|
||||
export type AwsCodepipelineEnableStageTransitionRequest = ContractBodyInput<
|
||||
typeof awsCodepipelineEnableStageTransitionContract
|
||||
>
|
||||
export type AwsCodepipelineEnableStageTransitionBody = ContractBody<
|
||||
typeof awsCodepipelineEnableStageTransitionContract
|
||||
>
|
||||
export type AwsCodepipelineEnableStageTransitionResponse = ContractJsonResponse<
|
||||
typeof awsCodepipelineEnableStageTransitionContract
|
||||
>
|
||||
@@ -0,0 +1,70 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const GetPipelineExecutionSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
pipelineName: z
|
||||
.string()
|
||||
.min(1, 'Pipeline name is required')
|
||||
.max(100, 'Pipeline name must be at most 100 characters'),
|
||||
pipelineExecutionId: z.string().min(1, 'Pipeline execution ID is required'),
|
||||
})
|
||||
|
||||
const GetPipelineExecutionResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
pipelineExecutionId: z.string(),
|
||||
pipelineName: z.string(),
|
||||
pipelineVersion: z.number().optional(),
|
||||
status: z.string(),
|
||||
statusSummary: z.string().optional(),
|
||||
executionMode: z.string().optional(),
|
||||
executionType: z.string().optional(),
|
||||
triggerType: z.string().optional(),
|
||||
triggerDetail: z.string().optional(),
|
||||
artifactRevisions: z.array(
|
||||
z.object({
|
||||
name: z.string(),
|
||||
revisionId: z.string().optional(),
|
||||
revisionSummary: z.string().optional(),
|
||||
revisionUrl: z.string().optional(),
|
||||
created: z.number().optional(),
|
||||
})
|
||||
),
|
||||
variables: z.array(
|
||||
z.object({
|
||||
name: z.string(),
|
||||
resolvedValue: z.string(),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCodepipelineGetPipelineExecutionContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/codepipeline/get-pipeline-execution',
|
||||
body: GetPipelineExecutionSchema,
|
||||
response: { mode: 'json', schema: GetPipelineExecutionResponseSchema },
|
||||
})
|
||||
export type AwsCodepipelineGetPipelineExecutionRequest = ContractBodyInput<
|
||||
typeof awsCodepipelineGetPipelineExecutionContract
|
||||
>
|
||||
export type AwsCodepipelineGetPipelineExecutionBody = ContractBody<
|
||||
typeof awsCodepipelineGetPipelineExecutionContract
|
||||
>
|
||||
export type AwsCodepipelineGetPipelineExecutionResponse = ContractJsonResponse<
|
||||
typeof awsCodepipelineGetPipelineExecutionContract
|
||||
>
|
||||
@@ -0,0 +1,73 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const GetPipelineStateSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
pipelineName: z
|
||||
.string()
|
||||
.min(1, 'Pipeline name is required')
|
||||
.max(100, 'Pipeline name must be at most 100 characters'),
|
||||
})
|
||||
|
||||
const ActionStateSchema = z.object({
|
||||
actionName: z.string(),
|
||||
status: z.string().optional(),
|
||||
summary: z.string().optional(),
|
||||
lastStatusChange: z.number().optional(),
|
||||
externalExecutionId: z.string().optional(),
|
||||
externalExecutionUrl: z.string().optional(),
|
||||
errorCode: z.string().optional(),
|
||||
errorMessage: z.string().optional(),
|
||||
percentComplete: z.number().optional(),
|
||||
token: z.string().optional(),
|
||||
revisionId: z.string().optional(),
|
||||
entityUrl: z.string().optional(),
|
||||
})
|
||||
|
||||
const StageStateSchema = z.object({
|
||||
stageName: z.string(),
|
||||
status: z.string().optional(),
|
||||
pipelineExecutionId: z.string().optional(),
|
||||
inboundTransitionEnabled: z.boolean().optional(),
|
||||
actionStates: z.array(ActionStateSchema),
|
||||
})
|
||||
|
||||
const GetPipelineStateResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
pipelineName: z.string(),
|
||||
pipelineVersion: z.number().optional(),
|
||||
created: z.number().optional(),
|
||||
updated: z.number().optional(),
|
||||
stageStates: z.array(StageStateSchema),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCodepipelineGetPipelineStateContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/codepipeline/get-pipeline-state',
|
||||
body: GetPipelineStateSchema,
|
||||
response: { mode: 'json', schema: GetPipelineStateResponseSchema },
|
||||
})
|
||||
export type AwsCodepipelineGetPipelineStateRequest = ContractBodyInput<
|
||||
typeof awsCodepipelineGetPipelineStateContract
|
||||
>
|
||||
export type AwsCodepipelineGetPipelineStateBody = ContractBody<
|
||||
typeof awsCodepipelineGetPipelineStateContract
|
||||
>
|
||||
export type AwsCodepipelineGetPipelineStateResponse = ContractJsonResponse<
|
||||
typeof awsCodepipelineGetPipelineStateContract
|
||||
>
|
||||
@@ -0,0 +1,82 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const GetPipelineSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
pipelineName: z
|
||||
.string()
|
||||
.min(1, 'Pipeline name is required')
|
||||
.max(100, 'Pipeline name must be at most 100 characters'),
|
||||
version: z.preprocess(
|
||||
(v) => (v === '' || v === undefined || v === null ? undefined : v),
|
||||
z.coerce.number().int().min(1).optional()
|
||||
),
|
||||
})
|
||||
|
||||
const ActionDeclarationSchema = z.object({
|
||||
name: z.string(),
|
||||
category: z.string(),
|
||||
owner: z.string(),
|
||||
provider: z.string(),
|
||||
version: z.string(),
|
||||
runOrder: z.number().optional(),
|
||||
configuration: z.record(z.string(), z.string()),
|
||||
inputArtifacts: z.array(z.string()),
|
||||
outputArtifacts: z.array(z.string()),
|
||||
})
|
||||
|
||||
const StageDeclarationSchema = z.object({
|
||||
stageName: z.string(),
|
||||
actions: z.array(ActionDeclarationSchema),
|
||||
})
|
||||
|
||||
const GetPipelineResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
pipelineName: z.string(),
|
||||
pipelineArn: z.string().optional(),
|
||||
roleArn: z.string(),
|
||||
version: z.number().optional(),
|
||||
pipelineType: z.string().optional(),
|
||||
executionMode: z.string().optional(),
|
||||
artifactStoreType: z.string().optional(),
|
||||
artifactStoreLocation: z.string().optional(),
|
||||
stages: z.array(StageDeclarationSchema),
|
||||
variables: z.array(
|
||||
z.object({
|
||||
name: z.string(),
|
||||
defaultValue: z.string().optional(),
|
||||
description: z.string().optional(),
|
||||
})
|
||||
),
|
||||
created: z.number().optional(),
|
||||
updated: z.number().optional(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCodepipelineGetPipelineContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/codepipeline/get-pipeline',
|
||||
body: GetPipelineSchema,
|
||||
response: { mode: 'json', schema: GetPipelineResponseSchema },
|
||||
})
|
||||
export type AwsCodepipelineGetPipelineRequest = ContractBodyInput<
|
||||
typeof awsCodepipelineGetPipelineContract
|
||||
>
|
||||
export type AwsCodepipelineGetPipelineBody = ContractBody<typeof awsCodepipelineGetPipelineContract>
|
||||
export type AwsCodepipelineGetPipelineResponse = ContractJsonResponse<
|
||||
typeof awsCodepipelineGetPipelineContract
|
||||
>
|
||||
@@ -0,0 +1,70 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const ListActionExecutionsSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
pipelineName: z
|
||||
.string()
|
||||
.min(1, 'Pipeline name is required')
|
||||
.max(100, 'Pipeline name must be at most 100 characters'),
|
||||
pipelineExecutionId: z.string().min(1).optional(),
|
||||
maxResults: z.preprocess(
|
||||
(v) => (v === '' || v === undefined || v === null ? undefined : v),
|
||||
z.coerce.number().int().min(1).max(100).optional()
|
||||
),
|
||||
nextToken: z.string().min(1).max(2048).optional(),
|
||||
})
|
||||
|
||||
const ActionExecutionDetailSchema = z.object({
|
||||
pipelineExecutionId: z.string().optional(),
|
||||
actionExecutionId: z.string().optional(),
|
||||
pipelineVersion: z.number().optional(),
|
||||
stageName: z.string().optional(),
|
||||
actionName: z.string().optional(),
|
||||
startTime: z.number().optional(),
|
||||
lastUpdateTime: z.number().optional(),
|
||||
updatedBy: z.string().optional(),
|
||||
status: z.string().optional(),
|
||||
externalExecutionId: z.string().optional(),
|
||||
externalExecutionSummary: z.string().optional(),
|
||||
externalExecutionUrl: z.string().optional(),
|
||||
errorCode: z.string().optional(),
|
||||
errorMessage: z.string().optional(),
|
||||
})
|
||||
|
||||
const ListActionExecutionsResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
actionExecutionDetails: z.array(ActionExecutionDetailSchema),
|
||||
nextToken: z.string().optional(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCodepipelineListActionExecutionsContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/codepipeline/list-action-executions',
|
||||
body: ListActionExecutionsSchema,
|
||||
response: { mode: 'json', schema: ListActionExecutionsResponseSchema },
|
||||
})
|
||||
export type AwsCodepipelineListActionExecutionsRequest = ContractBodyInput<
|
||||
typeof awsCodepipelineListActionExecutionsContract
|
||||
>
|
||||
export type AwsCodepipelineListActionExecutionsBody = ContractBody<
|
||||
typeof awsCodepipelineListActionExecutionsContract
|
||||
>
|
||||
export type AwsCodepipelineListActionExecutionsResponse = ContractJsonResponse<
|
||||
typeof awsCodepipelineListActionExecutionsContract
|
||||
>
|
||||
@@ -0,0 +1,75 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const ListPipelineExecutionsSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
pipelineName: z
|
||||
.string()
|
||||
.min(1, 'Pipeline name is required')
|
||||
.max(100, 'Pipeline name must be at most 100 characters'),
|
||||
maxResults: z.preprocess(
|
||||
(v) => (v === '' || v === undefined || v === null ? undefined : v),
|
||||
z.coerce.number().int().min(1).max(100).optional()
|
||||
),
|
||||
nextToken: z.string().min(1).max(2048).optional(),
|
||||
succeededInStage: z.string().min(1).max(100).optional(),
|
||||
})
|
||||
|
||||
const PipelineExecutionSummarySchema = z.object({
|
||||
pipelineExecutionId: z.string(),
|
||||
status: z.string(),
|
||||
statusSummary: z.string().optional(),
|
||||
startTime: z.number().optional(),
|
||||
lastUpdateTime: z.number().optional(),
|
||||
executionMode: z.string().optional(),
|
||||
executionType: z.string().optional(),
|
||||
stopTriggerReason: z.string().optional(),
|
||||
triggerType: z.string().optional(),
|
||||
triggerDetail: z.string().optional(),
|
||||
rollbackTargetPipelineExecutionId: z.string().optional(),
|
||||
sourceRevisions: z.array(
|
||||
z.object({
|
||||
actionName: z.string(),
|
||||
revisionId: z.string().optional(),
|
||||
revisionSummary: z.string().optional(),
|
||||
revisionUrl: z.string().optional(),
|
||||
})
|
||||
),
|
||||
})
|
||||
|
||||
const ListPipelineExecutionsResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
executions: z.array(PipelineExecutionSummarySchema),
|
||||
nextToken: z.string().optional(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCodepipelineListPipelineExecutionsContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/codepipeline/list-pipeline-executions',
|
||||
body: ListPipelineExecutionsSchema,
|
||||
response: { mode: 'json', schema: ListPipelineExecutionsResponseSchema },
|
||||
})
|
||||
export type AwsCodepipelineListPipelineExecutionsRequest = ContractBodyInput<
|
||||
typeof awsCodepipelineListPipelineExecutionsContract
|
||||
>
|
||||
export type AwsCodepipelineListPipelineExecutionsBody = ContractBody<
|
||||
typeof awsCodepipelineListPipelineExecutionsContract
|
||||
>
|
||||
export type AwsCodepipelineListPipelineExecutionsResponse = ContractJsonResponse<
|
||||
typeof awsCodepipelineListPipelineExecutionsContract
|
||||
>
|
||||
@@ -0,0 +1,57 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const ListPipelinesSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
maxResults: z.preprocess(
|
||||
(v) => (v === '' || v === undefined || v === null ? undefined : v),
|
||||
z.coerce.number().int().min(1).max(1000).optional()
|
||||
),
|
||||
nextToken: z.string().min(1).max(2048).optional(),
|
||||
})
|
||||
|
||||
const ListPipelinesResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
pipelines: z.array(
|
||||
z.object({
|
||||
name: z.string(),
|
||||
version: z.number().optional(),
|
||||
pipelineType: z.string().optional(),
|
||||
executionMode: z.string().optional(),
|
||||
created: z.number().optional(),
|
||||
updated: z.number().optional(),
|
||||
})
|
||||
),
|
||||
nextToken: z.string().optional(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCodepipelineListPipelinesContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/codepipeline/list-pipelines',
|
||||
body: ListPipelinesSchema,
|
||||
response: { mode: 'json', schema: ListPipelinesResponseSchema },
|
||||
})
|
||||
export type AwsCodepipelineListPipelinesRequest = ContractBodyInput<
|
||||
typeof awsCodepipelineListPipelinesContract
|
||||
>
|
||||
export type AwsCodepipelineListPipelinesBody = ContractBody<
|
||||
typeof awsCodepipelineListPipelinesContract
|
||||
>
|
||||
export type AwsCodepipelineListPipelinesResponse = ContractJsonResponse<
|
||||
typeof awsCodepipelineListPipelinesContract
|
||||
>
|
||||
@@ -0,0 +1,61 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const PutApprovalResultSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
pipelineName: z
|
||||
.string()
|
||||
.min(1, 'Pipeline name is required')
|
||||
.max(100, 'Pipeline name must be at most 100 characters'),
|
||||
stageName: z
|
||||
.string()
|
||||
.min(1, 'Stage name is required')
|
||||
.max(100, 'Stage name must be at most 100 characters'),
|
||||
actionName: z
|
||||
.string()
|
||||
.min(1, 'Action name is required')
|
||||
.max(100, 'Action name must be at most 100 characters'),
|
||||
token: z.string().min(1, 'Approval token is required'),
|
||||
status: z.enum(['Approved', 'Rejected']),
|
||||
summary: z
|
||||
.string()
|
||||
.min(1, 'Approval summary is required')
|
||||
.max(512, 'Approval summary must be at most 512 characters'),
|
||||
})
|
||||
|
||||
const PutApprovalResultResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
approvedAt: z.number().optional(),
|
||||
status: z.string(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCodepipelinePutApprovalResultContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/codepipeline/put-approval-result',
|
||||
body: PutApprovalResultSchema,
|
||||
response: { mode: 'json', schema: PutApprovalResultResponseSchema },
|
||||
})
|
||||
export type AwsCodepipelinePutApprovalResultRequest = ContractBodyInput<
|
||||
typeof awsCodepipelinePutApprovalResultContract
|
||||
>
|
||||
export type AwsCodepipelinePutApprovalResultBody = ContractBody<
|
||||
typeof awsCodepipelinePutApprovalResultContract
|
||||
>
|
||||
export type AwsCodepipelinePutApprovalResultResponse = ContractJsonResponse<
|
||||
typeof awsCodepipelinePutApprovalResultContract
|
||||
>
|
||||
@@ -0,0 +1,52 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const RetryStageExecutionSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
pipelineName: z
|
||||
.string()
|
||||
.min(1, 'Pipeline name is required')
|
||||
.max(100, 'Pipeline name must be at most 100 characters'),
|
||||
stageName: z
|
||||
.string()
|
||||
.min(1, 'Stage name is required')
|
||||
.max(100, 'Stage name must be at most 100 characters'),
|
||||
pipelineExecutionId: z.string().min(1, 'Pipeline execution ID is required'),
|
||||
retryMode: z.enum(['FAILED_ACTIONS', 'ALL_ACTIONS']),
|
||||
})
|
||||
|
||||
const RetryStageExecutionResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
pipelineExecutionId: z.string(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCodepipelineRetryStageExecutionContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/codepipeline/retry-stage-execution',
|
||||
body: RetryStageExecutionSchema,
|
||||
response: { mode: 'json', schema: RetryStageExecutionResponseSchema },
|
||||
})
|
||||
export type AwsCodepipelineRetryStageExecutionRequest = ContractBodyInput<
|
||||
typeof awsCodepipelineRetryStageExecutionContract
|
||||
>
|
||||
export type AwsCodepipelineRetryStageExecutionBody = ContractBody<
|
||||
typeof awsCodepipelineRetryStageExecutionContract
|
||||
>
|
||||
export type AwsCodepipelineRetryStageExecutionResponse = ContractJsonResponse<
|
||||
typeof awsCodepipelineRetryStageExecutionContract
|
||||
>
|
||||
@@ -0,0 +1,62 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const StartExecutionSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
pipelineName: z
|
||||
.string()
|
||||
.min(1, 'Pipeline name is required')
|
||||
.max(100, 'Pipeline name must be at most 100 characters'),
|
||||
clientRequestToken: z
|
||||
.string()
|
||||
.min(1)
|
||||
.max(128)
|
||||
.regex(/^[a-zA-Z0-9-]+$/, 'Client request token may only contain letters, digits, and hyphens')
|
||||
.optional(),
|
||||
variables: z
|
||||
.array(
|
||||
z.object({
|
||||
name: z.string().min(1, 'Variable name is required'),
|
||||
value: z.string().min(1, 'Variable value cannot be empty'),
|
||||
})
|
||||
)
|
||||
.min(1)
|
||||
.max(50)
|
||||
.optional(),
|
||||
})
|
||||
|
||||
const StartExecutionResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
pipelineExecutionId: z.string(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCodepipelineStartExecutionContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/codepipeline/start-execution',
|
||||
body: StartExecutionSchema,
|
||||
response: { mode: 'json', schema: StartExecutionResponseSchema },
|
||||
})
|
||||
export type AwsCodepipelineStartExecutionRequest = ContractBodyInput<
|
||||
typeof awsCodepipelineStartExecutionContract
|
||||
>
|
||||
export type AwsCodepipelineStartExecutionBody = ContractBody<
|
||||
typeof awsCodepipelineStartExecutionContract
|
||||
>
|
||||
export type AwsCodepipelineStartExecutionResponse = ContractJsonResponse<
|
||||
typeof awsCodepipelineStartExecutionContract
|
||||
>
|
||||
@@ -0,0 +1,49 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const StopExecutionSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
pipelineName: z
|
||||
.string()
|
||||
.min(1, 'Pipeline name is required')
|
||||
.max(100, 'Pipeline name must be at most 100 characters'),
|
||||
pipelineExecutionId: z.string().min(1, 'Pipeline execution ID is required'),
|
||||
abandon: z.boolean().optional(),
|
||||
reason: z.string().max(200, 'Stop reason must be at most 200 characters').optional(),
|
||||
})
|
||||
|
||||
const StopExecutionResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
output: z.object({
|
||||
pipelineExecutionId: z.string(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const awsCodepipelineStopExecutionContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/codepipeline/stop-execution',
|
||||
body: StopExecutionSchema,
|
||||
response: { mode: 'json', schema: StopExecutionResponseSchema },
|
||||
})
|
||||
export type AwsCodepipelineStopExecutionRequest = ContractBodyInput<
|
||||
typeof awsCodepipelineStopExecutionContract
|
||||
>
|
||||
export type AwsCodepipelineStopExecutionBody = ContractBody<
|
||||
typeof awsCodepipelineStopExecutionContract
|
||||
>
|
||||
export type AwsCodepipelineStopExecutionResponse = ContractJsonResponse<
|
||||
typeof awsCodepipelineStopExecutionContract
|
||||
>
|
||||
@@ -0,0 +1,40 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const DeleteSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
tableName: z.string().min(1, 'Table name is required'),
|
||||
key: z.record(z.string(), z.unknown()).refine((val) => Object.keys(val).length > 0, {
|
||||
message: 'Key is required',
|
||||
}),
|
||||
conditionExpression: z.string().optional(),
|
||||
expressionAttributeNames: z.record(z.string(), z.string()).optional(),
|
||||
expressionAttributeValues: z.record(z.string(), z.unknown()).optional(),
|
||||
})
|
||||
|
||||
const DeleteResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
})
|
||||
|
||||
export const awsDynamodbDeleteContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/dynamodb/delete',
|
||||
body: DeleteSchema,
|
||||
response: { mode: 'json', schema: DeleteResponseSchema },
|
||||
})
|
||||
export type AwsDynamodbDeleteRequest = ContractBodyInput<typeof awsDynamodbDeleteContract>
|
||||
export type AwsDynamodbDeleteBody = ContractBody<typeof awsDynamodbDeleteContract>
|
||||
export type AwsDynamodbDeleteResponse = ContractJsonResponse<typeof awsDynamodbDeleteContract>
|
||||
@@ -0,0 +1,46 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const GetSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
tableName: z.string().min(1, 'Table name is required'),
|
||||
key: z.record(z.string(), z.unknown()).refine((val) => Object.keys(val).length > 0, {
|
||||
message: 'Key is required',
|
||||
}),
|
||||
consistentRead: z
|
||||
.union([z.boolean(), z.string()])
|
||||
.optional()
|
||||
.transform((val) => {
|
||||
if (val === true || val === 'true') return true
|
||||
return undefined
|
||||
}),
|
||||
})
|
||||
|
||||
const GetResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
// untyped-response: DynamoDB Item is an arbitrary user attribute-value record
|
||||
item: z.record(z.string(), z.unknown()).nullable(),
|
||||
})
|
||||
|
||||
export const awsDynamodbGetContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/dynamodb/get',
|
||||
body: GetSchema,
|
||||
response: { mode: 'json', schema: GetResponseSchema },
|
||||
})
|
||||
export type AwsDynamodbGetRequest = ContractBodyInput<typeof awsDynamodbGetContract>
|
||||
export type AwsDynamodbGetBody = ContractBody<typeof awsDynamodbGetContract>
|
||||
export type AwsDynamodbGetResponse = ContractJsonResponse<typeof awsDynamodbGetContract>
|
||||
@@ -0,0 +1,67 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const IntrospectSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
tableName: z.string().optional(),
|
||||
})
|
||||
|
||||
const KeySchemaEntrySchema = z.object({
|
||||
attributeName: z.string(),
|
||||
keyType: z.enum(['HASH', 'RANGE']),
|
||||
})
|
||||
|
||||
const SecondaryIndexSchema = z.object({
|
||||
indexName: z.string(),
|
||||
keySchema: z.array(KeySchemaEntrySchema),
|
||||
projectionType: z.string(),
|
||||
indexStatus: z.string(),
|
||||
})
|
||||
|
||||
const TableDetailsSchema = z.object({
|
||||
tableName: z.string(),
|
||||
tableStatus: z.string(),
|
||||
keySchema: z.array(KeySchemaEntrySchema),
|
||||
attributeDefinitions: z.array(
|
||||
z.object({
|
||||
attributeName: z.string(),
|
||||
attributeType: z.enum(['S', 'N', 'B']),
|
||||
})
|
||||
),
|
||||
globalSecondaryIndexes: z.array(SecondaryIndexSchema),
|
||||
localSecondaryIndexes: z.array(SecondaryIndexSchema),
|
||||
itemCount: z.number(),
|
||||
tableSizeBytes: z.number(),
|
||||
billingMode: z.string(),
|
||||
})
|
||||
|
||||
const IntrospectResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
tables: z.array(z.string()),
|
||||
tableDetails: TableDetailsSchema.optional(),
|
||||
})
|
||||
|
||||
export const awsDynamodbIntrospectContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/dynamodb/introspect',
|
||||
body: IntrospectSchema,
|
||||
response: { mode: 'json', schema: IntrospectResponseSchema },
|
||||
})
|
||||
export type AwsDynamodbIntrospectRequest = ContractBodyInput<typeof awsDynamodbIntrospectContract>
|
||||
export type AwsDynamodbIntrospectBody = ContractBody<typeof awsDynamodbIntrospectContract>
|
||||
export type AwsDynamodbIntrospectResponse = ContractJsonResponse<
|
||||
typeof awsDynamodbIntrospectContract
|
||||
>
|
||||
@@ -0,0 +1,42 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const PutSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
tableName: z.string().min(1, 'Table name is required'),
|
||||
item: z.record(z.string(), z.unknown()).refine((val) => Object.keys(val).length > 0, {
|
||||
message: 'Item is required',
|
||||
}),
|
||||
conditionExpression: z.string().optional(),
|
||||
expressionAttributeNames: z.record(z.string(), z.string()).optional(),
|
||||
expressionAttributeValues: z.record(z.string(), z.unknown()).optional(),
|
||||
})
|
||||
|
||||
const PutResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
// untyped-response: DynamoDB Item is an arbitrary user attribute-value record
|
||||
item: z.record(z.string(), z.unknown()),
|
||||
})
|
||||
|
||||
export const awsDynamodbPutContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/dynamodb/put',
|
||||
body: PutSchema,
|
||||
response: { mode: 'json', schema: PutResponseSchema },
|
||||
})
|
||||
export type AwsDynamodbPutRequest = ContractBodyInput<typeof awsDynamodbPutContract>
|
||||
export type AwsDynamodbPutBody = ContractBody<typeof awsDynamodbPutContract>
|
||||
export type AwsDynamodbPutResponse = ContractJsonResponse<typeof awsDynamodbPutContract>
|
||||
@@ -0,0 +1,47 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const QuerySchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
tableName: z.string().min(1, 'Table name is required'),
|
||||
keyConditionExpression: z.string().min(1, 'Key condition expression is required'),
|
||||
filterExpression: z.string().optional(),
|
||||
expressionAttributeNames: z.record(z.string(), z.string()).optional(),
|
||||
expressionAttributeValues: z.record(z.string(), z.unknown()).optional(),
|
||||
indexName: z.string().optional(),
|
||||
limit: z.number().positive().optional(),
|
||||
exclusiveStartKey: z.record(z.string(), z.unknown()).optional(),
|
||||
scanIndexForward: z.boolean().optional(),
|
||||
})
|
||||
|
||||
const QueryResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
// untyped-response: DynamoDB Items are arbitrary user attribute-value records
|
||||
items: z.array(z.record(z.string(), z.unknown())),
|
||||
count: z.number(),
|
||||
// untyped-response: DynamoDB LastEvaluatedKey mirrors the table's primary key shape
|
||||
lastEvaluatedKey: z.record(z.string(), z.unknown()).optional(),
|
||||
})
|
||||
|
||||
export const awsDynamodbQueryContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/dynamodb/query',
|
||||
body: QuerySchema,
|
||||
response: { mode: 'json', schema: QueryResponseSchema },
|
||||
})
|
||||
export type AwsDynamodbQueryRequest = ContractBodyInput<typeof awsDynamodbQueryContract>
|
||||
export type AwsDynamodbQueryBody = ContractBody<typeof awsDynamodbQueryContract>
|
||||
export type AwsDynamodbQueryResponse = ContractJsonResponse<typeof awsDynamodbQueryContract>
|
||||
@@ -0,0 +1,45 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const ScanSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
tableName: z.string().min(1, 'Table name is required'),
|
||||
filterExpression: z.string().optional(),
|
||||
projectionExpression: z.string().optional(),
|
||||
expressionAttributeNames: z.record(z.string(), z.string()).optional(),
|
||||
expressionAttributeValues: z.record(z.string(), z.unknown()).optional(),
|
||||
limit: z.number().positive().optional(),
|
||||
exclusiveStartKey: z.record(z.string(), z.unknown()).optional(),
|
||||
})
|
||||
|
||||
const ScanResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
// untyped-response: DynamoDB Items are arbitrary user attribute-value records
|
||||
items: z.array(z.record(z.string(), z.unknown())),
|
||||
count: z.number(),
|
||||
// untyped-response: DynamoDB LastEvaluatedKey mirrors the table's primary key shape
|
||||
lastEvaluatedKey: z.record(z.string(), z.unknown()).optional(),
|
||||
})
|
||||
|
||||
export const awsDynamodbScanContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/dynamodb/scan',
|
||||
body: ScanSchema,
|
||||
response: { mode: 'json', schema: ScanResponseSchema },
|
||||
})
|
||||
export type AwsDynamodbScanRequest = ContractBodyInput<typeof awsDynamodbScanContract>
|
||||
export type AwsDynamodbScanBody = ContractBody<typeof awsDynamodbScanContract>
|
||||
export type AwsDynamodbScanResponse = ContractJsonResponse<typeof awsDynamodbScanContract>
|
||||
@@ -0,0 +1,43 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const UpdateSchema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
tableName: z.string().min(1, 'Table name is required'),
|
||||
key: z.record(z.string(), z.unknown()).refine((val) => Object.keys(val).length > 0, {
|
||||
message: 'Key is required',
|
||||
}),
|
||||
updateExpression: z.string().min(1, 'Update expression is required'),
|
||||
expressionAttributeNames: z.record(z.string(), z.string()).optional(),
|
||||
expressionAttributeValues: z.record(z.string(), z.unknown()).optional(),
|
||||
conditionExpression: z.string().optional(),
|
||||
})
|
||||
|
||||
const UpdateResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
// untyped-response: DynamoDB UpdateItem Attributes is an arbitrary user attribute-value record
|
||||
item: z.record(z.string(), z.unknown()).nullable(),
|
||||
})
|
||||
|
||||
export const awsDynamodbUpdateContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/dynamodb/update',
|
||||
body: UpdateSchema,
|
||||
response: { mode: 'json', schema: UpdateResponseSchema },
|
||||
})
|
||||
export type AwsDynamodbUpdateRequest = ContractBodyInput<typeof awsDynamodbUpdateContract>
|
||||
export type AwsDynamodbUpdateBody = ContractBody<typeof awsDynamodbUpdateContract>
|
||||
export type AwsDynamodbUpdateResponse = ContractJsonResponse<typeof awsDynamodbUpdateContract>
|
||||
@@ -0,0 +1,31 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const Schema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
userName: z.string().min(1, 'User name is required'),
|
||||
groupName: z.string().min(1, 'Group name is required'),
|
||||
})
|
||||
|
||||
export const awsIamAddUserToGroupContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/iam/add-user-to-group',
|
||||
body: Schema,
|
||||
response: { mode: 'json', schema: z.object({ message: z.string() }) },
|
||||
})
|
||||
export type AwsIamAddUserToGroupRequest = ContractBodyInput<typeof awsIamAddUserToGroupContract>
|
||||
export type AwsIamAddUserToGroupBody = ContractBody<typeof awsIamAddUserToGroupContract>
|
||||
export type AwsIamAddUserToGroupResponse = ContractJsonResponse<typeof awsIamAddUserToGroupContract>
|
||||
@@ -0,0 +1,33 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const Schema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
roleName: z.string().min(1, 'Role name is required'),
|
||||
policyArn: z.string().min(1, 'Policy ARN is required'),
|
||||
})
|
||||
|
||||
export const awsIamAttachRolePolicyContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/iam/attach-role-policy',
|
||||
body: Schema,
|
||||
response: { mode: 'json', schema: z.object({ message: z.string() }) },
|
||||
})
|
||||
export type AwsIamAttachRolePolicyRequest = ContractBodyInput<typeof awsIamAttachRolePolicyContract>
|
||||
export type AwsIamAttachRolePolicyBody = ContractBody<typeof awsIamAttachRolePolicyContract>
|
||||
export type AwsIamAttachRolePolicyResponse = ContractJsonResponse<
|
||||
typeof awsIamAttachRolePolicyContract
|
||||
>
|
||||
@@ -0,0 +1,33 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const Schema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
userName: z.string().min(1, 'User name is required'),
|
||||
policyArn: z.string().min(1, 'Policy ARN is required'),
|
||||
})
|
||||
|
||||
export const awsIamAttachUserPolicyContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/iam/attach-user-policy',
|
||||
body: Schema,
|
||||
response: { mode: 'json', schema: z.object({ message: z.string() }) },
|
||||
})
|
||||
export type AwsIamAttachUserPolicyRequest = ContractBodyInput<typeof awsIamAttachUserPolicyContract>
|
||||
export type AwsIamAttachUserPolicyBody = ContractBody<typeof awsIamAttachUserPolicyContract>
|
||||
export type AwsIamAttachUserPolicyResponse = ContractJsonResponse<
|
||||
typeof awsIamAttachUserPolicyContract
|
||||
>
|
||||
@@ -0,0 +1,41 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const Schema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
userName: z.string().optional().nullable(),
|
||||
})
|
||||
|
||||
const CreateAccessKeyResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
accessKeyId: z.string(),
|
||||
secretAccessKey: z.string(),
|
||||
userName: z.string(),
|
||||
status: z.string(),
|
||||
createDate: z.string().nullable(),
|
||||
})
|
||||
|
||||
export const awsIamCreateAccessKeyContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/iam/create-access-key',
|
||||
body: Schema,
|
||||
response: { mode: 'json', schema: CreateAccessKeyResponseSchema },
|
||||
})
|
||||
export type AwsIamCreateAccessKeyRequest = ContractBodyInput<typeof awsIamCreateAccessKeyContract>
|
||||
export type AwsIamCreateAccessKeyBody = ContractBody<typeof awsIamCreateAccessKeyContract>
|
||||
export type AwsIamCreateAccessKeyResponse = ContractJsonResponse<
|
||||
typeof awsIamCreateAccessKeyContract
|
||||
>
|
||||
@@ -0,0 +1,43 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const Schema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
roleName: z.string().min(1, 'Role name is required'),
|
||||
assumeRolePolicyDocument: z.string().min(1, 'Assume role policy document is required'),
|
||||
description: z.string().optional().nullable(),
|
||||
path: z.string().optional().nullable(),
|
||||
maxSessionDuration: z.number().int().min(3600).max(43200).optional().nullable(),
|
||||
})
|
||||
|
||||
const CreateRoleResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
roleName: z.string(),
|
||||
roleId: z.string(),
|
||||
arn: z.string(),
|
||||
path: z.string(),
|
||||
createDate: z.string().nullable(),
|
||||
})
|
||||
|
||||
export const awsIamCreateRoleContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/iam/create-role',
|
||||
body: Schema,
|
||||
response: { mode: 'json', schema: CreateRoleResponseSchema },
|
||||
})
|
||||
export type AwsIamCreateRoleRequest = ContractBodyInput<typeof awsIamCreateRoleContract>
|
||||
export type AwsIamCreateRoleBody = ContractBody<typeof awsIamCreateRoleContract>
|
||||
export type AwsIamCreateRoleResponse = ContractJsonResponse<typeof awsIamCreateRoleContract>
|
||||
@@ -0,0 +1,40 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const Schema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
userName: z.string().min(1, 'User name is required'),
|
||||
path: z.string().optional().nullable(),
|
||||
})
|
||||
|
||||
const CreateUserResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
userName: z.string(),
|
||||
userId: z.string(),
|
||||
arn: z.string(),
|
||||
path: z.string(),
|
||||
createDate: z.string().nullable(),
|
||||
})
|
||||
|
||||
export const awsIamCreateUserContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/iam/create-user',
|
||||
body: Schema,
|
||||
response: { mode: 'json', schema: CreateUserResponseSchema },
|
||||
})
|
||||
export type AwsIamCreateUserRequest = ContractBodyInput<typeof awsIamCreateUserContract>
|
||||
export type AwsIamCreateUserBody = ContractBody<typeof awsIamCreateUserContract>
|
||||
export type AwsIamCreateUserResponse = ContractJsonResponse<typeof awsIamCreateUserContract>
|
||||
@@ -0,0 +1,33 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const Schema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
accessKeyIdToDelete: z.string().min(1, 'Access key ID to delete is required'),
|
||||
userName: z.string().optional().nullable(),
|
||||
})
|
||||
|
||||
export const awsIamDeleteAccessKeyContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/iam/delete-access-key',
|
||||
body: Schema,
|
||||
response: { mode: 'json', schema: z.object({ message: z.string() }) },
|
||||
})
|
||||
export type AwsIamDeleteAccessKeyRequest = ContractBodyInput<typeof awsIamDeleteAccessKeyContract>
|
||||
export type AwsIamDeleteAccessKeyBody = ContractBody<typeof awsIamDeleteAccessKeyContract>
|
||||
export type AwsIamDeleteAccessKeyResponse = ContractJsonResponse<
|
||||
typeof awsIamDeleteAccessKeyContract
|
||||
>
|
||||
@@ -0,0 +1,30 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const Schema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
roleName: z.string().min(1, 'Role name is required'),
|
||||
})
|
||||
|
||||
export const awsIamDeleteRoleContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/iam/delete-role',
|
||||
body: Schema,
|
||||
response: { mode: 'json', schema: z.object({ message: z.string() }) },
|
||||
})
|
||||
export type AwsIamDeleteRoleRequest = ContractBodyInput<typeof awsIamDeleteRoleContract>
|
||||
export type AwsIamDeleteRoleBody = ContractBody<typeof awsIamDeleteRoleContract>
|
||||
export type AwsIamDeleteRoleResponse = ContractJsonResponse<typeof awsIamDeleteRoleContract>
|
||||
@@ -0,0 +1,30 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const Schema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
userName: z.string().min(1, 'User name is required'),
|
||||
})
|
||||
|
||||
export const awsIamDeleteUserContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/iam/delete-user',
|
||||
body: Schema,
|
||||
response: { mode: 'json', schema: z.object({ message: z.string() }) },
|
||||
})
|
||||
export type AwsIamDeleteUserRequest = ContractBodyInput<typeof awsIamDeleteUserContract>
|
||||
export type AwsIamDeleteUserBody = ContractBody<typeof awsIamDeleteUserContract>
|
||||
export type AwsIamDeleteUserResponse = ContractJsonResponse<typeof awsIamDeleteUserContract>
|
||||
@@ -0,0 +1,33 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const Schema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
roleName: z.string().min(1, 'Role name is required'),
|
||||
policyArn: z.string().min(1, 'Policy ARN is required'),
|
||||
})
|
||||
|
||||
export const awsIamDetachRolePolicyContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/iam/detach-role-policy',
|
||||
body: Schema,
|
||||
response: { mode: 'json', schema: z.object({ message: z.string() }) },
|
||||
})
|
||||
export type AwsIamDetachRolePolicyRequest = ContractBodyInput<typeof awsIamDetachRolePolicyContract>
|
||||
export type AwsIamDetachRolePolicyBody = ContractBody<typeof awsIamDetachRolePolicyContract>
|
||||
export type AwsIamDetachRolePolicyResponse = ContractJsonResponse<
|
||||
typeof awsIamDetachRolePolicyContract
|
||||
>
|
||||
@@ -0,0 +1,33 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const Schema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
userName: z.string().min(1, 'User name is required'),
|
||||
policyArn: z.string().min(1, 'Policy ARN is required'),
|
||||
})
|
||||
|
||||
export const awsIamDetachUserPolicyContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/iam/detach-user-policy',
|
||||
body: Schema,
|
||||
response: { mode: 'json', schema: z.object({ message: z.string() }) },
|
||||
})
|
||||
export type AwsIamDetachUserPolicyRequest = ContractBodyInput<typeof awsIamDetachUserPolicyContract>
|
||||
export type AwsIamDetachUserPolicyBody = ContractBody<typeof awsIamDetachUserPolicyContract>
|
||||
export type AwsIamDetachUserPolicyResponse = ContractJsonResponse<
|
||||
typeof awsIamDetachUserPolicyContract
|
||||
>
|
||||
@@ -0,0 +1,43 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const Schema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
roleName: z.string().min(1, 'Role name is required'),
|
||||
})
|
||||
|
||||
const GetRoleResponseSchema = z.object({
|
||||
roleName: z.string(),
|
||||
roleId: z.string(),
|
||||
arn: z.string(),
|
||||
path: z.string(),
|
||||
createDate: z.string().nullable(),
|
||||
description: z.string().nullable(),
|
||||
maxSessionDuration: z.number().nullable(),
|
||||
assumeRolePolicyDocument: z.string().nullable(),
|
||||
roleLastUsedDate: z.string().nullable(),
|
||||
roleLastUsedRegion: z.string().nullable(),
|
||||
})
|
||||
|
||||
export const awsIamGetRoleContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/iam/get-role',
|
||||
body: Schema,
|
||||
response: { mode: 'json', schema: GetRoleResponseSchema },
|
||||
})
|
||||
export type AwsIamGetRoleRequest = ContractBodyInput<typeof awsIamGetRoleContract>
|
||||
export type AwsIamGetRoleBody = ContractBody<typeof awsIamGetRoleContract>
|
||||
export type AwsIamGetRoleResponse = ContractJsonResponse<typeof awsIamGetRoleContract>
|
||||
@@ -0,0 +1,46 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const Schema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
userName: z.string().min(1).optional().nullable(),
|
||||
})
|
||||
|
||||
const GetUserResponseSchema = z.object({
|
||||
userName: z.string(),
|
||||
userId: z.string(),
|
||||
arn: z.string(),
|
||||
path: z.string(),
|
||||
createDate: z.string().nullable(),
|
||||
passwordLastUsed: z.string().nullable(),
|
||||
permissionsBoundaryArn: z.string().nullable(),
|
||||
tags: z.array(
|
||||
z.object({
|
||||
key: z.string(),
|
||||
value: z.string(),
|
||||
})
|
||||
),
|
||||
})
|
||||
|
||||
export const awsIamGetUserContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/iam/get-user',
|
||||
body: Schema,
|
||||
response: { mode: 'json', schema: GetUserResponseSchema },
|
||||
})
|
||||
export type AwsIamGetUserRequest = ContractBodyInput<typeof awsIamGetUserContract>
|
||||
export type AwsIamGetUserBody = ContractBody<typeof awsIamGetUserContract>
|
||||
export type AwsIamGetUserResponse = ContractJsonResponse<typeof awsIamGetUserContract>
|
||||
@@ -0,0 +1,51 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const Schema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
roleName: z.string().min(1, 'Role name is required'),
|
||||
pathPrefix: z.string().optional().nullable(),
|
||||
maxItems: z.number().int().min(1).max(1000).optional().nullable(),
|
||||
marker: z.string().optional().nullable(),
|
||||
})
|
||||
|
||||
const ListAttachedRolePoliciesResponseSchema = z.object({
|
||||
attachedPolicies: z.array(
|
||||
z.object({
|
||||
policyName: z.string(),
|
||||
policyArn: z.string(),
|
||||
})
|
||||
),
|
||||
isTruncated: z.boolean(),
|
||||
marker: z.string().nullable(),
|
||||
count: z.number(),
|
||||
})
|
||||
|
||||
export const awsIamListAttachedRolePoliciesContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/iam/list-attached-role-policies',
|
||||
body: Schema,
|
||||
response: { mode: 'json', schema: ListAttachedRolePoliciesResponseSchema },
|
||||
})
|
||||
export type AwsIamListAttachedRolePoliciesRequest = ContractBodyInput<
|
||||
typeof awsIamListAttachedRolePoliciesContract
|
||||
>
|
||||
export type AwsIamListAttachedRolePoliciesBody = ContractBody<
|
||||
typeof awsIamListAttachedRolePoliciesContract
|
||||
>
|
||||
export type AwsIamListAttachedRolePoliciesResponse = ContractJsonResponse<
|
||||
typeof awsIamListAttachedRolePoliciesContract
|
||||
>
|
||||
@@ -0,0 +1,51 @@
|
||||
import { z } from 'zod'
|
||||
import type {
|
||||
ContractBody,
|
||||
ContractBodyInput,
|
||||
ContractJsonResponse,
|
||||
} from '@/lib/api/contracts/types'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
import { validateAwsRegion } from '@/lib/core/security/input-validation'
|
||||
|
||||
const Schema = z.object({
|
||||
region: z
|
||||
.string()
|
||||
.min(1, 'AWS region is required')
|
||||
.refine((v) => validateAwsRegion(v).isValid, {
|
||||
message: 'Invalid AWS region format (e.g., us-east-1, eu-west-2)',
|
||||
}),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
userName: z.string().min(1, 'User name is required'),
|
||||
pathPrefix: z.string().optional().nullable(),
|
||||
maxItems: z.number().int().min(1).max(1000).optional().nullable(),
|
||||
marker: z.string().optional().nullable(),
|
||||
})
|
||||
|
||||
const ListAttachedUserPoliciesResponseSchema = z.object({
|
||||
attachedPolicies: z.array(
|
||||
z.object({
|
||||
policyName: z.string(),
|
||||
policyArn: z.string(),
|
||||
})
|
||||
),
|
||||
isTruncated: z.boolean(),
|
||||
marker: z.string().nullable(),
|
||||
count: z.number(),
|
||||
})
|
||||
|
||||
export const awsIamListAttachedUserPoliciesContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/tools/iam/list-attached-user-policies',
|
||||
body: Schema,
|
||||
response: { mode: 'json', schema: ListAttachedUserPoliciesResponseSchema },
|
||||
})
|
||||
export type AwsIamListAttachedUserPoliciesRequest = ContractBodyInput<
|
||||
typeof awsIamListAttachedUserPoliciesContract
|
||||
>
|
||||
export type AwsIamListAttachedUserPoliciesBody = ContractBody<
|
||||
typeof awsIamListAttachedUserPoliciesContract
|
||||
>
|
||||
export type AwsIamListAttachedUserPoliciesResponse = ContractJsonResponse<
|
||||
typeof awsIamListAttachedUserPoliciesContract
|
||||
>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user