Skip to content

feat(js): support new checkout totals shape#8727

Open
mauricioabreu wants to merge 2 commits into
feat/per-seat-costsfrom
mauricio-antunes/bill-1791-aio-update-to-use-new-totals-shape
Open

feat(js): support new checkout totals shape#8727
mauricioabreu wants to merge 2 commits into
feat/per-seat-costsfrom
mauricio-antunes/bill-1791-aio-update-to-use-new-totals-shape

Conversation

@mauricioabreu
Copy link
Copy Markdown
Contributor

Add discounts (prorated seat discount + total), totals_due_per_period (full recurring renewal breakdown), total_due_per_period, and top-level base_fee to checkout totals. The top-level totals now reflect only what is actively being purchased, while totals_due_per_period conveys the recurring charge. Parse the new fields and surface the prorated discount and renewal totals in the checkout form

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:

@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 2, 2026

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 3, 2026 12:01am

Request Review

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Jun 2, 2026

🦋 Changeset detected

Latest commit: a81cd41

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

This PR includes changesets to release 20 packages
Name Type
@clerk/clerk-js Patch
@clerk/shared Patch
@clerk/ui Patch
@clerk/localizations Patch
@clerk/msw Patch
@clerk/chrome-extension Patch
@clerk/expo Patch
@clerk/astro Patch
@clerk/backend Patch
@clerk/expo-passkeys Patch
@clerk/express Patch
@clerk/fastify Patch
@clerk/hono Patch
@clerk/nextjs Patch
@clerk/nuxt Patch
@clerk/react-router Patch
@clerk/react Patch
@clerk/tanstack-react-start Patch
@clerk/testing Patch
@clerk/vue 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

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Jun 2, 2026

Open in StackBlitz

@clerk/astro

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

@clerk/backend

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

@clerk/chrome-extension

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

@clerk/clerk-js

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

@clerk/expo

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

@clerk/expo-passkeys

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

@clerk/express

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

@clerk/fastify

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

@clerk/hono

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

@clerk/localizations

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

@clerk/nextjs

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

@clerk/nuxt

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

@clerk/react

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

@clerk/react-router

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

@clerk/shared

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

@clerk/tanstack-react-start

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

@clerk/testing

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

@clerk/ui

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

@clerk/upgrade

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

@clerk/vue

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

commit: f2c6a7a

@mauricioabreu mauricioabreu force-pushed the mauricio-antunes/bill-1791-aio-update-to-use-new-totals-shape branch from a8cef20 to 34342c8 Compare June 2, 2026 19:01
@mauricioabreu mauricioabreu force-pushed the mauricio-antunes/bill-1791-aio-update-to-use-new-totals-shape branch from 34342c8 to b8a9cd6 Compare June 2, 2026 19:26
@mauricioabreu mauricioabreu marked this pull request as ready for review June 2, 2026 20:28
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 2, 2026

API Changes Report

Generated by Break Check on 2026-06-02T20:56:21.786Z

Summary

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

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

Note
Break Check could not snapshot 3 subpaths; the diff below excludes them.

  • @clerk/astro ./env: Internal Error: Unable to determine module for: /home/runner/_work/javascript/javascript/packages/astro/env.d.ts You have encountered a software defect. Please consider reporting the issue to the maintainers of this application.
  • @clerk/shared ./cookie: Internal Error: Unable to follow symbol for "Cookies" You have encountered a software defect. Please consider reporting the issue to the maintainers of this application.
  • @clerk/testing ./cypress: Symbol not found for identifier: Cypress

@clerk/shared

Current version: 4.14.0
Recommended bump: MINOR → 4.15.0

Subpath ./types

🟡 Non-breaking Changes (1)

Modified: __internal_LocalizationResource
// ... 134 unchanged lines elided ...
      viewPayment: LocalizationValue;
      availableFeatures: LocalizationValue;
      subtotal: LocalizationValue;
+     subtotalRenewal: LocalizationValue;
      credit: LocalizationValue;
      prorationCredit: LocalizationValue;
      accountCredit: LocalizationValue;
      creditRemainder: LocalizationValue;
      payerCreditRemainder: LocalizationValue;
+     proratedDiscount: LocalizationValue;
      totalDue: LocalizationValue;
      totalDueToday: LocalizationValue;
+     totalDuePerPeriod: LocalizationValue;
      pastDue: LocalizationValue;
      pay: LocalizationValue<'amount'>;
      cancelSubscriptionTitle: LocalizationValue<'plan'>;
// ... 1760 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) (92%): The only differences between before and after are additions of new optional fields inside the billing sub-object (subtotalRenewal, proratedDiscount, totalDuePerPeriod); no existing fields were removed, renamed, or had their types narrowed, so existing consumers providing a partial localization object are unaffected.

🟢 Additions (36)

Click to expand 36 changes
Added: BillingCheckoutDiscounts
+ interface BillingCheckoutDiscounts

Added interface BillingCheckoutDiscounts

Added: BillingCheckoutDiscounts.proration
+ proration: BillingProrationDiscountDetail | null;

Added property BillingCheckoutDiscounts.proration

Added: BillingCheckoutDiscounts.total
+ total: BillingMoneyAmount;

Added property BillingCheckoutDiscounts.total

Added: BillingCheckoutDiscountsJSON
+ interface BillingCheckoutDiscountsJSON

Added interface BillingCheckoutDiscountsJSON

Added: BillingCheckoutDiscountsJSON.proration
+ proration: BillingProrationDiscountDetailJSON | null;

Added property BillingCheckoutDiscountsJSON.proration

Added: BillingCheckoutDiscountsJSON.total
+ total: BillingMoneyAmountJSON;

Added property BillingCheckoutDiscountsJSON.total

Added: BillingCheckoutTotals.baseFee
+ baseFee?: BillingMoneyAmount;

Added property BillingCheckoutTotals.baseFee

Added: BillingCheckoutTotals.discounts
+ discounts?: BillingCheckoutDiscounts | null;

Added property BillingCheckoutTotals.discounts

Added: BillingCheckoutTotals.totalDuePerPeriod
+ totalDuePerPeriod?: BillingMoneyAmount;

Added property BillingCheckoutTotals.totalDuePerPeriod

Added: BillingCheckoutTotals.totalsDuePerPeriod
+ totalsDuePerPeriod?: BillingPerPeriodTotals;

Added property BillingCheckoutTotals.totalsDuePerPeriod

Added: BillingCheckoutTotalsJSON.base_fee
+ base_fee: BillingMoneyAmountJSON;

Added property BillingCheckoutTotalsJSON.base_fee

Added: BillingCheckoutTotalsJSON.discounts
+ discounts: BillingCheckoutDiscountsJSON | null;

Added property BillingCheckoutTotalsJSON.discounts

Added: BillingCheckoutTotalsJSON.total_due_per_period
+ total_due_per_period: BillingMoneyAmountJSON;

Added property BillingCheckoutTotalsJSON.total_due_per_period

Added: BillingCheckoutTotalsJSON.totals_due_per_period
+ totals_due_per_period: BillingPerPeriodTotalsJSON;

Added property BillingCheckoutTotalsJSON.totals_due_per_period

Added: BillingPerPeriodTotals
+ interface BillingPerPeriodTotals

Added interface BillingPerPeriodTotals

Added: BillingPerPeriodTotals.baseFee
+ baseFee: BillingMoneyAmount;

Added property BillingPerPeriodTotals.baseFee

Added: BillingPerPeriodTotals.grandTotal
+ grandTotal: BillingMoneyAmount;

Added property BillingPerPeriodTotals.grandTotal

Added: BillingPerPeriodTotals.perUnitTotals
+ perUnitTotals?: BillingPerUnitTotal[];

Added property BillingPerPeriodTotals.perUnitTotals

Added: BillingPerPeriodTotals.subtotal
+ subtotal: BillingMoneyAmount;

Added property BillingPerPeriodTotals.subtotal

Added: BillingPerPeriodTotals.taxTotal
+ taxTotal: BillingMoneyAmount;

Added property BillingPerPeriodTotals.taxTotal

Added: BillingPerPeriodTotalsJSON
+ interface BillingPerPeriodTotalsJSON

Added interface BillingPerPeriodTotalsJSON

Added: BillingPerPeriodTotalsJSON.base_fee
+ base_fee: BillingMoneyAmountJSON;

Added property BillingPerPeriodTotalsJSON.base_fee

Added: BillingPerPeriodTotalsJSON.grand_total
+ grand_total: BillingMoneyAmountJSON;

Added property BillingPerPeriodTotalsJSON.grand_total

Added: BillingPerPeriodTotalsJSON.per_unit_totals
+ per_unit_totals?: BillingPerUnitTotalJSON[];

Added property BillingPerPeriodTotalsJSON.per_unit_totals

Added: BillingPerPeriodTotalsJSON.subtotal
+ subtotal: BillingMoneyAmountJSON;

Added property BillingPerPeriodTotalsJSON.subtotal

Added: BillingPerPeriodTotalsJSON.tax_total
+ tax_total: BillingMoneyAmountJSON;

Added property BillingPerPeriodTotalsJSON.tax_total

Added: BillingProrationDiscountDetail
+ interface BillingProrationDiscountDetail

Added interface BillingProrationDiscountDetail

Added: BillingProrationDiscountDetail.amount
+ amount: BillingMoneyAmount;

Added property BillingProrationDiscountDetail.amount

Added: BillingProrationDiscountDetail.cycleDaysPassed
+ cycleDaysPassed: number;

Added property BillingProrationDiscountDetail.cycleDaysPassed

Added: BillingProrationDiscountDetail.cycleDaysTotal
+ cycleDaysTotal: number;

Added property BillingProrationDiscountDetail.cycleDaysTotal

Added: BillingProrationDiscountDetail.cyclePassedPercent
+ cyclePassedPercent: number;

Added property BillingProrationDiscountDetail.cyclePassedPercent

Added: BillingProrationDiscountDetailJSON
+ interface BillingProrationDiscountDetailJSON

Added interface BillingProrationDiscountDetailJSON

Added: BillingProrationDiscountDetailJSON.amount
+ amount: BillingMoneyAmountJSON;

Added property BillingProrationDiscountDetailJSON.amount

Added: BillingProrationDiscountDetailJSON.cycle_days_passed
+ cycle_days_passed: number;

Added property BillingProrationDiscountDetailJSON.cycle_days_passed

Added: BillingProrationDiscountDetailJSON.cycle_days_total
+ cycle_days_total: number;

Added property BillingProrationDiscountDetailJSON.cycle_days_total

Added: BillingProrationDiscountDetailJSON.cycle_passed_percent
+ cycle_passed_percent: number;

Added property BillingProrationDiscountDetailJSON.cycle_passed_percent


Report generated by Break Check

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 2, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR extends the billing checkout data model with new pricing breakdown information. It introduces types for prorated discount details and per-period renewal totals in both JSON DTO and runtime contracts, adds parsing logic to convert backend JSON to runtime objects, updates mock data generation to populate the new fields, and extends the CheckoutForm UI to render prorated discounts and renewal period summaries. Localization keys are added for the new UI elements. The changeset documents version updates across multiple Clerk packages.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'feat(js): support new checkout totals shape' is clear and directly describes the main objective of the changeset.
Description check ✅ Passed The PR description is fully related to the changeset, detailing the new fields added to checkout totals and how they are parsed and surfaced in the checkout form.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.

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


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

Copy link
Copy Markdown
Contributor

@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: 1

🧹 Nitpick comments (1)
packages/clerk-js/src/utils/billing.ts (1)

59-128: ⚡ Quick win

Consider adding tests to cover the new parsing logic.

This PR introduces new converter functions and extends existing ones to handle additional billing fields. According to the repository guidelines, tests should be added to ensure the JSON-to-runtime conversions work correctly for all the new fields: discounts, totalDuePerPeriod, totalsDuePerPeriod, and baseFee.

As per coding guidelines: "If there are no tests added or modified as part of the PR, please suggest that tests be added to cover the changes."

🤖 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/utils/billing.ts` around lines 59 - 128, The PR added
new parsing logic (fields discounts, totalDuePerPeriod, totalsDuePerPeriod,
baseFee) in billingTotalsFromJSON and new helpers billingPerPeriodTotalsFromJSON
and billingCheckoutDiscountsFromJSON but no tests were added; add unit tests
that exercise these converters by providing representative JSON inputs
(including present/absent/null cases) and asserting the expected runtime objects
for billingTotalsFromJSON, billingPerPeriodTotalsFromJSON and
billingCheckoutDiscountsFromJSON (cover base_fee, discounts,
total_due_per_period, totals_due_per_period, and null/undefined branches) so the
new parsing paths are validated.
🤖 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/ui/src/components/Checkout/CheckoutForm.tsx`:
- Around line 42-44: Add tests in the Checkout.test.tsx for the CheckoutForm
component covering the two new conditionals: showProratedDiscount and
showRenewalTotals. For showProratedDiscount (derived from
totals.discounts.proration.amount.amount) add one test where you pass totals
with a positive proration amount and assert the prorated-discount row renders,
and another where amount is zero/undefined and assert it does not render (use
the same label/text used in CheckoutForm to query). For showRenewalTotals
(derived from totals.totalsDuePerPeriod) add tests that pass
totals.totalsDuePerPeriod with differing grandTotal vs totalDueNow to assert the
“Renewal” subtotal + per-period total render when true and do not render when
false. Also add a small assertion to verify the borderTop styling applied to the
Renewal rows (e.g., check the className or inline style on the rendered rows) to
confirm the UI nit mentioned in the review.

---

Nitpick comments:
In `@packages/clerk-js/src/utils/billing.ts`:
- Around line 59-128: The PR added new parsing logic (fields discounts,
totalDuePerPeriod, totalsDuePerPeriod, baseFee) in billingTotalsFromJSON and new
helpers billingPerPeriodTotalsFromJSON and billingCheckoutDiscountsFromJSON but
no tests were added; add unit tests that exercise these converters by providing
representative JSON inputs (including present/absent/null cases) and asserting
the expected runtime objects for billingTotalsFromJSON,
billingPerPeriodTotalsFromJSON and billingCheckoutDiscountsFromJSON (cover
base_fee, discounts, total_due_per_period, totals_due_per_period, and
null/undefined branches) so the new parsing paths are validated.
🪄 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), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 77314e33-076e-4e82-8895-07732c07f6f9

📥 Commits

Reviewing files that changed from the base of the PR and between c2ba134 and b8a9cd6.

📒 Files selected for processing (8)
  • .changeset/checkout-totals-new-shape.md
  • packages/clerk-js/src/utils/billing.ts
  • packages/localizations/src/en-US.ts
  • packages/msw/BillingService.ts
  • packages/shared/src/types/billing.ts
  • packages/shared/src/types/json.ts
  • packages/shared/src/types/localization.ts
  • packages/ui/src/components/Checkout/CheckoutForm.tsx

Comment thread packages/ui/src/components/Checkout/CheckoutForm.tsx
@mauricioabreu mauricioabreu force-pushed the mauricio-antunes/bill-1791-aio-update-to-use-new-totals-shape branch from b8a9cd6 to 896b6b9 Compare June 2, 2026 20:44
@mauricioabreu mauricioabreu force-pushed the mauricio-antunes/bill-1791-aio-update-to-use-new-totals-shape branch from 896b6b9 to f2c6a7a Compare June 2, 2026 20:51
@mauricioabreu mauricioabreu requested a review from a team June 2, 2026 20:53
Copy link
Copy Markdown
Contributor

@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.

🧹 Nitpick comments (1)
.changeset/checkout-totals-new-shape.md (1)

11-14: ⚡ Quick win

Consider varying sentence structure for readability.

Three consecutive bullet points begin with "Add", which can make the changelog slightly repetitive. Consider rephrasing for variety, e.g., "Introduces discounts...", "Exposes totalsDuePerPeriod...", "Includes baseFee...".

🤖 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 @.changeset/checkout-totals-new-shape.md around lines 11 - 14, The changelog
uses three consecutive bullets that all start with "Add", making it repetitive;
update the entries for BillingCheckoutTotals / BillingCheckoutTotalsJSON
(mentions discounts and BillingProrationDiscountDetail), totalsDuePerPeriod /
totals_due_per_period (BillingPerPeriodTotals), totalDuePerPeriod /
total_due_per_period, and baseFee / base_fee to vary sentence starters — e.g.,
change one or more "Add" lines to "Introduce", "Expose", or "Include" while
preserving the same symbol names and descriptions (proration details, per-period
totals structure, backwards-compatible totalDuePerPeriod, and top-level
baseFee).
🤖 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.

Nitpick comments:
In @.changeset/checkout-totals-new-shape.md:
- Around line 11-14: The changelog uses three consecutive bullets that all start
with "Add", making it repetitive; update the entries for BillingCheckoutTotals /
BillingCheckoutTotalsJSON (mentions discounts and
BillingProrationDiscountDetail), totalsDuePerPeriod / totals_due_per_period
(BillingPerPeriodTotals), totalDuePerPeriod / total_due_per_period, and baseFee
/ base_fee to vary sentence starters — e.g., change one or more "Add" lines to
"Introduce", "Expose", or "Include" while preserving the same symbol names and
descriptions (proration details, per-period totals structure,
backwards-compatible totalDuePerPeriod, and top-level baseFee).

ℹ️ Review info
⚙️ Run configuration

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

Review profile: CHILL

Plan: Pro

Run ID: cfc05e67-6c43-41c2-bd9f-dcbfdd3485b4

📥 Commits

Reviewing files that changed from the base of the PR and between 896b6b9 and f2c6a7a.

📒 Files selected for processing (9)
  • .changeset/checkout-totals-new-shape.md
  • packages/clerk-js/src/utils/billing.ts
  • packages/localizations/src/en-US.ts
  • packages/msw/BillingService.ts
  • packages/shared/src/types/billing.ts
  • packages/shared/src/types/json.ts
  • packages/shared/src/types/localization.ts
  • packages/ui/src/components/Checkout/CheckoutForm.tsx
  • packages/ui/src/components/Checkout/__tests__/Checkout.test.tsx
✅ Files skipped from review due to trivial changes (1)
  • packages/localizations/src/en-US.ts
🚧 Files skipped from review as they are similar to previous changes (7)
  • packages/shared/src/types/billing.ts
  • packages/ui/src/components/Checkout/CheckoutForm.tsx
  • packages/clerk-js/src/utils/billing.ts
  • packages/msw/BillingService.ts
  • packages/shared/src/types/localization.ts
  • packages/ui/src/components/Checkout/tests/Checkout.test.tsx
  • packages/shared/src/types/json.ts

Add `discounts` (prorated seat discount + total), `totals_due_per_period`
(full recurring renewal breakdown), `total_due_per_period`, and top-level
`base_fee` to checkout totals. The top-level totals now reflect only what is
actively being purchased, while `totals_due_per_period` conveys the recurring
charge. Parse the new fields and surface the prorated discount and
renewal totals in the checkout form
@mauricioabreu mauricioabreu force-pushed the mauricio-antunes/bill-1791-aio-update-to-use-new-totals-shape branch from f2c6a7a to ca72a27 Compare June 2, 2026 23:09
@mauricioabreu mauricioabreu changed the base branch from main to feat/per-seat-costs June 2, 2026 23:10
@github-actions github-actions Bot added the react label Jun 2, 2026
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.

2 participants