Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughIntroduces a complete webhook testing feature: a new POST endpoint that sends test webhook messages via Svix with delivery verification and retry logic, dashboard UI components for creating and testing endpoints with status feedback, and Admin interface methods to trigger test webhooks across multiple packages. Changes
Sequence DiagramsequenceDiagram
participant User as User
participant Dashboard as Dashboard UI
participant AdminAPI as Admin App
participant Backend as Backend Route
participant Svix as Svix Service
User->>Dashboard: Click "Test" on endpoint
activate Dashboard
Dashboard->>Dashboard: Open TestEndpointDialog
Dashboard->>AdminAPI: sendTestWebhook(endpointId)
deactivate Dashboard
activate AdminAPI
AdminAPI->>Backend: POST /send-test-webhook {endpoint_id}
deactivate AdminAPI
activate Backend
Backend->>Svix: Get endpoint
Backend->>Svix: Create test message
Note over Backend: Retry up to 3x
Backend->>Svix: List message attempts
Backend->>Svix: Verify successful delivery
Backend-->>AdminAPI: { success: true }
deactivate Backend
activate AdminAPI
AdminAPI-->>Dashboard: Result.ok()
deactivate AdminAPI
activate Dashboard
Dashboard->>Dashboard: Show success status
Dashboard->>User: Display test result & payload
deactivate Dashboard
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes The changes span multiple layers with varied complexity: async retry logic in the backend route with Svix integration, UI state management with form validation and dialog coordination, and interface consistency across three packages. While individual interface additions are simple, the orchestration across components and error handling patterns require careful review. Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Review by RecurseML
🔍 Review performed on b677e3f..c9bc00c
✨ No bugs found, your code is sparkling clean
✅ Files analyzed, no issues (5)
• apps/backend/src/app/api/latest/internal/send-test-webhook/route.tsx
• apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/webhooks/page-client.tsx
• packages/stack-shared/src/interface/admin-interface.ts
• packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts
• packages/template/src/lib/stack-app/apps/interfaces/admin-app.ts
There was a problem hiding this comment.
Greptile Overview
Summary
Adds webhook testing functionality that allows users to send test events to webhook endpoints and verify delivery through the dashboard.
Key Changes
- Backend: New
/internal/send-test-webhookAPI endpoint that sends astack.testevent to a specified endpoint and verifies delivery usingResult.retrypattern - Frontend: Enhanced webhook management UI with test dialogs, success/error states, and post-creation test flow
- Type-safe integration: Added
sendTestWebhookmethod across interface, implementation, and type definition layers
Implementation Details
- Uses SmartRouteHandler for the API endpoint (follows custom instruction ab376f82-1d3d-4684-a503-9fb6824b49c2)
- Retries webhook delivery check up to 3 times to allow for async processing
- Comprehensive error handling with user-friendly error messages
- Dialog-based UI with payload preview and status feedback
Confidence Score: 4/5
- This PR is safe to merge with minor style improvements recommended
- Well-structured implementation following established patterns. One minor style issue: form submission should use
runAsynchronouslyWithAlertper custom instructions. No logical errors or security concerns found. - page-client.tsx:117 should use
runAsynchronouslyWithAlertfor consistency with project conventions
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| apps/backend/src/app/api/latest/internal/send-test-webhook/route.tsx | 4/5 | New API endpoint for testing webhook delivery, uses SmartRouteHandler and Result.retry pattern correctly |
| apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/webhooks/page-client.tsx | 3/5 | Adds test webhook UI with dialogs and forms; async handler doesn't use runAsynchronouslyWithAlert |
Sequence Diagram
sequenceDiagram
participant User as User (Dashboard)
participant UI as Webhooks Page
participant AdminApp as StackAdminApp
participant API as Backend API
participant Svix as Svix Service
participant Endpoint as Webhook Endpoint
User->>UI: Click "Test" on endpoint
UI->>UI: Open TestEndpointDialog
User->>UI: Click "Send test event"
UI->>AdminApp: sendTestWebhook({endpointId})
AdminApp->>API: POST /internal/send-test-webhook
API->>Svix: getOrCreate(application)
API->>Svix: endpoint.get(endpointId)
alt Endpoint not found
Svix-->>API: Error
API-->>UI: {success: false, error_message}
UI->>UI: Show error alert
else Endpoint found
API->>Svix: message.create(stack.test event)
alt Message creation fails
Svix-->>API: Error
API->>API: captureError()
API-->>UI: {success: false, error_message}
UI->>UI: Show error alert
else Message created
API->>API: Result.retry(check attempts, 3 times)
loop Retry up to 3 times
API->>Svix: messageAttempt.listByMsg(messageId)
Svix-->>API: Attempt list
API->>API: Check if endpoint has successful attempt
end
alt Successful delivery
API-->>UI: {success: true}
UI->>UI: Show success alert
else No successful delivery
API-->>UI: {success: false, error_message}
UI->>UI: Show error alert
end
end
end
5 files reviewed, 1 comment
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/webhooks/page-client.tsx
Show resolved
Hide resolved
Documentation Changes Required1. docs/templates/concepts/webhooks.mdx
Example addition: ### Testing webhooks locally
In addition to third-party services like Svix Playground and Webhook.site, you can now use the built-in `sendTestWebhook` method to test your webhooks locally. This method is available in the StackAdminApp interface and allows you to send a test webhook to a specified endpoint.
Here's an example of how to use the `sendTestWebhook` method:
```typescript
const result = await stackAdminApp.sendTestWebhook({
endpointId: 'your-endpoint-id'
});
if (result.ok) {
console.log('Test webhook sent successfully');
} else {
console.error('Error sending test webhook:', result.error.errorMessage);
}This new feature provides a convenient way to test your webhook endpoints directly from your application. |
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/webhooks/page-client.tsx
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/webhooks/page-client.tsx (1)
196-205: Fix copy: “Delete domain” → “Delete endpoint”Dialog title mismatches the action (endpoints, not domains).
- title="Delete domain" + title="Delete endpoint"
🧹 Nitpick comments (4)
apps/backend/src/app/api/latest/internal/send-test-webhook/route.tsx (3)
78-87: Add small backoff and consider a few more retries to avoid false negativesImmediate polling can race delivery; add a short delay between retries and consider 5 attempts.
Apply for example:
- const attemptResult = await Result.retry(async () => { - const attempts = await svix.messageAttempt.listByMsg( - projectId, - messageResult.data.id, - { status: MessageStatus.Success } - ); - const success = attempts.data.some(a => a.endpointId === body.endpoint_id); - return success ? Result.ok(undefined) : Result.error("No successful attempt found"); - }, 3); + const attemptResult = await Result.retry(async () => { + // brief backoff to give delivery a chance to complete + await new Promise(r => setTimeout(r, 600)); + const attempts = await svix.messageAttempt.listByMsg( + projectId, + messageResult.data.id, + { status: MessageStatus.Success } + ); + const success = attempts.data.some(a => a.endpointId === body.endpoint_id); + return success ? Result.ok(undefined) : Result.error("No successful attempt found"); + }, 5);
48-60: Optional: ensure thestack.testevent type exists before sendingSending usually works without pre-creating, but creating once improves catalog visibility and filters in the portal.
const messageResult = await Result.fromPromise(svix.message.create( projectId, { eventType: "stack.test", payload: { type: "stack.test", data: { message: "Stack webhook test event triggered from the Stack dashboard.", endpointUrl: endpoint.url, }, }, }, )); + // Optionally ensure the event type exists for catalog/filters (no-op if it already exists) + // Ignore conflicts/duplicates. + // await svix.eventType.create({ name: "stack.test", description: "Stack dashboard test event" }).catch(() => {});Reference: Svix docs recommend adding event types ahead of time and show
eventType.createusage. (docs.svix.com)
78-85: Optimize attempt listing by filtering server-sideThe Svix SDK v1.76+ supports passing both
statusandendpointIdtomessageAttempt.listByMsg. Update to filter attempts server-side instead of scanning all results:const attempts = await svix.messageAttempt.listByMsg( projectId, messageResult.data.id, - { status: MessageStatus.Success } + { status: MessageStatus.Success, endpointId: body.endpoint_id } ); - const success = attempts.data.some(a => a.endpointId === body.endpoint_id); + const success = attempts.data.length > 0;apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/webhooks/page-client.tsx (1)
255-263: Disable “Send test event” while sending to avoid double-submitsPrevents duplicate requests if the user clicks multiple times.
- okButton={{ - label: 'Send test event', - onClick: async () => { + okButton={{ + label: 'Send test event', + props: { disabled: status === 'sending' }, + onClick: async () => { await sendTestEvent(); return 'prevent-close'; }, }}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
apps/backend/src/app/api/latest/internal/send-test-webhook/route.tsx(1 hunks)apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/webhooks/page-client.tsx(7 hunks)packages/stack-shared/src/interface/admin-interface.ts(1 hunks)packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts(1 hunks)packages/template/src/lib/stack-app/apps/interfaces/admin-app.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
packages/template/**
📄 CodeRabbit inference engine (AGENTS.md)
When modifying the SDK copies, make changes in packages/template (source of truth)
Files:
packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.tspackages/template/src/lib/stack-app/apps/interfaces/admin-app.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Prefer ES6 Map over Record when representing key–value collections
Files:
packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.tspackages/template/src/lib/stack-app/apps/interfaces/admin-app.tspackages/stack-shared/src/interface/admin-interface.tsapps/backend/src/app/api/latest/internal/send-test-webhook/route.tsxapps/dashboard/src/app/(main)/(protected)/projects/[projectId]/webhooks/page-client.tsx
apps/backend/src/app/api/latest/**
📄 CodeRabbit inference engine (AGENTS.md)
apps/backend/src/app/api/latest/**: Organize backend API routes by resource under /api/latest (e.g., auth at /api/latest/auth/, users at /api/latest/users/, teams at /api/latest/teams/, oauth providers at /api/latest/oauth-providers/)
Use the custom route handler system in the backend to ensure consistent API responses
Files:
apps/backend/src/app/api/latest/internal/send-test-webhook/route.tsx
{apps/dashboard,apps/dev-launchpad,packages/stack-ui,packages/react}/**/*.{tsx,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
For blocking alerts and errors in UI, do not use toast notifications; use alerts instead
Files:
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/webhooks/page-client.tsx
{apps/dashboard,apps/dev-launchpad,packages/stack-ui,packages/react}/**/*.{tsx,jsx,css}
📄 CodeRabbit inference engine (AGENTS.md)
Keep hover/click animations snappy; avoid pre-transition delays on hover and apply transitions after the action (e.g., fade-out on hover end)
Files:
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/webhooks/page-client.tsx
🧬 Code graph analysis (3)
packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts (1)
packages/stack-shared/src/utils/errors.tsx (1)
throwErr(10-19)
apps/backend/src/app/api/latest/internal/send-test-webhook/route.tsx (4)
apps/backend/src/route-handlers/smart-route-handler.tsx (1)
createSmartRouteHandler(209-294)packages/stack-shared/src/schema-fields.ts (6)
yupObject(247-251)adminAuthTypeSchema(483-483)adaptSchema(330-330)yupString(187-190)yupNumber(191-194)yupBoolean(195-198)apps/backend/src/lib/webhooks.tsx (1)
getSvixClient(13-18)packages/stack-shared/src/utils/errors.tsx (2)
captureError(126-134)StackAssertionError(69-85)
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/webhooks/page-client.tsx (6)
packages/stack-shared/src/schema-fields.ts (1)
urlSchema(334-342)packages/stack-ui/src/components/action-dialog.tsx (1)
ActionDialog(31-135)packages/stack-shared/src/utils/promises.tsx (1)
runAsynchronously(343-366)apps/dashboard/src/components/form-fields.tsx (1)
InputField(59-97)apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/webhooks/utils.tsx (1)
getSvixResult(12-32)apps/dashboard/src/components/settings.tsx (1)
SettingCard(11-48)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
- GitHub Check: Vercel Agent Review
- GitHub Check: all-good
- GitHub Check: build (22.x)
- GitHub Check: docker
- GitHub Check: build (22.x)
- GitHub Check: docker
- GitHub Check: restart-dev-and-test
- GitHub Check: check_prisma_migrations (22.x)
- GitHub Check: setup-tests
- GitHub Check: lint_and_build (latest)
- GitHub Check: Security Check
🔇 Additional comments (13)
packages/stack-shared/src/interface/admin-interface.ts (1)
357-368: LGTM: interface method matches backend route and response contractPayload key (
endpoint_id) and return shape are consistent with the server. No issues.packages/template/src/lib/stack-app/apps/interfaces/admin-app.ts (1)
59-60: LGTM: API surface is consistent with Result-pattern used elsewhereSignature and error mapping align with adjacent methods.
packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts (1)
467-477: LGTM: correct delegation and error mappingGood use of
throwErrfallback and consistent Result handling.apps/backend/src/app/api/latest/internal/send-test-webhook/route.tsx (5)
61-75: Nice: captured send failure with contextGood use of
captureErrorandStackAssertionErrorwithcauseand identifiers.
8-29: Schema and metadata look correctAdmin auth required, strict POST, and typed JSON response are aligned with our handler system.
34-47: Endpoint existence handling is clearReturning a friendly message when the endpoint is missing is good UX for admins.
98-106: LGTM: success pathConsistent response shape with interface/clients.
1-7: Confirmed: MessageStatus is compatible with Svix 1.25.0The Svix npm package version 1.25.0 exports the MessageStatus enum with members including Success, which is declared in the backend's package.json and used correctly at line 82 of the route file (
{ status: MessageStatus.Success }). No compatibility issues exist.apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/webhooks/page-client.tsx (5)
120-137: Good security UX: HTTP warningClear warning for insecure URLs in dev; aligns with our UI guidelines (alerts over toasts).
41-49: Form setup looks solidyupResolver + onChange mode and defaults are correct; resets on close to keep state clean.
59-67: Endpoint create flow is straightforwardCreates via Svix SDK then shows confirmation with follow-up actions. Nice touch using
onTestRequested.
321-326: Action menu addition is appropriate“Test” action wires through to dialog; good cohesion with
onTestEndpoint.
371-406: Provider wiring and test-dialog state handling look correctUses
useSvixToken, refresh via counter, and controlled dialog state. LGTM.
packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts
Show resolved
Hide resolved
|
You have run out of free Bugbot PR reviews for this billing cycle. This will reset on November 10. To receive reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial. |
https://www.loom.com/share/abbd19d1deaa4b3d8f8ae9c1f2f9b098?sid=d105ee21-f380-4c37-85f1-a58610cfff9d
High-level PR Summary
This PR adds webhook testing functionality to the dashboard, allowing users to send test events to their configured webhook endpoints and verify they're working correctly. The implementation adds a new backend API endpoint that creates a
stack.testevent via Svix, verifies successful delivery, and provides clear feedback. The dashboard UI is enhanced with a test dialog that shows a preview of the test payload and displays success or error messages, with the test action accessible both from the endpoint creation flow and the action menu for existing endpoints.⏱️ Estimated Review Time: 15-30 minutes
💡 Review Order Suggestion
packages/stack-shared/src/interface/admin-interface.tspackages/template/src/lib/stack-app/apps/interfaces/admin-app.tspackages/template/src/lib/stack-app/apps/implementations/admin-app-impl.tsapps/backend/src/app/api/latest/internal/send-test-webhook/route.tsxapps/dashboard/src/app/(main)/(protected)/projects/[projectId]/webhooks/page-client.tsxImportant
Add functionality to test webhooks from the dashboard, including backend route and frontend UI updates.
POSTroute insend-test-webhook/route.tsxto handle test webhook requests.yup.svixand handle success/error cases.page-client.tsxto include a dialog for creating and testing endpoints.TestEndpointDialogcomponent to handle the test webhook UI.CreateDialogandActionMenuto support triggering the test webhook.sendTestWebhookmethod toStackAdminInterfaceinadmin-interface.ts.sendTestWebhookin_StackAdminAppImplIncompleteinadmin-app-impl.ts.StackAdminAppinterface inadmin-app.tsto includesendTestWebhookmethod.This description was created by
for c9bc00c. You can customize this summary. It will automatically update as commits are pushed.