@dotdev/harmony-sdk 1.22.1 → 1.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -110,8 +110,15 @@ export class ApiHelper {
110
110
  static async parseError(error) {
111
111
  if (axios.isAxiosError(error)) {
112
112
  if (error?.response) {
113
- const parsedError = await ApiHelper.parseHarmonyErrorResponse(error?.response?.data);
114
- return new RequestError(`API request failed with status ${error.response.status}: {code: ${parsedError?.code}, name: ${parsedError?.name}, message: ${parsedError?.message}}`);
113
+ if (Utils.isValidXml(error?.response?.data)) {
114
+ const parsedError = await ApiHelper.parseHarmonyErrorResponse(error?.response?.data);
115
+ return new RequestError(`API request failed with status ${error.response.status}: {code: ${parsedError?.code}, name: ${parsedError?.name}, message: ${parsedError?.message}}`);
116
+ }
117
+ else {
118
+ logger.error(`API request error`);
119
+ logger.child({ error: error });
120
+ return new RequestError(`API request failed but error response is not in Harmony XML format. Please check the logs for more details.`);
121
+ }
115
122
  }
116
123
  else if (error?.request) {
117
124
  return new RequestError("No response received from the server during API call");
@@ -69,6 +69,12 @@ export declare abstract class Utils {
69
69
  * @returns {*} first value in the array
70
70
  */
71
71
  static getFirst(prop: any): string;
72
+ /**
73
+ * Validate whether the provided string is a valid XML.
74
+ * @param xmlString
75
+ * @returns
76
+ */
77
+ static isValidXml(xmlString: string): boolean;
72
78
  }
73
79
  export declare const TEST_HEADERS: {
74
80
  headers: {
@@ -137,6 +137,27 @@ export class Utils {
137
137
  static getFirst(prop) {
138
138
  return (prop ?? [])[0];
139
139
  }
140
+ /**
141
+ * Validate whether the provided string is a valid XML.
142
+ * @param xmlString
143
+ * @returns
144
+ */
145
+ static isValidXml(xmlString) {
146
+ let stack = [];
147
+ const regex = /<([^>]+)>/g;
148
+ let match;
149
+ while ((match = regex.exec(xmlString)) !== null) {
150
+ if (match[1].charAt(0) === "/") {
151
+ if (stack.length === 0 || stack.pop() !== match[1].slice(1)) {
152
+ return false;
153
+ }
154
+ }
155
+ else {
156
+ stack.push(match[1]);
157
+ }
158
+ }
159
+ return stack.length === 0;
160
+ }
140
161
  }
141
162
  export const TEST_HEADERS = {
142
163
  headers: {
@@ -107,4 +107,10 @@ describe("Misc", () => {
107
107
  // Check if Accept-Encoding is set to gzip, deflate, br for compression support (currently enabled for S2)
108
108
  expect(harmonyApi.axiosInstance.defaults.headers["Accept-Encoding"]).toEqual("gzip, deflate, br");
109
109
  });
110
+ test("validateXml() should validate XML correctly", () => {
111
+ expect(Utils.isValidXml("<root><child></child></root>")).toBe(true);
112
+ expect(Utils.isValidXml("<root><child></root>")).toBe(false);
113
+ expect(Utils.isValidXml("<root><child></child>")).toBe(false);
114
+ expect(Utils.isValidXml("<root><child></child></root><root>")).toBe(false);
115
+ });
110
116
  });
@@ -1,6 +1,6 @@
1
1
  import { Utils } from "../../../helpers";
2
2
  import { mapOptionalStockQueryParams } from "../../../helpers/mapper";
3
- import { OnlyNonZero, QtyType, StockLevelLookupRequestBody, } from "../types";
3
+ import { IgnoreSizePacks, OnlyNonZero, QtyType, StockLevelLookupRequestBody, } from "../types";
4
4
  export function mapWarehouse(src) {
5
5
  return {
6
6
  namekey: (src?.namekey ?? [])[0],
@@ -73,6 +73,7 @@ export function mapStockLevelLookupQueryParams(src) {
73
73
  WarehouseClassFr4: src?.warehouseClassFr4 ?? "",
74
74
  WarehouseClassTo4: src?.warehouseClassTo4 ?? "",
75
75
  WarehouseClassFr5: src?.warehouseClassFr5 ?? "",
76
+ IgnoreSizePacks: src?.ignoreSizePacks ?? IgnoreSizePacks.YES,
76
77
  ...optional,
77
78
  });
78
79
  }
@@ -3,7 +3,7 @@ import { ApiHelper, TEST_HEADERS, Utils } from "../../helpers";
3
3
  import { ServiceAlias } from "../shared";
4
4
  import { StockSearchType } from "../stock-lookup";
5
5
  import { StockLevelLookupModule } from "./stock-level-lookup.module";
6
- import { OnlyNonZero, QtyType, Summarised, } from "./types";
6
+ import { IgnoreSizePacks, OnlyNonZero, QtyType, Summarised, } from "./types";
7
7
  jest.mock("axios");
8
8
  const mAxios = axios;
9
9
  describe("StockLevelLookupModule.warehouseLookup()", () => {
@@ -88,6 +88,7 @@ describe("StockLevelLookupModule.stockLevelLookup()", () => {
88
88
  summarised: Summarised.EXPANDED,
89
89
  onlyNonZero: OnlyNonZero.NO,
90
90
  warehouse1: "123",
91
+ ignoreSizePacks: IgnoreSizePacks.NO,
91
92
  };
92
93
  const ns = "S";
93
94
  const expectedPayload = `
@@ -107,6 +108,7 @@ describe("StockLevelLookupModule.stockLevelLookup()", () => {
107
108
  <Summarised>${params.summarised}</Summarised>
108
109
  <OnlyNonZero>${params.onlyNonZero}</OnlyNonZero>
109
110
  <Warehouse1>${params.warehouse1}</Warehouse1>
111
+ <IgnoreSizePacks>${params.ignoreSizePacks}</IgnoreSizePacks>
110
112
  </${ServiceAlias.STOCK_LEVEL_LOOKUP}:StockLevelLookupRequest>
111
113
  </${ns}:Body>
112
114
  </${ns}:Envelope>
@@ -228,10 +230,11 @@ describe("StockLevelLookupModule.stockLevelLookup()", () => {
228
230
  </QtyType>
229
231
  <OnlyNonZero>${params.onlyNonZero}</OnlyNonZero>
230
232
  <Warehouse>${params.warehouse}</Warehouse>
233
+ <IgnoreSizePacks>Y</IgnoreSizePacks>
231
234
  </${ServiceAlias.STOCK_LEVEL_LOOKUP}:StockLevelLookupByWarehouseQuickViewRequest>
232
235
  </${ns}:Body>
233
236
  </${ns}:Envelope>
234
- `;
237
+ `; // ignore size pack set to Y by default
235
238
  const mockedResp = {
236
239
  data: `
237
240
  <?xml version='1.0' encoding='UTF-8'?>
@@ -113,6 +113,7 @@ export declare class StockLevelLookupRequestBody extends OptionalStockRequestBod
113
113
  WarehouseClassTo4?: string;
114
114
  WarehouseClassFr5?: string;
115
115
  WarehouseClassTo5?: string;
116
+ IgnoreSizePacks?: IgnoreSizePacks;
116
117
  constructor(obj: Partial<StockLevelLookupRequestBody>);
117
118
  toString(): string;
118
119
  }
@@ -142,6 +143,7 @@ export interface StockLevelLookupQueryParams extends OptionalStockQueryParams {
142
143
  warehouseClassTo4?: string;
143
144
  warehouseClassFr5?: string;
144
145
  warehouseClassTo5?: string;
146
+ ignoreSizePacks?: IgnoreSizePacks;
145
147
  }
146
148
  export declare enum QtyType {
147
149
  STK = "STK",
@@ -149,6 +151,10 @@ export declare enum QtyType {
149
151
  FUT = "FUT",
150
152
  AVL = "AVL"
151
153
  }
154
+ export declare enum IgnoreSizePacks {
155
+ YES = "Y",
156
+ NO = "N"
157
+ }
152
158
  export declare enum Summarised {
153
159
  EXPANDED = "E",
154
160
  SUMMARISED = "S"
@@ -25,6 +25,7 @@ export class StockLevelLookupRequestBody extends OptionalStockRequestBody {
25
25
  WarehouseClassTo4;
26
26
  WarehouseClassFr5;
27
27
  WarehouseClassTo5;
28
+ IgnoreSizePacks;
28
29
  constructor(obj) {
29
30
  if (!obj?.SearchType) {
30
31
  throw new Error("SearchType is required when constructing StockLookup request body");
@@ -49,6 +50,11 @@ export var QtyType;
49
50
  QtyType["FUT"] = "FUT";
50
51
  QtyType["AVL"] = "AVL";
51
52
  })(QtyType || (QtyType = {}));
53
+ export var IgnoreSizePacks;
54
+ (function (IgnoreSizePacks) {
55
+ IgnoreSizePacks["YES"] = "Y";
56
+ IgnoreSizePacks["NO"] = "N";
57
+ })(IgnoreSizePacks || (IgnoreSizePacks = {}));
52
58
  export var Summarised;
53
59
  (function (Summarised) {
54
60
  Summarised["EXPANDED"] = "E";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dotdev/harmony-sdk",
3
- "version": "1.22.1",
3
+ "version": "1.24.0",
4
4
  "description": "Harmony API SDK",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",