Conversation
WalkthroughAdds comprehensive type re-exports and value export for WebhookEventType in Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant C as Caller
participant M as decodeWebhook
participant V as validateToken
participant J as jwtDecoder
C->>M: decodeWebhook(token?, domain?)
M->>V: validateToken(token, domain)
V-->>M: isValid (true/false)
alt invalid
M-->>C: null
else valid
M->>J: jwtDecoder.decode<T>(token)
J-->>M: decoded event T
M-->>C: T
end
note right of V: validation gates decoding
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
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 |
63f33f2 to
7f7fb3c
Compare
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 (2)
lib/main.ts (1)
32-42: Narrowtokenbefore callingjwtDecoder
tokenisstring | undefined; passing it tojwtDecoderrisks a TS error and an undefined at runtime. Guard early and narrow before decode.export const decodeWebhook = async <T = WebhookEvent>( token?: string, domain?: string, ): Promise<T | null> => { - const tokenValid = await validateToken({ token, domain }); + // Fast‑fail for missing inputs + if (!token || !token.trim() || !domain || !domain.trim()) { + return null; + } + const tokenValid = await validateToken({ token, domain }); if (!tokenValid.valid) { return null; } - return jwtDecoder<T>(token); + return jwtDecoder<T>(token); };lib/main.test.ts (1)
65-97: Mock external JWT validator/decoder to avoid network-bound testslib/main.test.ts currently calls decodeWebhook which uses validateToken and jwtDecoder from @kinde — the tests will perform live JWKS/validation (flaky/offline‑hostile). Mock those modules and import the module-under-test after registering mocks.
Add near top of lib/main.test.ts (mock before importing ./main):
import { describe, it, expect, vi, beforeEach } from "vitest"; vi.mock("@kinde/jwt-validator", () => ({ validateToken: vi.fn() })); vi.mock("@kinde/jwt-decoder", () => ({ jwtDecoder: vi.fn() })); let decodeWebhook: any; let validateToken: any; let jwtDecoder: any; beforeEach(async () => { vi.resetAllMocks(); ({ decodeWebhook } = await import("./main")); ({ validateToken } = await import("@kinde/jwt-validator")); ({ jwtDecoder } = await import("@kinde/jwt-decoder")); });Then inside tests set deterministic behavior:
(validateToken as any).mockResolvedValue({ valid: true }); // or { valid: false } (jwtDecoder as any).mockReturnValue(/* decoded webhook object */);
🧹 Nitpick comments (5)
lib/main.test.ts (4)
74-81: Fix Vitest matcher chainingUse Jest-style matchers in Vitest: replace
.not.equal(...)with.not.toEqual(...).- expect(webhookEvent?.type).not.equal(WebhookEventType.organizationCreated); + expect(webhookEvent?.type).not.toEqual(WebhookEventType.organizationCreated);
100-132: Runtime checks on type-only exports will type‑error under common TS settingsUsing
typeof Exported*on type‑only exports often fails type‑checking. Prefer compile‑time assertions viaexpectTypeOfand import the items as types.- import { - decodeWebhook, - WebhookEventType as ExportedWebhookEventType, - WebhookEvent as ExportedWebhookEvent, - WebhookSource as ExportedWebhookSource, - WebhookBase as ExportedWebhookBase, - UserCreatedWebhookEvent as ExportedUserCreatedWebhookEvent, - UserUpdatedWebhookEvent as ExportedUserUpdatedWebhookEvent, - UserDeletedWebhookEvent as ExportedUserDeletedWebhookEvent, - UserAuthenticatedWebhookEvent as ExportedUserAuthenticatedWebhookEvent, - UserAuthenticationFailedWebhookEvent as ExportedUserAuthenticationFailedWebhookEvent, - AccessRequestCreatedWebhookEvent as ExportedAccessRequestCreatedWebhookEvent, - OrganizationCreatedWebhookEvent as ExportedOrganizationCreatedWebhookEvent, - OrganizationUpdatedWebhookEvent as ExportedOrganizationUpdatedWebhookEvent, - OrganizationDeletedWebhookEvent as ExportedOrganizationDeletedWebhookEvent, - PermissionCreatedWebhookEvent as ExportedPermissionCreatedWebhookEvent, - PermissionUpdatedWebhookEvent as ExportedPermissionUpdatedWebhookEvent, - PermissionDeletedWebhookEvent as ExportedPermissionDeletedWebhookEvent, - RoleCreatedWebhookEvent as ExportedRoleCreatedWebhookEvent, - RoleUpdatedWebhookEvent as ExportedRoleUpdatedWebhookEvent, - RoleDeletedWebhookEvent as ExportedRoleDeletedWebhookEvent, - SubscriberCreatedWebhookEvent as ExportedSubscriberCreatedWebhookEvent, - } from "./main"; + import { decodeWebhook, WebhookEventType as ExportedWebhookEventType } from "./main"; + import type { + WebhookEvent as ExportedWebhookEvent, + WebhookSource as ExportedWebhookSource, + WebhookBase as ExportedWebhookBase, + UserCreatedWebhookEvent as ExportedUserCreatedWebhookEvent, + UserUpdatedWebhookEvent as ExportedUserUpdatedWebhookEvent, + UserDeletedWebhookEvent as ExportedUserDeletedWebhookEvent, + UserAuthenticatedWebhookEvent as ExportedUserAuthenticatedWebhookEvent, + UserAuthenticationFailedWebhookEvent as ExportedUserAuthenticationFailedWebhookEvent, + AccessRequestCreatedWebhookEvent as ExportedAccessRequestCreatedWebhookEvent, + OrganizationCreatedWebhookEvent as ExportedOrganizationCreatedWebhookEvent, + OrganizationUpdatedWebhookEvent as ExportedOrganizationUpdatedWebhookEvent, + OrganizationDeletedWebhookEvent as ExportedOrganizationDeletedWebhookEvent, + PermissionCreatedWebhookEvent as ExportedPermissionCreatedWebhookEvent, + PermissionUpdatedWebhookEvent as ExportedPermissionUpdatedWebhookEvent, + PermissionDeletedWebhookEvent as ExportedPermissionDeletedWebhookEvent, + RoleCreatedWebhookEvent as ExportedRoleCreatedWebhookEvent, + RoleUpdatedWebhookEvent as ExportedRoleUpdatedWebhookEvent, + RoleDeletedWebhookEvent as ExportedRoleDeletedWebhookEvent, + SubscriberCreatedWebhookEvent as ExportedSubscriberCreatedWebhookEvent, + } from "./main";And replace the runtime “undefined” checks with compile‑time ones:
- it("should export all webhook event types", () => { - expect(typeof ExportedWebhookEvent).toBe("undefined"); - ... - }); + it("should export all webhook event types (types only)", () => { + expectTypeOf<ExportedWebhookEvent>().toEqualTypeOf<WebhookEvent>(); + expectTypeOf<ExportedWebhookSource>().toEqualTypeOf<WebhookSource>(); + expectTypeOf<ExportedWebhookBase>().toEqualTypeOf<WebhookBase>(); + expectTypeOf<ExportedUserCreatedWebhookEvent>().toEqualTypeOf<UserCreatedWebhookEvent>(); + expectTypeOf<ExportedUserUpdatedWebhookEvent>().toEqualTypeOf<UserUpdatedWebhookEvent>(); + expectTypeOf<ExportedUserDeletedWebhookEvent>().toEqualTypeOf<UserDeletedWebhookEvent>(); + expectTypeOf<ExportedUserAuthenticatedWebhookEvent>().toEqualTypeOf<UserAuthenticatedWebhookEvent>(); + expectTypeOf<ExportedUserAuthenticationFailedWebhookEvent>().toEqualTypeOf<UserAuthenticationFailedWebhookEvent>(); + expectTypeOf<ExportedAccessRequestCreatedWebhookEvent>().toEqualTypeOf<AccessRequestCreatedWebhookEvent>(); + expectTypeOf<ExportedOrganizationCreatedWebhookEvent>().toEqualTypeOf<OrganizationCreatedWebhookEvent>(); + expectTypeOf<ExportedOrganizationUpdatedWebhookEvent>().toEqualTypeOf<OrganizationUpdatedWebhookEvent>(); + expectTypeOf<ExportedOrganizationDeletedWebhookEvent>().toEqualTypeOf<OrganizationDeletedWebhookEvent>(); + expectTypeOf<ExportedPermissionCreatedWebhookEvent>().toEqualTypeOf<PermissionCreatedWebhookEvent>(); + expectTypeOf<ExportedPermissionUpdatedWebhookEvent>().toEqualTypeOf<PermissionUpdatedWebhookEvent>(); + expectTypeOf<ExportedPermissionDeletedWebhookEvent>().toEqualTypeOf<PermissionDeletedWebhookEvent>(); + expectTypeOf<ExportedRoleCreatedWebhookEvent>().toEqualTypeOf<RoleCreatedWebhookEvent>(); + expectTypeOf<ExportedRoleUpdatedWebhookEvent>().toEqualTypeOf<RoleUpdatedWebhookEvent>(); + expectTypeOf<ExportedRoleDeletedWebhookEvent>().toEqualTypeOf<RoleDeletedWebhookEvent>(); + expectTypeOf<ExportedSubscriberCreatedWebhookEvent>().toEqualTypeOf<SubscriberCreatedWebhookEvent>(); + });Also add the import:
- import { describe, it, expect } from "vitest"; + import { describe, it, expect, expectTypeOf } from "vitest";
1-1: Stale header commentHeader says
setToken.test.ts; update or drop to avoid confusion.
49-53: Sanitize sample token payloadsTokens embed an email. Prefer anonymized payloads or generate minimal fakes for tests to avoid committing PII.
lib/main.ts (1)
27-31: JSDoc grammar“Decode a webhook events” → “Decode a webhook event”.
- * Decode a webhook events + * Decode a webhook event
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
lib/main.test.ts(2 hunks)lib/main.ts(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
lib/main.test.ts (1)
lib/main.ts (2)
WebhookEventType(45-45)decodeWebhook(32-42)
🔇 Additional comments (1)
lib/main.ts (1)
44-68: Re-exports look goodValue export for
WebhookEventTypeand type‑only re‑exports keep the runtime surface minimal and match the tests’ intent.
7f7fb3c to
be87c46
Compare
be87c46 to
a54a81e
Compare
Explain your changes
Adds types to export and tests
Checklist
🛟 If you need help, consider asking for advice over in the Kinde community.