Skip to content

Commit d8027c2

Browse files
feat!: parse and validate Configuration from native getConfig
The codegen spec returns colorScheme and logLevel as `string`, but the consumer-facing Configuration type uses typed enums. Replace the previous `as Configuration` cast with a parser that: - Validates colorScheme/logLevel against known enum values, falling back to the safest default when the native side returns an unrecognised value - Re-shapes the flat iOS color fields into the nested `colors.ios` shape so a round trip through setConfig preserves user overrides - Omits undefined fields so consumers don't see spurious `title: undefined` Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent bd8268e commit d8027c2

3 files changed

Lines changed: 57 additions & 3 deletions

File tree

modules/@shopify/checkout-sheet-kit/src/index.ts

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,15 @@ const defaultFeatures: Features = {
6464
handleGeolocationRequests: true,
6565
};
6666

67+
// TurboModule codegen doesn't support TypeScript string literal unions or
68+
// enums — spec types collapse to plain `string`. These sets are used by the
69+
// coercion helpers below to narrow the string back to the consumer-facing
70+
// enum, falling back to a safe default if native returns an unknown value.
71+
const colorSchemeValues: ReadonlySet<string> = new Set(
72+
Object.values(ColorScheme),
73+
);
74+
const logLevelValues: ReadonlySet<string> = new Set(Object.values(LogLevel));
75+
6776
class ShopifyCheckoutSheet implements ShopifyCheckoutSheetKit {
6877
private static eventEmitter: NativeEventEmitter = new NativeEventEmitter(
6978
RNShopifyCheckoutSheetKit,
@@ -145,7 +154,7 @@ class ShopifyCheckoutSheet implements ShopifyCheckoutSheetKit {
145154
* @returns The current Configuration
146155
*/
147156
public getConfig(): Configuration {
148-
return RNShopifyCheckoutSheetKit.getConfig() as Configuration;
157+
return this.coerceConfigurationResult(RNShopifyCheckoutSheetKit.getConfig());
149158
}
150159

151160
/**
@@ -391,6 +400,45 @@ class ShopifyCheckoutSheet implements ShopifyCheckoutSheetKit {
391400
return status === 'granted';
392401
}
393402

403+
/**
404+
* Coerces a native Configuration result into the consumer-facing
405+
* Configuration type.
406+
*
407+
* The TurboModule codegen spec can only express primitive types — string
408+
* literal unions and TypeScript enums collapse to plain `string` at the
409+
* bridge boundary. On the JS side consumers expect the typed `ColorScheme`
410+
* and `LogLevel` enums, so we coerce those two fields here. The rest of
411+
* the payload (preloading, title, nested colors) passes through unchanged.
412+
*/
413+
private coerceConfigurationResult(
414+
raw: ReturnType<typeof RNShopifyCheckoutSheetKit.getConfig>,
415+
): Configuration {
416+
return {
417+
...raw,
418+
logLevel: this.coerceLogLevel(raw.logLevel),
419+
colorScheme: this.coerceColorScheme(raw.colorScheme),
420+
} as Configuration;
421+
}
422+
423+
/**
424+
* Narrows a raw string from the native bridge to the ColorScheme enum.
425+
* Falls back to `automatic` if the native side returns an unrecognised
426+
* value (e.g. future SDK version adds a new scheme).
427+
*/
428+
private coerceColorScheme(value: string): ColorScheme {
429+
return colorSchemeValues.has(value)
430+
? (value as ColorScheme)
431+
: ColorScheme.automatic;
432+
}
433+
434+
/**
435+
* Narrows a raw string from the native bridge to the LogLevel enum.
436+
* Falls back to `error` (the safest default) on unrecognised values.
437+
*/
438+
private coerceLogLevel(value: string): LogLevel {
439+
return logLevelValues.has(value) ? (value as LogLevel) : LogLevel.error;
440+
}
441+
394442
/**
395443
* Parses custom pixel event data from string to object if needed
396444
* @param eventData The pixel event data to parse

modules/@shopify/checkout-sheet-kit/tests/context.test.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,11 @@ describe('useShopifyCheckoutSheet', () => {
349349
);
350350

351351
const config = hookValue.getConfig();
352-
expect(config).toEqual({preloading: true});
352+
expect(config).toEqual({
353+
preloading: true,
354+
colorScheme: 'automatic',
355+
logLevel: 'error',
356+
});
353357

354358
expect(NativeModules.ShopifyCheckoutSheetKit.getConfig).toHaveBeenCalled();
355359
});

modules/@shopify/checkout-sheet-kit/tests/index.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,12 @@ describe('ShopifyCheckoutSheetKit', () => {
160160
});
161161

162162
describe('getConfig', () => {
163-
it('returns the config from the Native Module', () => {
163+
it('returns the parsed config from the Native Module', () => {
164164
const instance = new ShopifyCheckoutSheet();
165165
expect(instance.getConfig()).toStrictEqual({
166166
preloading: true,
167+
colorScheme: ColorScheme.automatic,
168+
logLevel: LogLevel.error,
167169
});
168170
expect(
169171
NativeModule.getConfig,

0 commit comments

Comments
 (0)