File
Blob: src/worker/presentation/serializers.ts
| 1 | import { |
| 2 | BranchName, |
| 3 | CommitSha, |
| 4 | type LogEvent, |
| 5 | OwnerSlug, |
| 6 | type PendingRunSummary, |
| 7 | type ProjectConfigSummary, |
| 8 | ProjectId, |
| 9 | type ProjectDetail, |
| 10 | ProjectSlug, |
| 11 | type ProjectSummary, |
| 12 | type RunDetail, |
| 13 | type RunExecutionState, |
| 14 | RunId, |
| 15 | RunStatus, |
| 16 | type RunStep, |
| 17 | type RunSummary, |
| 18 | TriggerType, |
| 19 | type UserSummary, |
| 20 | UserId, |
| 21 | type WebhookRecentDelivery, |
| 22 | type WebhookSummary, |
| 23 | WebhookDeliveryOutcome, |
| 24 | WebhookEventKind, |
| 25 | WebhookId, |
| 26 | WebhookProvider, |
| 27 | } from "@/contracts"; |
| 28 | import { |
| 29 | expectTrusted, |
| 30 | isoDateTimeFromTimestamp, |
| 31 | nullableIsoDateTimeFromTimestamp, |
| 32 | nullableTrusted, |
| 33 | type PendingRunState, |
| 34 | type RunLogRecord, |
| 35 | type RunMetaState, |
| 36 | type RunStepState, |
| 37 | } from "@/worker/contracts"; |
| 38 | import type { RunIndexRow, UserRow } from "@/worker/db/d1/repositories"; |
| 39 | import type { ParsedWebhookDeliveryRow, StoredProjectWebhook } from "@/worker/durable/project-do/webhooks/types"; |
| 40 | |
| 41 | interface ProjectSummarySource { |
| 42 | id: string; |
| 43 | ownerUserId: string; |
| 44 | ownerSlug: string; |
| 45 | projectSlug: string; |
| 46 | name: string; |
| 47 | repoUrl: string; |
| 48 | defaultBranch: string; |
| 49 | configPath: string; |
| 50 | createdAt: number; |
| 51 | updatedAt: number; |
| 52 | } |
| 53 | |
| 54 | interface ProjectConfigSummarySource extends ProjectSummarySource { |
| 55 | dispatchMode: "queue" | "workflows"; |
| 56 | } |
| 57 | |
| 58 | const toIso = (value: number | null) => nullableIsoDateTimeFromTimestamp(value); |
| 59 | |
| 60 | export const serializeUserSummary = (user: UserRow): UserSummary => ({ |
| 61 | id: expectTrusted(UserId, user.id, "UserId"), |
| 62 | slug: expectTrusted(OwnerSlug, user.slug, "OwnerSlug"), |
| 63 | email: user.email, |
| 64 | displayName: user.displayName, |
| 65 | createdAt: isoDateTimeFromTimestamp(user.createdAt), |
| 66 | disabledAt: toIso(user.disabledAt), |
| 67 | }); |
| 68 | |
| 69 | export const serializeProjectSummary = ( |
| 70 | project: ProjectSummarySource, |
| 71 | lastRunStatus: RunStatus | null, |
| 72 | ): ProjectSummary => ({ |
| 73 | id: expectTrusted(ProjectId, project.id, "ProjectId"), |
| 74 | ownerUserId: expectTrusted(UserId, project.ownerUserId, "UserId"), |
| 75 | ownerSlug: expectTrusted(OwnerSlug, project.ownerSlug, "OwnerSlug"), |
| 76 | projectSlug: expectTrusted(ProjectSlug, project.projectSlug, "ProjectSlug"), |
| 77 | name: project.name, |
| 78 | repoUrl: project.repoUrl, |
| 79 | defaultBranch: expectTrusted(BranchName, project.defaultBranch, "BranchName"), |
| 80 | configPath: project.configPath, |
| 81 | createdAt: isoDateTimeFromTimestamp(project.createdAt), |
| 82 | updatedAt: isoDateTimeFromTimestamp(project.updatedAt), |
| 83 | lastRunStatus, |
| 84 | }); |
| 85 | |
| 86 | export const serializeProjectConfigSummary = ( |
| 87 | project: ProjectConfigSummarySource, |
| 88 | lastRunStatus: RunStatus | null, |
| 89 | ): ProjectConfigSummary => ({ |
| 90 | ...serializeProjectSummary(project, lastRunStatus), |
| 91 | dispatchMode: project.dispatchMode, |
| 92 | }); |
| 93 | |
| 94 | export const serializePendingRunSummary = (pendingRun: PendingRunState): PendingRunSummary => ({ |
| 95 | runId: pendingRun.runId, |
| 96 | branch: pendingRun.branch, |
| 97 | queuedAt: isoDateTimeFromTimestamp(pendingRun.queuedAt), |
| 98 | }); |
| 99 | |
| 100 | export const serializeRunSummary = ( |
| 101 | run: Pick< |
| 102 | RunIndexRow, |
| 103 | | "id" |
| 104 | | "projectId" |
| 105 | | "triggeredByUserId" |
| 106 | | "triggerType" |
| 107 | | "branch" |
| 108 | | "commitSha" |
| 109 | | "status" |
| 110 | | "queuedAt" |
| 111 | | "startedAt" |
| 112 | | "finishedAt" |
| 113 | | "exitCode" |
| 114 | >, |
| 115 | ): RunSummary => ({ |
| 116 | id: expectTrusted(RunId, run.id, "RunId"), |
| 117 | projectId: expectTrusted(ProjectId, run.projectId, "ProjectId"), |
| 118 | triggeredByUserId: nullableTrusted(UserId, run.triggeredByUserId, "UserId"), |
| 119 | triggerType: expectTrusted(TriggerType, run.triggerType, "TriggerType"), |
| 120 | branch: expectTrusted(BranchName, run.branch, "BranchName"), |
| 121 | commitSha: nullableTrusted(CommitSha, run.commitSha, "CommitSha"), |
| 122 | status: expectTrusted(RunStatus, run.status, "RunStatus"), |
| 123 | queuedAt: isoDateTimeFromTimestamp(run.queuedAt), |
| 124 | startedAt: toIso(run.startedAt), |
| 125 | finishedAt: toIso(run.finishedAt), |
| 126 | exitCode: run.exitCode, |
| 127 | }); |
| 128 | |
| 129 | export const serializeRunStep = (step: RunStepState): RunStep => ({ |
| 130 | id: step.id, |
| 131 | runId: step.runId, |
| 132 | position: step.position, |
| 133 | name: step.name, |
| 134 | command: step.command, |
| 135 | status: step.status, |
| 136 | startedAt: toIso(step.startedAt), |
| 137 | finishedAt: toIso(step.finishedAt), |
| 138 | exitCode: step.exitCode, |
| 139 | }); |
| 140 | |
| 141 | export const serializeRunExecutionState = (meta: RunMetaState): RunExecutionState => ({ |
| 142 | status: meta.status, |
| 143 | currentStep: meta.currentStep, |
| 144 | startedAt: toIso(meta.startedAt), |
| 145 | finishedAt: toIso(meta.finishedAt), |
| 146 | exitCode: meta.exitCode, |
| 147 | errorMessage: meta.errorMessage, |
| 148 | }); |
| 149 | |
| 150 | export const serializeLogEvent = (event: RunLogRecord): LogEvent => ({ |
| 151 | id: event.id, |
| 152 | runId: event.runId, |
| 153 | seq: event.seq, |
| 154 | stream: event.stream, |
| 155 | chunk: event.chunk, |
| 156 | createdAt: isoDateTimeFromTimestamp(event.createdAt), |
| 157 | }); |
| 158 | |
| 159 | export const serializeProjectDetail = (detail: { |
| 160 | project: ProjectConfigSummarySource; |
| 161 | lastRunStatus: RunStatus | null; |
| 162 | activeRun: RunSummary | null; |
| 163 | pendingRuns: PendingRunSummary[]; |
| 164 | }): ProjectDetail => ({ |
| 165 | project: serializeProjectConfigSummary(detail.project, detail.lastRunStatus), |
| 166 | activeRun: detail.activeRun, |
| 167 | pendingRuns: detail.pendingRuns, |
| 168 | }); |
| 169 | |
| 170 | export const serializeRunDetail = (detail: { |
| 171 | run: RunSummary; |
| 172 | currentStep: number | null; |
| 173 | errorMessage: string | null; |
| 174 | steps: RunStep[]; |
| 175 | recentLogs: LogEvent[]; |
| 176 | detailAvailable: boolean; |
| 177 | }): RunDetail => ({ |
| 178 | run: detail.run, |
| 179 | currentStep: detail.currentStep, |
| 180 | errorMessage: detail.errorMessage, |
| 181 | steps: detail.steps, |
| 182 | recentLogs: detail.recentLogs, |
| 183 | detailAvailable: detail.detailAvailable, |
| 184 | }); |
| 185 | |
| 186 | export const serializeWebhookRecentDelivery = ( |
| 187 | delivery: Pick< |
| 188 | ParsedWebhookDeliveryRow, |
| 189 | | "provider" |
| 190 | | "deliveryId" |
| 191 | | "eventKind" |
| 192 | | "eventName" |
| 193 | | "outcome" |
| 194 | | "repoUrl" |
| 195 | | "ref" |
| 196 | | "branch" |
| 197 | | "commitSha" |
| 198 | | "beforeSha" |
| 199 | | "runId" |
| 200 | | "receivedAt" |
| 201 | >, |
| 202 | ): WebhookRecentDelivery => ({ |
| 203 | provider: expectTrusted(WebhookProvider, delivery.provider, "WebhookProvider"), |
| 204 | deliveryId: delivery.deliveryId, |
| 205 | eventKind: expectTrusted(WebhookEventKind, delivery.eventKind, "WebhookEventKind"), |
| 206 | eventName: delivery.eventName, |
| 207 | outcome: expectTrusted(WebhookDeliveryOutcome, delivery.outcome, "WebhookDeliveryOutcome"), |
| 208 | repoUrl: delivery.repoUrl, |
| 209 | ref: delivery.ref, |
| 210 | branch: nullableTrusted(BranchName, delivery.branch, "BranchName"), |
| 211 | commitSha: nullableTrusted(CommitSha, delivery.commitSha, "CommitSha"), |
| 212 | beforeSha: nullableTrusted(CommitSha, delivery.beforeSha, "CommitSha"), |
| 213 | runId: nullableTrusted(RunId, delivery.runId, "RunId"), |
| 214 | receivedAt: isoDateTimeFromTimestamp(delivery.receivedAt), |
| 215 | }); |
| 216 | |
| 217 | export const serializeWebhookSummary = (webhook: StoredProjectWebhook): WebhookSummary => ({ |
| 218 | id: expectTrusted(WebhookId, webhook.id, "WebhookId"), |
| 219 | projectId: expectTrusted(ProjectId, webhook.projectId, "ProjectId"), |
| 220 | provider: expectTrusted(WebhookProvider, webhook.provider, "WebhookProvider"), |
| 221 | enabled: webhook.enabled, |
| 222 | config: webhook.config, |
| 223 | createdAt: isoDateTimeFromTimestamp(webhook.createdAt), |
| 224 | updatedAt: isoDateTimeFromTimestamp(webhook.updatedAt), |
| 225 | recentDeliveries: webhook.recentDeliveries.map(serializeWebhookRecentDelivery), |
| 226 | }); |