From 11e442ae6e26fa3c412c0fbc550d1ddc724d9947 Mon Sep 17 00:00:00 2001 From: Kieran Osgood Date: Wed, 13 May 2026 09:52:20 +0100 Subject: [PATCH 1/8] Restore dual architecture support for 3.9 --- README.md | 11 +- __mocks__/react-native.ts | 6 + .../RNShopifyCheckoutSheetKit.podspec | 24 +++- .../checkout-sheet-kit/android/build.gradle | 21 ++- .../ShopifyCheckoutSheetKitModule.java | 18 ++- .../ShopifyCheckoutSheetKitPackage.java | 6 +- .../ios/ShopifyCheckoutSheetKit.mm | 57 ++++++++ .../ios/ShopifyCheckoutSheetKit.swift | 45 +++++++ .../@shopify/checkout-sheet-kit/package.json | 2 +- .../checkout-sheet-kit/src/context.tsx | 44 ++++--- .../checkout-sheet-kit/src/index.d.ts | 6 +- .../@shopify/checkout-sheet-kit/src/index.ts | 24 ++-- .../specs/NativeShopifyCheckoutSheetKit.ts | 42 +++++- .../checkout-sheet-kit/tests/context.test.tsx | 2 +- .../checkout-sheet-kit/tests/index.test.ts | 50 +++---- .../checkout-sheet-kit/tests/linking.test.ts | 122 +++++++++++++++--- sample/ios/Podfile.lock | 4 +- sample/src/context/Cart.tsx | 4 +- sample/src/screens/SettingsScreen.tsx | 11 +- 19 files changed, 396 insertions(+), 103 deletions(-) diff --git a/README.md b/README.md index afcd2440..50a87158 100644 --- a/README.md +++ b/README.md @@ -65,20 +65,21 @@ experiences. ## Platform Requirements -- **React Native** - Minimum version `0.76` (v4+) / `0.70` (v3 and earlier) +- **React Native** - Minimum version `0.76` (`3.9.0+`) / `0.70` (`<=3.8.x`) - **iOS** - Minimum version iOS 13 - **Android** - Minimum Java 11 & Android SDK version `23` ## Version Compatibility -Starting with **v4.0.0**, `@shopify/checkout-sheet-kit` requires the React Native -**New Architecture** (TurboModules + Fabric). Apps on the old architecture must -stay on the `v3.x` line until they migrate. +The **v3.9.x** line keeps the v3 public async API while supporting both React +Native architectures. Starting with **v4.0.0**, `@shopify/checkout-sheet-kit` +requires the React Native **New Architecture** (TurboModules + Fabric). | Package version | React Native | Architecture | | --------------- | -------------- | ------------------ | | `4.x` | `>= 0.76` | New Architecture | -| `3.x` | `>= 0.70` | Old Architecture | +| `3.9.x` | `>= 0.76` | Old + New | +| `<=3.8.x` | `>= 0.70` | Old Architecture | See the [React Native upgrade guide](https://reactnative.dev/docs/the-new-architecture/use-the-new-architecture) for help enabling the New Architecture in your app. diff --git a/__mocks__/react-native.ts b/__mocks__/react-native.ts index 3e9d71eb..6d22da6b 100644 --- a/__mocks__/react-native.ts +++ b/__mocks__/react-native.ts @@ -76,6 +76,12 @@ module.exports = { requireNativeComponent, codegenNativeComponent, TurboModuleRegistry: { + get: jest.fn((name: string) => { + if (name === 'ShopifyCheckoutSheetKit') { + return ShopifyCheckoutSheetKit; + } + return null; + }), getEnforcing: jest.fn((name: string) => { if (name === 'ShopifyCheckoutSheetKit') { return ShopifyCheckoutSheetKit; diff --git a/modules/@shopify/checkout-sheet-kit/RNShopifyCheckoutSheetKit.podspec b/modules/@shopify/checkout-sheet-kit/RNShopifyCheckoutSheetKit.podspec index 59fa16c5..5d7a7a00 100644 --- a/modules/@shopify/checkout-sheet-kit/RNShopifyCheckoutSheetKit.podspec +++ b/modules/@shopify/checkout-sheet-kit/RNShopifyCheckoutSheetKit.podspec @@ -2,6 +2,10 @@ require "json" package = JSON.parse(File.read(File.join(__dir__, "package.json"))) +folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' + +new_arch_enabled = ENV["RCT_NEW_ARCH_ENABLED"] == "1" + Pod::Spec.new do |s| s.name = "RNShopifyCheckoutSheetKit" s.version = package["version"] @@ -19,5 +23,23 @@ Pod::Spec.new do |s| s.dependency "ShopifyCheckoutSheetKit", "~> 3.8.0" s.dependency "ShopifyCheckoutSheetKit/AcceleratedCheckouts", "~> 3.8.0" - install_modules_dependencies(s) + if new_arch_enabled + if defined?(install_modules_dependencies) + install_modules_dependencies(s) + else + s.dependency "React-Codegen" + s.dependency "RCT-Folly", :modular_headers => true + s.dependency "RCTRequired" + s.dependency "RCTTypeSafety" + s.dependency "ReactCommon/turbomodule/core" + end + + s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1" + + s.pod_target_xcconfig = { + "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"", + "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1", + "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" + } + end end diff --git a/modules/@shopify/checkout-sheet-kit/android/build.gradle b/modules/@shopify/checkout-sheet-kit/android/build.gradle index dd55f324..a8650ec4 100644 --- a/modules/@shopify/checkout-sheet-kit/android/build.gradle +++ b/modules/@shopify/checkout-sheet-kit/android/build.gradle @@ -10,7 +10,20 @@ buildscript { } apply plugin: "com.android.library" -apply plugin: "com.facebook.react" + +def isNewArchitectureEnabled() { + def newArchEnabled = project.hasProperty("newArchEnabled") + ? project.property("newArchEnabled") + : rootProject.hasProperty("newArchEnabled") + ? rootProject.property("newArchEnabled") + : "false" + + return newArchEnabled.toString() == "true" +} + +if (isNewArchitectureEnabled()) { + apply plugin: "com.facebook.react" +} def getExtOrIntegerDefault(name) { return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties[name]).toInteger() @@ -37,6 +50,10 @@ android { if (supportsNamespace()) { namespace "com.shopify.reactnative.checkoutsheetkit" + buildFeatures { + buildConfig true + } + sourceSets { main { manifest.srcFile "src/main/AndroidManifestNew.xml" @@ -50,6 +67,7 @@ android { minSdkVersion getExtOrIntegerDefault("minSdkVersion") targetSdkVersion getExtOrIntegerDefault("targetSdkVersion") + buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() } buildTypes { @@ -93,4 +111,3 @@ dependencies { implementation("com.fasterxml.jackson.core:jackson-databind:2.12.5") debugImplementation("com.shopify:checkout-sheet-kit:${SHOPIFY_CHECKOUT_SDK_VERSION}") } - diff --git a/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java b/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java index 03427892..57bbaecd 100644 --- a/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java +++ b/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java @@ -27,21 +27,25 @@ of this software and associated documentation files (the "Software"), to deal import android.content.Context; import androidx.activity.ComponentActivity; import androidx.annotation.NonNull; -import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableMap; -import com.shopify.checkoutsheetkit.NativeShopifyCheckoutSheetKitSpec; +import com.facebook.react.module.annotations.ReactModule; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; import com.shopify.checkoutsheetkit.*; import java.util.HashMap; import java.util.Map; import java.util.Objects; -public class ShopifyCheckoutSheetKitModule extends NativeShopifyCheckoutSheetKitSpec { +@ReactModule(name = ShopifyCheckoutSheetKitModule.NAME) +public class ShopifyCheckoutSheetKitModule extends ReactContextBaseJavaModule implements TurboModule { + + public static final String NAME = "ShopifyCheckoutSheetKit"; public static Configuration checkoutConfig = new Configuration(); @@ -62,8 +66,14 @@ public ShopifyCheckoutSheetKitModule(ReactApplicationContext reactContext) { }); } + @NonNull + @Override + public String getName() { + return NAME; + } + @Override - protected Map getTypedExportedConstants() { + public Map getConstants() { final Map constants = new HashMap<>(); constants.put("version", ShopifyCheckoutSheetKit.version); return constants; diff --git a/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitPackage.java b/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitPackage.java index f6cda161..c97991dc 100644 --- a/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitPackage.java +++ b/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitPackage.java @@ -26,7 +26,7 @@ of this software and associated documentation files (the "Software"), to deal import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import com.facebook.react.TurboReactPackage; +import com.facebook.react.BaseReactPackage; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.module.model.ReactModuleInfo; @@ -38,7 +38,7 @@ of this software and associated documentation files (the "Software"), to deal import java.util.List; import java.util.Map; -public class ShopifyCheckoutSheetKitPackage extends TurboReactPackage { +public class ShopifyCheckoutSheetKitPackage extends BaseReactPackage { @NonNull @Override @@ -67,7 +67,7 @@ public ReactModuleInfoProvider getReactModuleInfoProvider() { false, // canOverrideExistingModule false, // needsEagerInit false, // isCxxModule - true // isTurboModule + BuildConfig.IS_NEW_ARCHITECTURE_ENABLED // isTurboModule )); return moduleInfos; }; diff --git a/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.mm b/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.mm index d93be8df..49a4ed23 100644 --- a/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.mm +++ b/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.mm @@ -24,6 +24,8 @@ of this software and associated documentation files (the "Software"), to deal #import #import + +#if RCT_NEW_ARCH_ENABLED #import // Registers the Swift module class (ShopifyCheckoutSheetKit.swift) with the RN @@ -61,6 +63,61 @@ @implementation RCTShopifyCheckoutSheetKit (TurboModule) params); } @end +#else +@interface RCT_EXTERN_MODULE (RCTShopifyCheckoutSheetKit, NSObject) + +/** + * Present checkout + */ +RCT_EXTERN_METHOD(present : (NSString*)checkoutURLString); + +/** + * Preload checkout + */ +RCT_EXTERN_METHOD(preload : (NSString*)checkoutURLString); + +/** + * Dismiss checkout + */ +RCT_EXTERN_METHOD(dismiss); + +/** + * Invalidate preload cache + */ +RCT_EXTERN_METHOD(invalidateCache); + +/** + * Set configuration for checkout + */ +RCT_EXTERN_METHOD(setConfig : (NSDictionary*)configuration); + +/** + * Return configuration for checkout + */ +RCT_EXTERN_METHOD(getConfig : (RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject); + +/** + * Configure AcceleratedCheckouts + */ +RCT_EXTERN_METHOD(configureAcceleratedCheckouts : (NSString*)storefrontDomain storefrontAccessToken : ( + NSString*)storefrontAccessToken customerEmail : (NSString*)customerEmail customerPhoneNumber : (NSString*) + customerPhoneNumber customerAccessToken : (NSString*)customerAccessToken applePayMerchantIdentifier : (NSString*) + applePayMerchantIdentifier applyPayContactFields : (NSArray*)applyPayContactFields supportedShippingCountries : (NSArray*)supportedShippingCountries resolve : ( + RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject); + +/** + * Check if accelerated checkout is available + */ +RCT_EXTERN_METHOD( + isAcceleratedCheckoutAvailable : (RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject); + +/** + * Check if Apple Pay is available + */ +RCT_EXTERN_METHOD(isApplePayAvailable : (RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject); + +@end +#endif /** * AcceleratedCheckoutButtons View Manager diff --git a/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.swift b/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.swift index e6b57522..1603d918 100644 --- a/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.swift +++ b/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.swift @@ -225,6 +225,13 @@ class RCTShopifyCheckoutSheetKit: RCTEventEmitter, CheckoutDelegate { ] } + @objc func getConfig( + _ resolve: @escaping RCTPromiseResolveBlock, + reject _: @escaping RCTPromiseRejectBlock + ) { + resolve(getConfig()) + } + @objc func configureAcceleratedCheckouts( _ storefrontDomain: String, storefrontAccessToken: String, @@ -274,6 +281,30 @@ class RCTShopifyCheckoutSheetKit: RCTEventEmitter, CheckoutDelegate { return NSNumber(value: true) } + @objc func configureAcceleratedCheckouts( + _ storefrontDomain: String, + storefrontAccessToken: String, + customerEmail: String?, + customerPhoneNumber: String?, + customerAccessToken: String?, + applePayMerchantIdentifier: String?, + applyPayContactFields: [String]?, + supportedShippingCountries: [String]?, + resolve: @escaping RCTPromiseResolveBlock, + reject _: @escaping RCTPromiseRejectBlock + ) { + resolve(configureAcceleratedCheckouts( + storefrontDomain, + storefrontAccessToken: storefrontAccessToken, + customerEmail: customerEmail, + customerPhoneNumber: customerPhoneNumber, + customerAccessToken: customerAccessToken, + applePayMerchantIdentifier: applePayMerchantIdentifier, + applyPayContactFields: applyPayContactFields, + supportedShippingCountries: supportedShippingCountries + )) + } + @objc func isAcceleratedCheckoutAvailable() -> NSNumber { guard #available(iOS 16.0, *) else { return NSNumber(value: false) @@ -282,6 +313,13 @@ class RCTShopifyCheckoutSheetKit: RCTEventEmitter, CheckoutDelegate { return NSNumber(value: AcceleratedCheckoutConfiguration.shared.available) } + @objc func isAcceleratedCheckoutAvailable( + _ resolve: @escaping RCTPromiseResolveBlock, + reject _: @escaping RCTPromiseRejectBlock + ) { + resolve(isAcceleratedCheckoutAvailable()) + } + @objc func isApplePayAvailable() -> NSNumber { guard #available(iOS 16.0, *) else { return NSNumber(value: false) @@ -292,6 +330,13 @@ class RCTShopifyCheckoutSheetKit: RCTEventEmitter, CheckoutDelegate { return NSNumber(value: available) } + @objc func isApplePayAvailable( + _ resolve: @escaping RCTPromiseResolveBlock, + reject _: @escaping RCTPromiseRejectBlock + ) { + resolve(isApplePayAvailable()) + } + @objc func initiateGeolocationRequest(_ allow: Bool) { // No-op on iOS — geolocation permission is handled natively } diff --git a/modules/@shopify/checkout-sheet-kit/package.json b/modules/@shopify/checkout-sheet-kit/package.json index c1347ba8..3280f64f 100644 --- a/modules/@shopify/checkout-sheet-kit/package.json +++ b/modules/@shopify/checkout-sheet-kit/package.json @@ -1,7 +1,7 @@ { "name": "@shopify/checkout-sheet-kit", "license": "MIT", - "version": "4.0.0", + "version": "3.9.0", "main": "lib/commonjs/index.js", "types": "src/index.ts", "source": "src/index.ts", diff --git a/modules/@shopify/checkout-sheet-kit/src/context.tsx b/modules/@shopify/checkout-sheet-kit/src/context.tsx index c3a5db4d..713c60c1 100644 --- a/modules/@shopify/checkout-sheet-kit/src/context.tsx +++ b/modules/@shopify/checkout-sheet-kit/src/context.tsx @@ -38,8 +38,8 @@ type Maybe = T | undefined; interface Context { acceleratedCheckoutsAvailable: boolean; addEventListener: AddEventListener; - getConfig: () => Configuration | undefined; - setConfig: (config: Configuration) => void; + getConfig: () => Promise; + setConfig: (config: Configuration) => Promise; removeEventListeners: RemoveEventListeners; preload: (checkoutUrl: string) => void; present: (checkoutUrl: string) => void; @@ -71,24 +71,28 @@ export function ShopifyCheckoutSheetProvider({ } useEffect(() => { - if (!instance.current || !configuration) { - return; - } - - const customer = configuration.acceleratedCheckouts?.customer; - if (customer?.accessToken && (customer?.email || customer?.phoneNumber)) { - // eslint-disable-next-line no-console - console.warn( - '[ShopifyCheckoutSheetKit] Providing accessToken with contactFields (email / phoneNumber) is deprecated and will become an error in v4.' + - 'When the user is authenticated with Customer Accounts, provide accessToken' + - 'When the user is otherwise authenticated, provide email/phoneNumber.', + async function configureCheckoutKit() { + if (!instance.current || !configuration) { + return; + } + + const customer = configuration.acceleratedCheckouts?.customer; + if (customer?.accessToken && (customer?.email || customer?.phoneNumber)) { + // eslint-disable-next-line no-console + console.warn( + '[ShopifyCheckoutSheetKit] Providing accessToken with contactFields (email / phoneNumber) is deprecated and will become an error in v4.' + + 'When the user is authenticated with Customer Accounts, provide accessToken' + + 'When the user is otherwise authenticated, provide email/phoneNumber.', + ); + } + + await instance.current.setConfig(configuration); + setAcceleratedCheckoutsAvailable( + instance.current.acceleratedCheckoutsReady, ); } - instance.current.setConfig(configuration); - setAcceleratedCheckoutsAvailable( - instance.current.acceleratedCheckoutsReady, - ); + configureCheckoutKit(); }, [configuration]); const addEventListener: AddEventListener = useCallback( @@ -122,11 +126,11 @@ export function ShopifyCheckoutSheetProvider({ instance.current?.dismiss(); }, []); - const setConfig = useCallback((config: Configuration) => { - instance.current?.setConfig(config); + const setConfig = useCallback(async (config: Configuration) => { + await instance.current?.setConfig(config); }, []); - const getConfig = useCallback(() => { + const getConfig = useCallback(async () => { return instance.current?.getConfig(); }, []); diff --git a/modules/@shopify/checkout-sheet-kit/src/index.d.ts b/modules/@shopify/checkout-sheet-kit/src/index.d.ts index 5a5d73b7..34147dad 100644 --- a/modules/@shopify/checkout-sheet-kit/src/index.d.ts +++ b/modules/@shopify/checkout-sheet-kit/src/index.d.ts @@ -325,7 +325,7 @@ export interface ShopifyCheckoutSheetKit { /** * Return the current config for the checkout. See README.md for more details. */ - getConfig(): Configuration; + getConfig(): Promise; /** * Listen for checkout events */ @@ -344,10 +344,10 @@ export interface ShopifyCheckoutSheetKit { */ configureAcceleratedCheckouts( config: AcceleratedCheckoutConfiguration, - ): boolean; + ): Promise; /** * Check if accelerated checkout is available for the given cart or product */ - isAcceleratedCheckoutAvailable(): boolean; + isAcceleratedCheckoutAvailable(): Promise; } diff --git a/modules/@shopify/checkout-sheet-kit/src/index.ts b/modules/@shopify/checkout-sheet-kit/src/index.ts index 8becbe0c..13fe173d 100644 --- a/modules/@shopify/checkout-sheet-kit/src/index.ts +++ b/modules/@shopify/checkout-sheet-kit/src/index.ts @@ -151,21 +151,23 @@ class ShopifyCheckoutSheet implements ShopifyCheckoutSheetKit { /** * Retrieves the current checkout configuration - * @returns The current Configuration + * @returns Promise containing the current Configuration */ - public getConfig(): Configuration { - return this.coerceConfigurationResult(RNShopifyCheckoutSheetKit.getConfig()); + public async getConfig(): Promise { + const config = await RNShopifyCheckoutSheetKit.getConfig(); + return this.coerceConfigurationResult(config); } /** * Updates the checkout configuration * @param configuration New configuration settings to apply */ - public setConfig(configuration: Configuration): void { + public async setConfig(configuration: Configuration): Promise { if (configuration.acceleratedCheckouts) { - this._acceleratedCheckoutsReady = this.configureAcceleratedCheckouts( - configuration.acceleratedCheckouts, - ); + this._acceleratedCheckoutsReady = + await this.configureAcceleratedCheckouts( + configuration.acceleratedCheckouts, + ); } RNShopifyCheckoutSheetKit.setConfig(configuration); } @@ -233,9 +235,9 @@ class ShopifyCheckoutSheet implements ShopifyCheckoutSheetKit { * Configure AcceleratedCheckouts for Shop Pay and Apple Pay buttons * @param config Configuration for AcceleratedCheckouts */ - public configureAcceleratedCheckouts( + public async configureAcceleratedCheckouts( config: AcceleratedCheckoutConfiguration, - ): boolean { + ): Promise { if (!this.acceleratedCheckoutsSupported) { return false; } @@ -265,9 +267,9 @@ class ShopifyCheckoutSheet implements ShopifyCheckoutSheetKit { /** * Check if accelerated checkout is available for the given cart or product - * @returns boolean indicating availability + * @returns Promise indicating availability */ - public isAcceleratedCheckoutAvailable(): boolean { + public async isAcceleratedCheckoutAvailable(): Promise { if (!this.acceleratedCheckoutsSupported) { return false; } diff --git a/modules/@shopify/checkout-sheet-kit/src/specs/NativeShopifyCheckoutSheetKit.ts b/modules/@shopify/checkout-sheet-kit/src/specs/NativeShopifyCheckoutSheetKit.ts index b2dd0fba..bc97e82f 100644 --- a/modules/@shopify/checkout-sheet-kit/src/specs/NativeShopifyCheckoutSheetKit.ts +++ b/modules/@shopify/checkout-sheet-kit/src/specs/NativeShopifyCheckoutSheetKit.ts @@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SO */ import type {TurboModule} from 'react-native'; -import {TurboModuleRegistry} from 'react-native'; +import {NativeModules, TurboModuleRegistry} from 'react-native'; type IosColorsSpec = { tintColor?: string; @@ -96,6 +96,40 @@ export interface Spec extends TurboModule { getConstants(): {version: string}; } -export default TurboModuleRegistry.getEnforcing( - 'ShopifyCheckoutSheetKit', -); +type LegacyNativeModule = Omit & { + getConstants?: () => {version: string}; + version?: string; +}; + +const LINKING_ERROR = + "The native module 'ShopifyCheckoutSheetKit' from '@shopify/checkout-sheet-kit' doesn't seem to be linked. Make sure the native module is installed and rebuilt."; + +function withLegacyConstants(nativeModule: LegacyNativeModule): Spec { + if (typeof nativeModule.getConstants === 'function') { + return nativeModule as Spec; + } + + return Object.assign(Object.create(nativeModule), { + getConstants: () => ({version: nativeModule.version ?? ''}), + }) as Spec; +} + +function getNativeModule(): Spec { + const turboModule = TurboModuleRegistry.get('ShopifyCheckoutSheetKit'); + + if (turboModule != null) { + return turboModule; + } + + const nativeModule = NativeModules.ShopifyCheckoutSheetKit as + | LegacyNativeModule + | undefined; + + if (nativeModule == null) { + throw new Error(LINKING_ERROR); + } + + return withLegacyConstants(nativeModule); +} + +export default getNativeModule(); diff --git a/modules/@shopify/checkout-sheet-kit/tests/context.test.tsx b/modules/@shopify/checkout-sheet-kit/tests/context.test.tsx index 8f22f503..9e18f686 100644 --- a/modules/@shopify/checkout-sheet-kit/tests/context.test.tsx +++ b/modules/@shopify/checkout-sheet-kit/tests/context.test.tsx @@ -348,7 +348,7 @@ describe('useShopifyCheckoutSheet', () => { , ); - const config = hookValue.getConfig(); + const config = await hookValue.getConfig(); expect(config).toEqual({ preloading: true, colorScheme: 'automatic', diff --git a/modules/@shopify/checkout-sheet-kit/tests/index.test.ts b/modules/@shopify/checkout-sheet-kit/tests/index.test.ts index 8beeb28a..dc87f70d 100644 --- a/modules/@shopify/checkout-sheet-kit/tests/index.test.ts +++ b/modules/@shopify/checkout-sheet-kit/tests/index.test.ts @@ -160,9 +160,9 @@ describe('ShopifyCheckoutSheetKit', () => { }); describe('getConfig', () => { - it('returns the parsed config from the Native Module', () => { + it('returns the parsed config from the Native Module', async () => { const instance = new ShopifyCheckoutSheet(); - expect(instance.getConfig()).toStrictEqual({ + await expect(instance.getConfig()).resolves.toStrictEqual({ preloading: true, colorScheme: ColorScheme.automatic, logLevel: LogLevel.error, @@ -732,7 +732,7 @@ describe('ShopifyCheckoutSheetKit', () => { NativeModule.configureAcceleratedCheckouts.mockReturnValue(true); const result = - instance.configureAcceleratedCheckouts(acceleratedConfig); + await instance.configureAcceleratedCheckouts(acceleratedConfig); expect(result).toBe(true); expect( @@ -757,7 +757,7 @@ describe('ShopifyCheckoutSheetKit', () => { }; NativeModule.configureAcceleratedCheckouts.mockReturnValue(true); - instance.configureAcceleratedCheckouts(minimalConfig); + await instance.configureAcceleratedCheckouts(minimalConfig); expect( NativeModule.configureAcceleratedCheckouts, @@ -778,7 +778,7 @@ describe('ShopifyCheckoutSheetKit', () => { const instance = new ShopifyCheckoutSheet(); const result = - instance.configureAcceleratedCheckouts(acceleratedConfig); + await instance.configureAcceleratedCheckouts(acceleratedConfig); expect(result).toBe(false); expect( @@ -794,9 +794,9 @@ describe('ShopifyCheckoutSheetKit', () => { }; const expectedError = new Error('`storefrontDomain` is required'); - expect( + await expect( instance.configureAcceleratedCheckouts(invalidConfig), - ).toBe(false); + ).resolves.toBe(false); expect(console.error).toHaveBeenCalledWith( '[ShopifyCheckoutSheetKit] Failed to configure accelerated checkouts with', expectedError, @@ -812,9 +812,9 @@ describe('ShopifyCheckoutSheetKit', () => { const expectedError = new Error('`storefrontAccessToken` is required'); - expect( + await expect( instance.configureAcceleratedCheckouts(invalidConfig), - ).toBe(false); + ).resolves.toBe(false); expect(console.error).toHaveBeenCalledWith( '[ShopifyCheckoutSheetKit] Failed to configure accelerated checkouts with', expectedError, @@ -837,9 +837,9 @@ describe('ShopifyCheckoutSheetKit', () => { '`wallets.applePay.merchantIdentifier` is required', ); - expect( + await expect( instance.configureAcceleratedCheckouts(invalidConfig), - ).toBe(false); + ).resolves.toBe(false); expect(console.error).toHaveBeenCalledWith( '[ShopifyCheckoutSheetKit] Failed to configure accelerated checkouts with', expectedError, @@ -862,16 +862,16 @@ describe('ShopifyCheckoutSheetKit', () => { `'wallets.applePay.contactFields' contains unexpected values. Expected "email, phone", received "invalid"`, ); - expect( + await expect( instance.configureAcceleratedCheckouts(invalidConfig as any), - ).toBe(false); + ).resolves.toBe(false); expect(console.error).toHaveBeenCalledWith( '[ShopifyCheckoutSheetKit] Failed to configure accelerated checkouts with', expectedError, ); }); - it('does not throw when Apple Pay wallet is not configured', () => { + it('does not throw when Apple Pay wallet is not configured', async () => { const instance = new ShopifyCheckoutSheet(); const configWithoutApplePay = { storefrontDomain: 'test-shop.myshopify.com', @@ -879,12 +879,12 @@ describe('ShopifyCheckoutSheetKit', () => { }; NativeModule.configureAcceleratedCheckouts.mockReturnValue(true); - expect( + await expect( instance.configureAcceleratedCheckouts(configWithoutApplePay), - ).toBe(true); + ).resolves.toBe(true); }); - it('throws when a non-string value is given for supportedShippingCountries', () => { + it('throws when a non-string value is given for supportedShippingCountries', async () => { const instance = new ShopifyCheckoutSheet(); const invalidConfig = { ...acceleratedConfig, @@ -901,9 +901,9 @@ describe('ShopifyCheckoutSheetKit', () => { `'wallets.applePay.supportedShippingCountries' contains unexpected values. Expects ISO 3166-1 alpha-2 country codes (e.g., "US", "CA", "GB").`, ); - expect( + await expect( instance.configureAcceleratedCheckouts(invalidConfig as any), - ).toBe(false); + ).resolves.toBe(false); expect(console.error).toHaveBeenCalledWith( '[ShopifyCheckoutSheetKit] Failed to configure accelerated checkouts with', expectedError, @@ -913,7 +913,7 @@ describe('ShopifyCheckoutSheetKit', () => { it('calls configureAcceleratedCheckouts with an empty array for supportShippingCountries when omitted', async () => { const instance = new ShopifyCheckoutSheet(); - instance.configureAcceleratedCheckouts({ + await instance.configureAcceleratedCheckouts({ ...acceleratedConfig, wallets: { applePay: { @@ -940,7 +940,7 @@ describe('ShopifyCheckoutSheetKit', () => { it('calls configureAcceleratedCheckouts with supportShippingCountries when given', async () => { const instance = new ShopifyCheckoutSheet(); - instance.configureAcceleratedCheckouts({ + await instance.configureAcceleratedCheckouts({ ...acceleratedConfig, wallets: { applePay: { @@ -967,25 +967,25 @@ describe('ShopifyCheckoutSheetKit', () => { }); describe('isAcceleratedCheckoutAvailable', () => { - it('calls native isAcceleratedCheckoutAvailable on iOS', () => { + it('calls native isAcceleratedCheckoutAvailable on iOS', async () => { const instance = new ShopifyCheckoutSheet(); NativeModule.isAcceleratedCheckoutAvailable.mockReturnValue(true); const result = instance.isAcceleratedCheckoutAvailable(); - expect(result).toBe(true); + await expect(result).resolves.toBe(true); expect( NativeModule.isAcceleratedCheckoutAvailable, ).toHaveBeenCalledTimes(1); }); - it('returns false on Android', () => { + it('returns false on Android', async () => { Platform.OS = 'android'; const instance = new ShopifyCheckoutSheet(); const result = instance.isAcceleratedCheckoutAvailable(); - expect(result).toBe(false); + await expect(result).resolves.toBe(false); expect( NativeModule.isAcceleratedCheckoutAvailable, ).not.toHaveBeenCalled(); diff --git a/modules/@shopify/checkout-sheet-kit/tests/linking.test.ts b/modules/@shopify/checkout-sheet-kit/tests/linking.test.ts index f83795f8..91e3fff2 100644 --- a/modules/@shopify/checkout-sheet-kit/tests/linking.test.ts +++ b/modules/@shopify/checkout-sheet-kit/tests/linking.test.ts @@ -1,22 +1,114 @@ -jest.mock('react-native', () => ({ - NativeModules: {}, - NativeEventEmitter: jest.fn(), - Platform: { - OS: 'ios', - }, - TurboModuleRegistry: { - getEnforcing: jest.fn((name: string) => { - throw new Error( - `TurboModuleRegistry.getEnforcing(...): '${name}' could not be found.`, - ); - }), - }, -})); +function createNativeModule(version: string) { + return { + version, + getConstants: jest.fn(() => ({version})), + preload: jest.fn(), + present: jest.fn(), + dismiss: jest.fn(), + invalidateCache: jest.fn(), + getConfig: jest.fn(() => ({ + preloading: true, + colorScheme: 'automatic', + logLevel: 'error', + })), + setConfig: jest.fn(), + addEventListener: jest.fn(), + removeEventListeners: jest.fn(), + initiateGeolocationRequest: jest.fn(), + configureAcceleratedCheckouts: jest.fn(() => true), + isAcceleratedCheckoutAvailable: jest.fn(() => true), + isApplePayAvailable: jest.fn(() => true), + addListener: jest.fn(), + removeListeners: jest.fn(), + }; +} + +function createLegacyNativeModule(version: string) { + const {getConstants: _getConstants, ...nativeModule} = + createNativeModule(version); + + return nativeModule; +} + +function mockReactNative({ + turboModule, + legacyModule, +}: { + turboModule?: ReturnType | null; + legacyModule?: + | ReturnType + | ReturnType + | null; +}) { + jest.doMock('react-native', () => ({ + NativeModules: legacyModule ? {ShopifyCheckoutSheetKit: legacyModule} : {}, + NativeEventEmitter: jest.fn(() => ({ + addListener: jest.fn(), + removeAllListeners: jest.fn(), + })), + PermissionsAndroid: { + requestMultiple: jest.fn(async () => ({})), + }, + Platform: { + OS: 'ios', + Version: '16.0', + }, + TurboModuleRegistry: { + get: jest.fn((name: string) => + name === 'ShopifyCheckoutSheetKit' ? turboModule : null, + ), + getEnforcing: jest.fn((name: string) => { + if (name === 'ShopifyCheckoutSheetKit' && turboModule) { + return turboModule; + } + throw new Error( + `TurboModuleRegistry.getEnforcing(...): '${name}' could not be found.`, + ); + }), + }, + codegenNativeComponent: jest.fn(() => 'RCTAcceleratedCheckoutButtons'), + requireNativeComponent: jest.fn(() => 'RCTAcceleratedCheckoutButtons'), + StyleSheet: { + flatten: jest.fn(style => style), + }, + })); +} describe('Native Module Linking', () => { + beforeEach(() => { + jest.resetModules(); + }); + + afterEach(() => { + jest.dontMock('react-native'); + }); + + it('uses the TurboModule when it is available', () => { + mockReactNative({turboModule: createNativeModule('turbo')}); + + const {ShopifyCheckoutSheet} = require('../src'); + const checkoutSheet = new ShopifyCheckoutSheet(); + + expect(checkoutSheet.version).toBe('turbo'); + }); + + it('falls back to the legacy NativeModules bridge', () => { + mockReactNative({ + turboModule: null, + legacyModule: createLegacyNativeModule('legacy'), + }); + + const {ShopifyCheckoutSheet} = require('../src'); + const checkoutSheet = new ShopifyCheckoutSheet(); + + expect(checkoutSheet.version).toBe('legacy'); + }); + it('throws error when native module is not linked', () => { + mockReactNative({turboModule: null, legacyModule: null}); + expect(() => { - require('../src/index'); + require('../src'); }).toThrow('ShopifyCheckoutSheetKit'); }); }); diff --git a/sample/ios/Podfile.lock b/sample/ios/Podfile.lock index 07faf199..dd6728c1 100644 --- a/sample/ios/Podfile.lock +++ b/sample/ios/Podfile.lock @@ -2578,7 +2578,7 @@ PODS: - ReactCommon/turbomodule/core - SocketRocket - Yoga - - RNShopifyCheckoutSheetKit (4.0.0): + - RNShopifyCheckoutSheetKit (3.9.0): - boost - DoubleConversion - fast_float @@ -2996,7 +2996,7 @@ SPEC CHECKSUMS: RNGestureHandler: eeb622199ef1fb3a076243131095df1c797072f0 RNReanimated: 237d420b7bb4378ef1dacc7d7a5c674fddb4b5d2 RNScreens: 3fc29af06302e1f1c18a7829fe57cbc2c0259912 - RNShopifyCheckoutSheetKit: 2a8c97d7780466538843d4cb1368c7ed76a33689 + RNShopifyCheckoutSheetKit: 04a94fbd56700f61478c658307eec38fb6c9439b RNVectorIcons: be4d047a76ad307ffe54732208fb0498fcb8477f ShopifyCheckoutSheetKit: 5253ca4da4c4f31069286509693930d02b4150d8 SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 diff --git a/sample/src/context/Cart.tsx b/sample/src/context/Cart.tsx index a3b15272..c4235be5 100644 --- a/sample/src/context/Cart.tsx +++ b/sample/src/context/Cart.tsx @@ -119,9 +119,9 @@ export const CartProvider: React.FC = ({children}) => { }, [cartId, fetchCart, setTotalQuantity]); const preloadCheckout = useCallback( - (checkoutURL: string) => { + async (checkoutURL: string) => { if (checkoutURL) { - const config = shopify.getConfig(); + const config = await shopify.getConfig(); if (config?.preloading) { shopify.preload(checkoutURL); } diff --git a/sample/src/screens/SettingsScreen.tsx b/sample/src/screens/SettingsScreen.tsx index 2d670204..5de4ce4c 100644 --- a/sample/src/screens/SettingsScreen.tsx +++ b/sample/src/screens/SettingsScreen.tsx @@ -101,8 +101,11 @@ function SettingsScreen() { const [preloadingEnabled, setPreloadingEnabled] = useState(false); useEffect(() => { - const config = shopify.getConfig(); - setPreloadingEnabled(config?.preloading ?? false); + async function loadConfig() { + const config = await shopify.getConfig(); + setPreloadingEnabled(config?.preloading ?? false); + } + loadConfig(); }, [shopify]); const handleColorSchemeChange = useCallback( @@ -116,8 +119,8 @@ function SettingsScreen() { [appConfig, setAppConfig, setColorScheme], ); - const handleTogglePreloading = useCallback(() => { - const currentConfig = shopify.getConfig(); + const handleTogglePreloading = useCallback(async () => { + const currentConfig = await shopify.getConfig(); const newPreloadingValue = !currentConfig?.preloading; shopify.setConfig({ ...currentConfig, From 67519dcc5eda5e474483e786fa1dc5f0b3753d82 Mon Sep 17 00:00:00 2001 From: Kieran Osgood Date: Mon, 24 Aug 2026 14:58:18 +0100 Subject: [PATCH 2/8] fix: clean pod file install rules --- .../RNShopifyCheckoutSheetKit.podspec | 26 +++---------------- .../android/gradle.properties | 2 +- sample/android/gradle.properties | 2 +- sample/ios/Podfile.lock | 16 ++++++------ 4 files changed, 13 insertions(+), 33 deletions(-) diff --git a/modules/@shopify/checkout-sheet-kit/RNShopifyCheckoutSheetKit.podspec b/modules/@shopify/checkout-sheet-kit/RNShopifyCheckoutSheetKit.podspec index 5d7a7a00..e3644386 100644 --- a/modules/@shopify/checkout-sheet-kit/RNShopifyCheckoutSheetKit.podspec +++ b/modules/@shopify/checkout-sheet-kit/RNShopifyCheckoutSheetKit.podspec @@ -2,8 +2,6 @@ require "json" package = JSON.parse(File.read(File.join(__dir__, "package.json"))) -folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' - new_arch_enabled = ENV["RCT_NEW_ARCH_ENABLED"] == "1" Pod::Spec.new do |s| @@ -20,26 +18,8 @@ Pod::Spec.new do |s| s.source_files = "ios/*.{h,m,mm,swift}" s.dependency "React-Core" - s.dependency "ShopifyCheckoutSheetKit", "~> 3.8.0" - s.dependency "ShopifyCheckoutSheetKit/AcceleratedCheckouts", "~> 3.8.0" - - if new_arch_enabled - if defined?(install_modules_dependencies) - install_modules_dependencies(s) - else - s.dependency "React-Codegen" - s.dependency "RCT-Folly", :modular_headers => true - s.dependency "RCTRequired" - s.dependency "RCTTypeSafety" - s.dependency "ReactCommon/turbomodule/core" - end - - s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1" + s.dependency "ShopifyCheckoutSheetKit", "= 3.8.2" + s.dependency "ShopifyCheckoutSheetKit/AcceleratedCheckouts", "= 3.8.2" - s.pod_target_xcconfig = { - "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"", - "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1", - "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" - } - end + install_modules_dependencies(s) if new_arch_enabled end diff --git a/modules/@shopify/checkout-sheet-kit/android/gradle.properties b/modules/@shopify/checkout-sheet-kit/android/gradle.properties index e7588be9..63baed59 100644 --- a/modules/@shopify/checkout-sheet-kit/android/gradle.properties +++ b/modules/@shopify/checkout-sheet-kit/android/gradle.properties @@ -5,4 +5,4 @@ ndkVersion=23.1.7779620 buildToolsVersion = "35.0.0" # Version of Shopify Checkout SDK to use with React Native -SHOPIFY_CHECKOUT_SDK_VERSION=3.6.0 +SHOPIFY_CHECKOUT_SDK_VERSION=3.6.2 diff --git a/sample/android/gradle.properties b/sample/android/gradle.properties index 985f1eb6..525d7810 100644 --- a/sample/android/gradle.properties +++ b/sample/android/gradle.properties @@ -39,4 +39,4 @@ hermesEnabled=true newArchEnabled=true # Note: only used here for testing -SHOPIFY_CHECKOUT_SDK_VERSION=3.6.0 +SHOPIFY_CHECKOUT_SDK_VERSION=3.6.2 diff --git a/sample/ios/Podfile.lock b/sample/ios/Podfile.lock index dd6728c1..58481226 100644 --- a/sample/ios/Podfile.lock +++ b/sample/ios/Podfile.lock @@ -2605,8 +2605,8 @@ PODS: - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - ShopifyCheckoutSheetKit (~> 3.8.0) - - ShopifyCheckoutSheetKit/AcceleratedCheckouts (~> 3.8.0) + - ShopifyCheckoutSheetKit (= 3.8.2) + - ShopifyCheckoutSheetKit/AcceleratedCheckouts (= 3.8.2) - SocketRocket - Yoga - RNVectorIcons (10.3.0): @@ -2638,11 +2638,11 @@ PODS: - ReactCommon/turbomodule/core - SocketRocket - Yoga - - ShopifyCheckoutSheetKit (3.8.0): - - ShopifyCheckoutSheetKit/Core (= 3.8.0) - - ShopifyCheckoutSheetKit/AcceleratedCheckouts (3.8.0): + - ShopifyCheckoutSheetKit (3.8.2): + - ShopifyCheckoutSheetKit/Core (= 3.8.2) + - ShopifyCheckoutSheetKit/AcceleratedCheckouts (3.8.2): - ShopifyCheckoutSheetKit/Core - - ShopifyCheckoutSheetKit/Core (3.8.0) + - ShopifyCheckoutSheetKit/Core (3.8.2) - SocketRocket (0.7.1) - Yoga (0.0.0) @@ -2996,9 +2996,9 @@ SPEC CHECKSUMS: RNGestureHandler: eeb622199ef1fb3a076243131095df1c797072f0 RNReanimated: 237d420b7bb4378ef1dacc7d7a5c674fddb4b5d2 RNScreens: 3fc29af06302e1f1c18a7829fe57cbc2c0259912 - RNShopifyCheckoutSheetKit: 04a94fbd56700f61478c658307eec38fb6c9439b + RNShopifyCheckoutSheetKit: 1ad510f4f43572863f80c9f4817c7fff956c1955 RNVectorIcons: be4d047a76ad307ffe54732208fb0498fcb8477f - ShopifyCheckoutSheetKit: 5253ca4da4c4f31069286509693930d02b4150d8 + ShopifyCheckoutSheetKit: 14273b696ae1943735807893b1a619a5c18b3ab4 SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 Yoga: a742cc68e8366fcfc681808162492bc0aa7a9498 From 4ad8d0821b27a42ed7526b8a0dc094eaaa2f3324 Mon Sep 17 00:00:00 2001 From: Kieran Osgood Date: Tue, 25 Aug 2026 16:34:52 +0100 Subject: [PATCH 3/8] feat: bump to latest android sdk version --- modules/@shopify/checkout-sheet-kit/android/gradle.properties | 2 +- sample/android/gradle.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/@shopify/checkout-sheet-kit/android/gradle.properties b/modules/@shopify/checkout-sheet-kit/android/gradle.properties index 63baed59..885f30c6 100644 --- a/modules/@shopify/checkout-sheet-kit/android/gradle.properties +++ b/modules/@shopify/checkout-sheet-kit/android/gradle.properties @@ -5,4 +5,4 @@ ndkVersion=23.1.7779620 buildToolsVersion = "35.0.0" # Version of Shopify Checkout SDK to use with React Native -SHOPIFY_CHECKOUT_SDK_VERSION=3.6.2 +SHOPIFY_CHECKOUT_SDK_VERSION=3.6.3 diff --git a/sample/android/gradle.properties b/sample/android/gradle.properties index 525d7810..5c45b0dd 100644 --- a/sample/android/gradle.properties +++ b/sample/android/gradle.properties @@ -39,4 +39,4 @@ hermesEnabled=true newArchEnabled=true # Note: only used here for testing -SHOPIFY_CHECKOUT_SDK_VERSION=3.6.2 +SHOPIFY_CHECKOUT_SDK_VERSION=3.6.3 From 7d086921bdbf33cd3bacb630c27e8bef7e7ed6a3 Mon Sep 17 00:00:00 2001 From: Kieran Osgood Date: Tue, 25 Aug 2026 16:35:16 +0100 Subject: [PATCH 4/8] release testflight an dapp store builds for testing --- sample/android/app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sample/android/app/build.gradle b/sample/android/app/build.gradle index 9e54dfc0..6fd6e13c 100644 --- a/sample/android/app/build.gradle +++ b/sample/android/app/build.gradle @@ -108,7 +108,7 @@ android { applicationId "com.shopify.checkoutkitreactnative" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 11 + versionCode 12 versionName "1.1" } signingConfigs { From 868c1be48372bbcc89db1816ef9b025f530a7798 Mon Sep 17 00:00:00 2001 From: Kieran Osgood Date: Tue, 25 Aug 2026 17:31:25 +0100 Subject: [PATCH 5/8] fix: expose source to React Native bundlers Assisted-By: devx/414037a7-8b00-4d1b-b4ff-20c6919aa6df --- modules/@shopify/checkout-sheet-kit/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/@shopify/checkout-sheet-kit/package.json b/modules/@shopify/checkout-sheet-kit/package.json index 3280f64f..550579ab 100644 --- a/modules/@shopify/checkout-sheet-kit/package.json +++ b/modules/@shopify/checkout-sheet-kit/package.json @@ -3,8 +3,9 @@ "license": "MIT", "version": "3.9.0", "main": "lib/commonjs/index.js", - "types": "src/index.ts", + "types": "lib/typescript/src/index.d.ts", "source": "src/index.ts", + "react-native": "src/index.ts", "module": "lib/module/index.js", "description": "A React Native library for Shopify's Checkout Kit.", "author": "Shopify", From e2c516623cc49519c0a432d364780eb7b288c574 Mon Sep 17 00:00:00 2001 From: Kieran Osgood Date: Wed, 26 Aug 2026 09:06:34 +0100 Subject: [PATCH 6/8] fix: use promise for existing v3 methods --- .../ShopifyCheckoutSheetKitModule.java | 28 +++++---- .../ios/ShopifyCheckoutSheetKit.swift | 16 ++--- .../@shopify/checkout-sheet-kit/package.json | 2 +- .../@shopify/checkout-sheet-kit/src/index.ts | 2 +- .../specs/NativeShopifyCheckoutSheetKit.ts | 8 +-- .../checkout-sheet-kit/tests/linking.test.ts | 8 +-- .../ShopifyCheckoutSheetKitModuleTest.java | 55 ++++++++++++++-- .../ShopifyCheckoutSheetKitTests.swift | 62 +++++++++++++++++++ 8 files changed, 145 insertions(+), 36 deletions(-) diff --git a/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java b/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java index 57bbaecd..10f71db7 100644 --- a/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java +++ b/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java @@ -31,6 +31,7 @@ of this software and associated documentation files (the "Software"), to deal import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableMap; @@ -123,15 +124,15 @@ public void invalidateCache() { ShopifyCheckoutSheetKit.invalidate(); } - @ReactMethod(isBlockingSynchronousMethod = true) - public WritableMap getConfig() { + @ReactMethod + public void getConfig(Promise promise) { WritableMap resultConfig = Arguments.createMap(); resultConfig.putBoolean("preloading", checkoutConfig.getPreloading().getEnabled()); resultConfig.putString("colorScheme", colorSchemeToString(checkoutConfig.getColorScheme())); resultConfig.putString("logLevel", logLevelToString(checkoutConfig.getLogLevel())); - return resultConfig; + promise.resolve(resultConfig); } @ReactMethod @@ -175,8 +176,8 @@ public void setConfig(ReadableMap config) { }); } - @ReactMethod(isBlockingSynchronousMethod = true) - public boolean configureAcceleratedCheckouts( + @ReactMethod + public void configureAcceleratedCheckouts( String storefrontDomain, String storefrontAccessToken, String customerEmail, @@ -184,21 +185,22 @@ public boolean configureAcceleratedCheckouts( String customerAccessToken, String applePayMerchantIdentifier, ReadableArray applyPayContactFields, - ReadableArray supportedShippingCountries) { + ReadableArray supportedShippingCountries, + Promise promise) { // Accelerated checkouts not supported on Android - return false; + promise.resolve(false); } - @ReactMethod(isBlockingSynchronousMethod = true) - public boolean isAcceleratedCheckoutAvailable() { + @ReactMethod + public void isAcceleratedCheckoutAvailable(Promise promise) { // Accelerated checkouts not supported on Android - return false; + promise.resolve(false); } - @ReactMethod(isBlockingSynchronousMethod = true) - public boolean isApplePayAvailable() { + @ReactMethod + public void isApplePayAvailable(Promise promise) { // Apple Pay not available on Android - return false; + promise.resolve(false); } @ReactMethod diff --git a/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.swift b/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.swift index 1603d918..59e2ec7a 100644 --- a/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.swift +++ b/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.swift @@ -213,7 +213,7 @@ class RCTShopifyCheckoutSheetKit: RCTEventEmitter, CheckoutDelegate { NotificationCenter.default.post(name: Notification.Name("CheckoutKitConfigurationUpdated"), object: nil) } - @objc func getConfig() -> NSDictionary { + private func configurationDictionary() -> NSDictionary { return [ "title": ShopifyCheckoutSheetKit.configuration.title, "preloading": ShopifyCheckoutSheetKit.configuration.preloading.enabled, @@ -229,10 +229,10 @@ class RCTShopifyCheckoutSheetKit: RCTEventEmitter, CheckoutDelegate { _ resolve: @escaping RCTPromiseResolveBlock, reject _: @escaping RCTPromiseRejectBlock ) { - resolve(getConfig()) + resolve(configurationDictionary()) } - @objc func configureAcceleratedCheckouts( + private func configureAcceleratedCheckoutsResult( _ storefrontDomain: String, storefrontAccessToken: String, customerEmail: String?, @@ -293,7 +293,7 @@ class RCTShopifyCheckoutSheetKit: RCTEventEmitter, CheckoutDelegate { resolve: @escaping RCTPromiseResolveBlock, reject _: @escaping RCTPromiseRejectBlock ) { - resolve(configureAcceleratedCheckouts( + resolve(configureAcceleratedCheckoutsResult( storefrontDomain, storefrontAccessToken: storefrontAccessToken, customerEmail: customerEmail, @@ -305,7 +305,7 @@ class RCTShopifyCheckoutSheetKit: RCTEventEmitter, CheckoutDelegate { )) } - @objc func isAcceleratedCheckoutAvailable() -> NSNumber { + private func acceleratedCheckoutAvailable() -> NSNumber { guard #available(iOS 16.0, *) else { return NSNumber(value: false) } @@ -317,10 +317,10 @@ class RCTShopifyCheckoutSheetKit: RCTEventEmitter, CheckoutDelegate { _ resolve: @escaping RCTPromiseResolveBlock, reject _: @escaping RCTPromiseRejectBlock ) { - resolve(isAcceleratedCheckoutAvailable()) + resolve(acceleratedCheckoutAvailable()) } - @objc func isApplePayAvailable() -> NSNumber { + private func applePayAvailable() -> NSNumber { guard #available(iOS 16.0, *) else { return NSNumber(value: false) } @@ -334,7 +334,7 @@ class RCTShopifyCheckoutSheetKit: RCTEventEmitter, CheckoutDelegate { _ resolve: @escaping RCTPromiseResolveBlock, reject _: @escaping RCTPromiseRejectBlock ) { - resolve(isApplePayAvailable()) + resolve(applePayAvailable()) } @objc func initiateGeolocationRequest(_ allow: Bool) { diff --git a/modules/@shopify/checkout-sheet-kit/package.json b/modules/@shopify/checkout-sheet-kit/package.json index 550579ab..d15dfd45 100644 --- a/modules/@shopify/checkout-sheet-kit/package.json +++ b/modules/@shopify/checkout-sheet-kit/package.json @@ -3,7 +3,7 @@ "license": "MIT", "version": "3.9.0", "main": "lib/commonjs/index.js", - "types": "lib/typescript/src/index.d.ts", + "types": "src/index.ts", "source": "src/index.ts", "react-native": "src/index.ts", "module": "lib/module/index.js", diff --git a/modules/@shopify/checkout-sheet-kit/src/index.ts b/modules/@shopify/checkout-sheet-kit/src/index.ts index 13fe173d..ee19bb74 100644 --- a/modules/@shopify/checkout-sheet-kit/src/index.ts +++ b/modules/@shopify/checkout-sheet-kit/src/index.ts @@ -413,7 +413,7 @@ class ShopifyCheckoutSheet implements ShopifyCheckoutSheetKit { * the payload (preloading, title, nested colors) passes through unchanged. */ private coerceConfigurationResult( - raw: ReturnType, + raw: Awaited>, ): Configuration { return { ...raw, diff --git a/modules/@shopify/checkout-sheet-kit/src/specs/NativeShopifyCheckoutSheetKit.ts b/modules/@shopify/checkout-sheet-kit/src/specs/NativeShopifyCheckoutSheetKit.ts index bc97e82f..88da2d0c 100644 --- a/modules/@shopify/checkout-sheet-kit/src/specs/NativeShopifyCheckoutSheetKit.ts +++ b/modules/@shopify/checkout-sheet-kit/src/specs/NativeShopifyCheckoutSheetKit.ts @@ -77,7 +77,7 @@ export interface Spec extends TurboModule { dismiss(): void; invalidateCache(): void; setConfig(configuration: ConfigurationSpec): void; - getConfig(): ConfigurationResultSpec; + getConfig(): Promise; configureAcceleratedCheckouts( storefrontDomain: string, storefrontAccessToken: string, @@ -87,9 +87,9 @@ export interface Spec extends TurboModule { applePayMerchantIdentifier: string | null, applyPayContactFields: string[], supportedShippingCountries: string[], - ): boolean; - isAcceleratedCheckoutAvailable(): boolean; - isApplePayAvailable(): boolean; + ): Promise; + isAcceleratedCheckoutAvailable(): Promise; + isApplePayAvailable(): Promise; initiateGeolocationRequest(allow: boolean): void; addListener(eventName: string): void; removeListeners(count: number): void; diff --git a/modules/@shopify/checkout-sheet-kit/tests/linking.test.ts b/modules/@shopify/checkout-sheet-kit/tests/linking.test.ts index 91e3fff2..ac5595b3 100644 --- a/modules/@shopify/checkout-sheet-kit/tests/linking.test.ts +++ b/modules/@shopify/checkout-sheet-kit/tests/linking.test.ts @@ -6,7 +6,7 @@ function createNativeModule(version: string) { present: jest.fn(), dismiss: jest.fn(), invalidateCache: jest.fn(), - getConfig: jest.fn(() => ({ + getConfig: jest.fn(async () => ({ preloading: true, colorScheme: 'automatic', logLevel: 'error', @@ -15,9 +15,9 @@ function createNativeModule(version: string) { addEventListener: jest.fn(), removeEventListeners: jest.fn(), initiateGeolocationRequest: jest.fn(), - configureAcceleratedCheckouts: jest.fn(() => true), - isAcceleratedCheckoutAvailable: jest.fn(() => true), - isApplePayAvailable: jest.fn(() => true), + configureAcceleratedCheckouts: jest.fn(async () => true), + isAcceleratedCheckoutAvailable: jest.fn(async () => true), + isApplePayAvailable: jest.fn(async () => true), addListener: jest.fn(), removeListeners: jest.fn(), }; diff --git a/sample/android/app/src/test/java/com/shopify/checkoutkitreactnative/ShopifyCheckoutSheetKitModuleTest.java b/sample/android/app/src/test/java/com/shopify/checkoutkitreactnative/ShopifyCheckoutSheetKitModuleTest.java index f202f2a1..e4f409fa 100644 --- a/sample/android/app/src/test/java/com/shopify/checkoutkitreactnative/ShopifyCheckoutSheetKitModuleTest.java +++ b/sample/android/app/src/test/java/com/shopify/checkoutkitreactnative/ShopifyCheckoutSheetKitModuleTest.java @@ -3,6 +3,7 @@ import androidx.activity.ComponentActivity; import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.JavaOnlyArray; import com.facebook.react.bridge.JavaOnlyMap; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; @@ -421,7 +422,7 @@ public void testGetConfigReturnsDebugForDebugLogLevel() { shopifyCheckoutSheetKitModule.setConfig(config); - WritableMap result = shopifyCheckoutSheetKitModule.getConfig(); + WritableMap result = getResolvedConfig(); assertThat(result).isNotNull(); assertThat(result.getString("logLevel")).isEqualTo("debug"); @@ -434,7 +435,7 @@ public void testGetConfigReturnsErrorForErrorLogLevel() { shopifyCheckoutSheetKitModule.setConfig(config); - WritableMap result = shopifyCheckoutSheetKitModule.getConfig(); + WritableMap result = getResolvedConfig(); assertThat(result).isNotNull(); assertThat(result.getString("logLevel")).isEqualTo("error"); @@ -447,7 +448,7 @@ public void testGetConfigReturnsErrorForNoneLogLevel() { shopifyCheckoutSheetKitModule.setConfig(config); - WritableMap result = shopifyCheckoutSheetKitModule.getConfig(); + WritableMap result = getResolvedConfig(); assertThat(result).isNotNull(); assertThat(result.getString("logLevel")).isEqualTo("error"); @@ -460,7 +461,7 @@ public void testGetConfigReturnsErrorForInvalidLogLevel() { shopifyCheckoutSheetKitModule.setConfig(config); - WritableMap result = shopifyCheckoutSheetKitModule.getConfig(); + WritableMap result = getResolvedConfig(); assertThat(result).isNotNull(); assertThat(result.getString("logLevel")).isEqualTo("error"); @@ -468,12 +469,48 @@ public void testGetConfigReturnsErrorForInvalidLogLevel() { @Test public void testGetConfigReturnsDefaultLogLevel() { - WritableMap result = shopifyCheckoutSheetKitModule.getConfig(); + WritableMap result = getResolvedConfig(); assertThat(result).isNotNull(); assertThat(result.getString("logLevel")).isEqualTo("error"); } + @Test + public void testConfigureAcceleratedCheckoutsResolvesFalse() { + PromiseMock promise = new PromiseMock(); + + shopifyCheckoutSheetKitModule.configureAcceleratedCheckouts( + "shop.example.com", + "token", + null, + null, + null, + null, + new JavaOnlyArray(), + new JavaOnlyArray(), + promise); + + assertThat(promise.resolvedValue).isEqualTo(false); + } + + @Test + public void testAcceleratedCheckoutAvailabilityResolvesFalse() { + PromiseMock promise = new PromiseMock(); + + shopifyCheckoutSheetKitModule.isAcceleratedCheckoutAvailable(promise); + + assertThat(promise.resolvedValue).isEqualTo(false); + } + + @Test + public void testApplePayAvailabilityResolvesFalse() { + PromiseMock promise = new PromiseMock(); + + shopifyCheckoutSheetKitModule.isApplePayAvailable(promise); + + assertThat(promise.resolvedValue).isEqualTo(false); + } + /** * Events */ @@ -633,6 +670,14 @@ public void testCompleteConfigurationAndEventFlow() { * Helpers */ + private WritableMap getResolvedConfig() { + PromiseMock promise = new PromiseMock(); + + shopifyCheckoutSheetKitModule.getConfig(promise); + + return (WritableMap) promise.resolvedValue; + } + private JavaOnlyMap createValidLightColors() { JavaOnlyMap colors = new JavaOnlyMap(); colors.putString("backgroundColor", BACKGROUND_COLOR); diff --git a/sample/ios/ReactNativeTests/ShopifyCheckoutSheetKitTests.swift b/sample/ios/ReactNativeTests/ShopifyCheckoutSheetKitTests.swift index 2f4708c1..da749653 100644 --- a/sample/ios/ReactNativeTests/ShopifyCheckoutSheetKitTests.swift +++ b/sample/ios/ReactNativeTests/ShopifyCheckoutSheetKitTests.swift @@ -503,6 +503,68 @@ class RCTShopifyCheckoutSheetKitMock: RCTShopifyCheckoutSheetKit { } } +extension RCTShopifyCheckoutSheetKit { + func getConfig() -> NSDictionary { + var configuration: NSDictionary? + + getConfig({ result in + configuration = result as? NSDictionary + }, reject: { _, _, _ in }) + + return configuration ?? [:] + } + + func configureAcceleratedCheckouts( + _ storefrontDomain: String, + storefrontAccessToken: String, + customerEmail: String?, + customerPhoneNumber: String?, + customerAccessToken: String?, + applePayMerchantIdentifier: String?, + applyPayContactFields: [String]?, + supportedShippingCountries: [String]? + ) -> NSNumber { + var configured = NSNumber(value: false) + + configureAcceleratedCheckouts( + storefrontDomain, + storefrontAccessToken: storefrontAccessToken, + customerEmail: customerEmail, + customerPhoneNumber: customerPhoneNumber, + customerAccessToken: customerAccessToken, + applePayMerchantIdentifier: applePayMerchantIdentifier, + applyPayContactFields: applyPayContactFields, + supportedShippingCountries: supportedShippingCountries, + resolve: { result in + configured = result as? NSNumber ?? NSNumber(value: false) + }, + reject: { _, _, _ in } + ) + + return configured + } + + func isAcceleratedCheckoutAvailable() -> NSNumber { + var available = NSNumber(value: false) + + isAcceleratedCheckoutAvailable({ result in + available = result as? NSNumber ?? NSNumber(value: false) + }, reject: { _, _, _ in }) + + return available + } + + func isApplePayAvailable() -> NSNumber { + var available = NSNumber(value: false) + + isApplePayAvailable({ result in + available = result as? NSNumber ?? NSNumber(value: false) + }, reject: { _, _, _ in }) + + return available + } +} + class AsyncRCTShopifyCheckoutSheetKitMock: RCTShopifyCheckoutSheetKit { var didSendEvent = false var eventName: String? From 4aa378b26ad1a264882b9e44adeb08929fedb557 Mon Sep 17 00:00:00 2001 From: Kieran Osgood Date: Wed, 26 Aug 2026 09:52:34 +0100 Subject: [PATCH 7/8] feat: ensure no regression on public js api --- .github/workflows/ci.yml | 2 +- .../checkout-sheet-kit/api-extractor.json | 47 ++ .../api/checkout-sheet-kit.api.md | 517 ++++++++++++++++++ .../@shopify/checkout-sheet-kit/package.json | 5 +- .../scripts/extract-api.mjs | 124 +++++ .../@shopify/checkout-sheet-kit/src/index.ts | 14 +- pnpm-lock.yaml | 324 +++++++++-- sample/android/app/build.gradle | 2 +- 8 files changed, 989 insertions(+), 46 deletions(-) create mode 100644 modules/@shopify/checkout-sheet-kit/api-extractor.json create mode 100644 modules/@shopify/checkout-sheet-kit/api/checkout-sheet-kit.api.md create mode 100644 modules/@shopify/checkout-sheet-kit/scripts/extract-api.mjs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fbb16a99..11356dec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,7 +33,7 @@ jobs: - run: | pnpm module clean - pnpm module build + pnpm module api:check pnpm compare-snapshot lint: diff --git a/modules/@shopify/checkout-sheet-kit/api-extractor.json b/modules/@shopify/checkout-sheet-kit/api-extractor.json new file mode 100644 index 00000000..c15fa1ef --- /dev/null +++ b/modules/@shopify/checkout-sheet-kit/api-extractor.json @@ -0,0 +1,47 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", + "projectFolder": ".", + "mainEntryPointFilePath": "/lib/typescript/src/index.d.ts", + "compiler": { + "tsconfigFilePath": "/tsconfig.build.json" + }, + "newlineKind": "lf", + "apiReport": { + "enabled": true, + "reportFolder": "/api/", + "reportFileName": "checkout-sheet-kit.api.md" + }, + "docModel": { + "enabled": false + }, + "dtsRollup": { + "enabled": false + }, + "tsdocMetadata": { + "enabled": false + }, + "messages": { + "compilerMessageReporting": { + "default": { + "logLevel": "warning" + } + }, + "extractorMessageReporting": { + "default": { + "logLevel": "warning" + }, + "ae-missing-release-tag": { + "logLevel": "none" + }, + "ae-forgotten-export": { + "logLevel": "none", + "addToApiReportFile": false + } + }, + "tsdocMessageReporting": { + "default": { + "logLevel": "none" + } + } + } +} diff --git a/modules/@shopify/checkout-sheet-kit/api/checkout-sheet-kit.api.md b/modules/@shopify/checkout-sheet-kit/api/checkout-sheet-kit.api.md new file mode 100644 index 00000000..d1f88bc5 --- /dev/null +++ b/modules/@shopify/checkout-sheet-kit/api/checkout-sheet-kit.api.md @@ -0,0 +1,517 @@ +## API Report File for "@shopify/checkout-sheet-kit" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import type { CheckoutCompletedEvent as CheckoutCompletedEvent_2 } from '../events'; +import type { CheckoutException as CheckoutException_2 } from '../errors'; +import type { EmitterSubscription } from 'react-native'; +import type { PixelEvent as PixelEvent_2 } from '../pixels'; +import type { PropsWithChildren } from 'react'; +import { default as React_2 } from 'react'; + +// @public (undocumented) +export const AcceleratedCheckoutButtons: React_2.FC; + +// @public (undocumented) +export type AcceleratedCheckoutButtonsProps = (CartProps | VariantProps) & CommonAcceleratedCheckoutButtonsProps; + +// @public +export interface AcceleratedCheckoutConfiguration { + customer?: { + email?: string; + phoneNumber?: string; + accessToken?: string; + }; + + storefrontAccessToken: string; + + storefrontDomain: string; + + wallets?: { + applePay?: { + contactFields: ApplePayContactField[]; + merchantIdentifier: string; + supportedShippingCountries?: string[]; + }; + }; +} + +// @public +export enum AcceleratedCheckoutWallet { + // (undocumented) + applePay = 'applePay', + // (undocumented) + shopPay = 'shopPay', +} + +// @public (undocumented) +export enum ApplePayContactField { + // (undocumented) + email = 'email', + // (undocumented) + phone = 'phone', +} + +// @public (undocumented) +export enum ApplePayLabel { + // (undocumented) + addMoney = "addMoney", + // (undocumented) + book = "book", + // (undocumented) + buy = "buy", + // (undocumented) + checkout = "checkout", + // (undocumented) + continue = "continue", + // (undocumented) + contribute = "contribute", + // (undocumented) + donate = "donate", + // (undocumented) + inStore = "inStore", + // (undocumented) + order = "order", + // (undocumented) + plain = "plain", + // (undocumented) + reload = "reload", + // (undocumented) + rent = "rent", + // (undocumented) + setUp = "setUp", + // (undocumented) + subscribe = "subscribe", + // (undocumented) + support = "support", + // (undocumented) + tip = "tip", + // (undocumented) + topUp = "topUp" +} + +// @public (undocumented) +export enum ApplePayStyle { + // (undocumented) + automatic = "automatic", + // (undocumented) + black = "black", + // (undocumented) + white = "white", + // (undocumented) + whiteOutline = "whiteOutline" +} + +// @public (undocumented) +export class CheckoutClientError extends GenericErrorWithCode {} + +// @public (undocumented) +export namespace CheckoutCompletedEvent { + // (undocumented) + export interface Address { + // (undocumented) + address1?: string; + // (undocumented) + address2?: string; + // (undocumented) + city?: string; + // (undocumented) + countryCode?: string; + // (undocumented) + firstName?: string; + // (undocumented) + lastName?: string; + // (undocumented) + name?: string; + // (undocumented) + phone?: string; + // (undocumented) + postalCode?: string; + // (undocumented) + referenceId?: string; + // (undocumented) + zoneCode?: string; + } + + // (undocumented) + export interface CartInfo { + // (undocumented) + lines: CartLine[]; + // (undocumented) + price: Price; + // (undocumented) + token: string; + } + + // (undocumented) + export interface CartLine { + // (undocumented) + discounts?: Discount[]; + // (undocumented) + image?: CartLineImage; + // (undocumented) + merchandiseId?: string; + // (undocumented) + price: Money; + // (undocumented) + productId?: string; + // (undocumented) + quantity: number; + // (undocumented) + title: string; + } + + // (undocumented) + export interface CartLineImage { + // (undocumented) + altText?: string; + // (undocumented) + lg: string; + // (undocumented) + md: string; + // (undocumented) + sm: string; + } + + // (undocumented) + export interface DeliveryDetails { + // (undocumented) + additionalInfo?: string; + // (undocumented) + location?: Address; + // (undocumented) + name?: string; + } + + // (undocumented) + export interface DeliveryInfo { + // (undocumented) + details: DeliveryDetails; + // (undocumented) + method: string; + } + + // (undocumented) + export interface Discount { + // (undocumented) + amount?: Money; + // (undocumented) + applicationType?: string; + // (undocumented) + title?: string; + // (undocumented) + value?: number; + // (undocumented) + valueType?: string; + } + + // (undocumented) + export interface Money { + // (undocumented) + amount?: number; + // (undocumented) + currencyCode?: string; + } + + // (undocumented) + export interface OrderDetails { + // (undocumented) + billingAddress?: Address; + // (undocumented) + cart: CartInfo; + // (undocumented) + deliveries?: DeliveryInfo[]; + // (undocumented) + email?: string; + // (undocumented) + id: string; + // (undocumented) + paymentMethods?: PaymentMethod[]; + // (undocumented) + phone?: string; + } + + // (undocumented) + export interface PaymentMethod { + // (undocumented) + details: {[key: string]: string | null}; + // (undocumented) + type: string; + } + + // (undocumented) + export interface Price { + // (undocumented) + discounts?: Discount[]; + // (undocumented) + shipping?: Money; + // (undocumented) + subtotal?: Money; + // (undocumented) + taxes?: Money; + // (undocumented) + total?: Money; + } +} + +// @public (undocumented) +export interface CheckoutCompletedEvent { + // (undocumented) + orderDetails: CheckoutCompletedEvent.OrderDetails; +} + +// @public (undocumented) +export enum CheckoutErrorCode { + // (undocumented) + cartCompleted = 'cart_completed', + // (undocumented) + cartExpired = 'cart_expired', + // (undocumented) + clientError = 'client_error', + // (undocumented) + httpError = 'http_error', + // (undocumented) + invalidCart = 'invalid_cart', + // (undocumented) + receivingBridgeEventError = 'error_receiving_message', + // (undocumented) + renderProcessGone = 'render_process_gone', + // (undocumented) + sendingBridgeEventError = 'error_sending_message', + // (undocumented) + storefrontPasswordRequired = 'storefront_password_required', + // (undocumented) + unknown = 'unknown', +} + +// @public (undocumented) +export type CheckoutEvent = +| 'close' +| 'completed' +| 'error' +| 'geolocationRequest' +| 'pixel'; + +// @public (undocumented) +export type CheckoutEventCallback = +| CloseEventCallback +| CheckoutExceptionCallback +| CheckoutCompletedEventCallback +| GeolocationRequestEventCallback +| PixelEventCallback; + +// @public (undocumented) +export type CheckoutException = +| CheckoutClientError +| CheckoutExpiredError +| CheckoutHTTPError +| ConfigurationError +| GenericError +| InternalError; + +// @public (undocumented) +export class CheckoutExpiredError extends GenericErrorWithCode {} + +// @public (undocumented) +export class CheckoutHTTPError extends GenericNetworkError {} + +// @public (undocumented) +export enum CheckoutNativeErrorType { + // (undocumented) + CheckoutClientError = 'CheckoutClientError', + // (undocumented) + CheckoutExpiredError = 'CheckoutExpiredError', + // (undocumented) + CheckoutHTTPError = 'CheckoutHTTPError', + // (undocumented) + ConfigurationError = 'ConfigurationError', + // (undocumented) + InternalError = 'InternalError', + // (undocumented) + UnknownError = 'UnknownError', +} + +// @public (undocumented) +export enum ColorScheme { + // (undocumented) + automatic = 'automatic', + // (undocumented) + dark = 'dark', + // (undocumented) + light = 'light', + // (undocumented) + web = 'web_default', +} + +// @public (undocumented) +export type Configuration = CommonConfiguration & { + acceleratedCheckouts?: AcceleratedCheckoutConfiguration; +} & ( +| { + colorScheme?: ColorScheme.web | ColorScheme.light | ColorScheme.dark; + colors?: { + ios?: IosColors; + android?: AndroidColors; + }; +} +| { + colorScheme?: ColorScheme.automatic; + colors?: { + ios?: IosColors; + android?: AndroidAutomaticColors; + }; +} +); + +// @public (undocumented) +export class ConfigurationError extends GenericErrorWithCode {} + +// @public +export interface CustomEvent { + /* A snapshot of various read-only properties of the browser at the time of the event */ + // (undocumented) + context?: Context_2; + customData?: any; + // (undocumented) + id?: string; + // (undocumented) + name?: string; + // (undocumented) + timestamp?: string; + // (undocumented) + type?: 'CUSTOM'; +} + +// @public +export interface Features { + handleGeolocationRequests: boolean; +} + +// @public (undocumented) +export class GenericError { + constructor(exception?: CheckoutNativeError) { + this.code = getCheckoutErrorCode(exception?.code); + this.message = exception?.message; + this.name = this.constructor.name; + this.recoverable = exception?.recoverable ?? false; + this.statusCode = exception?.statusCode; + } + // (undocumented) + code: CheckoutErrorCode; + // (undocumented) + message?: string; + // (undocumented) + name: string; + // (undocumented) + recoverable: boolean; + // (undocumented) + statusCode?: number; +} + +// @public (undocumented) +export interface GeolocationRequestEvent { + // (undocumented) + origin: string; +} + +// @public (undocumented) +export class InternalError { + constructor(exception: CheckoutNativeError) { + this.code = getCheckoutErrorCode(exception.code); + this.message = exception.message; + this.recoverable = exception.recoverable; + } + // (undocumented) + code: CheckoutErrorCode; + // (undocumented) + message: string; + // (undocumented) + recoverable: boolean; +} + +// @public (undocumented) +export class LifecycleEventParseError extends Error { + constructor(message?: string, options?: ErrorOptions); +} + +// @public +export enum LogLevel { + debug = 'debug', + error = 'error', +} + +// @public (undocumented) +export type PixelEvent = CustomEvent | StandardEvent; + +// @public (undocumented) +export enum RenderState { + // (undocumented) + Error = "error", + // (undocumented) + Loading = "loading", + // (undocumented) + Rendered = "rendered" +} + +// @public (undocumented) +export type RenderStateChangeEvent = { + state: RenderState.Error; + reason?: string; +} | { + state: Omit; +}; + +// @public (undocumented) +export class ShopifyCheckoutSheet implements ShopifyCheckoutSheetKit { + constructor(configuration?: Configuration, features?: Partial); + // (undocumented) + get acceleratedCheckoutsReady(): boolean; + addEventListener(event: CheckoutEvent, callback: CheckoutEventCallback): EmitterSubscription | undefined; + configureAcceleratedCheckouts(config: AcceleratedCheckoutConfiguration): Promise; + dismiss(): void; + getConfig(): Promise; + initiateGeolocationRequest(allow: boolean): Promise; + invalidate(): void; + isAcceleratedCheckoutAvailable(): Promise; + preload(checkoutUrl: string): void; + present(checkoutUrl: string): void; + removeEventListeners(event: CheckoutEvent): void; + setConfig(configuration: Configuration): Promise; + teardown(): void; + // (undocumented) + readonly version: string; +} + +// @public (undocumented) +export function ShopifyCheckoutSheetProvider(input: PropsWithChildren): React_2.JSX.Element; + +// @public +export interface StandardEvent { + /* A snapshot of various read-only properties of the browser at the time of the event */ + // (undocumented) + context?: Context_2; + /* Event data */ + // (undocumented) + data?: StandardEventData; + /* Event data */ + // (undocumented) + id?: string; + /* Event data */ + // (undocumented) + name?: string; + /* Event data */ + // (undocumented) + timestamp?: string; + /* Event data */ + // (undocumented) + type?: 'STANDARD'; +} + +// @public (undocumented) +export function useShopifyCheckoutSheet(): Context; + +// (No @packageDocumentation comment for this package) + +``` diff --git a/modules/@shopify/checkout-sheet-kit/package.json b/modules/@shopify/checkout-sheet-kit/package.json index d15dfd45..d959eae0 100644 --- a/modules/@shopify/checkout-sheet-kit/package.json +++ b/modules/@shopify/checkout-sheet-kit/package.json @@ -21,7 +21,9 @@ "clean": "rm -rf lib", "build": "bob build", "lint": "pnpm run typecheck && eslint src", - "typecheck": "tsc --noEmit" + "typecheck": "tsc --noEmit", + "api:check": "pnpm build && node ./scripts/extract-api.mjs", + "api:dump": "pnpm build && node ./scripts/extract-api.mjs --local" }, "files": [ "LICENSE", @@ -52,6 +54,7 @@ "react-native": "*" }, "devDependencies": { + "@microsoft/api-extractor": "^7.58.7", "react-native-builder-bob": "^0.23.2", "typescript": "^5.9.2" }, diff --git a/modules/@shopify/checkout-sheet-kit/scripts/extract-api.mjs b/modules/@shopify/checkout-sheet-kit/scripts/extract-api.mjs new file mode 100644 index 00000000..37378e77 --- /dev/null +++ b/modules/@shopify/checkout-sheet-kit/scripts/extract-api.mjs @@ -0,0 +1,124 @@ +#!/usr/bin/env node + +import { + cpSync, + mkdirSync, + mkdtempSync, + readFileSync, + readdirSync, + rmSync, + statSync, + writeFileSync, +} from 'node:fs'; +import {tmpdir} from 'node:os'; +import {dirname, join, relative} from 'node:path'; +import {fileURLToPath} from 'node:url'; +import {Extractor, ExtractorConfig} from '@microsoft/api-extractor'; + +const moduleRoot = dirname(dirname(fileURLToPath(import.meta.url))); +const sourceDirectory = join(moduleRoot, 'src'); +const generatedDeclarationDirectory = join(moduleRoot, 'lib', 'typescript'); +const temporaryDirectory = mkdtempSync( + join(tmpdir(), 'checkout-sheet-kit-api-extractor-'), +); +const declarationOutputRoot = join(temporaryDirectory, 'typescript'); +const declarationOutputDirectory = join(declarationOutputRoot, 'src'); +const relocatedDeclarationDirectory = join( + declarationOutputDirectory, + '_types', +); +const declarationNames = readdirSync(sourceDirectory) + .filter(entry => entry.endsWith('.d.ts')) + .map(entry => entry.slice(0, -'.d.ts'.length)); + +function declarationFiles(directory) { + return readdirSync(directory).flatMap(entry => { + const entryPath = join(directory, entry); + + if (statSync(entryPath).isDirectory()) { + return declarationFiles(entryPath); + } + + return entryPath.endsWith('.d.ts') ? [entryPath] : []; + }); +} + +function relocateDeclarations() { + mkdirSync(relocatedDeclarationDirectory, {recursive: true}); + + for (const declarationName of declarationNames) { + const sourcePath = join(sourceDirectory, `${declarationName}.d.ts`); + const destinationPath = join( + relocatedDeclarationDirectory, + `${declarationName}.d.ts`, + ); + const contents = readFileSync(sourcePath, 'utf8').replace( + /(['"])\.\//g, + '$1../', + ); + + writeFileSync(destinationPath, contents); + } +} + +function rewriteImports() { + for (const declarationPath of declarationFiles(declarationOutputDirectory)) { + let contents = readFileSync(declarationPath, 'utf8'); + + for (const declarationName of declarationNames) { + const relativeTarget = relative( + dirname(declarationPath), + join(relocatedDeclarationDirectory, declarationName), + ).replace(/\\/g, '/'); + const importTarget = relativeTarget.startsWith('.') + ? relativeTarget + : `./${relativeTarget}`; + const importPattern = new RegExp( + `(['"])\\./${declarationName}\\.d\\1`, + 'g', + ); + + contents = contents.replace(importPattern, `$1${importTarget}$1`); + } + + writeFileSync(declarationPath, contents); + } +} + +function extractApi() { + const configPath = join(moduleRoot, 'api-extractor.json'); + const config = ExtractorConfig.loadFile(configPath); + + config.projectFolder = moduleRoot; + config.mainEntryPointFilePath = join( + declarationOutputDirectory, + 'index.d.ts', + ); + config.apiReport.reportFolder = join(moduleRoot, 'api'); + config.apiReport.reportTempFolder = join(temporaryDirectory, 'report'); + + const extractorConfig = ExtractorConfig.prepare({ + configObject: config, + configObjectFullPath: configPath, + packageJsonFullPath: join(moduleRoot, 'package.json'), + }); + const result = Extractor.invoke(extractorConfig, { + localBuild: process.argv.includes('--local'), + showVerboseMessages: true, + }); + + if (!result.succeeded) { + process.exitCode = 1; + } +} + +try { + cpSync(generatedDeclarationDirectory, declarationOutputRoot, { + recursive: true, + }); + relocateDeclarations(); + rewriteImports(); + extractApi(); +} finally { + rmSync(temporaryDirectory, {recursive: true, force: true}); +} diff --git a/modules/@shopify/checkout-sheet-kit/src/index.ts b/modules/@shopify/checkout-sheet-kit/src/index.ts index ee19bb74..deda8499 100644 --- a/modules/@shopify/checkout-sheet-kit/src/index.ts +++ b/modules/@shopify/checkout-sheet-kit/src/index.ts @@ -54,7 +54,10 @@ import { import {CheckoutErrorCode} from './errors.d'; import type {CheckoutCompletedEvent} from './events.d'; import type {CustomEvent, PixelEvent, StandardEvent} from './pixels.d'; -import {ApplePayLabel, ApplePayStyle} from './components/AcceleratedCheckoutButtons'; +import { + ApplePayLabel, + ApplePayStyle, +} from './components/AcceleratedCheckoutButtons'; import type { AcceleratedCheckoutButtonsProps, RenderStateChangeEvent, @@ -83,19 +86,12 @@ class ShopifyCheckoutSheet implements ShopifyCheckoutSheetKit { private _acceleratedCheckoutsReady = false; - // TurboModule constants are immutable for the lifetime of the process — - // capture once so `version` (and any future constants) can be read without - // re-crossing the JSI boundary on every access. - private readonly constants = RNShopifyCheckoutSheetKit.getConstants(); + public readonly version = RNShopifyCheckoutSheetKit.getConstants().version; public get acceleratedCheckoutsReady(): boolean { return this._acceleratedCheckoutsReady; } - public get version(): string { - return this.constants.version; - } - /** * Initializes a new ShopifyCheckoutSheet instance * @param configuration Optional configuration settings for the checkout diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d514be2f..b0b373d6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -105,6 +105,9 @@ importers: specifier: '*' version: 0.80.2(@babel/core@7.28.3)(@react-native-community/cli@19.1.1(typescript@5.9.2))(@types/react@19.1.12)(react@19.1.0) devDependencies: + '@microsoft/api-extractor': + specifier: ^7.58.7 + version: 7.58.12(@types/node@20.9.3) react-native-builder-bob: specifier: ^0.23.2 version: 0.23.2 @@ -1013,7 +1016,7 @@ packages: engines: {node: '>=6.9.0'} '@babel/traverse@7.29.0': - resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} + resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==, tarball: https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz} engines: {node: '>=6.9.0'} '@babel/types@7.28.2': @@ -1035,13 +1038,13 @@ packages: engines: {node: '>=0.8.0'} '@emnapi/core@1.4.3': - resolution: {integrity: sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==} + resolution: {integrity: sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==, tarball: https://registry.npmjs.org/@emnapi/core/-/core-1.4.3.tgz} '@emnapi/runtime@1.4.3': - resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==} + resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==, tarball: https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz} '@emnapi/wasi-threads@1.0.2': - resolution: {integrity: sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==} + resolution: {integrity: sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==, tarball: https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.2.tgz} '@eslint-community/eslint-utils@4.4.0': resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} @@ -1238,8 +1241,21 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@microsoft/api-extractor-model@7.33.10': + resolution: {integrity: sha512-uPUK17xGxeQ3av6TN7awp+dTTSTvx8fZC0XFL1gyt7hFapYuxND3XLXH8vkmI7UjfW92oogzFAFqHSifmJROaw==, tarball: https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.33.10.tgz} + + '@microsoft/api-extractor@7.58.12': + resolution: {integrity: sha512-VNpgC/1LaroLbn+UKmwDYspq+9r3EHyj4vJ3qUy/g8vB0rKt+1Wgs7WFj/JGpgxhG8SNyXs1XwYwe7nqkk8IDg==, tarball: https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.58.12.tgz} + hasBin: true + + '@microsoft/tsdoc-config@0.18.1': + resolution: {integrity: sha512-9brPoVdfN9k9g0dcWkFeA7IH9bbcttzDJlXvkf8b2OBzd5MueR1V2wkKBL0abn0otvmkHJC6aapBOTJDDeMCZg==, tarball: https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.18.1.tgz} + + '@microsoft/tsdoc@0.16.0': + resolution: {integrity: sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA==, tarball: https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.16.0.tgz} + '@napi-rs/wasm-runtime@0.2.11': - resolution: {integrity: sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==} + resolution: {integrity: sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==, tarball: https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.11.tgz} '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} @@ -1257,7 +1273,7 @@ packages: engines: {node: '>= 8'} '@pkgjs/parseargs@0.11.0': - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==, tarball: https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz} engines: {node: '>=14'} '@pkgr/core@0.2.7': @@ -1445,6 +1461,36 @@ packages: react-native-safe-area-context: '>= 4.0.0' react-native-screens: '>= 4.0.0' + '@rushstack/node-core-library@5.23.3': + resolution: {integrity: sha512-f6uuza7Um65bwsIJgf0MRs7IPA5IG+A+zs1AYGQvpZmLjtTGdfHowhQw4kwF0pPhJCrU4UHNhK8Qa6tLygYZCA==, tarball: https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.23.3.tgz} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/problem-matcher@0.2.1': + resolution: {integrity: sha512-gulfhBs6n+I5b7DvjKRfhMGyUejtSgOHTclF/eONr8hcgF1APEDjhxIsfdUYYMzC3rvLwGluqLjbwCFZ8nxrog==, tarball: https://registry.npmjs.org/@rushstack/problem-matcher/-/problem-matcher-0.2.1.tgz} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/rig-package@0.7.3': + resolution: {integrity: sha512-aAA518n6wxxjCfnTAOjQnm7ngNE0FVHxHAw2pxKlIhxrMn0XQjGcXKF0oKWpjBgJOmsaJpVob/v+zr3zxgPWuA==, tarball: https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.7.3.tgz} + + '@rushstack/terminal@0.24.2': + resolution: {integrity: sha512-KB7PpvzDyKMw/RGU3TxOwxTs3OwZ4gq6+WHlTJN/JfQH4ezliNtWIqver78jTaAJyz/ZAAlJGH7a/M1WyFLFSw==, tarball: https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.24.2.tgz} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/ts-command-line@5.3.12': + resolution: {integrity: sha512-Vg2n24arSf7JvUNga2DMHYTbxnVq9L5OtVCp4Gfr8YC/kmL/bmdR8FQhGcpMzMYNY9Vdw3+TaimG11Sf+z1Tpw==, tarball: https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-5.3.12.tgz} + '@sideway/address@4.1.5': resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==} @@ -1485,7 +1531,10 @@ packages: resolution: {integrity: sha512-cWG+s5ZJfEBhaJbCs8QqeWhGbYHhUoq93+wOAdGzh1k/m7FkEmJkUTVsCVJ+rhLpwTNIVrLaHL/IUfBne5D6mw==} '@tybys/wasm-util@0.9.0': - resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} + resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==, tarball: https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz} + + '@types/argparse@1.0.38': + resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==, tarball: https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz} '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -1652,105 +1701,105 @@ packages: resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} '@unrs/resolver-binding-android-arm-eabi@1.9.2': - resolution: {integrity: sha512-tS+lqTU3N0kkthU+rYp0spAYq15DU8ld9kXkaKg9sbQqJNF+WPMuNHZQGCgdxrUOEO0j22RKMwRVhF1HTl+X8A==} + resolution: {integrity: sha512-tS+lqTU3N0kkthU+rYp0spAYq15DU8ld9kXkaKg9sbQqJNF+WPMuNHZQGCgdxrUOEO0j22RKMwRVhF1HTl+X8A==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.9.2.tgz} cpu: [arm] os: [android] '@unrs/resolver-binding-android-arm64@1.9.2': - resolution: {integrity: sha512-MffGiZULa/KmkNjHeuuflLVqfhqLv1vZLm8lWIyeADvlElJ/GLSOkoUX+5jf4/EGtfwrNFcEaB8BRas03KT0/Q==} + resolution: {integrity: sha512-MffGiZULa/KmkNjHeuuflLVqfhqLv1vZLm8lWIyeADvlElJ/GLSOkoUX+5jf4/EGtfwrNFcEaB8BRas03KT0/Q==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.9.2.tgz} cpu: [arm64] os: [android] '@unrs/resolver-binding-darwin-arm64@1.9.2': - resolution: {integrity: sha512-dzJYK5rohS1sYl1DHdJ3mwfwClJj5BClQnQSyAgEfggbUwA9RlROQSSbKBLqrGfsiC/VyrDPtbO8hh56fnkbsQ==} + resolution: {integrity: sha512-dzJYK5rohS1sYl1DHdJ3mwfwClJj5BClQnQSyAgEfggbUwA9RlROQSSbKBLqrGfsiC/VyrDPtbO8hh56fnkbsQ==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.9.2.tgz} cpu: [arm64] os: [darwin] '@unrs/resolver-binding-darwin-x64@1.9.2': - resolution: {integrity: sha512-gaIMWK+CWtXcg9gUyznkdV54LzQ90S3X3dn8zlh+QR5Xy7Y+Efqw4Rs4im61K1juy4YNb67vmJsCDAGOnIeffQ==} + resolution: {integrity: sha512-gaIMWK+CWtXcg9gUyznkdV54LzQ90S3X3dn8zlh+QR5Xy7Y+Efqw4Rs4im61K1juy4YNb67vmJsCDAGOnIeffQ==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.9.2.tgz} cpu: [x64] os: [darwin] '@unrs/resolver-binding-freebsd-x64@1.9.2': - resolution: {integrity: sha512-S7QpkMbVoVJb0xwHFwujnwCAEDe/596xqY603rpi/ioTn9VDgBHnCCxh+UFrr5yxuMH+dliHfjwCZJXOPJGPnw==} + resolution: {integrity: sha512-S7QpkMbVoVJb0xwHFwujnwCAEDe/596xqY603rpi/ioTn9VDgBHnCCxh+UFrr5yxuMH+dliHfjwCZJXOPJGPnw==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.9.2.tgz} cpu: [x64] os: [freebsd] '@unrs/resolver-binding-linux-arm-gnueabihf@1.9.2': - resolution: {integrity: sha512-+XPUMCuCCI80I46nCDFbGum0ZODP5NWGiwS3Pj8fOgsG5/ctz+/zzuBlq/WmGa+EjWZdue6CF0aWWNv84sE1uw==} + resolution: {integrity: sha512-+XPUMCuCCI80I46nCDFbGum0ZODP5NWGiwS3Pj8fOgsG5/ctz+/zzuBlq/WmGa+EjWZdue6CF0aWWNv84sE1uw==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.9.2.tgz} cpu: [arm] os: [linux] '@unrs/resolver-binding-linux-arm-musleabihf@1.9.2': - resolution: {integrity: sha512-sqvUyAd1JUpwbz33Ce2tuTLJKM+ucSsYpPGl2vuFwZnEIg0CmdxiZ01MHQ3j6ExuRqEDUCy8yvkDKvjYFPb8Zg==} + resolution: {integrity: sha512-sqvUyAd1JUpwbz33Ce2tuTLJKM+ucSsYpPGl2vuFwZnEIg0CmdxiZ01MHQ3j6ExuRqEDUCy8yvkDKvjYFPb8Zg==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.9.2.tgz} cpu: [arm] os: [linux] '@unrs/resolver-binding-linux-arm64-gnu@1.9.2': - resolution: {integrity: sha512-UYA0MA8ajkEDCFRQdng/FVx3F6szBvk3EPnkTTQuuO9lV1kPGuTB+V9TmbDxy5ikaEgyWKxa4CI3ySjklZ9lFA==} + resolution: {integrity: sha512-UYA0MA8ajkEDCFRQdng/FVx3F6szBvk3EPnkTTQuuO9lV1kPGuTB+V9TmbDxy5ikaEgyWKxa4CI3ySjklZ9lFA==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.9.2.tgz} cpu: [arm64] os: [linux] libc: [glibc] '@unrs/resolver-binding-linux-arm64-musl@1.9.2': - resolution: {integrity: sha512-P/CO3ODU9YJIHFqAkHbquKtFst0COxdphc8TKGL5yCX75GOiVpGqd1d15ahpqu8xXVsqP4MGFP2C3LRZnnL5MA==} + resolution: {integrity: sha512-P/CO3ODU9YJIHFqAkHbquKtFst0COxdphc8TKGL5yCX75GOiVpGqd1d15ahpqu8xXVsqP4MGFP2C3LRZnnL5MA==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.9.2.tgz} cpu: [arm64] os: [linux] libc: [musl] '@unrs/resolver-binding-linux-ppc64-gnu@1.9.2': - resolution: {integrity: sha512-uKStFlOELBxBum2s1hODPtgJhY4NxYJE9pAeyBgNEzHgTqTiVBPjfTlPFJkfxyTjQEuxZbbJlJnMCrRgD7ubzw==} + resolution: {integrity: sha512-uKStFlOELBxBum2s1hODPtgJhY4NxYJE9pAeyBgNEzHgTqTiVBPjfTlPFJkfxyTjQEuxZbbJlJnMCrRgD7ubzw==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.9.2.tgz} cpu: [ppc64] os: [linux] libc: [glibc] '@unrs/resolver-binding-linux-riscv64-gnu@1.9.2': - resolution: {integrity: sha512-LkbNnZlhINfY9gK30AHs26IIVEZ9PEl9qOScYdmY2o81imJYI4IMnJiW0vJVtXaDHvBvxeAgEy5CflwJFIl3tQ==} + resolution: {integrity: sha512-LkbNnZlhINfY9gK30AHs26IIVEZ9PEl9qOScYdmY2o81imJYI4IMnJiW0vJVtXaDHvBvxeAgEy5CflwJFIl3tQ==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.9.2.tgz} cpu: [riscv64] os: [linux] libc: [glibc] '@unrs/resolver-binding-linux-riscv64-musl@1.9.2': - resolution: {integrity: sha512-vI+e6FzLyZHSLFNomPi+nT+qUWN4YSj8pFtQZSFTtmgFoxqB6NyjxSjAxEC1m93qn6hUXhIsh8WMp+fGgxCoRg==} + resolution: {integrity: sha512-vI+e6FzLyZHSLFNomPi+nT+qUWN4YSj8pFtQZSFTtmgFoxqB6NyjxSjAxEC1m93qn6hUXhIsh8WMp+fGgxCoRg==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.9.2.tgz} cpu: [riscv64] os: [linux] libc: [musl] '@unrs/resolver-binding-linux-s390x-gnu@1.9.2': - resolution: {integrity: sha512-sSO4AlAYhSM2RAzBsRpahcJB1msc6uYLAtP6pesPbZtptF8OU/CbCPhSRW6cnYOGuVmEmWVW5xVboAqCnWTeHQ==} + resolution: {integrity: sha512-sSO4AlAYhSM2RAzBsRpahcJB1msc6uYLAtP6pesPbZtptF8OU/CbCPhSRW6cnYOGuVmEmWVW5xVboAqCnWTeHQ==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.9.2.tgz} cpu: [s390x] os: [linux] libc: [glibc] '@unrs/resolver-binding-linux-x64-gnu@1.9.2': - resolution: {integrity: sha512-jkSkwch0uPFva20Mdu8orbQjv2A3G88NExTN2oPTI1AJ+7mZfYW3cDCTyoH6OnctBKbBVeJCEqh0U02lTkqD5w==} + resolution: {integrity: sha512-jkSkwch0uPFva20Mdu8orbQjv2A3G88NExTN2oPTI1AJ+7mZfYW3cDCTyoH6OnctBKbBVeJCEqh0U02lTkqD5w==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.9.2.tgz} cpu: [x64] os: [linux] libc: [glibc] '@unrs/resolver-binding-linux-x64-musl@1.9.2': - resolution: {integrity: sha512-Uk64NoiTpQbkpl+bXsbeyOPRpUoMdcUqa+hDC1KhMW7aN1lfW8PBlBH4mJ3n3Y47dYE8qi0XTxy1mBACruYBaw==} + resolution: {integrity: sha512-Uk64NoiTpQbkpl+bXsbeyOPRpUoMdcUqa+hDC1KhMW7aN1lfW8PBlBH4mJ3n3Y47dYE8qi0XTxy1mBACruYBaw==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.9.2.tgz} cpu: [x64] os: [linux] libc: [musl] '@unrs/resolver-binding-wasm32-wasi@1.9.2': - resolution: {integrity: sha512-EpBGwkcjDicjR/ybC0g8wO5adPNdVuMrNalVgYcWi+gYtC1XYNuxe3rufcO7dA76OHGeVabcO6cSkPJKVcbCXQ==} + resolution: {integrity: sha512-EpBGwkcjDicjR/ybC0g8wO5adPNdVuMrNalVgYcWi+gYtC1XYNuxe3rufcO7dA76OHGeVabcO6cSkPJKVcbCXQ==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.9.2.tgz} engines: {node: '>=14.0.0'} cpu: [wasm32] '@unrs/resolver-binding-win32-arm64-msvc@1.9.2': - resolution: {integrity: sha512-EdFbGn7o1SxGmN6aZw9wAkehZJetFPao0VGZ9OMBwKx6TkvDuj6cNeLimF/Psi6ts9lMOe+Dt6z19fZQ9Ye2fw==} + resolution: {integrity: sha512-EdFbGn7o1SxGmN6aZw9wAkehZJetFPao0VGZ9OMBwKx6TkvDuj6cNeLimF/Psi6ts9lMOe+Dt6z19fZQ9Ye2fw==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.9.2.tgz} cpu: [arm64] os: [win32] '@unrs/resolver-binding-win32-ia32-msvc@1.9.2': - resolution: {integrity: sha512-JY9hi1p7AG+5c/dMU8o2kWemM8I6VZxfGwn1GCtf3c5i+IKcMo2NQ8OjZ4Z3/itvY/Si3K10jOBQn7qsD/whUA==} + resolution: {integrity: sha512-JY9hi1p7AG+5c/dMU8o2kWemM8I6VZxfGwn1GCtf3c5i+IKcMo2NQ8OjZ4Z3/itvY/Si3K10jOBQn7qsD/whUA==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.9.2.tgz} cpu: [ia32] os: [win32] '@unrs/resolver-binding-win32-x64-msvc@1.9.2': - resolution: {integrity: sha512-ryoo+EB19lMxAd80ln9BVf8pdOAxLb97amrQ3SFN9OCRn/5M5wvwDgAe4i8ZjhpbiHoDeP8yavcTEnpKBo7lZg==} + resolution: {integrity: sha512-ryoo+EB19lMxAd80ln9BVf8pdOAxLb97amrQ3SFN9OCRn/5M5wvwDgAe4i8ZjhpbiHoDeP8yavcTEnpKBo7lZg==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.9.2.tgz} cpu: [x64] os: [win32] @@ -1799,9 +1848,31 @@ packages: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} + ajv-draft-04@1.0.0: + resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==, tarball: https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz} + peerDependencies: + ajv: ^8.5.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==, tarball: https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ajv@8.18.0: + resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==, tarball: https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz} + + ajv@8.20.0: + resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==, tarball: https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz} + anser@1.4.10: resolution: {integrity: sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==} @@ -1968,6 +2039,10 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==, tarball: https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz} + engines: {node: 18 || 20 || >=22} + base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -1984,6 +2059,10 @@ packages: brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + brace-expansion@5.0.9: + resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==, tarball: https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz} + engines: {node: 20 || >=22} + braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} @@ -2287,6 +2366,10 @@ packages: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + diff@8.0.4: + resolution: {integrity: sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==, tarball: https://registry.npmjs.org/diff/-/diff-8.0.4.tgz} + engines: {node: '>=0.3.1'} + dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -2573,6 +2656,9 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + fast-uri@3.1.6: + resolution: {integrity: sha512-7Ical1vFEMr0onbVzEDIreM22I4khW+fzyQPwvAFWBp1iwdshSZRsL4jjRvPG9JP1uiqMHRto+YU6R2/CzDz5Q==, tarball: https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.6.tgz} + fast-xml-parser@4.5.6: resolution: {integrity: sha512-Yd4vkROfJf8AuJrDIVMVmYfULKmIJszVsMv7Vo71aocsKgFxpdlpSHXSaInvyYfgw2PRuObQSW2GFpVMUjxu9A==} hasBin: true @@ -2640,6 +2726,10 @@ packages: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} + fs-extra@11.3.6: + resolution: {integrity: sha512-w8ZNZr2mKIc7qeNaQ9AVPT1+iFaI+Avd4xudVOvdDJ8VytREi1Ft5Ih7hd9jjehod8vAM5GMsfQ/TpPf4EyoEA==, tarball: https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.6.tgz} + engines: {node: '>=14.14'} + fs-extra@8.1.0: resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} engines: {node: '>=6 <7 || >=8'} @@ -2648,7 +2738,7 @@ packages: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==, tarball: https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] @@ -2847,6 +2937,10 @@ packages: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} + import-lazy@4.0.0: + resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==, tarball: https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz} + engines: {node: '>=8'} + import-local@3.2.0: resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} engines: {node: '>=8'} @@ -3252,6 +3346,9 @@ packages: node-notifier: optional: true + jju@1.4.0: + resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==, tarball: https://registry.npmjs.org/jju/-/jju-1.4.0.tgz} + joi@17.13.3: resolution: {integrity: sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==} @@ -3309,6 +3406,9 @@ packages: json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==, tarball: https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz} + json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} @@ -3524,6 +3624,10 @@ packages: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} + minimatch@10.2.3: + resolution: {integrity: sha512-Rwi3pnapEqirPSbWbrZaa6N3nmqq4Xer/2XooiOKyV3q12ML06f7MOuc5DVH8ONZIFhwIYQ3yzPH4nt7iWHaTg==, tarball: https://registry.npmjs.org/minimatch/-/minimatch-10.2.3.tgz} + engines: {node: 18 || 20 || >=22} + minimatch@3.1.5: resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} @@ -4055,6 +4159,10 @@ packages: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==, tarball: https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz} + engines: {node: '>=0.10.0'} + require-main-filename@2.0.0: resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} @@ -4128,6 +4236,11 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==, tarball: https://registry.npmjs.org/semver/-/semver-7.7.4.tgz} + engines: {node: '>=10'} + hasBin: true + send@0.19.0: resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} engines: {node: '>= 0.8.0'} @@ -4254,6 +4367,10 @@ packages: resolution: {integrity: sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==} engines: {node: '>=4'} + string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==, tarball: https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz} + engines: {node: '>=0.6.19'} + string-length@4.0.2: resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} engines: {node: '>=10'} @@ -4412,32 +4529,32 @@ packages: typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' turbo-darwin-64@1.13.4: - resolution: {integrity: sha512-A0eKd73R7CGnRinTiS7txkMElg+R5rKFp9HV7baDiEL4xTG1FIg/56Vm7A5RVgg8UNgG2qNnrfatJtb+dRmNdw==} + resolution: {integrity: sha512-A0eKd73R7CGnRinTiS7txkMElg+R5rKFp9HV7baDiEL4xTG1FIg/56Vm7A5RVgg8UNgG2qNnrfatJtb+dRmNdw==, tarball: https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-1.13.4.tgz} cpu: [x64] os: [darwin] turbo-darwin-arm64@1.13.4: - resolution: {integrity: sha512-eG769Q0NF6/Vyjsr3mKCnkG/eW6dKMBZk6dxWOdrHfrg6QgfkBUk0WUUujzdtVPiUIvsh4l46vQrNVd9EOtbyA==} + resolution: {integrity: sha512-eG769Q0NF6/Vyjsr3mKCnkG/eW6dKMBZk6dxWOdrHfrg6QgfkBUk0WUUujzdtVPiUIvsh4l46vQrNVd9EOtbyA==, tarball: https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-1.13.4.tgz} cpu: [arm64] os: [darwin] turbo-linux-64@1.13.4: - resolution: {integrity: sha512-Bq0JphDeNw3XEi+Xb/e4xoKhs1DHN7OoLVUbTIQz+gazYjigVZvtwCvgrZI7eW9Xo1eOXM2zw2u1DGLLUfmGkQ==} + resolution: {integrity: sha512-Bq0JphDeNw3XEi+Xb/e4xoKhs1DHN7OoLVUbTIQz+gazYjigVZvtwCvgrZI7eW9Xo1eOXM2zw2u1DGLLUfmGkQ==, tarball: https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-1.13.4.tgz} cpu: [x64] os: [linux] turbo-linux-arm64@1.13.4: - resolution: {integrity: sha512-BJcXw1DDiHO/okYbaNdcWN6szjXyHWx9d460v6fCHY65G8CyqGU3y2uUTPK89o8lq/b2C8NK0yZD+Vp0f9VoIg==} + resolution: {integrity: sha512-BJcXw1DDiHO/okYbaNdcWN6szjXyHWx9d460v6fCHY65G8CyqGU3y2uUTPK89o8lq/b2C8NK0yZD+Vp0f9VoIg==, tarball: https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-1.13.4.tgz} cpu: [arm64] os: [linux] turbo-windows-64@1.13.4: - resolution: {integrity: sha512-OFFhXHOFLN7A78vD/dlVuuSSVEB3s9ZBj18Tm1hk3aW1HTWTuAw0ReN6ZNlVObZUHvGy8d57OAGGxf2bT3etQw==} + resolution: {integrity: sha512-OFFhXHOFLN7A78vD/dlVuuSSVEB3s9ZBj18Tm1hk3aW1HTWTuAw0ReN6ZNlVObZUHvGy8d57OAGGxf2bT3etQw==, tarball: https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-1.13.4.tgz} cpu: [x64] os: [win32] turbo-windows-arm64@1.13.4: - resolution: {integrity: sha512-u5A+VOKHswJJmJ8o8rcilBfU5U3Y1TTAfP9wX8bFh8teYF1ghP0EhtMRLjhtp6RPa+XCxHHVA2CiC3gbh5eg5g==} + resolution: {integrity: sha512-u5A+VOKHswJJmJ8o8rcilBfU5U3Y1TTAfP9wX8bFh8teYF1ghP0EhtMRLjhtp6RPa+XCxHHVA2CiC3gbh5eg5g==, tarball: https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-1.13.4.tgz} cpu: [arm64] os: [win32] @@ -4493,8 +4610,13 @@ packages: engines: {node: '>=14.17'} hasBin: true + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==, tarball: https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz} + engines: {node: '>=14.17'} + hasBin: true + uglify-js@3.19.3: - resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} + resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==, tarball: https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz} engines: {node: '>=0.8.0'} hasBin: true @@ -6088,6 +6210,41 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@microsoft/api-extractor-model@7.33.10(@types/node@20.9.3)': + dependencies: + '@microsoft/tsdoc': 0.16.0 + '@microsoft/tsdoc-config': 0.18.1 + '@rushstack/node-core-library': 5.23.3(@types/node@20.9.3) + transitivePeerDependencies: + - '@types/node' + + '@microsoft/api-extractor@7.58.12(@types/node@20.9.3)': + dependencies: + '@microsoft/api-extractor-model': 7.33.10(@types/node@20.9.3) + '@microsoft/tsdoc': 0.16.0 + '@microsoft/tsdoc-config': 0.18.1 + '@rushstack/node-core-library': 5.23.3(@types/node@20.9.3) + '@rushstack/rig-package': 0.7.3 + '@rushstack/terminal': 0.24.2(@types/node@20.9.3) + '@rushstack/ts-command-line': 5.3.12(@types/node@20.9.3) + diff: 8.0.4 + minimatch: 10.2.3 + resolve: 1.22.10 + semver: 7.7.4 + source-map: 0.6.1 + typescript: 5.9.3 + transitivePeerDependencies: + - '@types/node' + + '@microsoft/tsdoc-config@0.18.1': + dependencies: + '@microsoft/tsdoc': 0.16.0 + ajv: 8.18.0 + jju: 1.4.0 + resolve: 1.22.10 + + '@microsoft/tsdoc@0.16.0': {} + '@napi-rs/wasm-runtime@0.2.11': dependencies: '@emnapi/core': 1.4.3 @@ -6400,7 +6557,9 @@ snapshots: metro-runtime: 0.82.5 transitivePeerDependencies: - '@babel/core' + - bufferutil - supports-color + - utf-8-validate '@react-native/normalize-colors@0.80.2': {} @@ -6494,6 +6653,45 @@ snapshots: transitivePeerDependencies: - '@react-native-masked-view/masked-view' + '@rushstack/node-core-library@5.23.3(@types/node@20.9.3)': + dependencies: + ajv: 8.20.0 + ajv-draft-04: 1.0.0(ajv@8.20.0) + ajv-formats: 3.0.1(ajv@8.20.0) + fs-extra: 11.3.6 + import-lazy: 4.0.0 + jju: 1.4.0 + resolve: 1.22.10 + semver: 7.7.4 + optionalDependencies: + '@types/node': 20.9.3 + + '@rushstack/problem-matcher@0.2.1(@types/node@20.9.3)': + optionalDependencies: + '@types/node': 20.9.3 + + '@rushstack/rig-package@0.7.3': + dependencies: + jju: 1.4.0 + resolve: 1.22.10 + + '@rushstack/terminal@0.24.2(@types/node@20.9.3)': + dependencies: + '@rushstack/node-core-library': 5.23.3(@types/node@20.9.3) + '@rushstack/problem-matcher': 0.2.1(@types/node@20.9.3) + supports-color: 8.1.1 + optionalDependencies: + '@types/node': 20.9.3 + + '@rushstack/ts-command-line@5.3.12(@types/node@20.9.3)': + dependencies: + '@rushstack/terminal': 0.24.2(@types/node@20.9.3) + '@types/argparse': 1.0.38 + argparse: 1.0.10 + string-argv: 0.3.2 + transitivePeerDependencies: + - '@types/node' + '@sideway/address@4.1.5': dependencies: '@hapi/hoek': 9.3.0 @@ -6537,6 +6735,8 @@ snapshots: tslib: 2.8.1 optional: true + '@types/argparse@1.0.38': {} + '@types/babel__core@7.20.5': dependencies: '@babel/parser': 7.28.3 @@ -6857,6 +7057,14 @@ snapshots: clean-stack: 2.2.0 indent-string: 4.0.0 + ajv-draft-04@1.0.0(ajv@8.20.0): + optionalDependencies: + ajv: 8.20.0 + + ajv-formats@3.0.1(ajv@8.20.0): + optionalDependencies: + ajv: 8.20.0 + ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 @@ -6864,6 +7072,20 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ajv@8.18.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.6 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ajv@8.20.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.6 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + anser@1.4.10: {} ansi-escapes@4.3.2: @@ -7102,6 +7324,8 @@ snapshots: balanced-match@1.0.2: {} + balanced-match@4.0.4: {} + base64-js@1.5.1: {} bl@4.1.0: @@ -7136,6 +7360,10 @@ snapshots: dependencies: balanced-match: 1.0.2 + brace-expansion@5.0.9: + dependencies: + balanced-match: 4.0.4 + braces@3.0.3: dependencies: fill-range: 7.1.1 @@ -7431,6 +7659,8 @@ snapshots: diff-sequences@29.6.3: {} + diff@8.0.4: {} + dir-glob@3.0.1: dependencies: path-type: 4.0.0 @@ -7795,6 +8025,8 @@ snapshots: fast-levenshtein@2.0.6: {} + fast-uri@3.1.6: {} + fast-xml-parser@4.5.6: dependencies: strnum: 1.1.2 @@ -7874,6 +8106,12 @@ snapshots: jsonfile: 6.2.1 universalify: 2.0.1 + fs-extra@11.3.6: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.1 + universalify: 2.0.1 + fs-extra@8.1.0: dependencies: graceful-fs: 4.2.11 @@ -8091,6 +8329,8 @@ snapshots: parent-module: 1.0.1 resolve-from: 4.0.0 + import-lazy@4.0.0: {} + import-local@3.2.0: dependencies: pkg-dir: 4.2.0 @@ -8726,6 +8966,8 @@ snapshots: - supports-color - ts-node + jju@1.4.0: {} + joi@17.13.3: dependencies: '@hapi/hoek': 9.3.0 @@ -8766,6 +9008,8 @@ snapshots: json-schema-traverse@0.4.1: {} + json-schema-traverse@1.0.0: {} + json-stable-stringify-without-jsonify@1.0.1: {} json5@2.2.3: {} @@ -9078,6 +9322,10 @@ snapshots: min-indent@1.0.1: {} + minimatch@10.2.3: + dependencies: + brace-expansion: 5.0.9 + minimatch@3.1.5: dependencies: brace-expansion: 1.1.11 @@ -9651,6 +9899,8 @@ snapshots: require-directory@2.1.1: {} + require-from-string@2.0.2: {} + require-main-filename@2.0.0: {} reselect@4.1.8: {} @@ -9715,6 +9965,8 @@ snapshots: semver@7.7.2: {} + semver@7.7.4: {} + send@0.19.0: dependencies: debug: 2.6.9 @@ -9855,6 +10107,8 @@ snapshots: strict-uri-encode@2.0.0: {} + string-argv@0.3.2: {} + string-length@4.0.2: dependencies: char-regex: 1.0.2 @@ -10085,6 +10339,8 @@ snapshots: typescript@5.9.2: {} + typescript@5.9.3: {} + uglify-js@3.19.3: optional: true diff --git a/sample/android/app/build.gradle b/sample/android/app/build.gradle index 6fd6e13c..0349caf2 100644 --- a/sample/android/app/build.gradle +++ b/sample/android/app/build.gradle @@ -108,7 +108,7 @@ android { applicationId "com.shopify.checkoutkitreactnative" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 12 + versionCode 13 versionName "1.1" } signingConfigs { From b137016e36e59235e5088550cb3facdec07f23b8 Mon Sep 17 00:00:00 2001 From: Kieran Osgood Date: Wed, 26 Aug 2026 11:15:32 +0100 Subject: [PATCH 8/8] review comments --- .../ShopifyCheckoutSheetKitModule.java | 4 +- .../checkout-sheet-kit/src/context.tsx | 79 +++++++++++-------- 2 files changed, 48 insertions(+), 35 deletions(-) diff --git a/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java b/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java index 10f71db7..424e3100 100644 --- a/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java +++ b/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java @@ -92,7 +92,7 @@ public void removeListeners(double count) { @ReactMethod public void present(String checkoutURL) { - Activity currentActivity = getCurrentActivity(); + Activity currentActivity = getReactApplicationContext().getCurrentActivity(); if (currentActivity instanceof ComponentActivity) { checkoutEventProcessor = new CustomCheckoutEventProcessor(currentActivity, this.reactContext); currentActivity.runOnUiThread(() -> { @@ -112,7 +112,7 @@ public void dismiss() { @ReactMethod public void preload(String checkoutURL) { - Activity currentActivity = getCurrentActivity(); + Activity currentActivity = getReactApplicationContext().getCurrentActivity(); if (currentActivity instanceof ComponentActivity) { ShopifyCheckoutSheetKit.preload(checkoutURL, (ComponentActivity) currentActivity); diff --git a/modules/@shopify/checkout-sheet-kit/src/context.tsx b/modules/@shopify/checkout-sheet-kit/src/context.tsx index 713c60c1..1bf64de1 100644 --- a/modules/@shopify/checkout-sheet-kit/src/context.tsx +++ b/modules/@shopify/checkout-sheet-kit/src/context.tsx @@ -70,9 +70,11 @@ export function ShopifyCheckoutSheetProvider({ instance.current = new ShopifyCheckoutSheet(configuration, features); } + const checkout = instance.current; + useEffect(() => { async function configureCheckoutKit() { - if (!instance.current || !configuration) { + if (!configuration) { return; } @@ -81,58 +83,68 @@ export function ShopifyCheckoutSheetProvider({ // eslint-disable-next-line no-console console.warn( '[ShopifyCheckoutSheetKit] Providing accessToken with contactFields (email / phoneNumber) is deprecated and will become an error in v4.' + - 'When the user is authenticated with Customer Accounts, provide accessToken' + - 'When the user is otherwise authenticated, provide email/phoneNumber.', + 'When the user is authenticated with Customer Accounts, provide accessToken' + + 'When the user is otherwise authenticated, provide email/phoneNumber.', ); } - await instance.current.setConfig(configuration); - setAcceleratedCheckoutsAvailable( - instance.current.acceleratedCheckoutsReady, - ); + await checkout.setConfig(configuration); + setAcceleratedCheckoutsAvailable(checkout.acceleratedCheckoutsReady); } configureCheckoutKit(); - }, [configuration]); + }, [checkout, configuration]); const addEventListener: AddEventListener = useCallback( (eventName, callback): EmitterSubscription | undefined => { - return instance.current?.addEventListener(eventName, callback); + return checkout.addEventListener(eventName, callback); }, - [], + [checkout], ); - const removeEventListeners = useCallback((eventName: CheckoutEvent) => { - instance.current?.removeEventListeners(eventName); - }, []); + const removeEventListeners = useCallback( + (eventName: CheckoutEvent) => { + checkout.removeEventListeners(eventName); + }, + [checkout], + ); - const present = useCallback((checkoutUrl: string) => { - if (checkoutUrl) { - instance.current?.present(checkoutUrl); - } - }, []); + const present = useCallback( + (checkoutUrl: string) => { + if (checkoutUrl) { + checkout.present(checkoutUrl); + } + }, + [checkout], + ); - const preload = useCallback((checkoutUrl: string) => { - if (checkoutUrl) { - instance.current?.preload(checkoutUrl); - } - }, []); + const preload = useCallback( + (checkoutUrl: string) => { + if (checkoutUrl) { + checkout.preload(checkoutUrl); + } + }, + [checkout], + ); const invalidate = useCallback(() => { - instance.current?.invalidate(); - }, []); + checkout.invalidate(); + }, [checkout]); const dismiss = useCallback(() => { - instance.current?.dismiss(); - }, []); + checkout.dismiss(); + }, [checkout]); - const setConfig = useCallback(async (config: Configuration) => { - await instance.current?.setConfig(config); - }, []); + const setConfig = useCallback( + async (config: Configuration) => { + await checkout.setConfig(config); + }, + [checkout], + ); const getConfig = useCallback(async () => { - return instance.current?.getConfig(); - }, []); + return checkout.getConfig(); + }, [checkout]); const context = useMemo((): Context => { return { @@ -145,11 +157,12 @@ export function ShopifyCheckoutSheetProvider({ present, invalidate, removeEventListeners, - version: instance.current?.version, + version: checkout.version, }; }, [ acceleratedCheckoutsAvailable, addEventListener, + checkout, dismiss, removeEventListeners, getConfig,