Skip to content
This repository has been archived by the owner on Feb 6, 2024. It is now read-only.

Commit

Permalink
feat: handle edge cases, add listordersbynexttoken
Browse files Browse the repository at this point in the history
  • Loading branch information
gigobyte committed May 9, 2020
1 parent 2489885 commit 27800a8
Show file tree
Hide file tree
Showing 6 changed files with 727 additions and 43 deletions.
16 changes: 15 additions & 1 deletion src/parsing.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/** A collection of parsing codecs */
import { array, Codec, record, string, unknown } from 'purify-ts/Codec'
import { array, Codec, date, record, string, unknown } from 'purify-ts/Codec'
import { Left, Right } from 'purify-ts/Either'

export const ensureArray = <T>(tag: string, codec: Codec<T>): Codec<T[]> => {
Expand Down Expand Up @@ -31,6 +31,14 @@ export const ensureArray = <T>(tag: string, codec: Codec<T>): Codec<T[]> => {
})
}

/** If a string is a valid number it will be parsed as such by our xml parser, even though it should still be a string */
export const ensureString = Codec.custom({
decode: (x) =>
string.decode(x).chainLeft((error) => (typeof x === 'number' ? Right(String(x)) : Left(error))),
encode: string.encode,
schema: () => ({ oneOf: [{ type: 'string' }, { type: 'number' }] }),
})

export const mwsBoolean = Codec.custom<boolean>({
decode: (x) => {
switch (x) {
Expand All @@ -50,6 +58,12 @@ export const mwsBoolean = Codec.custom<boolean>({
schema: () => ({ type: 'string', enum: ['Yes', 'No'] }),
})

export const mwsDate = Codec.custom<Date>({
decode: (x) => string.decode(x).chain((aString) => date.decode(decodeURIComponent(aString))),
encode: date.encode,
schema: date.schema,
})

export enum ServiceStatus {
Green = 'GREEN',
Yellow = 'YELLOW',
Expand Down
93 changes: 65 additions & 28 deletions src/sections/orders.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {
boolean,
Codec,
date,
exactly,
GetInterface,
number,
Expand All @@ -12,7 +11,13 @@ import {

import { ParsingError } from '../error'
import { HttpClient, RequestMeta, Resource } from '../http'
import { ensureArray, nextToken } from '../parsing'
import {
ensureArray,
ensureString,
mwsDate,
NextToken,
nextToken as nextTokenCodec,
} from '../parsing'
import { getServiceStatusByResource } from './shared'

const ORDERS_API_VERSION = '2013-09-01'
Expand Down Expand Up @@ -88,7 +93,7 @@ const Address = Codec.interface({
Country: optional(string),
District: optional(string),
StateOrRegion: optional(string),
PostalCode: optional(string),
PostalCode: optional(ensureString),
CountryCode: optional(string),
Phone: optional(string),
AddressType: optional(adddressType),
Expand All @@ -115,16 +120,16 @@ const Money = Codec.interface({
})

const ListOrders = Codec.interface({
NextToken: optional(nextToken('ListOrders')),
LastUpdatedBefore: optional(date),
CreatedBefore: optional(date),
NextToken: optional(nextTokenCodec('ListOrders')),
LastUpdatedBefore: optional(mwsDate),
CreatedBefore: optional(mwsDate),
Orders: ensureArray(
'Order',
Codec.interface({
AmazonOrderId: string,
SellerOrderId: optional(string),
PurchaseDate: date,
LastUpdateDate: date,
PurchaseDate: mwsDate,
LastUpdateDate: mwsDate,
OrderStatus: orderStatus,
FulfillmentChannel: optional(fulfillmentChannel),
SalesChannel: optional(string),
Expand Down Expand Up @@ -154,21 +159,21 @@ const ListOrders = Codec.interface({
BuyerEmail: optional(string),
BuyerName: optional(string),
BuyerCounty: optional(string),
BuyerTaxInfo,
BuyerTaxInfo: optional(BuyerTaxInfo),
ShipmentServiceLevelCategory: optional(string),
EasyShipShipmentStatus: optional(string),
OrderType: optional(string),
EarliestShipDate: optional(date),
LatestShipDate: optional(date),
EarliestDeliveryDate: optional(date),
LatestDeliveryDate: optional(date),
EarliestShipDate: optional(mwsDate),
LatestShipDate: optional(mwsDate),
EarliestDeliveryDate: optional(mwsDate),
LatestDeliveryDate: optional(mwsDate),
IsBusinessOrder: optional(boolean),
IsSoldByAB: optional(boolean),
PurchaseOrderNumber: optional(string),
IsPrime: optional(boolean),
IsPremiumOrder: optional(boolean),
IsGlobalExpressEnabled: optional(boolean),
PromiseResponseDueDate: optional(date),
PromiseResponseDueDate: optional(mwsDate),
IsEstimatedShipDateSet: optional(boolean),
}),
),
Expand All @@ -180,8 +185,31 @@ const ListOrdersResponse = Codec.interface({
}),
})

const ListOrdersByNextTokenResponse = Codec.interface({
ListOrdersByNextTokenResponse: Codec.interface({
ListOrdersByNextTokenResult: ListOrders,
}),
})

type ListOrders = GetInterface<typeof ListOrders>

const canonicalizeParameters = (parameters: ListOrderParameters) => {
return {
CreatedAfter: parameters.CreatedAfter,
CreatedBefore: parameters.CreatedBefore,
LastUpdatedAfter: parameters.LastUpdatedAfter,
LastUpdatedBefore: parameters.LastUpdatedBefore,
'OrderStatus.Status': parameters.OrderStatus,
'MarketplaceId.Id': parameters.MarketplaceId,
'FulfillmentChannel.Channel': parameters.FulfillmentChannel,
'PaymentMethod.Method': parameters.PaymentMethod,
'EasyShipShipmentStatus.Status': parameters.EasyShipShipmentStatus,
BuyerEmail: parameters.BuyerEmail,
SellerOrderId: parameters.SellerOrderId,
MaxResultsPerPage: parameters.MaxResultsPerPage,
}
}

export class Orders {
constructor(private httpClient: HttpClient) {}

Expand All @@ -190,20 +218,7 @@ export class Orders {
resource: Resource.Orders,
version: ORDERS_API_VERSION,
action: 'ListOrders',
parameters: {
CreatedAfter: parameters.CreatedAfter,
CreatedBefore: parameters.CreatedBefore,
LastUpdatedAfter: parameters.LastUpdatedAfter,
LastUpdatedBefore: parameters.LastUpdatedBefore,
'OrderStatus.Status': parameters.OrderStatus,
'MarketplaceId.Id': parameters.MarketplaceId,
'FulfillmentChannel.Channel': parameters.FulfillmentChannel,
'PaymentMethod.Method': parameters.PaymentMethod,
'EasyShipShipmentStatus.Status': parameters.EasyShipShipmentStatus,
BuyerEmail: parameters.BuyerEmail,
SellerOrderId: parameters.SellerOrderId,
MaxResultsPerPage: parameters.MaxResultsPerPage,
},
parameters: canonicalizeParameters(parameters),
})

return ListOrdersResponse.decode(response).caseOf({
Expand All @@ -214,6 +229,28 @@ export class Orders {
})
}

async listOrdersByNextToken(
nextToken: NextToken<'ListOrders'>,
parameters: ListOrderParameters,
): Promise<[ListOrders, RequestMeta]> {
const [response, meta] = await this.httpClient.request('POST', {
resource: Resource.Orders,
version: ORDERS_API_VERSION,
action: 'ListOrdersByNextToken',
parameters: {
...canonicalizeParameters(parameters),
NextToken: nextToken.token,
},
})

return ListOrdersByNextTokenResponse.decode(response).caseOf({
Right: (x) => [x.ListOrdersByNextTokenResponse.ListOrdersByNextTokenResult, meta],
Left: (error) => {
throw new ParsingError(error)
},
})
}

async getServiceStatus() {
return getServiceStatusByResource(this.httpClient, Resource.Orders, ORDERS_API_VERSION)
}
Expand Down

0 comments on commit 27800a8

Please sign in to comment.