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

Commit

Permalink
Merge pull request #22 from ScaleLeap/feature/orders-api
Browse files Browse the repository at this point in the history
feat: listOrders api
  • Loading branch information
gigobyte authored May 11, 2020
2 parents dc06670 + e557509 commit b834af3
Show file tree
Hide file tree
Showing 17 changed files with 1,179 additions and 162 deletions.
16 changes: 13 additions & 3 deletions src/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,30 @@ export class MWSError extends Error {
}

export class HttpError extends MWSError {
public message = 'Encountered an error while sending a request'
public message = 'MWS: Encountered an error while sending a request: '

constructor(public error: unknown, ...parameters: string[]) {
constructor(public error: Error, ...parameters: string[]) {
super(...parameters)
this.message += error.message
Object.setPrototypeOf(this, HttpError.prototype)

if (Error.captureStackTrace) {
Error.captureStackTrace(this, HttpError)
}
}
}

export class ParsingError extends MWSError {
public message = 'Encountered an error while parsing a response'
public message = 'MWS: Encountered an error while parsing a response: '

constructor(public error: string, ...parameters: string[]) {
super(...parameters)
this.message += error
Object.setPrototypeOf(this, ParsingError.prototype)

if (Error.captureStackTrace) {
Error.captureStackTrace(this, ParsingError)
}
}
}
/* eslint-enable max-classes-per-file */
32 changes: 29 additions & 3 deletions src/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,26 @@ export interface MWSOptions {
}

type HttpMethod = 'GET' | 'POST'
type Parameters = Record<string, string | string[]>
type Parameters = Record<string, string | number | (number | string)[] | undefined>
type CleanParameters = Record<string, string>

export enum Resource {
Sellers = 'Sellers',
Orders = 'Orders',
}

interface ResourceActions {
[Resource.Sellers]:
| 'ListMarketplaceParticipations'
| 'ListMarketplaceParticipationsByNextToken'
| 'GetServiceStatus'
[Resource.Orders]:
| 'ListOrders'
| 'ListOrdersByNextToken'
| 'GetOrder'
| 'ListOrderItems'
| 'ListOrderItemsByNextToken'
| 'GetServiceStatus'
}

interface Request {
Expand Down Expand Up @@ -55,12 +64,29 @@ interface RequestResponse {
headers: Record<string, string>
}

const canonicalizeParameters = (parameters: Parameters): string => {
const canonicalizeParameters = (parameters: CleanParameters): string => {
const sp = new URLSearchParams(parameters)
sp.sort()
return sp.toString().replace(/\+/g, '%20')
}

/* eslint-disable no-param-reassign */
const cleanParameters = (parameters: Parameters): CleanParameters =>
Object.entries(parameters)
.filter(([, v]) => v !== undefined)
.reduce((result, [k, v]) => {
if (Array.isArray(v)) {
for (let index = 0; index < v.length; index += 1) {
result[`${k}.${index + 1}`] = String(v)
}
} else {
result[k] = String(v)
}

return result
}, {} as CleanParameters)
/* eslint-enable no-param-reassign */

const defaultFetch = ({ url, method, headers, data }: Request): Promise<RequestResponse> =>
axios({ method, url, headers, data }).then((response) => ({
data: response.data,
Expand Down Expand Up @@ -106,7 +132,7 @@ export class HttpClient {
SignatureVersion: '2',
Timestamp: new Date().toISOString(),
Version: info.version,
...info.parameters,
...cleanParameters(info.parameters),
}

const parametersForSigning = canonicalizeParameters(parameters)
Expand Down
7 changes: 4 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export { MWS } from './mws'
export { Sellers } from './sections/sellers'
export { HttpClient } from './http'
export * from './http'
export * from './mws'
export * from './sections/sellers'
export * from './sections/orders'
export * from './error'
export * from '@scaleleap/amazon-marketplaces'
11 changes: 11 additions & 0 deletions src/mws.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { HttpClient } from './http'
import { Orders } from './sections/orders'
import { Sellers } from './sections/sellers'

export class MWS {
private _sellers!: Sellers

private _orders!: Orders

constructor(private httpClient: HttpClient) {}

get sellers() {
Expand All @@ -13,4 +16,12 @@ export class MWS {

return this._sellers
}

get orders() {
if (!this._orders) {
this._orders = new Orders(this.httpClient)
}

return this._orders
}
}
38 changes: 33 additions & 5 deletions src/parsing.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,44 @@
/** A collection of parsing codecs */
import { array, Codec, string } 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>(codec: Codec<T>): Codec<T[]> => {
export const ensureArray = <T>(tag: string, codec: Codec<T>): Codec<T[]> => {
const schema = codec.schema()

return Codec.custom({
decode: (x) => {
const arrayX = Array.isArray(x) ? x : [x]
return array(codec).decode(arrayX)
if (x === '') {
return Right([])
}

return record(string, unknown)
.decode(x)
.chain((object) => {
const possiblyElements = object[tag]
const elements = Array.isArray(possiblyElements) ? possiblyElements : [possiblyElements]

return array(codec).decode(elements)
})
},
encode: (x) => x,
schema: () => ({
oneOf: [schema, { type: 'array', items: [schema], minItems: 1 }],
oneOf: [
schema,
{ type: 'array', items: [schema], minItems: 1 },
{ type: 'string', enum: [''] },
],
}),
})
}

/** 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 @@ -36,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
Loading

0 comments on commit b834af3

Please sign in to comment.