Skip to content

@W-18349405@ Download and generate multiple versions of ShopperBaskets#198

Merged
vcua-mobify merged 15 commits intofeature/oasfrom
include-nested-api-directories
Jun 19, 2025
Merged

@W-18349405@ Download and generate multiple versions of ShopperBaskets#198
vcua-mobify merged 15 commits intofeature/oasfrom
include-nested-api-directories

Conversation

@vcua-mobify
Copy link
Contributor

@vcua-mobify vcua-mobify commented Jun 5, 2025

This PR contains the following changes to support handling both ShopperBaskets v1 and v2:

  1. An update to allow the generatre-oas script to look into subdirectories for exchange.json files.

With this change, we can now look for the exchange.json files in the following directory structure:

  • shopper-baskets
    • shopper-baskets-v1
      • exchange.json
    • shopper-baskets-v2
      • exchange.json
  1. Updates to how information is extracted from exchange.json + handling the API name for both ShopperBasketsV1 and ShopperBasketsV2
  1. A fix to handle -internal vs -public OAS files. The generator will only consider -internal files.

  2. A template adjustment to handle differences in ShopperProductQueryParameters between getProduct and getProducts (Thanks @joeluong-sfcc for this!)

  3. A test update following the change to allow unknown query parameters.

  4. Update to api versions + a manual fix to x-sdk-classname format.

Testing these changes:
Generate the SDk with npm run renderTemplates

Run npm run test

Verify that all tests pass and that the generated SDK has no errors (areas to look at would be ShopperBaskets V1 / V2, ShopperProducts, ShopperContexts, and the top level index.ts)

@vcua-mobify vcua-mobify changed the base branch from main to feature/oas June 5, 2025 21:44
@vcua-mobify vcua-mobify marked this pull request as ready for review June 10, 2025 19:45
@vcua-mobify vcua-mobify requested a review from a team as a code owner June 10, 2025 19:45
@vcua-mobify vcua-mobify changed the title Include nested api directories @W-18349405@ Download and generate multiple versions of ShopperBaskets Jun 13, 2025

// Special handling for shopper-baskets-v2
if (
exchangeConfig.assetId === 'shopper-baskets-oas' &&
Copy link
Contributor

@alexvuong alexvuong Jun 16, 2025

Choose a reason for hiding this comment

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

Can we be a bit generic for all apis ? If other apis happen to have version 2, we have to come back and manually fix this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's fair. We can update this so that if apiVersion is v2, then append v2 to the various names

refreshToken: 'refresh_token',
response_type: 'code',
usid: 'usid',
const unexpectedQueryParams = {
Copy link
Contributor

Choose a reason for hiding this comment

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

Dumb question, why do we need to change this test?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This test fix addresses a change that was made to for allowing any query parameters through: #196

Rather than check for expected options, I think it's better we assert that the code challenge wasn't included. That way, if new non-breaking options appear in the future, this test will continue to work.

scripts/utils.ts Outdated
const matchedApis = await download.search(
`"${name}" category:Visibility = "External" category:"SDK Type" = "Commerce" category:"SDK Type" = "Isomorphic"`,
undefined,
true
Copy link
Contributor

Choose a reason for hiding this comment

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

I assumed the search has error handling?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is applying a subset of the changes from #200.

It may be better for us to merge the changes from @unandyala first then add this one after

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 changes from #200 are in

outputDir: `${outputDir}`,
templateDir: `${TEMPLATE_DIRECTORY}`,
skipValidateSpec: true,
flags: `--reserved-words-mappings delete=delete`,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is needed to address some naming collisions around the delete methods that are generated for the SDK

Copy link
Contributor

Choose a reason for hiding this comment

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

What does skipValidateSpec do? Do we not want to include it alongside the new flags?

Also what naming collisions do we have with the delete keyword? Or is it just to bring it in alignment with the node SDK

Copy link
Contributor Author

Choose a reason for hiding this comment

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

skipValidateSpec was an argument I was passing in the early days of this work to force the generator to run even when there were errors in the oas spec (back when I was pulling down snapshots rather than stable versions of the specs).

We don't need to set it now that we're downloading stable versions of the spec but the setup allows us to add it again in the future.

Copy link
Contributor

Choose a reason for hiding this comment

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

can you add a comment explaining the delete flag

Copy link
Contributor

@joeluong-sfcc joeluong-sfcc left a comment

Choose a reason for hiding this comment

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

Correct me if I'm wrong, but it seems like the main change is we use a new helper function that recursively goes through the api directory and collects all the sub directories with an exchange.json file into an array

LGTM

outputDir: `${outputDir}`,
templateDir: `${TEMPLATE_DIRECTORY}`,
skipValidateSpec: true,
flags: `--reserved-words-mappings delete=delete`,
Copy link
Contributor

Choose a reason for hiding this comment

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

What does skipValidateSpec do? Do we not want to include it alongside the new flags?

Also what naming collisions do we have with the delete keyword? Or is it just to bring it in alignment with the node SDK

@vcua-mobify
Copy link
Contributor Author

@joeluong-sfcc , re: --reserved-words-mappings delete=delete, yes I was aligning the isomorphic and node sdks so that they used the same flags. We can adjust the flags though if we need to


return {
filepath: path.join(directory, exchangeConfig.main),
filepath: path.join(
Copy link
Contributor

Choose a reason for hiding this comment

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

Feels like this should be part of the search query parameter to the raml-toolkit downloader. I think it is fine for now. Can we create a followup ticket to make this change in raml-toolkit and remove this code from here?

Copy link
Contributor Author

@vcua-mobify vcua-mobify Jun 19, 2025

Choose a reason for hiding this comment

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

New ticket W-18833027 created for this suggestion

}

export function resolveApiName(name: string, version: string): string {
if (name === 'Shopper Baskets OAS') {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we make this generic instead of hard-coding? That way any V2 api will be generated

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've modified the function to be more generic when appending V2. But I left the special case for appending V1 to ShopperBaskets specifically for now. We'll need to remove it if ShopperBasketsV1 is reverted to just ShopperBaskets by the IPA team.

outputDir: `${outputDir}`,
templateDir: `${TEMPLATE_DIRECTORY}`,
skipValidateSpec: true,
flags: `--reserved-words-mappings delete=delete`,
Copy link
Contributor

Choose a reason for hiding this comment

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

can you add a comment explaining the delete flag

fs.writeFileSync(`${TARGET_DIRECTORY}/version.ts`, generatedVersion);
}

export function getAllDirectoriesWithExchangeFiles(
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: rename to getAllApiDirectories as it is easy to understand? And add a doc for the function

: item;

if (fs.lstatSync(itemPath).isDirectory()) {
if (fs.existsSync(path.join(itemPath, 'exchange.json'))) {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Add a comment "Only directories with exchange.json are considered as valid APIs"

price: 20.99
- description: Order received the next business day
id: '003'
name: Overn
Copy link
Contributor

Choose a reason for hiding this comment

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

Wait, was this a manual change or did the IPA team add this?

If it's the IPA team, we'll have to ask them to revert this as we probably just want the classname to be ShopperBaskets as its the default right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

IPA team made this change to set the x-sdk-classname to ShopperBaskets v1.

}
return name.replace(/\s+/g, '').replace('OAS', '');

return version !== 'v1' ? apiName + version.toUpperCase() : apiName;
Copy link
Contributor

Choose a reason for hiding this comment

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

This seem to be opposite of what you are doing for Shopper Baskets? Why do we need this?

Copy link
Contributor Author

@vcua-mobify vcua-mobify Jun 19, 2025

Choose a reason for hiding this comment

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

This was my adjustment to allow for a more generic v2 as per your comment above.

Here, if apiVersion in exchange.json is v1, we don't append V1. This results in just the api name being returned. Ie. ShopperProducts

If the apiVersion in exchange.json is v2, this returns ShopperProductsV2.

ShopperBaskets is a special case where the API team have set x-sdk-classname to ShopperBasketsV1 in the -internal OAS spec. So the API name returned here has to match that (ie. ShopperBasketsV1) since the imports in the top level index.ts are generated using these API names by Handlebars rather than produced by the OAS generator.

We don't want to append V1 to other APIs (ie. we don't want ShopperProductsV1).

@vcua-mobify vcua-mobify merged commit 88d2c83 into feature/oas Jun 19, 2025
4 of 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.

4 participants