Skip to content

feat: export types and add tests#5

Merged
DanielRivers merged 1 commit intomainfrom
feat/export-types
Sep 16, 2025
Merged

feat: export types and add tests#5
DanielRivers merged 1 commit intomainfrom
feat/export-types

Conversation

@DanielRivers
Copy link
Member

Explain your changes

Adds types to export and tests

Checklist

🛟 If you need help, consider asking for advice over in the Kinde community.

@coderabbitai
Copy link

coderabbitai bot commented Sep 16, 2025

Walkthrough

Adds comprehensive type re-exports and value export for WebhookEventType in lib/main.ts. Updates decodeWebhook to accept optional token and domain, validate them via validateToken, and return null on invalid input before decoding. Adds tests in lib/main.test.ts to verify public exports, enum values, and type-only exports.

Changes

Cohort / File(s) Summary
Public API & decode flow
lib/main.ts
Re-exports webhook-related types via export type { ... } and exports WebhookEventType as a runtime value. Updates decodeWebhook signature to `async <T = WebhookEvent>(token?: string, domain?: string): Promise<T
Export validation tests
lib/main.test.ts
Adds an "Export types" test suite that imports exported items (aliased) and asserts: decodeWebhook is exported as a function; WebhookEventType is exported and contains the full set of expected enum values; webhook event types are exported as type-only (runtime typeof is "undefined"); and includes a type-checked example webhook event using exported types.

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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The PR title "feat: export types and add tests" concisely and accurately describes the primary work in this changeset — exporting TypeScript webhook types from lib/main and adding tests to validate those exports — so it is relevant and clear for a reviewer scanning history.
Description Check ✅ Passed The PR description states "Adds types to export and tests" and includes the contributor checklist, which is directly related to the changeset; although brief, it is on-topic and satisfies this lenient description check.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/export-types

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7f7fb3c and a54a81e.

📒 Files selected for processing (2)
  • lib/main.test.ts (2 hunks)
  • lib/main.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/main.ts
  • lib/main.test.ts

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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: Narrow token before calling jwtDecoder

token is string | undefined; passing it to jwtDecoder risks 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 tests

lib/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 chaining

Use 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 settings

Using typeof Exported* on type‑only exports often fails type‑checking. Prefer compile‑time assertions via expectTypeOf and 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 comment

Header says setToken.test.ts; update or drop to avoid confusion.


49-53: Sanitize sample token payloads

Tokens 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

📥 Commits

Reviewing files that changed from the base of the PR and between 451c31e and 7f7fb3c.

📒 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 good

Value export for WebhookEventType and type‑only re‑exports keep the runtime surface minimal and match the tests’ intent.

@DanielRivers DanielRivers merged commit 9a69d45 into main Sep 16, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant