(ctx context.Context, in *ListDeliveriesInput)
| 329 | } |
| 330 | |
| 331 | func (s *Server) handleListWebhookDeliveries(ctx context.Context, in *ListDeliveriesInput) (*listDeliveriesOutput, error) { |
| 332 | user, err := s.requireAccountUser(ctx) |
| 333 | if err != nil { |
| 334 | return nil, err |
| 335 | } |
| 336 | if s.deps.ListDeliveries == nil { |
| 337 | return nil, NewError(http.StatusNotFound, "not_found", "deliveries endpoint not configured") |
| 338 | } |
| 339 | // Ownership: deliveries are scoped to a webhook the caller owns. |
| 340 | if wh, err := s.deps.GetWebhook(ctx, in.ID, user.ID); err != nil || wh == nil { |
| 341 | return nil, NewError(http.StatusNotFound, "not_found", "webhook not found") |
| 342 | } |
| 343 | limit := in.Limit |
| 344 | if limit <= 0 { |
| 345 | limit = 50 |
| 346 | } |
| 347 | rows, err := s.deps.ListDeliveries(ctx, in.ID, in.Status, limit) |
| 348 | if err != nil { |
| 349 | return nil, NewError(http.StatusInternalServerError, "internal_error", "failed to list deliveries") |
| 350 | } |
| 351 | items := make([]WebhookDeliveryView, 0, len(rows)) |
| 352 | for _, d := range rows { |
| 353 | v := WebhookDeliveryView{ |
| 354 | ID: d.ID, EventType: d.EventType, Status: d.Status, Attempts: d.Attempts, |
| 355 | LastError: d.LastError, LastStatusCode: d.LastStatusCode, |
| 356 | NextRetryAt: d.NextRetryAt.UTC().Format(time.RFC3339), |
| 357 | CreatedAt: d.CreatedAt.UTC().Format(time.RFC3339), |
| 358 | } |
| 359 | if d.LastAttemptAt != nil { |
| 360 | v.LastAttemptAt = d.LastAttemptAt.UTC().Format(time.RFC3339) |
| 361 | } |
| 362 | items = append(items, v) |
| 363 | } |
| 364 | // No cursor continuation in the store (limit only) — next_cursor null. |
| 365 | return &listDeliveriesOutput{Body: NewPage(items, "")}, nil |
| 366 | } |
| 367 | |
| 368 | // UpdateWebhookRequest mirrors the legacy PATCH body — pointer fields so |
| 369 | // absent != zero; url/events/filters are full-replace when present. |
nothing calls this directly
no test coverage detected