@nuskin/product-status-client
v1.1.0
Published
JavaScript client for the Nu Skin Product Status Service web API
Downloads
12
Keywords
Readme
Product Status Service Client
JavaScript client for the Nu Skin Product Status Service web API
Installing
Using npm:
$ npm install @nuskin/product-status-client
Using Yarn:
$ yarn add @nuskin/product-status-client
Initializing the Client
Initialize a new instance of the client by providing the following parameters to the constructor:
baseURL
- The web API's base URL. Currently, this is the base URL of Nu Skin's cloud web services.clientID
- The web API client ID.clientSecret
- The web API client secret.country
- Country code of the market that requests will be made for.
The following optional parameters may also be provided:
{
// Additional query parameters to include in product status requests.
params: {
paramName: "paramValue",
otherParamName: 12345
},
// The requested product quantity.
// By default, the requested product quantity is 1000.
quantity: 1000, // Default
// The maximum wait time for batching requests together.
// Wait time is given in milliseconds.
// By default, the batch wait time is 1 millisecond.
// See the section on batch wait time for further details.
maxWait: 1, // Default
// The maximum size of a request batch.
// By default, the maximum batch size is 36.
// See the section on batch size for further details.
batchSize: 36, // Default
// Storage provider for locally caching product status data.
// Provider must expose get and set methods.
// See the section on status caching for further details.
store: {
// Key argument is string
get: function(key) {
// Retrieve value for given key
return value;
},
// Key and value arguments are strings
set: function(key, value) {
/* ... */
}
},
// Array of time-to-live settings for cached product status data.
// Each entry should have a minimum quantity and a time-to-live value
// in seconds for that quantity.
// See the section on status caching for further details.
ttl: [
{ qty: 100, ttl: 60 },
{ qty: 250, ttl: 300 }
]
}
Example:
import { ProductStatusClient } from "@nuskin/product-status-client";
const client = new ProductStatusClient({
baseURL: "https://api.cloud.nuskin.com",
clientID: "0123...aeae",
clientSecret: "8888...aa00",
country: "US",
params: {
foo: "bar"
},
maxWait: 25,
store: {
get: sessionStorage.get,
set: sessionStorage.set
},
ttl: [
{ qty: 100, ttl: 30 },
{ qty: 500, ttl: 120 },
{ qty: 1000, ttl: 300 }
]
});
Using the Client
Call .getProductStatuses()
to retrieve product status information for one or more product SKUs.
This function can be called with either a single SKU string or an array of SKU strings:
client.getProductStatuses("80801234").then(...)
client.getProductStatuses(["55555555", "55555556", "55555557"]).then(...)
The function returns a promise that resolves to an array of product statuses:
client.getProductStatuses(["12345678", "99999999"])
.then(statuses => {
console.log(statuses[0]); // {SKU: "12345678", availableQuantity: 1000, ...}
console.log(statuses[1]); // {SKU: "99999999", availableQuantity: 565, ...}
});
Product Status Structure
Product statuses returned by the client take the following form:
// Product status information object, version 2
interface ProductStatusV2 {
// Product SKU
SKU: string;
// Product available quantity
availableQuantity: number;
// Flag indicating whether product is enabled for sale on the web
webEnabled: boolean;
// List of attribute flags
attribute: Array<{
// Attribute flag name
type: string;
// Attribute flag value
value: boolean;
}>;
// Product availability information
// Possible values include "RELEASED_FOR_SALE", "DISCONTINUED", "PHASE_OUT", "APPROVED_FOR_SALE", "NOT_FOUND"
status: {
// Retail availability status
retail: string;
// Wholesale availability status
wholesale: string;
};
// List of allowed order types for this product
orderType: string[];
// Product pricing breakdown
pricing: {
// Pricing details map for the retail channel
// Map keys are order types
retail: {
[orderType: string]: PricingDetail
};
// Pricing details map for the wholesale channel
// Map keys are order types
wholesale: {
[orderType: string]: PricingDetail
};
};
}
// Pricing details specific to an order type
interface PricingDetail {
// Product price
price: number;
// Product personal volume (PV) value
pv?: number;
// Product commissionable volume (CV) value
cv?: number;
// Product price in ADR points
Points?: number;
}
Legacy Support for Version 1 Product Statuses
Legacy support is offered for Version 1 product statuses.
Version 1 product statuses take the following form:
// Product status information object, version 1
interface ProductStatusV1 {
// Product SKU
SKU: string;
// Product available quantity
availableQuantity: number;
// Status of the product available quantity: "ESTIMATED", "CURRENT", "STALE", "UNKNOWN"
availableQuantityStatus: string;
// Order types that can include this product, e.g. "ORDER", "ADR"
orderType: string[];
// Product's availability status: "RELEASED_FOR_SALE", "DISCONTINUED", "PHASE_OUT", "APPROVED_FOR_SALE", "NOT_FOUND"
status: string;
// Flag indicating whether product is enabled for sale on the web
webEnabled?: boolean;
// Map of price types to price values.
// Keys are price types, e.g. "RTL", "WHL", "WADR", "WADW", "WRTL", etc.
// Values are prices.
price: { [key: string]: number }[];
// Map of price types to PV values.
// Keys are price types, e.g. "RTL", "WHL", "WADR", "WADW", "WRTL", etc.
// Values are prices.
psv: { [key: string]: number }[];
// Map of price types to CV values.
// Keys are price types, e.g. "RTL", "WHL", "WADR", "WADW", "WRTL", etc.
// Values are prices.
csv: { [key: string]: number }[];
}
Call the static method ProductStatusClient.toV1Statuses()
to convert Version 2 product statuses to Version 1.
Example:
client.getProductStatuses("99999999")
.then(v2Statuses => ProductStatusClient.toV1Statuses(v2Statuses))
.then(v1Statuses => {
...
});
Request Batching
The product status web service that this client encapsulates can accept requests containing multiple SKUs at once. This is also much more efficient for the server than processing each SKU in its own request. Because of this, the Product Status Web Client submits requested SKUs together in batches.
Batch Wait Time
The first call to .getProductStatuses()
opens a new batch and begins a countdown timer. Any additional calls to .getProductStatuses()
during this countdown are added to the batch.
Once the batch countdown timer expires, a single server request is executed for all SKUs in the batch. The promises that were returned by .getProductStatuses()
are then resolved, each with the product statuses requested by its function call.
This is illustrated below:
Client Server
| |
.getStatuses() => | new batch opened |
| |
.getStatuses() => | |
.getStatuses() => | |
| batch timer ends |
| |
|-------- REQUEST ------->|
Promises resolved |<------------------------|
| |
The lenth of the batch timer delay can be configured by providing a maxWait
parameter to the constructor.
Batch Max Size
Due to server constraints, there is a limit to the number of SKUs that a single server request can contain. Because of this, if a batch reaches its maximum allowed size, it is immediately submitted as a server request and a new batch is begun for any remaining SKUs being requested.
This is illustrated below:
Client Server
| |
.getStatuses() => | batch 1 opened |
.getStatuses() => | |
.getStatuses() => | batch 1 max size |
.getStatuses() => | batch 2 opened |
|------- REQUEST 1 ------>|
Promises resolved |<------------------------|
| |
.getStatuses() => | |
| |
| |
| batch 2 timer ends |
| |
|------- REQUEST 2 ------>|
Promises resolved |<------------------------|
| |
Batch size can be configured by providing a batchSize
parameter to the constructor.
Caching Product Status Data
Caching support is offered for product status data, to avoid redundant API requests and increase the speed of repeated retrievals for the same statuses.
Cache Provider
You can provide your choice of caching storage provider to the constructor via the store
parameter.
store
must be an object that exposes a .get()
and a .set()
method.
.get()
must accept a key string and return a value string:
get: (key: string) => string
.set()
must accept a key string and a value string:
set: (key: string, value: string) => void
Example 1, in-memory caching:
const cache = new Map();
const client = new ProductStatusClient({
...
store: {
get: (key) => cache.get(key),
set: (key, value) => cache.set(key, value)
}
});
Example 2, browser session storage caching:
const client = new ProductStatusClient({
...
store: {
get: (key) => sessionStorage.getItem(key),
set: (key, value) => sessionStorage.setItem(key, value)
}
});
Cache Time to Live
Cached statuses have a time-to-live (ttl) value. If you provide a caching provider to the constructor via the store
parameter, you must also provide ttl settings via the ttl
parameter.
ttl
must be an array of ttl setting objects. A ttl setting object has the following properties:
qty
- The minimum available quantity that a product status must have to qualify for this time to livettl
- The time to live for the cached product status, in seconds
const ttlSettings = [
// Product statuses with an available quantity >= 200 will be cached for up to 60 seconds
{ qty: 200, ttl: 60 },
// Product statuses with an available quantity >= 500 will be cached for up to 120 seconds
{ qty: 500, ttl: 120 },
// Product statuses with an available quantity >= 1000 will be cached for up to 300 seconds
{ qty: 1000, ttl: 300 }
];
const client = new ProductStatusClient({
...
ttl: ttlSettings
});