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,295 @@
|
||||
import { z } from 'zod'
|
||||
import { defineRouteContract } from '@/lib/api/contracts/types'
|
||||
|
||||
export const webhooksRouteQuerySchema = z.object({
|
||||
workflowId: z.string().optional(),
|
||||
blockId: z.string().optional(),
|
||||
})
|
||||
|
||||
export const webhooksByBlockQuerySchema = z.object({
|
||||
workflowId: z.string().min(1),
|
||||
blockId: z.string().min(1),
|
||||
})
|
||||
|
||||
export const webhookProviderConfigSchema = z.record(z.string(), z.unknown())
|
||||
|
||||
export const webhookDataSchema = z
|
||||
.object({
|
||||
id: z.string(),
|
||||
path: z.string().optional(),
|
||||
providerConfig: webhookProviderConfigSchema.optional(),
|
||||
isActive: z.boolean().optional(),
|
||||
})
|
||||
.passthrough()
|
||||
|
||||
export type WebhookData = z.output<typeof webhookDataSchema>
|
||||
|
||||
export const webhookListItemSchema = z.object({
|
||||
webhook: webhookDataSchema,
|
||||
workflow: z
|
||||
.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
})
|
||||
.optional(),
|
||||
})
|
||||
|
||||
export type WebhookListItem = z.output<typeof webhookListItemSchema>
|
||||
|
||||
export const webhookUpsertBodySchema = z
|
||||
.object({
|
||||
workflowId: z.string().optional(),
|
||||
path: z.string().optional(),
|
||||
provider: z.string().optional(),
|
||||
providerConfig: webhookProviderConfigSchema.optional(),
|
||||
blockId: z.string().optional(),
|
||||
})
|
||||
.strict()
|
||||
|
||||
export type WebhookUpsertBody = z.input<typeof webhookUpsertBodySchema>
|
||||
|
||||
export const webhookIdParamsSchema = z.object({
|
||||
id: z.string().min(1),
|
||||
})
|
||||
|
||||
export const webhookPatchBodySchema = z
|
||||
.object({
|
||||
isActive: z.boolean().optional(),
|
||||
failedCount: z
|
||||
.number({ error: 'failedCount must be a number' })
|
||||
.finite('failedCount must be a valid number')
|
||||
.int('failedCount must be an integer')
|
||||
.min(0, 'failedCount must be at least 0')
|
||||
.optional(),
|
||||
})
|
||||
.strict()
|
||||
export type WebhookPatchBody = z.input<typeof webhookPatchBodySchema>
|
||||
|
||||
export const webhookPollingParamsSchema = z.object({
|
||||
provider: z.string().min(1),
|
||||
})
|
||||
|
||||
export const webhookTriggerParamsSchema = z.object({
|
||||
path: z.string().min(1),
|
||||
})
|
||||
|
||||
export const webhookSvixHeadersSchema = z.object({
|
||||
'svix-id': z.string().min(1),
|
||||
'svix-timestamp': z.string().min(1),
|
||||
'svix-signature': z.string().min(1),
|
||||
})
|
||||
|
||||
export const agentMailEnvelopeSchema = z
|
||||
.object({
|
||||
event_type: z.string(),
|
||||
message: z.unknown().optional(),
|
||||
})
|
||||
.passthrough()
|
||||
|
||||
const agentMailAttachmentSchema = z
|
||||
.object({
|
||||
attachment_id: z.string(),
|
||||
filename: z.string(),
|
||||
content_type: z.string(),
|
||||
size: z.number(),
|
||||
inline: z.boolean().optional(),
|
||||
})
|
||||
.passthrough()
|
||||
|
||||
export const agentMailMessageSchema = z
|
||||
.object({
|
||||
message_id: z.string(),
|
||||
thread_id: z.string(),
|
||||
inbox_id: z.string(),
|
||||
organization_id: z.string().optional(),
|
||||
from: z.string(),
|
||||
to: z.array(z.string()),
|
||||
cc: z.array(z.string()).optional(),
|
||||
bcc: z.array(z.string()).optional(),
|
||||
reply_to: z.array(z.string()).optional(),
|
||||
subject: z.string().optional(),
|
||||
preview: z.string().optional(),
|
||||
text: z.string().nullable().optional(),
|
||||
html: z.string().nullable().optional(),
|
||||
attachments: z.array(agentMailAttachmentSchema).optional(),
|
||||
in_reply_to: z.string().optional(),
|
||||
references: z.array(z.string()).optional(),
|
||||
labels: z.array(z.string()).optional(),
|
||||
sort_key: z.string().optional(),
|
||||
updated_at: z.string().optional(),
|
||||
created_at: z.string(),
|
||||
})
|
||||
.passthrough()
|
||||
|
||||
export const listWebhooksByBlockResponseSchema = z.object({
|
||||
webhooks: z.array(webhookListItemSchema),
|
||||
})
|
||||
|
||||
export type ListWebhooksByBlockResponse = z.output<typeof listWebhooksByBlockResponseSchema>
|
||||
|
||||
const listWebhooksResponseSchema = z.object({
|
||||
webhooks: z.array(webhookListItemSchema),
|
||||
})
|
||||
|
||||
const upsertWebhookResponseSchema = z.object({
|
||||
webhook: webhookDataSchema,
|
||||
})
|
||||
|
||||
const getWebhookResponseSchema = z.object({
|
||||
webhook: webhookListItemSchema,
|
||||
})
|
||||
|
||||
const updateWebhookResponseSchema = z.object({
|
||||
webhook: webhookDataSchema,
|
||||
})
|
||||
|
||||
const deleteWebhookResponseSchema = z.object({
|
||||
success: z.literal(true),
|
||||
})
|
||||
|
||||
const webhookPollingResponseSchema = z
|
||||
.object({
|
||||
success: z.boolean(),
|
||||
message: z.string(),
|
||||
requestId: z.string(),
|
||||
status: z.enum(['skip', 'completed']).optional(),
|
||||
total: z.number().optional(),
|
||||
successful: z.number().optional(),
|
||||
failed: z.number().optional(),
|
||||
error: z.string().optional(),
|
||||
})
|
||||
.passthrough()
|
||||
|
||||
export const listWebhooksByBlockContract = defineRouteContract({
|
||||
method: 'GET',
|
||||
path: '/api/webhooks',
|
||||
query: webhooksByBlockQuerySchema,
|
||||
response: {
|
||||
mode: 'json',
|
||||
schema: listWebhooksByBlockResponseSchema,
|
||||
},
|
||||
})
|
||||
|
||||
export const listWebhooksContract = defineRouteContract({
|
||||
method: 'GET',
|
||||
path: '/api/webhooks',
|
||||
query: webhooksRouteQuerySchema,
|
||||
response: {
|
||||
mode: 'json',
|
||||
schema: listWebhooksResponseSchema,
|
||||
},
|
||||
})
|
||||
|
||||
export const upsertWebhookContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/webhooks',
|
||||
body: webhookUpsertBodySchema,
|
||||
response: {
|
||||
mode: 'json',
|
||||
schema: upsertWebhookResponseSchema,
|
||||
},
|
||||
})
|
||||
|
||||
export const getWebhookContract = defineRouteContract({
|
||||
method: 'GET',
|
||||
path: '/api/webhooks/[id]',
|
||||
params: webhookIdParamsSchema,
|
||||
response: {
|
||||
mode: 'json',
|
||||
schema: getWebhookResponseSchema,
|
||||
},
|
||||
})
|
||||
|
||||
export const updateWebhookContract = defineRouteContract({
|
||||
method: 'PATCH',
|
||||
path: '/api/webhooks/[id]',
|
||||
params: webhookIdParamsSchema,
|
||||
body: webhookPatchBodySchema,
|
||||
response: {
|
||||
mode: 'json',
|
||||
schema: updateWebhookResponseSchema,
|
||||
},
|
||||
})
|
||||
|
||||
export const deleteWebhookContract = defineRouteContract({
|
||||
method: 'DELETE',
|
||||
path: '/api/webhooks/[id]',
|
||||
params: webhookIdParamsSchema,
|
||||
response: {
|
||||
mode: 'json',
|
||||
schema: deleteWebhookResponseSchema,
|
||||
},
|
||||
})
|
||||
|
||||
export const webhookPollingContract = defineRouteContract({
|
||||
method: 'GET',
|
||||
path: '/api/webhooks/poll/[provider]',
|
||||
params: webhookPollingParamsSchema,
|
||||
response: {
|
||||
mode: 'json',
|
||||
schema: webhookPollingResponseSchema,
|
||||
},
|
||||
})
|
||||
|
||||
/**
|
||||
* Webhook trigger endpoints proxy provider responses back to the caller. The
|
||||
* payload shape varies per provider (challenge text, queued execution result,
|
||||
* pre-deployment verification, etc.) so the response is genuinely unbounded
|
||||
* and stays as `z.unknown()`.
|
||||
*/
|
||||
export const webhookTriggerGetContract = defineRouteContract({
|
||||
method: 'GET',
|
||||
path: '/api/webhooks/trigger/[path]',
|
||||
params: webhookTriggerParamsSchema,
|
||||
response: {
|
||||
mode: 'json',
|
||||
// untyped-response: webhook trigger forwards arbitrary provider verification or workflow execution payloads
|
||||
schema: z.unknown(),
|
||||
},
|
||||
})
|
||||
|
||||
export const webhookTriggerPostContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/webhooks/trigger/[path]',
|
||||
params: webhookTriggerParamsSchema,
|
||||
response: {
|
||||
mode: 'json',
|
||||
// untyped-response: webhook trigger forwards arbitrary provider challenge or workflow execution payloads
|
||||
schema: z.unknown(),
|
||||
},
|
||||
})
|
||||
|
||||
/**
|
||||
* TikTok app-level webhook ingress. Signature is verified from the raw body
|
||||
* before this schema runs; `content` remains a JSON string per TikTok docs.
|
||||
*/
|
||||
export const tiktokWebhookEnvelopeSchema = z.object({
|
||||
client_key: z.string().min(1).max(255),
|
||||
event: z.string().min(1).max(255),
|
||||
create_time: z.number().int().nonnegative(),
|
||||
user_openid: z.string().min(1).max(255),
|
||||
content: z.string().max(1_000_000),
|
||||
})
|
||||
|
||||
export type TikTokWebhookEnvelope = z.input<typeof tiktokWebhookEnvelopeSchema>
|
||||
|
||||
export const tiktokWebhookHeadersSchema = z.object({
|
||||
'tiktok-signature': z.string().min(1),
|
||||
})
|
||||
|
||||
export const tiktokWebhookResponseSchema = z.union([
|
||||
z.object({ ok: z.literal(true) }),
|
||||
z.object({ error: z.string().min(1) }),
|
||||
])
|
||||
|
||||
export const tiktokWebhookContract = defineRouteContract({
|
||||
method: 'POST',
|
||||
path: '/api/webhooks/tiktok',
|
||||
headers: tiktokWebhookHeadersSchema,
|
||||
// Body is validated after HMAC verification against the raw payload.
|
||||
body: tiktokWebhookEnvelopeSchema,
|
||||
response: {
|
||||
mode: 'json',
|
||||
schema: tiktokWebhookResponseSchema,
|
||||
},
|
||||
})
|
||||
Reference in New Issue
Block a user