Skip to content

feat(clerk-js, localizations, ui): Add credits information in the user/org profile#8977

Open
l-armstrong wants to merge 8 commits into
mainfrom
lamone/bill-1613-add-credits-information-in-the-userorg-profile
Open

feat(clerk-js, localizations, ui): Add credits information in the user/org profile#8977
l-armstrong wants to merge 8 commits into
mainfrom
lamone/bill-1613-add-credits-information-in-the-userorg-profile

Conversation

@l-armstrong

@l-armstrong l-armstrong commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Display the C2's remaining account credit and their account credit history in the user/org profile.

Description

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

Summary by CodeRabbit

  • New Features
    • Added an account credits section showing the current credit balance in user and organization billing/profile views.
    • Added a credit history page with a back link, localized headers, and formatted credit transactions (amounts and dates), plus navigation to view history.
  • Bug Fixes
    • Billing subscription data now includes the payer reference required for credit-balance and credit-history views.
  • Documentation
    • Added new localization strings for the account credits and credit history UI.

@vercel

vercel Bot commented Jun 24, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment Jun 24, 2026 9:48pm
swingset Ready Ready Preview, Comment Jun 24, 2026 9:48pm

Request Review

@changeset-bot

changeset-bot Bot commented Jun 24, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 697cf41

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 23 packages
Name Type
@clerk/localizations Minor
@clerk/clerk-js Minor
@clerk/shared Minor
@clerk/ui Minor
@clerk/react Patch
@clerk/chrome-extension Patch
@clerk/electron Patch
@clerk/expo Patch
@clerk/astro Patch
@clerk/backend Patch
@clerk/expo-passkeys Patch
@clerk/express Patch
@clerk/fastify Patch
@clerk/headless Patch
@clerk/hono Patch
@clerk/msw Patch
@clerk/nextjs Patch
@clerk/nuxt Patch
@clerk/react-router Patch
@clerk/tanstack-react-start Patch
@clerk/testing Patch
@clerk/vue Patch
@clerk/swingset Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds billing credit balance and history APIs, shared types/resources/hooks, UI sections and routes, localization entries, release metadata, and two bundlewatch threshold increases.

Changes

Billing credits

Layer / File(s) Summary
Billing credit API and resources
packages/shared/src/types/billing.ts, packages/shared/src/types/json.ts, packages/clerk-js/src/core/modules/billing/namespace.ts, packages/clerk-js/src/core/resources/BillingCreditBalance.ts, packages/clerk-js/src/core/resources/BillingCreditLedger.ts, packages/clerk-js/src/core/resources/BillingSubscription.ts, packages/clerk-js/src/core/resources/internal.ts
BillingNamespace gains credit balance/history methods and new credit DTO/resource types, while BillingSubscription now stores payerId.
Credit query hooks and cache keys
packages/shared/src/react/stable-keys.ts, packages/shared/src/react/hooks/index.ts, packages/shared/src/react/hooks/useCreditBalance.tsx, packages/shared/src/react/hooks/useCreditHistory.tsx, packages/ui/src/contexts/components/Plans.tsx
New credit cache keys and hook exports are added, and the UI billing hooks call the new credit balance/history queries with payer-scoped params.
Account credits section and labels
packages/shared/src/types/elementIds.ts, packages/shared/src/types/localization.ts, packages/localizations/src/en-US.ts, packages/ui/src/components/AccountCredits/AccountCredits.tsx, packages/ui/src/components/AccountCredits/index.ts, packages/ui/src/components/OrganizationProfile/OrganizationBillingPage.tsx, packages/ui/src/components/UserProfile/BillingPage.tsx, .changeset/fancy-rats-stick.md
Account credits labels are added to the localization contracts and English strings, the balance section component is introduced, and both billing pages render it.
Credit history page and routes
packages/ui/src/components/AccountCredits/CreditHistoryPage.tsx, packages/ui/src/components/OrganizationProfile/OrganizationProfileRoutes.tsx, packages/ui/src/components/UserProfile/UserProfileRoutes.tsx
The credit history page formats and displays credit ledger rows, and both billing route trees add a credit-history route.

Bundlewatch thresholds

Layer / File(s) Summary
Dist size limits
packages/clerk-js/bundlewatch.config.json
The maxSize values for dist/clerk.legacy.browser.js and dist/clerk.native.js are increased by 1KB each.

Sequence Diagram(s)

Included above in the hidden review stack artifact.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • dstaley
  • mauricioabreu

Poem

A bunny found credits in a leafy green trail 🐇
Then hopped through the routes with a flick of the tail
The balance said “here,” and the history sang
While bundles grew comfy with a tiny size pang

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding credits information to user and organization profiles across clerk-js, localizations, and ui.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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

@pkg-pr-new

pkg-pr-new Bot commented Jun 24, 2026

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@8977

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@8977

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@8977

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@8977

@clerk/electron

npm i https://pkg.pr.new/@clerk/electron@8977

@clerk/electron-passkeys

npm i https://pkg.pr.new/@clerk/electron-passkeys@8977

@clerk/eslint-plugin

npm i https://pkg.pr.new/@clerk/eslint-plugin@8977

@clerk/expo

npm i https://pkg.pr.new/@clerk/expo@8977

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@8977

@clerk/express

npm i https://pkg.pr.new/@clerk/express@8977

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@8977

@clerk/hono

npm i https://pkg.pr.new/@clerk/hono@8977

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@8977

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@8977

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@8977

@clerk/react

npm i https://pkg.pr.new/@clerk/react@8977

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@8977

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@8977

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@8977

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@8977

@clerk/ui

npm i https://pkg.pr.new/@clerk/ui@8977

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@8977

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@8977

commit: 697cf41

@l-armstrong l-armstrong changed the title feat(clerk-js, localizations, ui): add credits information in the user/org profile feat(clerk-js, localizations, ui): Add credits information in the user/org profile Jun 24, 2026
@github-actions

github-actions Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

API Changes Report

Generated by Break Check on 2026-06-24T21:50:28.545Z

Summary

Metric Count
Packages analyzed 19
Packages with changes 1
🔴 Breaking changes 0
🟡 Non-breaking changes 2
🟢 Additions 28

🤖 This report was reviewed by claude-sonnet-4-6.


@clerk/shared

Current version: 4.21.0
Recommended bump: MINOR → 4.22.0

Subpath ./types

🟡 Non-breaking Changes (2)

Modified: __internal_LocalizationResource
Diff (before: 1943 lines, after: 1961 lines). Click to expand.
// ... 845 unchanged lines elided ...
      };
      billingPage: {
        title: LocalizationValue;
+       accountCreditsSection: {
+         title: LocalizationValue;
+         viewHistory: LocalizationValue;
+       };
+       creditHistoryPage: {
+         title: LocalizationValue;
+         tableHeader__amount: LocalizationValue;
+         tableHeader__date: LocalizationValue;
+       };
        start: {
          headerTitle__payments: LocalizationValue;
          headerTitle__plans: LocalizationValue;
          headerTitle__subscriptions: LocalizationValue;
          headerTitle__statements: LocalizationValue;
        };
        statementsSection: {
          empty: LocalizationValue;
          itemCaption__paidForPlan: LocalizationValue;
          itemCaption__proratedCredit: LocalizationValue;
          itemCaption__payerCredit: LocalizationValue;
          itemCaption__subscribedAndPaidForPlan: LocalizationValue;
          notFound: LocalizationValue;
          tableHeader__date: LocalizationValue;
          tableHeader__amount: LocalizationValue;
          title: LocalizationValue;
          totalPaid: LocalizationValue;
        };
        switchPlansSection: {
          title: LocalizationValue;
        };
        subscriptionsListSection: {
          tableHeader__plan: LocalizationValue;
          tableHeader__startDate: LocalizationValue;
          tableHeader__edit: LocalizationValue;
          title: LocalizationValue;
          actionLabel__newSubscription: LocalizationValue;
          actionLabel__manageSubscription: LocalizationValue;
          actionLabel__switchPlan: LocalizationValue;
          overview: LocalizationValue;
        };
        paymentHistorySection: {
          empty: LocalizationValue;
          notFound: LocalizationValue;
          tableHeader__date: LocalizationValue;
          tableHeader__amount: LocalizationValue;
          tableHeader__status: LocalizationValue;
        };
        paymentMethodsSection: {
          title: LocalizationValue;
          add: LocalizationValue;
          addSubtitle: LocalizationValue;
          cancelButton: LocalizationValue;
          actionLabel__default: LocalizationValue;
          actionLabel__remove: LocalizationValue;
          formButtonPrimary__add: LocalizationValue;
          formButtonPrimary__pay: LocalizationValue;
          removeMethod: {
            title: LocalizationValue;
            messageLine1: LocalizationValue<'identifier'>;
            messageLine2: LocalizationValue;
            successMessage: LocalizationValue<'paymentMethod'>;
          };
          payWithTestCardButton: LocalizationValue;
        };
        subscriptionsSection: {
          actionLabel__default: LocalizationValue;
        };
      };
      plansPage: {
        title: LocalizationValue;
        alerts: {
          noPermissionsToManageBilling: LocalizationValue;
        };
      };
    };
    userButton: {
      action__manageAccount: LocalizationValue;
      action__signOut: LocalizationValue;
      action__signOutAll: LocalizationValue;
      action__addAccount: LocalizationValue;
      action__openUserMenu: LocalizationValue;
      action__closeUserMenu: LocalizationValue;
      label__userButtonPopover?: LocalizationValue;
      label__accountActions?: LocalizationValue;
      label__activeSessions?: LocalizationValue;
    };
    organizationSwitcher: {
      personalWorkspace: LocalizationValue;
      notSelected: LocalizationValue;
      action__createOrganization: LocalizationValue;
      action__manageOrganization: LocalizationValue;
      action__invitationAccept: LocalizationValue;
      action__suggestionsAccept: LocalizationValue;
      action__openOrganizationSwitcher: LocalizationValue;
      action__closeOrganizationSwitcher: LocalizationValue;
      suggestionsAcceptedLabel: LocalizationValue;
    };
    impersonationFab: {
      title: LocalizationValue<'identifier'>;
      action__signOut: LocalizationValue;
    };
    organizationProfile: {
      navbar: {
        title: LocalizationValue;
        description: LocalizationValue;
        general: LocalizationValue;
        members: LocalizationValue;
        billing: LocalizationValue;
        apiKeys: LocalizationValue;
        security: LocalizationValue;
      };
      badge__unverified: LocalizationValue;
      badge__automaticInvitation: LocalizationValue;
      badge__automaticSuggestion: LocalizationValue;
      badge__manualInvitation: LocalizationValue;
      badge__enterpriseSso: LocalizationValue;
      start: {
        headerTitle__members: LocalizationValue;
        membershipSeatUsageLabel: LocalizationValue<'count' | 'limit'>;
        headerTitle__general: LocalizationValue;
        profileSection: {
          title: LocalizationValue;
          primaryButton: LocalizationValue;
          uploadAction__title: LocalizationValue;
        };
      };
      profilePage: {
        title: LocalizationValue;
        successMessage: LocalizationValue;
        dangerSection: {
          title: LocalizationValue;
          leaveOrganization: {
            title: LocalizationValue;
            messageLine1: LocalizationValue;
            messageLine2: LocalizationValue;
            successMessage: LocalizationValue;
            actionDescription: LocalizationValue<'organizationName'>;
          };
          deleteOrganization: {
            title: LocalizationValue;
            messageLine1: LocalizationValue;
            messageLine2: LocalizationValue;
            actionDescription: LocalizationValue<'organizationName'>;
            successMessage: LocalizationValue;
          };
        };
        domainSection: {
          title: LocalizationValue;
          subtitle: LocalizationValue;
          primaryButton: LocalizationValue;
          menuAction__verify: LocalizationValue;
          menuAction__remove: LocalizationValue;
          menuAction__manage: LocalizationValue;
        };
      };
      createDomainPage: {
        title: LocalizationValue;
        subtitle: LocalizationValue;
      };
      verifyDomainPage: {
        title: LocalizationValue;
        subtitle: LocalizationValue<'domainName'>;
        subtitleVerificationCodeScreen: LocalizationValue<'emailAddress'>;
        formTitle: LocalizationValue;
        formSubtitle: LocalizationValue;
        resendButton: LocalizationValue;
      };
      verifiedDomainPage: {
        title: LocalizationValue<'domain'>;
        subtitle: LocalizationValue<'domain'>;
        start: {
          headerTitle__enrollment: LocalizationValue;
          headerTitle__danger: LocalizationValue;
        };
        enrollmentTab: {
          subtitle: LocalizationValue;
          manualInvitationOption__label: LocalizationValue;
          manualInvitationOption__description: LocalizationValue;
          automaticInvitationOption__label: LocalizationValue;
          automaticInvitationOption__description: LocalizationValue;
          automaticSuggestionOption__label: LocalizationValue;
          automaticSuggestionOption__description: LocalizationValue;
          calloutInfoLabel: LocalizationValue;
          calloutInvitationCountLabel: LocalizationValue<'count'>;
          calloutSuggestionCountLabel: LocalizationValue<'count'>;
        };
        dangerTab: {
          removeDomainTitle: LocalizationValue;
          removeDomainSubtitle: LocalizationValue;
          removeDomainActionLabel__remove: LocalizationValue;
          calloutInfoLabel: LocalizationValue;
        };
      };
      invitePage: {
        title: LocalizationValue;
        subtitle: LocalizationValue;
        successMessage: LocalizationValue;
        detailsTitle__inviteFailed: LocalizationValue<'email_addresses'>;
        formButtonPrimary__continue: LocalizationValue;
        formButtonPrimary__purchaseSeats: LocalizationValue;
        selectDropdown__role: LocalizationValue;
      };
      removeDomainPage: {
        title: LocalizationValue;
        messageLine1: LocalizationValue<'domain'>;
        messageLine2: LocalizationValue;
        successMessage: LocalizationValue;
      };
      securityPage: {
        title: LocalizationValue;
        removeDialog: {
          title: LocalizationValue;
          subtitle: LocalizationValue;
          confirmButton: LocalizationValue;
        };
        ssoSection: {
          title: LocalizationValue;
          badge__unconfigured: LocalizationValue;
          badge__inProgress: LocalizationValue;
          badge__active: LocalizationValue;
          badge__inactive: LocalizationValue;
          descriptionLine1: LocalizationValue;
          primaryButton__startConfiguration: LocalizationValue;
          primaryButton__continueConfiguration: LocalizationValue;
          domainLabel: LocalizationValue;
          menuAction__edit: LocalizationValue;
          menuAction__activate: LocalizationValue;
          menuAction__deactivate: LocalizationValue;
          menuAction__remove: LocalizationValue;
          tooltip: LocalizationValue<'role'>;
          tooltip__noRole: LocalizationValue;
          tooltipLabel: LocalizationValue;
        };
      };
      membersPage: {
        detailsTitle__emptyRow: LocalizationValue;
        action__invite: LocalizationValue;
        action__search: LocalizationValue;
        start: {
          headerTitle__members: LocalizationValue;
          headerTitle__invitations: LocalizationValue;
          headerTitle__requests: LocalizationValue;
        };
        activeMembersTab: {
          tableHeader__user: LocalizationValue;
          tableHeader__joined: LocalizationValue;
          tableHeader__role: LocalizationValue;
          tableHeader__actions: LocalizationValue;
          menuAction__remove: LocalizationValue;
        };
        invitedMembersTab: {
          tableHeader__invited: LocalizationValue;
          menuAction__revoke: LocalizationValue;
        };
        invitationsTab: {
          table__emptyRow: LocalizationValue;
          autoInvitations: {
            headerTitle: LocalizationValue;
            headerSubtitle: LocalizationValue;
            primaryButton: LocalizationValue;
          };
        };
        requestsTab: {
          tableHeader__requested: LocalizationValue;
          menuAction__approve: LocalizationValue;
          menuAction__reject: LocalizationValue;
          table__emptyRow: LocalizationValue;
          autoSuggestions: {
            headerTitle: LocalizationValue;
            headerSubtitle: LocalizationValue;
            primaryButton: LocalizationValue;
          };
        };
        alerts: {
          roleSetMigrationInProgress: {
            title: LocalizationValue;
            subtitle: LocalizationValue;
          };
        };
      };
      billingPage: {
        title: LocalizationValue;
+       accountCreditsSection: {
+         title: LocalizationValue;
+         viewHistory: LocalizationValue;
+       };
+       creditHistoryPage: {
+         title: LocalizationValue;
+         tableHeader__amount: LocalizationValue;
+         tableHeader__date: LocalizationValue;
+       };
        start: {
          headerTitle__payments: LocalizationValue;
          headerTitle__plans: LocalizationValue;
// ... 819 unchanged lines elided ...

Static analyzer: Breaking change in type alias __internal_LocalizationResource: Type changed: {locale:string;maintenanceMode:import("@clerk/shared").LocalizationValue;roles:{[r:string]:import("@clerk/shared").Loca…{locale:string;maintenanceMode:import("@clerk/shared").LocalizationValue;roles:{[r:string]:import("@clerk/shared").Loca…

🤖 AI review (reclassified as non-breaking) (72%): __internal_LocalizationResource is used as the base for LocalizationResource (an output/extension type via DeepPartial<DeepLocalizationWithoutObjects<...>>), and the diff shows only additional lines (18 more lines elided in the after snippet), meaning new fields were added to a type consumers only read/extend rather than construct directly.

Modified: ProfileSectionId
- type ProfileSectionId = 'profile' | 'username' | 'emailAddresses' | 'phoneNumbers' | 'connectedAccounts' | 'enterpriseAccounts' | 'web3Wallets' | 'password' | 'passkeys' | 'mfa' | 'danger' | 'activeDevices' | 'organizationProfile' | 'organizationDanger' | 'organizationDomains' | 'manageVerifiedDomains' | 'subscriptionsList' | 'paymentMethods' | 'sso' | 'ssoStatus' | 'enableSso' | 'ssoDomain' | 'ssoConfiguration' | 'configureAgain' | 'resetSso' | 'testSsoUrl' | 'testResults';
+ type ProfileSectionId = 'profile' | 'username' | 'emailAddresses' | 'phoneNumbers' | 'connectedAccounts' | 'enterpriseAccounts' | 'web3Wallets' | 'password' | 'passkeys' | 'mfa' | 'danger' | 'activeDevices' | 'organizationProfile' | 'organizationDanger' | 'organizationDomains' | 'manageVerifiedDomains' | 'subscriptionsList' | 'paymentMethods' | 'sso' | 'ssoStatus' | 'enableSso' | 'ssoDomain' | 'ssoConfiguration' | 'configureAgain' | 'resetSso' | 'testSsoUrl' | 'testResults' | 'accountCredits';

Static analyzer: Breaking change in type alias ProfileSectionId: Type changed: 'activeDevices'|'configureAgain'|'connectedAccounts'|'danger'|'emailAddresses'|'enableSso'|'enterpriseAccounts'|'manage…'accountCredits'|'activeDevices'|'configureAgain'|'connectedAccounts'|'danger'|'emailAddresses'|'enableSso'|'enterprise…

🤖 AI review (reclassified as non-breaking) (90%): A new literal variant 'accountCredits' was added to ProfileSectionId; existing consumers who exhaustively switch on this union (e.g. with a never fallthrough) could be affected, but the change is purely additive — no existing variant was removed or renamed.

🟢 Additions (28)

Click to expand 28 changes
Added: BillingCreditBalanceJSON
+ interface BillingCreditBalanceJSON

Added interface BillingCreditBalanceJSON

Added: BillingCreditBalanceJSON.balance
+ balance: BillingMoneyAmountJSON | null;

Added property BillingCreditBalanceJSON.balance

Added: BillingCreditBalanceJSON.object
+ object: 'commerce_credit_balance';

Added property BillingCreditBalanceJSON.object

Added: BillingCreditBalanceResource
+ interface BillingCreditBalanceResource

Added interface BillingCreditBalanceResource

Added: BillingCreditBalanceResource.balance
+ balance: BillingMoneyAmount | null;

Added property BillingCreditBalanceResource.balance

Added: BillingCreditLedgerJSON
+ interface BillingCreditLedgerJSON

Added interface BillingCreditLedgerJSON

Added: BillingCreditLedgerJSON.amount
+ amount: number;

Added property BillingCreditLedgerJSON.amount

Added: BillingCreditLedgerJSON.created_at
+ created_at: number;

Added property BillingCreditLedgerJSON.created_at

Added: BillingCreditLedgerJSON.currency
+ currency: string;

Added property BillingCreditLedgerJSON.currency

Added: BillingCreditLedgerJSON.id
+ id: string;

Added property BillingCreditLedgerJSON.id

Added: BillingCreditLedgerJSON.object
+ object: 'commerce_credit_ledger';

Added property BillingCreditLedgerJSON.object

Added: BillingCreditLedgerJSON.payer_id
+ payer_id: string;

Added property BillingCreditLedgerJSON.payer_id

Added: BillingCreditLedgerJSON.source_id
+ source_id: string;

Added property BillingCreditLedgerJSON.source_id

Added: BillingCreditLedgerJSON.source_type
+ source_type: string;

Added property BillingCreditLedgerJSON.source_type

Added: BillingCreditLedgerResource
+ interface BillingCreditLedgerResource

Added interface BillingCreditLedgerResource

Added: BillingCreditLedgerResource.amount
+ amount: number;

Added property BillingCreditLedgerResource.amount

Added: BillingCreditLedgerResource.createdAt
+ createdAt: Date;

Added property BillingCreditLedgerResource.createdAt

Added: BillingCreditLedgerResource.currency
+ currency: string;

Added property BillingCreditLedgerResource.currency

Added: BillingCreditLedgerResource.id
+ id: string;

Added property BillingCreditLedgerResource.id

Added: BillingCreditLedgerResource.payerId
+ payerId: string;

Added property BillingCreditLedgerResource.payerId

Added: BillingCreditLedgerResource.sourceId
+ sourceId: string;

Added property BillingCreditLedgerResource.sourceId

Added: BillingCreditLedgerResource.sourceType
+ sourceType: string;

Added property BillingCreditLedgerResource.sourceType

Added: BillingNamespace.getCreditBalance
+ getCreditBalance: (params: GetCreditBalanceParams) => Promise<BillingCreditBalanceResource>;

Added property BillingNamespace.getCreditBalance

Added: BillingNamespace.getCreditHistory
+ getCreditHistory: (params: GetCreditHistoryParams) => Promise<ClerkPaginatedResponse<BillingCreditLedgerResource>>;

Added property BillingNamespace.getCreditHistory

Added: BillingSubscriptionJSON.payer_id
+ payer_id: string;

Added property BillingSubscriptionJSON.payer_id

Added: BillingSubscriptionResource.payerId
+ payerId: string;

Added property BillingSubscriptionResource.payerId

Added: GetCreditBalanceParams
+ type GetCreditBalanceParams = {
+   orgId?: string;
+   payerId: string;
+ };

Added type alias GetCreditBalanceParams

Added: GetCreditHistoryParams
+ type GetCreditHistoryParams = {
+   orgId?: string;
+   payerId: string;
+ };

Added type alias GetCreditHistoryParams


Report generated by Break Check

Last ran on 697cf41.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (5)
packages/clerk-js/src/core/resources/BillingCreditLedger.ts (1)

7-35: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

extends BaseResource appears unnecessary here.

BillingCreditLedger extends BaseResource but uses none of its capabilities (no _fetch, withDefault, etc.), while the sibling BillingCreditBalance is a plain class. For consistency and to avoid pulling in BaseResource plumbing, consider making this a plain class implementing BillingCreditLedgerResource. If the inheritance is intentional (e.g., a future need for BaseResource helpers), disregard.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/clerk-js/src/core/resources/BillingCreditLedger.ts` around lines 7 -
35, BillingCreditLedger is inheriting BaseResource without using any
BaseResource behavior, so simplify it for consistency with BillingCreditBalance.
Update the BillingCreditLedger class to be a plain class that still implements
BillingCreditLedgerResource, and keep the existing constructor/fromJSON
data-mapping logic intact. If there is no current or planned use of BaseResource
helpers in BillingCreditLedger, remove the inheritance so the class is
self-contained.
packages/shared/src/types/billing.ts (3)

960-969: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add the @experimental JSDoc block to GetCreditBalanceParams.

GetCreditHistoryParams (Line 974) carries the @experimental notice, but GetCreditBalanceParams does not. Keep them consistent since both are reference-facing.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/shared/src/types/billing.ts` around lines 960 - 969, Add the missing
`@experimental` JSDoc block to GetCreditBalanceParams so it matches
GetCreditHistoryParams and stays consistent with the other reference-facing
billing types. Update the GetCreditBalanceParams type definition in billing.ts
to include the same experimental notice alongside its existing property docs,
without changing the shape of the type.

Source: Path instructions


985-996: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document BillingCreditLedgerResource properties.

Unlike BillingSubscriptionResource and BillingCreditBalanceResource, the ledger properties (amount, currency, sourceType, sourceId, etc.) have no JSDoc. These render in the generated Clerk reference docs, so per-property descriptions help avoid customer-facing docs drift; the Docs team may want to review. Also consider documenting that amount/currency are raw values here rather than a BillingMoneyAmount like the balance resource, since that asymmetry is easy to misuse downstream (e.g. formatting in the history page).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/shared/src/types/billing.ts` around lines 985 - 996, Document the
fields on BillingCreditLedgerResource with per-property JSDoc so the generated
Clerk reference docs have clear descriptions for id, payerId, amount, currency,
sourceType, sourceId, and createdAt. Use the BillingSubscriptionResource and
BillingCreditBalanceResource typings as the style reference, and add a note near
amount/currency that these are raw values here rather than a BillingMoneyAmount
to avoid misuse in downstream formatting. Keep the comments aligned with the
BillingCreditLedgerResource interface so the Docs team can review the updated
public API wording.

Source: Path instructions


86-98: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add @returns to the new method JSDoc for docs consistency.

Every other BillingNamespace method documents its return shape with @returns (see getStatements, getPlan, etc.), which the generated Clerk reference docs render. getCreditBalance and getCreditHistory omit it. Since these are reference-facing APIs, the Docs team may need to review.

📝 Proposed JSDoc
   /**
    * Gets the credit balance for the current payer.
    *
+   * `@returns` A [`BillingCreditBalanceResource`](/docs/reference/types/billing-credit-balance-resource) object.
+   *
    * `@experimental` This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. It is advised to [pin](https://clerk.com/docs/pinning) the SDK version and the clerk-js version to avoid breaking changes.
    */
   getCreditBalance: (params: GetCreditBalanceParams) => Promise<BillingCreditBalanceResource>;

   /**
    * Gets the credit history for the current payer.
    *
+   * `@returns` A [`ClerkPaginatedResponse`](/docs/reference/types/clerk-paginated-response) of [`BillingCreditLedgerResource`](/docs/reference/types/billing-credit-ledger-resource) objects.
+   *
    * `@experimental` This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. It is advised to [pin](https://clerk.com/docs/pinning) the SDK version and the clerk-js version to avoid breaking changes.
    */
   getCreditHistory: (params: GetCreditHistoryParams) => Promise<ClerkPaginatedResponse<BillingCreditLedgerResource>>;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/shared/src/types/billing.ts` around lines 86 - 98, Add `@returns`
JSDoc entries to the BillingNamespace methods getCreditBalance and
getCreditHistory in billing.ts so they match the rest of the namespace docs.
Keep the existing experimental notes, and document the return shapes for
BillingCreditBalanceResource and
ClerkPaginatedResponse<BillingCreditLedgerResource> in the same JSDoc blocks so
the generated reference docs include them consistently.

Sources: Coding guidelines, Path instructions

packages/ui/src/contexts/components/Plans.tsx (1)

98-114: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add explicit return types to the new exported hooks.

useCreditBalance and useCreditHistory are exported but lack explicit return types. Annotating them with the underlying result types (e.g. CreditBalanceResult / the credit-history query result) keeps the public surface self-documenting and stable.

As per coding guidelines: "Always define explicit return types for functions, especially public APIs".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ui/src/contexts/components/Plans.tsx` around lines 98 - 114, Add
explicit return type annotations to the exported hooks in Plans.tsx.
`useCreditBalance` and `useCreditHistory` are public APIs, so update their
signatures to return the appropriate underlying result types instead of relying
on inference. Use the existing symbols `useCreditBalance`, `useCreditHistory`,
`__experimental_useCreditBalance`, and `__internal_useCreditHistoryQuery` to
match the hook result types already returned.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/clerk-js/src/core/resources/BillingSubscription.ts`:
- Line 39: The BillingSubscription model currently declares payerId as non-null
even though it is assigned from backend data.payer_id in the resource
initializer, so it can be undefined at runtime if the response omits that field.
Update the payerId typing and assignment in BillingSubscription (including the
related parsing/serialization path around the class constructor or load method)
to reflect the actual API contract: either make payerId optional or provide a
safe default, and ensure any downstream accessors or consumers that rely on
payerId handle the missing case correctly.

In `@packages/ui/src/components/AccountCredits/CreditHistoryPage.tsx`:
- Line 23: Add an explicit return type to the exported CreditHistoryPage
component so its signature is unambiguous; update the CreditHistoryPage function
declaration itself to return JSX.Element (or the project’s equivalent React
component return type) rather than relying on inference.

---

Nitpick comments:
In `@packages/clerk-js/src/core/resources/BillingCreditLedger.ts`:
- Around line 7-35: BillingCreditLedger is inheriting BaseResource without using
any BaseResource behavior, so simplify it for consistency with
BillingCreditBalance. Update the BillingCreditLedger class to be a plain class
that still implements BillingCreditLedgerResource, and keep the existing
constructor/fromJSON data-mapping logic intact. If there is no current or
planned use of BaseResource helpers in BillingCreditLedger, remove the
inheritance so the class is self-contained.

In `@packages/shared/src/types/billing.ts`:
- Around line 960-969: Add the missing `@experimental` JSDoc block to
GetCreditBalanceParams so it matches GetCreditHistoryParams and stays consistent
with the other reference-facing billing types. Update the GetCreditBalanceParams
type definition in billing.ts to include the same experimental notice alongside
its existing property docs, without changing the shape of the type.
- Around line 985-996: Document the fields on BillingCreditLedgerResource with
per-property JSDoc so the generated Clerk reference docs have clear descriptions
for id, payerId, amount, currency, sourceType, sourceId, and createdAt. Use the
BillingSubscriptionResource and BillingCreditBalanceResource typings as the
style reference, and add a note near amount/currency that these are raw values
here rather than a BillingMoneyAmount to avoid misuse in downstream formatting.
Keep the comments aligned with the BillingCreditLedgerResource interface so the
Docs team can review the updated public API wording.
- Around line 86-98: Add `@returns` JSDoc entries to the BillingNamespace methods
getCreditBalance and getCreditHistory in billing.ts so they match the rest of
the namespace docs. Keep the existing experimental notes, and document the
return shapes for BillingCreditBalanceResource and
ClerkPaginatedResponse<BillingCreditLedgerResource> in the same JSDoc blocks so
the generated reference docs include them consistently.

In `@packages/ui/src/contexts/components/Plans.tsx`:
- Around line 98-114: Add explicit return type annotations to the exported hooks
in Plans.tsx. `useCreditBalance` and `useCreditHistory` are public APIs, so
update their signatures to return the appropriate underlying result types
instead of relying on inference. Use the existing symbols `useCreditBalance`,
`useCreditHistory`, `__experimental_useCreditBalance`, and
`__internal_useCreditHistoryQuery` to match the hook result types already
returned.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 2e63fbf1-9fc8-4594-b074-906d797443be

📥 Commits

Reviewing files that changed from the base of the PR and between 8024cac and e050888.

📒 Files selected for processing (23)
  • packages/clerk-js/bundlewatch.config.json
  • packages/clerk-js/src/core/modules/billing/namespace.ts
  • packages/clerk-js/src/core/resources/BillingCreditBalance.ts
  • packages/clerk-js/src/core/resources/BillingCreditLedger.ts
  • packages/clerk-js/src/core/resources/BillingSubscription.ts
  • packages/clerk-js/src/core/resources/internal.ts
  • packages/localizations/src/en-US.ts
  • packages/shared/src/react/hooks/index.ts
  • packages/shared/src/react/hooks/useCreditBalance.tsx
  • packages/shared/src/react/hooks/useCreditHistory.tsx
  • packages/shared/src/react/stable-keys.ts
  • packages/shared/src/types/billing.ts
  • packages/shared/src/types/elementIds.ts
  • packages/shared/src/types/json.ts
  • packages/shared/src/types/localization.ts
  • packages/ui/src/components/AccountCredits/AccountCredits.tsx
  • packages/ui/src/components/AccountCredits/CreditHistoryPage.tsx
  • packages/ui/src/components/AccountCredits/index.ts
  • packages/ui/src/components/OrganizationProfile/OrganizationBillingPage.tsx
  • packages/ui/src/components/OrganizationProfile/OrganizationProfileRoutes.tsx
  • packages/ui/src/components/UserProfile/BillingPage.tsx
  • packages/ui/src/components/UserProfile/UserProfileRoutes.tsx
  • packages/ui/src/contexts/components/Plans.tsx

Comment thread packages/clerk-js/src/core/resources/BillingSubscription.ts
Comment thread packages/ui/src/components/AccountCredits/CreditHistoryPage.tsx Outdated
'@clerk/ui': minor
---

Display the C2s Account Credits in the user/org profile.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💭 Maybe we should mention Billing somewhere here

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

also keep in mind that "C2" is an internal term, and likely not recognizable to our end users

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants