Skip to content

Make protocol TypeScript declarations emittable in isolation - #962

Open
kiftio wants to merge 2 commits into
mainfrom
dk/protocol-isolated-declarations
Open

kiftio wants to merge 2 commits into
mainfrom
dk/protocol-isolated-declarations

Conversation

@kiftio

@kiftio kiftio commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

What changes are you making?

Enable isolatedDeclarations for protocol/languages/typescript, so every exported value has a type that can be emitted file-by-file without cross-file inference. tsc --isolatedDeclarations reported five sites; this fixes them at the source:

  • Generated catalog (generate_typescript_notifications.mjs): checkoutProtocolCatalogPayloadDecoders, notificationDescriptors and requestDescriptors get explicit named types (CheckoutProtocolCatalogPayloadDecoders, NotificationDescriptors, RequestDescriptors) in place of satisfies. The types are the same mapped types that were previously used for satisfies; the three new aliases are additive exports.
  • EmbeddedCheckoutProtocol: explicit annotation using typeof queries instead of as const inference over shorthand properties.
  • tsconfig: isolatedDeclarations: true (+ declaration: true, which it requires), so pnpm typecheck enforces this going forward.
  • Codegen: the declaration-emit tsc call passes --isolatedDeclarations too, so regenerated .d.ts stay compliant.

The committed .d.ts files are regenerated: ProtocolNotifications.d.ts is 43 lines shorter (named mapped types instead of expanded object types) and embedded_checkout_protocol.d.ts uses typeof. Structurally identical: Checkout Kit Web's rolled-up dist/index.d.ts is byte-for-byte unchanged before and after, because API Extractor resolves the named types to the same shapes it produced before.

Why: this is the protocol-side half of the path recorded in #958. Four of the six config workarounds the rolldown-plugin-dts spike needed (generator: 'tsc', resolver: 'tsc', eager, isolatedDeclarations: false) existed only because the protocol package couldn't be emitted in isolation. With this in, a future swap to rolldown-plugin-dts needs essentially no workarounds — and the change is worth having regardless: isolated declarations make the package's types explicit and its declaration emit parallelisable. It doesn't do the swap; that remains a separate decision.

Stacked on #961 (Vite 8.3) so the eventual swap has both prerequisites in place.

How to test

cd protocol/languages/typescript && pnpm typecheck      # isolatedDeclarations on
cd protocol && pnpm test                                 # 88 tests incl. the generator
cd platforms/web && pnpm lint && pnpm test && pnpm build && pnpm verify && pnpm compare-snapshot
diff <(git show HEAD~1:… dist/index.d.ts) dist/index.d.ts   # empty

Validated: protocol typecheck with isolated declarations, 88 protocol tests, web lint / 337 unit / build / 9 built-package tests / snapshot, and the web index.d.ts diff is empty.


Before you merge

Important

  • I've added tests to support my implementation (covered by isolatedDeclarations enforcement in typecheck and existing suites)
  • I have read and agree with the Contribution Guidelines
  • I have read and agree with the Code of Conduct
  • I've updated the relevant platform README (not applicable)

kiftio added 2 commits October 9, 2026 10:38
Vite 8.0 -> 8.3.4 (rolldown 1.0 -> 1.2). Build output is unchanged in
shape: declarations are byte-identical, including the tag-name
augmentation, and runtime JS moves by +42 B net (-52 B index.js,
+94 B component chunk) from rolldown codegen changes.

Also address Vite's forward-compatibility warning for the future native
config loader: import package.json with a JSON import attribute and the
tag-name-map helper with its file extension.
Enable isolatedDeclarations for the protocol TypeScript package so every
exported value carries a type that can be emitted without type inference
across files:

- The generated catalog (`checkoutProtocolCatalogPayloadDecoders`,
  `notificationDescriptors`, `requestDescriptors`) now has explicit named
  types instead of `satisfies`. The three new type aliases are additive.
- `EmbeddedCheckoutProtocol` is annotated with `typeof` queries instead of
  relying on `as const` inference over shorthand properties.
- Codegen passes --isolatedDeclarations to the declaration emit so the
  committed .d.ts files stay compliant.

The committed declarations are shorter (named mapped types rather than
expanded object types) but structurally identical: Checkout Kit Web's
rolled-up dist/index.d.ts is byte-for-byte unchanged.

This removes the protocol-package reasons that rolldown-plugin-dts needed
tsc-mode workarounds for in the #958 spike.
@kiftio
kiftio requested a review from a team as a code owner October 9, 2026 09:43
@github-actions github-actions Bot added the #gsd:50662 Rebase Checkout Kit on UCP label Oct 9, 2026
@github-actions

github-actions Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Bundle Size Budgets

Budget Size Limits Result
Web JavaScript (uncompressed) 35.58 KiB (0 B) 35 KiB soft / 50 KiB hard ➖ Above budget; no increase
React Native npm package (gzip) 119.12 KiB (-513 B) 130 KiB soft / 150 KiB hard ✅ Within budget
Android AAR package (ZIP) 408.54 KiB (0 B) 450 KiB soft / 500 KiB hard ✅ Within budget

Bundle and package size

Web bundle sizes cover shipped runtime JavaScript. Package sizes cover the full published archive, including any source maps, declarations, and documentation it contains.

Platform Measurement Compression Base Head Delta
Web JavaScript bundle Uncompressed 35.6 KiB 35.6 KiB 0 B
Web JavaScript bundle gzip 11.1 KiB 11.1 KiB 0 B
Web npm package (.tgz) gzip 99.1 KiB 99.2 KiB +139 B
React Native npm package (.tgz) gzip 119.6 KiB 119.1 KiB -513 B
Android Library package (.aar) ZIP 408.5 KiB 408.5 KiB 0 B
Web package files (uncompressed)

These are uncompressed file sizes; they do not sum to the compressed package size above.

File Base Head Delta
dist/chunks/shopify-checkout.js.map 264.3 KiB 264.9 KiB +572 B
dist/custom-elements.json 54.7 KiB 54.7 KiB 0 B
dist/index.d.ts 49.5 KiB 49.5 KiB 0 B
dist/chunks/shopify-checkout.js 35.2 KiB 35.2 KiB 0 B
README.md 24.5 KiB 24.5 KiB 0 B
package.json 3.9 KiB 3.9 KiB 0 B
LICENSE 1.1 KiB 1.1 KiB 0 B
dist/shopify-checkout.js.map 850 B 850 B 0 B
dist/index.js 255 B 255 B 0 B
dist/shopify-checkout.js 156 B 156 B 0 B
dist/shopify-checkout.d.ts 33 B 33 B 0 B
React Native package files (uncompressed)

These are uncompressed file sizes; they do not sum to the compressed package size above.

File Base Head Delta
node_modules/@shopify/checkout-kit-protocol/src/generated/Models.ts 108.7 KiB 108.7 KiB 0 B
node_modules/@shopify/checkout-kit-protocol/src/generated/Models.d.ts 73.1 KiB 73.1 KiB 0 B
android/src/main/java/com/shopify/reactnative/checkoutkit/ShopifyCheckoutKitModule.java 16.2 KiB 16.2 KiB 0 B
ios/ShopifyCheckoutKit.swift 16.1 KiB 16.1 KiB 0 B
ios/AcceleratedCheckoutButtons.swift 14.1 KiB 14.1 KiB 0 B
src/components/AcceleratedCheckoutButtons.tsx 13.0 KiB 13.0 KiB 0 B
src/index.ts 12.7 KiB 12.7 KiB 0 B
lib/commonjs/index.js 12.4 KiB 12.4 KiB 0 B
lib/commonjs/components/AcceleratedCheckoutButtons.js 11.4 KiB 11.4 KiB 0 B
src/index.d.ts 11.3 KiB 11.3 KiB 0 B
lib/commonjs/components/AcceleratedCheckoutButtons.js.map 10.4 KiB 10.4 KiB 0 B
lib/module/index.js 10.4 KiB 10.4 KiB 0 B
lib/module/components/AcceleratedCheckoutButtons.js 10.2 KiB 10.2 KiB 0 B
node_modules/@shopify/checkout-kit-protocol/src/generated/ProtocolNotifications.ts 9.5 KiB 9.6 KiB +185 B
lib/module/components/AcceleratedCheckoutButtons.js.map 9.1 KiB 9.1 KiB 0 B
lib/module/index.js.map 8.1 KiB 8.1 KiB 0 B
src/present-dispatcher.ts 8.0 KiB 8.0 KiB 0 B
lib/commonjs/index.js.map 7.9 KiB 7.9 KiB 0 B
node_modules/@shopify/checkout-kit-protocol/src/generated/ProtocolRenameMap.ts 7.8 KiB 7.8 KiB 0 B
node_modules/@shopify/checkout-kit-protocol/src/generated/ProtocolNotifications.d.ts 7.6 KiB 5.7 KiB -1.9 KiB
…and 117 smaller files
Android package files (uncompressed)

These are uncompressed file sizes; they do not sum to the compressed package size above.

File Base Head Delta
classes.jar 435.2 KiB 435.2 KiB 0 B
res/layout/checkout_view_content.xml 2.6 KiB 2.6 KiB 0 B
res/layout/checkout_sheet_content.xml 2.0 KiB 2.0 KiB 0 B
res/values/values.xml 1.3 KiB 1.3 KiB 0 B
R.txt 1.2 KiB 1.2 KiB 0 B
AndroidManifest.xml 922 B 922 B 0 B
proguard.txt 798 B 798 B 0 B
res/drawable/close.xml 431 B 431 B 0 B
res/menu/checkout_menu.xml 354 B 354 B 0 B
META-INF/com/android/build/gradle/aar-metadata.properties 157 B 157 B 0 B
How sizes are measured

Measured from the PR base SHA and PR head SHA. Web bundle rows sum shipped .js, .mjs, and .cjs files under dist/, excluding source maps and declarations. The gzip bundle size sums files compressed individually with gzip -n -9. npm package sizes are gzip-compressed .tgz archives; Android AAR sizes are ZIP archives. Package sizes are not final app binary sizes.

@kiftio
kiftio added this pull request to stack #963 October 9, 2026 09:51
@github-actions

github-actions Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Coverage Report

Status Platform / target Lines Branches Functions Report
✅ Web 98.3% 86.86% 97.22% Full report
✅ React Native 91.49% 87.3% 100% Full report
✅ Embedded Checkout Protocol (TS) 94.05% 89.17% 90.91% Full report

@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown

Protocol — Coverage Report

Lines Statements Branches Functions
Coverage: 94%
93.49% (158/169) 89.16% (107/120) 90.9% (30/33)

@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown

React Native — Coverage Report

Lines Statements Branches Functions
Coverage: 91%
90.97% (363/399) 87.29% (213/244) 100% (92/92)

@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown

Web — Coverage Report

Lines Statements Branches Functions
Coverage: 98%
95.62% (437/457) 86.86% (238/274) 97.22% (105/108)

@bitrise

bitrise Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Bitrise builds

E2E · iOS CI

Install this build

Open Tophat, select your target device, then click Install. Links open on the Mac running Tophat.

SDK Install
React Native Install with Tophat
Swift Install with Tophat
Kotlin Install with Tophat

Checkout Kit E2E results

Status Tags Target Platform OS version tag Device
✅ launch, checkout-presentation, checkout-completion, buyer-identity react-native ios latest iPhone 15
iOS 27 Beta
✅ launch, checkout-presentation, checkout-completion, buyer-identity react-native android latest Google Pixel 9
Android 17.0
✅ launch, checkout-presentation, checkout-completion, buyer-identity, preload kotlin android latest Google Pixel 9
Android 17.0
❌ launch, checkout-presentation, checkout-completion, buyer-identity, preload swift ios latest iPhone 15
iOS 27 Beta

Failures

Caution

If you believe an assertion is flaky, please raise a ticket in the #checkout-kit-devs channel so it can be addressed.

BrowserStack artifacts require BrowserStack access. Sign in to BrowserStack App Automate before opening artifact links.

iOS — swift

RuntimeError: BrowserStack build timed out: f1b90dd48099bd86bc9fcc3107ef30d7a6c7d186

Test Status Artifacts
— ❌ BrowserStack

Base automatically changed from dk/vite-8-3 to main October 9, 2026 10:26
@kiftio
kiftio force-pushed the dk/protocol-isolated-declarations branch from 80a4a86 to 1bc6ad1 Compare October 9, 2026 10:26
kiftio added a commit that referenced this pull request Oct 9, 2026
Replace vite-plugin-dts (API Extractor) with rolldown-plugin-dts, which
keeps `declare global` augmentations in the bundled declarations
(microsoft/rushstack#1709). The tag-name collection workaround from #958
(scripts/tag-name-map.ts and its tests) is deleted.

The HTMLElementTagNameMap entry moves from register.ts to the class module
it describes: both the package root and the component entry import that
module, so either import types <shopify-checkout>, and the component entry
declaration stays a shim onto the root as before. The custom-elements
manifest is unchanged.

With #961 (Vite 8.3, Rolldown >= 1.2) and #962 (protocol declarations
emittable in isolation), the plugin runs on its default isolated-
declarations generator with two config lines: an oxc exclude for emitted
declarations and `sideEffects: true`. No tsc-mode workarounds remain.

Output: one rolled-up dist/index.d.ts with the same 26 exports as before,
the protocol package still inlined, no external imports. Package file set
is unchanged. The full web build is ~0.8 s end to end.
@kiftio
kiftio force-pushed the dk/protocol-isolated-declarations branch from 1bc6ad1 to 80a4a86 Compare October 9, 2026 10:47
kiftio added a commit that referenced this pull request Oct 9, 2026
Replace vite-plugin-dts (API Extractor) with rolldown-plugin-dts, which
keeps `declare global` augmentations in the bundled declarations
(microsoft/rushstack#1709). The tag-name collection workaround from #958
(scripts/tag-name-map.ts and its tests) is deleted.

The HTMLElementTagNameMap entry moves from register.ts to the class module
it describes: both the package root and the component entry import that
module, so either import types <shopify-checkout>, and the component entry
declaration stays a shim onto the root as before. The custom-elements
manifest is unchanged.

With #961 (Vite 8.3, Rolldown >= 1.2) and #962 (protocol declarations
emittable in isolation), the plugin runs on its default isolated-
declarations generator with two config lines: an oxc exclude for emitted
declarations and `sideEffects: true`. No tsc-mode workarounds remain.

Output: one rolled-up dist/index.d.ts with the same 26 exports as before,
the protocol package still inlined, no external imports. Package file set
is unchanged. The full web build is ~0.8 s end to end.

This branch has not been deployed

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

Labels

#gsd:50662 Rebase Checkout Kit on UCP

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant