@metriport/shared 0.32.2-alpha.0 → 0.32.3

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.
@@ -59,4 +59,67 @@ describe("limitStringLength", () => {
59
59
  expect(resp).toContain("12" + customSuffix);
60
60
  });
61
61
  });
62
+ describe("safeTrim", () => {
63
+ it("returns undefined when it gets undefined", async () => {
64
+ const resp = (0, string_1.safeTrim)(undefined);
65
+ expect(resp).toBeUndefined();
66
+ });
67
+ it("returns undefined when it gets null", async () => {
68
+ const resp = (0, string_1.safeTrim)(null);
69
+ expect(resp).toBeUndefined();
70
+ });
71
+ it("returns trimmed string for regular strings", async () => {
72
+ const input = " hello world ";
73
+ const resp = (0, string_1.safeTrim)(input);
74
+ expect(resp).toEqual("hello world");
75
+ });
76
+ it("trims leading whitespace", async () => {
77
+ const input = " hello";
78
+ const resp = (0, string_1.safeTrim)(input);
79
+ expect(resp).toEqual("hello");
80
+ });
81
+ it("trims trailing whitespace", async () => {
82
+ const input = "hello ";
83
+ const resp = (0, string_1.safeTrim)(input);
84
+ expect(resp).toEqual("hello");
85
+ });
86
+ it("returns empty string for empty string", async () => {
87
+ const resp = (0, string_1.safeTrim)("");
88
+ expect(resp).toEqual("");
89
+ });
90
+ it("returns empty string for whitespace-only string", async () => {
91
+ const resp = (0, string_1.safeTrim)(" ");
92
+ expect(resp).toEqual("");
93
+ });
94
+ it("stringifies and trims numbers", async () => {
95
+ const resp = (0, string_1.safeTrim)(123);
96
+ expect(resp).toEqual("123");
97
+ });
98
+ it("stringifies and trims booleans", async () => {
99
+ expect((0, string_1.safeTrim)(true)).toEqual("true");
100
+ expect((0, string_1.safeTrim)(false)).toEqual("false");
101
+ });
102
+ it("stringifies and trims objects", async () => {
103
+ const resp = (0, string_1.safeTrim)({ key: "value" });
104
+ expect(resp).toEqual('{"key":"value"}');
105
+ });
106
+ it("stringifies and trims arrays", async () => {
107
+ const resp = (0, string_1.safeTrim)([1, 2, 3]);
108
+ expect(resp).toEqual("[1,2,3]");
109
+ });
110
+ it("falls back to String() when JSON.stringify throws", async function () {
111
+ const circular = {};
112
+ circular.self = circular;
113
+ const resp = (0, string_1.safeTrim)(circular);
114
+ expect(resp).toEqual("[object Object]");
115
+ });
116
+ it("stringifies and trims nested objects", async () => {
117
+ const resp = (0, string_1.safeTrim)({ key: "value", nested: { foo: "bar" } });
118
+ expect(resp).toEqual('{"key":"value","nested":{"foo":"bar"}}');
119
+ });
120
+ it("handles zero", async () => {
121
+ const resp = (0, string_1.safeTrim)(0);
122
+ expect(resp).toEqual("0");
123
+ });
124
+ });
62
125
  //# sourceMappingURL=string.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"string.test.js","sourceRoot":"","sources":["../../../src/common/__tests__/string.test.ts"],"names":[],"mappings":";;AAAA,2CAAwC;AACxC,sCAA8C;AAE9C,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,IAAI,GAAG,IAAA,0BAAiB,EAAC,SAAS,CAAC,CAAC;QAC1C,MAAM,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;QAChD,MAAM,QAAQ,GAAG,EAAE,CAAC;QACpB,MAAM,IAAI,GAAG,IAAA,0BAAiB,EAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,QAAQ,GAAG,aAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC9C,MAAM,IAAI,GAAG,IAAA,0BAAiB,EAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,YAAY,GAAG,aAAK,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;QAC5D,MAAM,QAAQ,GAAG,aAAK,CAAC,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;QACzD,MAAM,IAAI,GAAG,IAAA,0BAAiB,EAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,QAAQ,GAAG,aAAK,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QAChD,MAAM,IAAI,GAAG,IAAA,0BAAiB,EAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,QAAQ,GAAG,aAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC9C,MAAM,IAAI,GAAG,IAAA,0BAAiB,EAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,KAAK,IAAI,EAAE;QAC3C,MAAM,QAAQ,GAAG,QAAQ,CAAC;QAC1B,MAAM,IAAI,GAAG,IAAA,0BAAiB,EAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2BAA2B,EAAE,KAAK,IAAI,EAAE;QACzC,MAAM,KAAK,GAAG,aAAK,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC;QACjD,MAAM,IAAI,GAAG,IAAA,0BAAiB,EAAC,KAAK,CAAC,CAAC;QACtC,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;QAC7C,MAAM,QAAQ,GAAG,QAAQ,CAAC;QAC1B,MAAM,IAAI,GAAG,IAAA,0BAAiB,EAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;QAChD,MAAM,QAAQ,GAAG,QAAQ,CAAC;QAC1B,MAAM,YAAY,GAAG,KAAK,CAAC;QAC3B,MAAM,IAAI,GAAG,IAAA,0BAAiB,EAAC,QAAQ,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC;QAC1D,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,IAAI,GAAG,YAAY,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"string.test.js","sourceRoot":"","sources":["../../../src/common/__tests__/string.test.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"merge-settings.js","sourceRoot":"","sources":["../../src/common/merge-settings.ts"],"names":[],"mappings":";;;AAAA,mCAA6D;AAS7D;;;;;;;;;GASG;AACH,SAAgB,aAAa,CAAI,EAC/B,WAAW,EACX,WAAW,GAIZ;IACC,IAAI,CAAC,WAAW;QAAE,OAAO,WAAW,CAAC;IAErC,OAAO,IAAA,kBAAS,EAAC,IAAA,kBAAS,EAAC,WAAW,CAAC,EAAE,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE;QACnE,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QACpC,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QACrC,IAAI,CAAC,IAAA,sBAAa,EAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QACtC,OAAO,SAAS,CAAC;IACnB,CAAC,CAAM,CAAC;AACV,CAAC;AAfD,sCAeC"}
1
+ {"version":3,"file":"merge-settings.js","sourceRoot":"","sources":["../../src/common/merge-settings.ts"],"names":[],"mappings":";;;AAAA,mCAA6D;AAS7D;;;;;;;;;GASG;AACH,SAAgB,aAAa,CAAI,EAC/B,WAAW,EACX,WAAW,GAIZ;IACC,IAAI,CAAC,WAAW;QAAE,OAAO,WAAW,CAAC;IAErC,OAAO,IAAA,kBAAS,EAAC,IAAA,kBAAS,EAAC,WAAW,CAAC,EAAE,WAAW,EAAE,CAAC,IAAa,EAAE,IAAa,EAAE,EAAE;QACrF,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QACpC,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QACrC,IAAI,CAAC,IAAA,sBAAa,EAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QACtC,OAAO,SAAS,CAAC;IACnB,CAAC,CAAM,CAAC;AACV,CAAC;AAfD,sCAeC"}
@@ -7,4 +7,10 @@ export declare function stripPeriods(str: string): string;
7
7
  * numbers back to a string when returning the trimmed result.
8
8
  */
9
9
  export declare function trimWhitespace(str: unknown): string | undefined;
10
+ /**
11
+ * Stringifies and trims the value. Returns undefined if the value is null or undefined.
12
+ * @param str - The value to stringify and trim
13
+ * @returns The stringified and trimmed string or undefined if the value is null or undefined
14
+ */
15
+ export declare function safeTrim(str: unknown): string | undefined;
10
16
  //# sourceMappingURL=string.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"string.d.ts","sourceRoot":"","sources":["../../src/common/string.ts"],"names":[],"mappings":"AAAA,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,MAAM,GAAG,SAAS,EAC5D,KAAK,EAAE,CAAC,EACR,GAAG,SAAM,EACT,MAAM,SAAQ,GACb,CAAC,CAOH;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAI/D"}
1
+ {"version":3,"file":"string.d.ts","sourceRoot":"","sources":["../../src/common/string.ts"],"names":[],"mappings":"AAAA,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,MAAM,GAAG,SAAS,EAC5D,KAAK,EAAE,CAAC,EACR,GAAG,SAAM,EACT,MAAM,SAAQ,GACb,CAAC,CAOH;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAI/D;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAWzD"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.trimWhitespace = exports.stripPeriods = exports.stripNonNumericChars = exports.limitStringLength = void 0;
3
+ exports.safeTrim = exports.trimWhitespace = exports.stripPeriods = exports.stripNonNumericChars = exports.limitStringLength = void 0;
4
4
  function limitStringLength(value, max = 255, suffix = "...") {
5
5
  if (!value)
6
6
  return value;
@@ -30,4 +30,25 @@ function trimWhitespace(str) {
30
30
  return str.trim();
31
31
  }
32
32
  exports.trimWhitespace = trimWhitespace;
33
+ /**
34
+ * Stringifies and trims the value. Returns undefined if the value is null or undefined.
35
+ * @param str - The value to stringify and trim
36
+ * @returns The stringified and trimmed string or undefined if the value is null or undefined
37
+ */
38
+ function safeTrim(str) {
39
+ if (str == null)
40
+ return undefined;
41
+ if (typeof str === "string")
42
+ return str.trim();
43
+ if (typeof str === "object") {
44
+ try {
45
+ return JSON.stringify(str).trim();
46
+ }
47
+ catch {
48
+ return String(str).trim();
49
+ }
50
+ }
51
+ return String(str).trim();
52
+ }
53
+ exports.safeTrim = safeTrim;
33
54
  //# sourceMappingURL=string.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"string.js","sourceRoot":"","sources":["../../src/common/string.ts"],"names":[],"mappings":";;;AAAA,SAAgB,iBAAiB,CAC/B,KAAQ,EACR,GAAG,GAAG,GAAG,EACT,MAAM,GAAG,KAAK;IAEd,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,OAAO,CACL,KAAK,CAAC,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM;QAChD,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM;QAClD,CAAC,CAAC,KAAK,CACL,CAAC;AACT,CAAC;AAXD,8CAWC;AAED,SAAgB,oBAAoB,CAAC,GAAW;IAC9C,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACvC,CAAC;AAFD,oDAEC;AAED,SAAgB,YAAY,CAAC,GAAW;IACtC,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACvC,CAAC;AAFD,oCAEC;AAED;;;;GAIG;AACH,SAAgB,cAAc,CAAC,GAAY;IACzC,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;IACnD,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC9C,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;AACpB,CAAC;AAJD,wCAIC"}
1
+ {"version":3,"file":"string.js","sourceRoot":"","sources":["../../src/common/string.ts"],"names":[],"mappings":";;;AAAA,SAAgB,iBAAiB,CAC/B,KAAQ,EACR,GAAG,GAAG,GAAG,EACT,MAAM,GAAG,KAAK;IAEd,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,OAAO,CACL,KAAK,CAAC,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM;QAChD,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM;QAClD,CAAC,CAAC,KAAK,CACL,CAAC;AACT,CAAC;AAXD,8CAWC;AAED,SAAgB,oBAAoB,CAAC,GAAW;IAC9C,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACvC,CAAC;AAFD,oDAEC;AAED,SAAgB,YAAY,CAAC,GAAW;IACtC,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACvC,CAAC;AAFD,oCAEC;AAED;;;;GAIG;AACH,SAAgB,cAAc,CAAC,GAAY;IACzC,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;IACnD,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC9C,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;AACpB,CAAC;AAJD,wCAIC;AAED;;;;GAIG;AACH,SAAgB,QAAQ,CAAC,GAAY;IACnC,IAAI,GAAG,IAAI,IAAI;QAAE,OAAO,SAAS,CAAC;IAClC,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;IAC/C,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;QAC3B,IAAI;YACF,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;SACnC;QAAC,MAAM;YACN,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;SAC3B;KACF;IACD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AAC5B,CAAC;AAXD,4BAWC"}
@@ -328,8 +328,8 @@ export declare const tcmEncounterListQuerySchema: z.ZodIntersection<z.ZodObject<
328
328
  search: z.ZodOptional<z.ZodString>;
329
329
  encounterClass: z.ZodEffects<z.ZodOptional<z.ZodUnion<[z.ZodEnum<["inpatient encounter", "ambulatory", "emergency", "short stay", "pre-admission"]>, z.ZodArray<z.ZodEnum<["inpatient encounter", "ambulatory", "emergency", "short stay", "pre-admission"]>, "many">, z.ZodPipeline<z.ZodEffects<z.ZodString, string[], string>, z.ZodArray<z.ZodEnum<["inpatient encounter", "ambulatory", "emergency", "short stay", "pre-admission"]>, "many">>]>>, ("ambulatory" | "inpatient encounter" | "emergency" | "short stay" | "pre-admission")[] | undefined, string | ("ambulatory" | "inpatient encounter" | "emergency" | "short stay" | "pre-admission")[] | undefined>;
330
330
  }, "strip", z.ZodTypeAny, {
331
- search?: string | undefined;
332
331
  status?: "Not Started" | "Attempted" | "Completed" | undefined;
332
+ search?: string | undefined;
333
333
  coding?: "cardiac" | undefined;
334
334
  facilityId?: string | undefined;
335
335
  after?: string | undefined;
@@ -338,8 +338,8 @@ export declare const tcmEncounterListQuerySchema: z.ZodIntersection<z.ZodObject<
338
338
  eventType?: "Admitted" | "Discharged" | undefined;
339
339
  encounterClass?: ("ambulatory" | "inpatient encounter" | "emergency" | "short stay" | "pre-admission")[] | undefined;
340
340
  }, {
341
- search?: string | undefined;
342
341
  status?: "Not Started" | "Attempted" | "Completed" | undefined;
342
+ search?: string | undefined;
343
343
  coding?: "cardiac" | undefined;
344
344
  facilityId?: string | undefined;
345
345
  after?: string | undefined;
@@ -1,7 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const faker_1 = require("@faker-js/faker");
4
+ const axios_1 = require("axios");
5
+ const bad_request_1 = require("../bad-request");
4
6
  const metriport_error_1 = require("../metriport-error");
7
+ const not_found_1 = require("../not-found");
5
8
  const shared_1 = require("../shared");
6
9
  beforeEach(() => {
7
10
  jest.restoreAllMocks();
@@ -77,5 +80,460 @@ describe("errorToString", () => {
77
80
  const res = (0, shared_1.errorToString)(error, { detailed: true });
78
81
  expect(res).toEqual(expectedMessage);
79
82
  });
83
+ it("does not expose PHI from AxiosError response.data or config.data", () => {
84
+ const axiosError = {
85
+ message: "Request failed with status code 400",
86
+ code: "ERR_BAD_REQUEST",
87
+ isAxiosError: true,
88
+ config: {
89
+ method: "post",
90
+ url: "http://example.com/api/convert",
91
+ data: "<ClinicalDocument>SUPER SECRET PHI</ClinicalDocument>",
92
+ headers: {
93
+ Authorization: "Bearer secret-token",
94
+ },
95
+ },
96
+ response: {
97
+ status: 400,
98
+ statusText: "Bad Request",
99
+ data: { patientName: "John Doe", ssn: "123-45-6789" },
100
+ },
101
+ };
102
+ const result = (0, shared_1.errorToString)(axiosError);
103
+ // Should only contain safe fields
104
+ expect(result).toContain("Request failed with status code 400");
105
+ expect(result).toContain("ERR_BAD_REQUEST");
106
+ expect(result).toContain("400");
107
+ // Should NOT contain PHI
108
+ expect(result).not.toContain("SUPER SECRET PHI");
109
+ expect(result).not.toContain("John Doe");
110
+ expect(result).not.toContain("123-45-6789");
111
+ expect(result).not.toContain("secret-token");
112
+ });
113
+ });
114
+ describe("sanitizeError", () => {
115
+ it("strips config.data and config.headers from AxiosError", () => {
116
+ const axiosError = {
117
+ message: "Request failed with status code 400",
118
+ name: "AxiosError",
119
+ code: "ERR_BAD_REQUEST",
120
+ isAxiosError: true,
121
+ stack: "ORIGINAL_STACK",
122
+ config: {
123
+ method: "post",
124
+ url: "http://example.com/api/convert",
125
+ data: "<ClinicalDocument>SUPER SECRET PHI</ClinicalDocument>",
126
+ headers: {
127
+ Authorization: "Bearer secret-token",
128
+ "Content-Type": "text/plain",
129
+ },
130
+ },
131
+ response: {
132
+ status: 400,
133
+ statusText: "Bad Request",
134
+ data: { error: "Invalid input" },
135
+ },
136
+ };
137
+ const result = (0, shared_1.sanitizeError)(axiosError);
138
+ expect(result).toBeInstanceOf(Error);
139
+ expect(result.message).toBe("Request failed with status code 400");
140
+ expect(result.name).toBe("AxiosError");
141
+ expect(result.code).toBe("ERR_BAD_REQUEST");
142
+ expect(result.status).toBe(400);
143
+ expect(result.statusText).toBe("Bad Request");
144
+ expect(result.method).toBe("POST");
145
+ expect(result.url).toBe("http://example.com/api/convert");
146
+ expect(result.config).toBeUndefined();
147
+ expect(result.data).toBeUndefined();
148
+ expect(result.headers).toBeUndefined();
149
+ expect(result.stack).toBe("ORIGINAL_STACK");
150
+ });
151
+ it("returns non-AxiosError unchanged", () => {
152
+ const regularError = new Error("something broke");
153
+ const result = (0, shared_1.sanitizeError)(regularError);
154
+ expect(result).toBe(regularError);
155
+ });
156
+ it("returns primitive values unchanged", () => {
157
+ expect((0, shared_1.sanitizeError)(null)).toBeNull();
158
+ expect((0, shared_1.sanitizeError)(undefined)).toBeUndefined();
159
+ expect((0, shared_1.sanitizeError)("string error")).toBe("string error");
160
+ });
161
+ it("works with real AxiosError from axios library", () => {
162
+ const headers = new axios_1.AxiosHeaders({
163
+ Authorization: "Bearer token123",
164
+ });
165
+ const config = {
166
+ method: "post",
167
+ url: "http://example.com/convert",
168
+ data: "<xml>PHI HERE</xml>",
169
+ headers: headers,
170
+ };
171
+ const axiosError = new axios_1.AxiosError("Request failed", "ERR_BAD_REQUEST", config, undefined, {
172
+ status: 400,
173
+ statusText: "Bad Request",
174
+ data: {},
175
+ headers: {},
176
+ config: config,
177
+ });
178
+ const result = (0, shared_1.sanitizeError)(axiosError);
179
+ expect(result).toBeInstanceOf(Error);
180
+ expect(result.message).toBe("Request failed");
181
+ expect(result.name).toBe("AxiosError");
182
+ expect(result.code).toBe("ERR_BAD_REQUEST");
183
+ expect(result.status).toBe(400);
184
+ expect(result.method).toBe("POST");
185
+ expect(result.url).toBe("http://example.com/convert");
186
+ // Verify PHI is stripped
187
+ expect(JSON.stringify(result)).not.toContain("PHI HERE");
188
+ expect(JSON.stringify(result)).not.toContain("Bearer token123");
189
+ });
190
+ it("sanitizes AxiosError when it's the cause of MetriportError", () => {
191
+ const axiosError = {
192
+ message: "Request failed with status code 400",
193
+ code: "ERR_BAD_REQUEST",
194
+ isAxiosError: true,
195
+ config: {
196
+ method: "post",
197
+ url: "http://example.com/api/convert",
198
+ data: "<ClinicalDocument>SUPER SECRET PHI</ClinicalDocument>",
199
+ headers: {
200
+ Authorization: "Bearer secret-token",
201
+ },
202
+ },
203
+ response: {
204
+ status: 400,
205
+ statusText: "Bad Request",
206
+ data: { patientName: "John Doe", ssn: "123-45-6789" },
207
+ },
208
+ };
209
+ const metriportError = new metriport_error_1.MetriportError("Conversion failed", axiosError);
210
+ const result = (0, shared_1.sanitizeError)(metriportError);
211
+ expect(result).toBeInstanceOf(metriport_error_1.MetriportError);
212
+ expect(result.message).toBe("Conversion failed");
213
+ expect(result.cause).toBeInstanceOf(Error);
214
+ expect(result.cause.message).toBe("Request failed with status code 400");
215
+ expect(result.cause.name).toBe("AxiosError");
216
+ expect(result.cause.code).toBe("ERR_BAD_REQUEST");
217
+ expect(result.cause.status).toBe(400);
218
+ expect(result.cause.statusText).toBe("Bad Request");
219
+ expect(result.cause.method).toBe("POST");
220
+ expect(result.cause.url).toBe("http://example.com/api/convert");
221
+ // Verify PHI is stripped from cause
222
+ expect(JSON.stringify(result.cause)).not.toContain("SUPER SECRET PHI");
223
+ expect(JSON.stringify(result.cause)).not.toContain("John Doe");
224
+ expect(JSON.stringify(result.cause)).not.toContain("123-45-6789");
225
+ expect(JSON.stringify(result.cause)).not.toContain("secret-token");
226
+ });
227
+ it("recursively sanitizes nested MetriportError chains with AxiosError", () => {
228
+ const axiosError = {
229
+ message: "Network error",
230
+ code: "ECONNREFUSED",
231
+ isAxiosError: true,
232
+ config: {
233
+ method: "get",
234
+ url: "http://example.com/data",
235
+ data: "<PHI>Secret Data</PHI>",
236
+ },
237
+ response: {
238
+ status: 500,
239
+ statusText: "Internal Server Error",
240
+ data: { error: "Server error" },
241
+ },
242
+ };
243
+ const innerError = new metriport_error_1.MetriportError("Inner error", axiosError);
244
+ const outerError = new metriport_error_1.MetriportError("Outer error", innerError);
245
+ const result = (0, shared_1.sanitizeError)(outerError);
246
+ expect(result).toBeInstanceOf(metriport_error_1.MetriportError);
247
+ expect(result.message).toBe("Outer error");
248
+ expect(result.cause).toBeInstanceOf(metriport_error_1.MetriportError);
249
+ expect(result.cause.message).toBe("Inner error");
250
+ expect(result.cause.cause).toBeInstanceOf(Error);
251
+ expect(result.cause.cause.message).toBe("Network error");
252
+ expect(result.cause.cause.name).toBe("AxiosError");
253
+ expect(result.cause.cause.code).toBe("ECONNREFUSED");
254
+ expect(result.cause.cause.status).toBe(500);
255
+ expect(result.cause.cause.statusText).toBe("Internal Server Error");
256
+ expect(result.cause.cause.method).toBe("GET");
257
+ expect(result.cause.cause.url).toBe("http://example.com/data");
258
+ // Verify PHI is stripped
259
+ expect(JSON.stringify(result)).not.toContain("Secret Data");
260
+ });
261
+ it("leaves MetriportError unchanged if cause is not AxiosError (same instance)", () => {
262
+ const regularError = new Error("Regular error");
263
+ const metriportError = new metriport_error_1.MetriportError("Wrapper error", regularError);
264
+ const result = (0, shared_1.sanitizeError)(metriportError);
265
+ expect(result).toBe(metriportError);
266
+ expect(result.cause).toBe(regularError);
267
+ });
268
+ it("leaves MetriportError unchanged if it has no cause", () => {
269
+ const metriportError = new metriport_error_1.MetriportError("Simple error");
270
+ const result = (0, shared_1.sanitizeError)(metriportError);
271
+ expect(result).toBeInstanceOf(metriport_error_1.MetriportError);
272
+ expect(result.message).toBe("Simple error");
273
+ expect(result.cause).toBeUndefined();
274
+ });
275
+ it("returns the same MetriportError instance when cause is unchanged (preserves stack)", () => {
276
+ const regularError = new Error("Regular error");
277
+ const metriportError = new metriport_error_1.MetriportError("Wrapper error", regularError);
278
+ metriportError.stack = "ORIGINAL_STACK";
279
+ const result = (0, shared_1.sanitizeError)(metriportError);
280
+ expect(result).toBe(metriportError);
281
+ expect(result.cause).toBe(regularError);
282
+ expect(result.stack).toBe("ORIGINAL_STACK");
283
+ });
284
+ it("preserves BadRequestError subclass type when sanitizing AxiosError cause", () => {
285
+ const axiosError = {
286
+ message: "Request failed with status code 400",
287
+ code: "ERR_BAD_REQUEST",
288
+ isAxiosError: true,
289
+ config: {
290
+ method: "post",
291
+ url: "http://example.com/api/resource",
292
+ data: "<PHI>Secret Patient Data</PHI>",
293
+ headers: { Authorization: "Bearer secret-token" },
294
+ },
295
+ response: {
296
+ status: 400,
297
+ statusText: "Bad Request",
298
+ data: { patientName: "John Doe" },
299
+ },
300
+ };
301
+ const error = new bad_request_1.BadRequestError("Invalid input", axiosError, { field: "name" });
302
+ const result = (0, shared_1.sanitizeError)(error);
303
+ expect(result).toBeInstanceOf(bad_request_1.BadRequestError);
304
+ expect(result).toBeInstanceOf(metriport_error_1.MetriportError);
305
+ expect(result.status).toBe(400);
306
+ expect(result.name).toBe("BadRequestError");
307
+ expect(result.message).toBe("Invalid input");
308
+ expect(result.additionalInfo).toEqual({ field: "name" });
309
+ expect(JSON.stringify(result.cause)).not.toContain("Secret Patient Data");
310
+ expect(JSON.stringify(result.cause)).not.toContain("secret-token");
311
+ });
312
+ it("preserves NotFoundError subclass type when sanitizing AxiosError cause", () => {
313
+ const axiosError = {
314
+ message: "Request failed with status code 404",
315
+ code: "ERR_BAD_REQUEST",
316
+ isAxiosError: true,
317
+ config: {
318
+ method: "get",
319
+ url: "http://example.com/api/patient/123",
320
+ data: "<PHI>Secret Patient Data</PHI>",
321
+ },
322
+ response: {
323
+ status: 404,
324
+ statusText: "Not Found",
325
+ data: { detail: "Patient not found" },
326
+ },
327
+ };
328
+ const error = new not_found_1.NotFoundError("Resource not found", axiosError);
329
+ const result = (0, shared_1.sanitizeError)(error);
330
+ expect(result).toBeInstanceOf(not_found_1.NotFoundError);
331
+ expect(result).toBeInstanceOf(metriport_error_1.MetriportError);
332
+ expect(result.status).toBe(404);
333
+ expect(result.name).toBe("NotFoundError");
334
+ expect(result.message).toBe("Resource not found");
335
+ expect(JSON.stringify(result.cause)).not.toContain("Secret Patient Data");
336
+ });
337
+ it("preserves subclass type in nested chain with AxiosError at the bottom", () => {
338
+ const axiosError = {
339
+ message: "Network error",
340
+ code: "ECONNREFUSED",
341
+ isAxiosError: true,
342
+ config: {
343
+ method: "get",
344
+ url: "http://example.com/data",
345
+ data: "<PHI>Secret Data</PHI>",
346
+ },
347
+ response: {
348
+ status: 500,
349
+ statusText: "Internal Server Error",
350
+ data: { error: "Server error" },
351
+ },
352
+ };
353
+ const innerError = new bad_request_1.BadRequestError("Bad input", axiosError, { key: "val" });
354
+ const outerError = new not_found_1.NotFoundError("Wrapper not found", innerError);
355
+ const result = (0, shared_1.sanitizeError)(outerError);
356
+ expect(result).toBeInstanceOf(not_found_1.NotFoundError);
357
+ expect(result.status).toBe(404);
358
+ expect(result.name).toBe("NotFoundError");
359
+ expect(result.cause).toBeInstanceOf(bad_request_1.BadRequestError);
360
+ expect(result.cause.status).toBe(400);
361
+ expect(result.cause.name).toBe("BadRequestError");
362
+ expect(JSON.stringify(result)).not.toContain("Secret Data");
363
+ });
364
+ it("preserves subclass type when cause is a non-AxiosError", () => {
365
+ const regularError = new Error("Something broke");
366
+ const error = new bad_request_1.BadRequestError("Bad request", regularError);
367
+ const result = (0, shared_1.sanitizeError)(error);
368
+ expect(result).toBeInstanceOf(bad_request_1.BadRequestError);
369
+ expect(result).toBeInstanceOf(metriport_error_1.MetriportError);
370
+ expect(result.status).toBe(400);
371
+ expect(result.name).toBe("BadRequestError");
372
+ expect(result.cause).toBe(regularError);
373
+ });
374
+ it("preserves all properties including future ones when sanitizing MetriportError with AxiosError cause", () => {
375
+ const axiosError = {
376
+ message: "Request failed with status code 400",
377
+ code: "ERR_BAD_REQUEST",
378
+ isAxiosError: true,
379
+ config: {
380
+ method: "post",
381
+ url: "http://example.com/api/resource",
382
+ data: "<PHI>Secret Patient Data</PHI>",
383
+ headers: { Authorization: "Bearer secret-token" },
384
+ },
385
+ response: {
386
+ status: 400,
387
+ statusText: "Bad Request",
388
+ data: { patientName: "John Doe", ssn: "123-45-6789" },
389
+ },
390
+ };
391
+ const error = new bad_request_1.BadRequestError("Invalid input", axiosError, { field: "name" });
392
+ // Simulate future properties that might be added to MetriportError or its subclasses
393
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
394
+ error.customProperty = "custom-value";
395
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
396
+ error.metadata = { requestId: "req-123", timestamp: 1234567890 };
397
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
398
+ error.retryCount = 3;
399
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
400
+ error.context = { userId: "user-456", operation: "validate" };
401
+ const result = (0, shared_1.sanitizeError)(error);
402
+ // Verify subclass type is preserved
403
+ expect(result).toBeInstanceOf(bad_request_1.BadRequestError);
404
+ expect(result).toBeInstanceOf(metriport_error_1.MetriportError);
405
+ expect(result.status).toBe(400);
406
+ expect(result.name).toBe("BadRequestError");
407
+ expect(result.message).toBe("Invalid input");
408
+ expect(result.additionalInfo).toEqual({ field: "name" });
409
+ // Verify all future properties are preserved (proves maintenance-free approach)
410
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
411
+ expect(result.customProperty).toBe("custom-value");
412
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
413
+ expect(result.metadata).toEqual({ requestId: "req-123", timestamp: 1234567890 });
414
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
415
+ expect(result.retryCount).toBe(3);
416
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
417
+ expect(result.context).toEqual({ userId: "user-456", operation: "validate" });
418
+ expect(JSON.stringify(result.cause)).not.toContain("Secret Patient Data");
419
+ expect(JSON.stringify(result.cause)).not.toContain("secret-token");
420
+ expect(JSON.stringify(result.cause)).not.toContain("John Doe");
421
+ expect(JSON.stringify(result.cause)).not.toContain("123-45-6789");
422
+ expect(JSON.stringify(result)).not.toContain("Secret Patient Data");
423
+ expect(JSON.stringify(result)).not.toContain("secret-token");
424
+ expect(JSON.stringify(result)).not.toContain("John Doe");
425
+ expect(JSON.stringify(result)).not.toContain("123-45-6789");
426
+ });
427
+ it("rebuilds MetriportError when cause is sanitized (and preserves wrapper stack)", () => {
428
+ const axiosError = {
429
+ message: "Request failed",
430
+ name: "AxiosError",
431
+ code: "ERR_BAD_REQUEST",
432
+ isAxiosError: true,
433
+ config: {
434
+ method: "post",
435
+ url: "http://example.com/api",
436
+ data: "<PHI>Secret</PHI>",
437
+ headers: { Authorization: "Bearer token" },
438
+ },
439
+ response: { status: 400, statusText: "Bad Request", data: { patient: "John Doe" } },
440
+ };
441
+ const metriportError = new metriport_error_1.MetriportError("Wrapper error", axiosError);
442
+ metriportError.stack = "ORIGINAL_WRAPPER_STACK";
443
+ const result = (0, shared_1.sanitizeError)(metriportError);
444
+ // Should rebuild because cause was sanitized (new Error object)
445
+ expect(result).not.toBe(metriportError);
446
+ // But wrapper stack should be preserved (your code copies it)
447
+ expect(result.stack).toBe("ORIGINAL_WRAPPER_STACK");
448
+ // And PHI should not appear on the cause
449
+ expect(JSON.stringify(result.cause)).not.toContain("Secret");
450
+ expect(JSON.stringify(result.cause)).not.toContain("Bearer token");
451
+ expect(JSON.stringify(result.cause)).not.toContain("John Doe");
452
+ });
453
+ it("preserves all properties in nested MetriportError chain with future properties", () => {
454
+ const axiosError = {
455
+ message: "Network error",
456
+ code: "ECONNREFUSED",
457
+ isAxiosError: true,
458
+ config: {
459
+ method: "get",
460
+ url: "http://example.com/data",
461
+ data: "<PHI>Secret Data</PHI>",
462
+ headers: { Authorization: "Bearer token-xyz" },
463
+ },
464
+ response: {
465
+ status: 500,
466
+ statusText: "Internal Server Error",
467
+ data: { error: "Server error", patientId: "patient-789" },
468
+ },
469
+ };
470
+ const innerError = new bad_request_1.BadRequestError("Bad input", axiosError, { key: "val" });
471
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
472
+ innerError.innerCustomProp = "inner-value";
473
+ const outerError = new not_found_1.NotFoundError("Wrapper not found", innerError);
474
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
475
+ outerError.outerCustomProp = "outer-value";
476
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
477
+ outerError.traceId = "trace-abc";
478
+ const result = (0, shared_1.sanitizeError)(outerError);
479
+ // Verify outer error type and properties
480
+ expect(result).toBeInstanceOf(not_found_1.NotFoundError);
481
+ expect(result.status).toBe(404);
482
+ expect(result.name).toBe("NotFoundError");
483
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
484
+ expect(result.outerCustomProp).toBe("outer-value");
485
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
486
+ expect(result.traceId).toBe("trace-abc");
487
+ // Verify inner error type and properties
488
+ expect(result.cause).toBeInstanceOf(bad_request_1.BadRequestError);
489
+ expect(result.cause.status).toBe(400);
490
+ expect(result.cause.name).toBe("BadRequestError");
491
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
492
+ expect(result.cause.innerCustomProp).toBe("inner-value");
493
+ // Verify PHI is stripped from entire chain
494
+ expect(JSON.stringify(result)).not.toContain("Secret Data");
495
+ expect(JSON.stringify(result)).not.toContain("token-xyz");
496
+ expect(JSON.stringify(result)).not.toContain("patient-789");
497
+ });
498
+ it("strips PHI from deeply nested error chains", () => {
499
+ const axiosError = {
500
+ message: "Request failed",
501
+ code: "ERR_BAD_REQUEST",
502
+ isAxiosError: true,
503
+ config: {
504
+ method: "post",
505
+ url: "http://example.com/api",
506
+ data: "<ClinicalDocument><Patient><Name>Jane Doe</Name><SSN>987-65-4321</SSN></Patient></ClinicalDocument>",
507
+ headers: { Authorization: "Bearer sensitive-token-123" },
508
+ },
509
+ response: {
510
+ status: 400,
511
+ statusText: "Bad Request",
512
+ data: { error: "Validation failed", patientData: { name: "Jane Doe", dob: "1990-01-01" } },
513
+ },
514
+ };
515
+ const level3 = new metriport_error_1.MetriportError("Level 3 error", axiosError);
516
+ const level2 = new bad_request_1.BadRequestError("Level 2 error", level3, { level: 2 });
517
+ const level1 = new not_found_1.NotFoundError("Level 1 error", level2);
518
+ const result = (0, shared_1.sanitizeError)(level1);
519
+ // Verify all error types are preserved
520
+ expect(result).toBeInstanceOf(not_found_1.NotFoundError);
521
+ expect(result.cause).toBeInstanceOf(bad_request_1.BadRequestError);
522
+ expect(result.cause.cause).toBeInstanceOf(metriport_error_1.MetriportError);
523
+ expect(result.cause.cause.cause).toBeInstanceOf(Error);
524
+ // Verify PHI is completely stripped from entire chain
525
+ const resultString = JSON.stringify(result);
526
+ expect(resultString).not.toContain("Jane Doe");
527
+ expect(resultString).not.toContain("987-65-4321");
528
+ expect(resultString).not.toContain("sensitive-token-123");
529
+ expect(resultString).not.toContain("1990-01-01");
530
+ expect(resultString).not.toContain("ClinicalDocument");
531
+ expect(resultString).not.toContain("Patient");
532
+ // Verify safe information is preserved
533
+ expect(result.message).toBe("Level 1 error");
534
+ expect(result.cause.message).toBe("Level 2 error");
535
+ expect(result.cause.cause.message).toBe("Level 3 error");
536
+ expect(result.cause.additionalInfo).toEqual({ level: 2 });
537
+ });
80
538
  });
81
539
  //# sourceMappingURL=shared.test.js.map