Skip to content

Fix: Isomorphic OAS SDK gaps (@W-18669767@)#197

Merged
joeluong-sfcc merged 13 commits intofeature/oasfrom
ju/fix-enum-collision
Jun 11, 2025
Merged

Fix: Isomorphic OAS SDK gaps (@W-18669767@)#197
joeluong-sfcc merged 13 commits intofeature/oasfrom
ju/fix-enum-collision

Conversation

@joeluong-sfcc
Copy link
Contributor

@joeluong-sfcc joeluong-sfcc commented Jun 4, 2025

This PR fixes the gaps in OAS SDK generation, namely the typescript naming collisions in the generated index.cjs.d.ts and index.esm.d.ts files, and adds support for implementing a custom class name for Shopper Context via the custom vendor extension, x-sdk-classname.

This PR also does the following:

  • cleans up some failing linting issues and unit tests
  • removes support for node versions 12, 14, 16, and 18, as they have reached end of life and we are doing a major version release.

Problem

There are several reasons why the naming collisions occur. rollup/rollup-plugin-ts is good about name collisions between types, and will append extra characters to prevent naming collisions. Example:

type ShippingItem = { ... }
type ShippingItem$0 = { ... }
type ShippingItem$1 = { ... }

However, there are certain cases where rollup isn't able to resolve these naming collisions, such as for namespaces and variables.

Solution

There are several ways we solve the naming collision issues:

  1. There were naming collisions between all the ApiTypes and ModelTypes, so we append the classname to those, such as ShopperCustomersApiTypes
  2. The way we imported types in the main index.ts file caused the generated *.d.ts file to duplicate types, we just had to fix the way we imported here (templates/index.ts.hbs)
  3. For some reason, the new way we have the API classes/directory set up, ShopperLogin is exported twice due to the SLAS helpers files due to the usage of TokenResponse type and creating a type from the ShopperLogin class. The fix was to create an interface that we use for typing instead. We do this in the commerce SDK: https://github.com/SalesforceCommerceCloud/commerce-sdk/blob/1c729a9a93af9bde5aea9a4a760be6e2d1533b19/src/static/helpers/slasClient.ts#L47

@@ -25,14 +25,12 @@ export enum {{classname}}{{enumName}} {
{{/allowableValues}}
}
{{/stringEnums}}{{^stringEnums}}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The resulting type is functionally the same, we just remove the exported variable. Example:

Before:

export const BasketChannelTypeEnum = {
    Storefront: 'storefront',
    Callcenter: 'callcenter',
    Marketplace: 'marketplace',
    Dss: 'dss',
    Store: 'store',
    Pinterest: 'pinterest',
    Twitter: 'twitter',
    Facebookads: 'facebookads',
    Subscriptions: 'subscriptions',
    Onlinereservation: 'onlinereservation',
    Customerservicecenter: 'customerservicecenter',
    Instagramcommerce: 'instagramcommerce',
    Tiktok: 'tiktok',
    Snapchat: 'snapchat',
    Google: 'google',
    Whatsapp: 'whatsapp',
    Youtube: 'youtube'
} as const;

// type BasketChannelTypeEnum = "storefront" | "callcenter" | "marketplace" | "dss" | "store" | "pinterest" | "twitter" | "facebookads" | "subscriptions" | "onlinereservation" | "customerservicecenter" | ... 5 more ... | "youtube" 
export type BasketChannelTypeEnum = typeof BasketChannelTypeEnum[keyof typeof BasketChannelTypeEnum];

After:

export type BasketChannelTypeEnum = 
    'storefront'|
    'callcenter'|
    'marketplace'|
    'dss'|
    'store'|
    'pinterest'|
    'twitter'|
    'facebookads'|
    'subscriptions'|
    'onlinereservation'|
    'customerservicecenter'|
    'instagramcommerce'|
    'tiktok'|
    'snapchat'|
    'google'|
    'whatsapp'|
    'youtube';


// There should be no code_challenge for private client
const expectedReqOptions = {
accessToken: "access_token",
Copy link
Contributor

Choose a reason for hiding this comment

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

heads up that I applied a fix to this test also as part of #198 .

In there, I replaced expectedReqOptions with a check that ensures code_challenge wasn't included.

Copy link
Contributor

@vcua-mobify vcua-mobify left a comment

Choose a reason for hiding this comment

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

I noted a question but the PR looks good to me.

We might have a conflict with the slasHelper test fixes with https://github.com/SalesforceCommerceCloud/commerce-sdk-isomorphic/pull/198/files though. Could you apply the fix from there?

TokenResponse,
} from '../../lib/shopperLogin';
} from '../../lib/shopperLogin/apis';
import {TokenResponse} from '../../lib/shopperLogin/models';
Copy link
Contributor

Choose a reason for hiding this comment

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

We went over this in the meet earlier but could you restate why this change in particular is needed or how the original version resulted in a conflict in the rolled up typescript?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, when we imported directly from the top level index file, it would duplicate the namespace ShopperLoginTypes in the generated *.d.ts file

By importing from the apis/models directory directly, we circumvent this issue

*
*/
export class {{#lambda.titlecase}}{{#lambda.camelcase}}{{appName}}{{/lambda.camelcase}}{{/lambda.titlecase}}<ConfigParameters extends {{#lambda.titlecase}}{{#lambda.camelcase}}{{appName}}{{/lambda.camelcase}}{{/lambda.titlecase}}Parameters & Record<string, unknown>> {
export class {{#vendorExtensions}}{{#x-sdk-classname}}{{{ . }}}{{/x-sdk-classname}}{{^x-sdk-classname}}{{#lambda.titlecase}}{{#lambda.camelcase}}{{appName}}{{/lambda.camelcase}}{{/lambda.titlecase}}{{/x-sdk-classname}}{{/vendorExtensions}}{{^vendorExtensions}}{{#lambda.titlecase}}{{#lambda.camelcase}}{{appName}}{{/lambda.camelcase}}{{/lambda.titlecase}}{{/vendorExtensions}}<ConfigParameters extends {{#lambda.titlecase}}{{#lambda.camelcase}}{{appName}}{{/lambda.camelcase}}{{/lambda.titlecase}}Parameters & Record<string, unknown>> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for this; I've applied the template changes (with some slight tweaks) to the node SDK PR: SalesforceCommerceCloud/commerce-sdk#418

The tweaks were to account for the namespacing that we do in the node sdk.

In the future I wonder if there is some way we can make this easier to read or some way to extract it so we only define the full vendorExtensions block once. Not a blocker for this PR though.

Copy link
Contributor

@unandyala unandyala left a comment

Choose a reason for hiding this comment

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

I see the issues with the generated ShopperContexts classname and type

export class {classname=ShopperContexts}
export namespace {classname=ShopperContexts}Types {

other than that the changes look good to me

@joeluong-sfcc
Copy link
Contributor Author

I see the issues with the generated ShopperContexts classname and type

export class {classname=ShopperContexts}
export namespace {classname=ShopperContexts}Types {

other than that the changes look good to me

@unandyala could you clarify where you see this issue?

@joeluong-sfcc joeluong-sfcc marked this pull request as ready for review June 11, 2025 15:57
@joeluong-sfcc joeluong-sfcc requested a review from a team as a code owner June 11, 2025 15:57
@joeluong-sfcc joeluong-sfcc merged commit eaf5a59 into feature/oas Jun 11, 2025
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants