whitebox-co / walmart-marketplace-api

A fully typed TypeScript, Javascript, and Node.js API library for the Walmart Marketplace API
MIT License
25 stars 10 forks source link
api nodejs openapi rest typescript walmart walmart-api walmart-connector

Walmart Marketplace API SDK

GitHub GitHub GitHub Workflow Status GitHub Workflow Status GitHub Workflow Status GitHub Workflow Status GitHub Workflow Status

A fully typed and auto generated TypeScript library for the Walmart Marketplace Rest API.

This library automatically generates typescript types, classes, interfaces, integration tests, and UI documentation based directly off of the Walmart Marketplace OpenAPI specification.

Why?

TLDR: It did not exist and we really needed it!

How it works

Installation

Packages are maintained on both Github and NPM.

npm install @whitebox-co/walmart-marketplace-api

For development assuming all prerequisites are met.

npm install

Usage

Due to how Walmart has structured its OpenApi schema, the auto API generation requires the passing of authorization details on each API method call. This can become quite tedious and can create a lot of repetitive and duplicated code.

To try and resolve this issue, our approach was to create convenience methods that will configure every API and return a fully configured instance of the API with token caching built-in. These convenience methods intercept all API methods to prevent the user from having to input the same auth credentials for each call.

Until Walmart changes their OpenApi schema so that auto-generation does not require these parameters, this the approach will greatly simplify making API calls.

Preferred Usage

import walmartMarketplaceApi, { OrdersApi, defaultParams } from '@whitebox-co/walmart-marketplace-api';

/**
 * Init the marketplace api with client credentials and get back a fully
 * configured instance of the api with token caching built in.
 *
 * Any subsequent call using the same credentials but a different api
 * will use cached credentials until they expire.
 */
const ordersApi = await walmartMarketplaceApi.getConfiguredApi(OrdersApi, {
    clientId,
    clientSecret,
    consumerChannelType,
});

/**
 * defaultParams are necessary due to ts typing. When using the convenience methods,
 * the method calls are intercepted and the default params are automatically filled
 * out. These can effectively be ignored if using js or by using es-lint ignore
 * statements if you so choose.
 *
 * customParams in this example are anything part of the getAnOrder
 * request that is required but not part of the defaultParams walmart
 * requires for authorization. See each api's individual documentation
 * for all acceptable params.
 */
const exampleOrder = await ordersApi.getAnOrder({
    ...defaultParams,
    ...customParams,
});

Class Based Alternative

import { WalmartApi, OrdersApi, defaultParams } from '@whitebox-co/walmart-marketplace-api';

const walmartApi = new WalmartApi({
    clientId,
    clientSecret,
    consumerChannelType,
});

const ordersApi = await walmartApi.getConfiguredApi(OrdersApi);

const exampleOrder = await ordersApi.getAnOrder({
    ...defaultParams,
    ...customParams,
});

Direct API Usage

import { Configuration, AuthenticationApi, OrdersApi } from '@whitebox-co/walmart-marketplace-api';
import { Buffer } from 'buffer/'; // trailing slash is important and not a mistake

// configure authorization api
const configuration = new Configuration();
const authApi = new AuthenticationApi(configuration);
const authorization = 'Basic ' + Buffer.from(env.CLIENT_ID + ':' + env.CLIENT_SECRET).toString('base64');

// get response token
const tokenResponse = await authApi.tokenAPI({
    authorization,
    wMQOSCORRELATIONID: uuidv4(),
    wMSVCNAME: '@whitebox-co/walmart-marketplace-api',
    grantType: 'client_credentials',
    wMCONSUMERCHANNELTYPE: env.CONSUMER_CHANNEL_TYPE,
});

// configure orders api
const ordersApi = new OrdersApi(configuration);

// make subsequent order calls
const orderResponse = await ordersApi.getAnOrder({
    authorization,
    wMSECACCESSTOKEN: tokenResponse.data?.access_token,
    wMQOSCORRELATIONID: uuidv4(),
    wMSVCNAME: '@whitebox-co/walmart-marketplace-api',
    wMCONSUMERCHANNELTYPE: env.CONSUMER_CHANNEL_TYPE,
    id: 1,
});

Helpers

Some parts of the Walmart REST endpoint require helpers in order to achieve proper usage above what the auto-generated library provides. These helpers will generally be available in the util folder.

Request Helpers

requestHelper Can be found in the util folder.

// getAllRecursively usage
import { getAllRecursively } from '../../../src/util/requestHelpers';

const walmartApi = new WalmartApi(...);
const ordersApi = await walmartApi.getConfiguredApi(...);
const requestParams = {limit: 20};
const orders = await getAllRecursively(ordersApi, ordersApi.getAllOrders.name, requestParams);

Docs

There are three different types of documentation included for this repo.

  1. Redoc - Used as an alternative to visiting the walmart developer site (which is based off of redoc).
  2. SwaggerUI - Used as an alternative to visiting the walmart sandbox documentation. (which is based of of swaggerui).
  3. TypeDoc - Typescript type and class documentation of the main library.

Redoc and SwaggerUI are included as an alternative to having to visit Walmart's developer website, which we have found often times become unresponsive in certain browsers.

Viewing Docs

We have packaged http-server as a dev dependency as a way to quickly view the docs. Issue any one of the following commands to build and view any of the docs.

npm run docs # or `npm run docs:typedoc`
npm run docs:redoc
npm run docs:swaggerui

Note: http-server will try and serve the docs on port 8080 and will auto launch your browser to the specified documentation.

Development

Prerequisites

Commands

npm run build       # build the project (output to ./lib)
npm run dev         # run ts-node-dev to watch and rebuild project while in development.
npm run start       # runs ts-node to compile project.
npm run lint        # runs eslint linter

API Generation

API Generation is handled automatically by github actions. We perform a task daily to check if the Walmart API has been updated and if it has we perform the schema downloads and subsequent API Generation. From there we automatically generate the new docs and a new version of the library is built and deployed to npm.

If you wish to manually perform those steps see the sections below.

Manual Schema Download

Walmart exposes and endpoint that allows for the download of the openapi json. To pull down all of those models simply run the following:

npm run download-schemas

If any changed have occurred to the api the new updates will overwrite the existing schemas in the ./docs/schemas directory.

Manual API Generation

Once you have the schemas downloaded you can run the api generation by running the following:

npm run generate-apis

Which will start the generation and processing of all of the schemas and eventually finish with all api's created in the src/apis directory.

Model Generation

Walmart uses a bunch of JSON Schema files that define how data should be formatted for bulk creations and updates. These all use JSON schemas specific to each operation. These schemas are available on Walmart's Developer site but we also download and keep them in the ./docs/ directory.

Each schema is generated into types using quicktype and saved in their respective src/model folders.

Please Note:

In certain instances (bulk file uploads) we had to modify request headers to contain Header Parameters that are not included in the auto-generation. This is a problem with the Schemas provided by Walmart. The schemas should define an Accept Header that is properly set.

If this Header is not properly set 520 or 521 errors are possible to occur with multipart uploads.

This has been added in getConfiguredApi to configure this for all api's.

authorizedConfiguration.baseOptions = {
    headers: {
        Accept: 'application/json',
    },
};

In the future, we hope Walmart properly sets the Accept header so that we don't have to make this assumption for all endpoints.

Item Model Generation

Item Models (MP_ITEM_MATCH, MP_ITEM, MP_MAINTENANCE, MP_WFS_ITEM) are saved to the docs/item-schemas directory.

These schemas are generated manually using quicktype into the src/models/items directory.

If you wish to generate these for some reason, install quicktype globally and issue the following commands:

quicktype -s schema ./docs/item-schemas/MP_ITEM_MATCH_v4.json -o ./src/models/item/v4/mpItemMatch4.ts
quicktype -s schema ./docs/item-schemas/MP_ITEM_SPEC_4.3.json -o ./src/models/item/v4/mpItem4.3.ts
quicktype -s schema ./docs/item-schemas/MP_MAINTENANCE_SPEC_4.3.json -o ./src/models/item/v4/mpMaintenance4.3.ts
quicktype -s schema ./docs/item-schemas/MP_WFS_ITEM_SPEC_4.2.json -o ./src/models/item/v4/mpWfsItem4.2.ts

quicktype -s schema ./docs/item-schemas/V3-Spec-Marketplace-Items-3.2-JSON/ -o ./src/models/item/v3/mpItems3.2.ts

MP_MAINTENANCE_SPEC_4.3.json will fail to generate as is not a complete schema. It is missing at the end of the file. Complain to walmart!

Inventory Model Generation

Inventory Model InventoryJSONSchemaV1 is saved to the docs/inventory-schemas directory.

These schemas are generated manually using quicktype into the src/models/inventory directory.

If you wish to generate these for some reason, install quicktype globally and issue the following commands:

quicktype -s schema ./docs/inventory-schemas/Inventory.json -o ./src/models/inventory/v1/inventory.ts
quicktype -s schema ./docs/inventory-schemas/InventoryFeed.json -o ./src/models/inventory/v1/inventoryFeed.ts
quicktype -s schema ./docs/inventory-schemas/InventoryHeader.json -o ./src/models/inventory/v1/inventoryHeader.ts
quicktype -s schema ./docs/inventory-schemas/WfsInventory.json -o ./src/models/inventory/v1/wfsInventory.ts

Price Model Generation

Price Model PriceJSONSchemaV1 is saved to the docs/price-schemas directory.

These schemas are generated manually using quicktype into the src/models/price directory.

If you wish to generate these for some reason, install quicktype globally and issue the following commands:

quicktype -s schema ./docs/price-schemas/Price.json -o ./src/models/price/v1/price.ts
quicktype -s schema ./docs/price-schemas/PriceFeed.json -o ./src/models/price/v1/priceFeed.ts
quicktype -s schema ./docs/price-schemas/PriceHeader.json -o ./src/models/price/v1/priceHeader.ts

The Price.json schema is not able to be used with quicktype for typescript generation without modification.

The currency definition:

    "currency": {
        "type": "object",
        "additionalProperties": false,
        "enum": ["USD", "CAD"]
    }

should be:

    "currency": {
        "enum": ["USD", "CAD"]
    }

This seems like a bug with the schema but will leave that up to Walmart to decide.

We have changed this in our downloaded schema doc but you should be aware if you download the schema from walmart directly.

Token Authorization and Caching

Tokens are retrieved from walmart during the authorization process and then get cached until they expire. When they expire another call to the getToken endpoint is sent to walmart.

Any time you request a new api from the walmartMarketplaceApi using the same clientID, the cached credential token will be used to authorize the request.

Issues

Please report any issues you find in the github issues section. We will do our best to address any issue in a timely manner.

Known Issues

These need to be moved over to github issues.

Contributing

Feel free to open PR's. Whitebox is currently using this in our production code and we will evaluate changes on a case by case basis.

See the Contributing documentation for further details.

Code of Conduct

This project has adopted the Contributor Covenant Code of Conduct.

See the Code Of Conduct documentation for further details.

License

GitHub

A copy of the license is provided in the root directory under LICENSE