erpnext-queue-client 2.6.3 → 2.6.4

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.
@@ -1,6 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const vitest_1 = require("vitest");
4
3
  const zod_1 = require("zod");
5
4
  const client_1 = require("./client");
6
5
  const responseSchema = zod_1.z
@@ -10,14 +9,14 @@ const responseSchema = zod_1.z
10
9
  })),
11
10
  })
12
11
  .describe('Dispatcher Preset List with fields ["name"]');
13
- (0, vitest_1.describe)("TemporalClient.executeERPNextRequestWorkflow", () => {
12
+ describe("TemporalClient.executeERPNextRequestWorkflow", () => {
14
13
  const originalNodeEnv = process.env.NODE_ENV;
15
14
  const originalRunInTestEnv = process.env.RUN_IN_TEST_ENV;
16
- (0, vitest_1.afterEach)(() => {
15
+ afterEach(() => {
17
16
  process.env.NODE_ENV = originalNodeEnv;
18
17
  process.env.RUN_IN_TEST_ENV = originalRunInTestEnv;
19
18
  });
20
- (0, vitest_1.test)("includes a preview of invalid string responses in validation errors", async () => {
19
+ test("includes a preview of invalid string responses in validation errors", async () => {
21
20
  process.env.NODE_ENV = "test";
22
21
  process.env.RUN_IN_TEST_ENV = "true";
23
22
  const temporalClient = new client_1.TemporalClient({
@@ -34,8 +33,8 @@ const responseSchema = zod_1.z
34
33
  responseValidationModel: responseSchema,
35
34
  }, "erpnext")
36
35
  .catch((err) => err);
37
- (0, vitest_1.expect)(error).toBeInstanceOf(Error);
38
- (0, vitest_1.expect)(error.message).toContain("Response preview:");
39
- (0, vitest_1.expect)(error.message).toContain("<html>Cloudflare Access denied</html>");
36
+ expect(error).toBeInstanceOf(Error);
37
+ expect(error.message).toContain("Response preview:");
38
+ expect(error.message).toContain("<html>Cloudflare Access denied</html>");
40
39
  });
41
40
  });
@@ -2,7 +2,7 @@ import { AnyZodObject, z, ZodArray, ZodNullable, ZodObject, ZodOptional, ZodRawS
2
2
  import { Prettify } from "../../utils/utils";
3
3
  import { KeysOf } from "../../utils/zodUtils";
4
4
  import { DocTypeChildTableEntryMeta, DocTypeMeta, SubmittableMeta } from "./ERPNextDocTypeMeta";
5
- export type KeysOfModel<T> = KeysOf<T extends AnyZodObject ? DocModelListEntryType<T> : never>;
5
+ export type KeysOfModel<T> = Extract<KeysOf<T extends AnyZodObject ? DocModelListEntryType<T> : never>, string>;
6
6
  /**
7
7
  * Extracts the alias from a field name if it contains " as ".
8
8
  * For example: "`tabItemTaxTemplateDetail`.rate as rate" -> "rate"
@@ -16,7 +16,7 @@ type ExtractAlias<T extends string> = T extends `${infer _Before} as ${infer Ali
16
16
  type PickWithAliases<TModel extends AnyZodObject, TFields extends readonly string[]> = {
17
17
  [K in TFields[number] as ExtractAlias<K>]: ExtractAlias<K> extends keyof z.infer<DocModelListEntryType<TModel>> ? z.infer<DocModelListEntryType<TModel>>[ExtractAlias<K>] : never;
18
18
  };
19
- export type GetListReturnValue<TModel, TFieldOptions extends KeysOfModel<TModel>, TSelectedFields, TAsDict> = Prettify<TAsDict extends false ? Array<Array<string>> : TModel extends AnyZodObject ? TSelectedFields extends undefined ? Array<{
19
+ export type GetListReturnValue<TModel, TFieldOptions extends string, TSelectedFields, TAsDict> = Prettify<TAsDict extends false ? Array<Array<string>> : TModel extends AnyZodObject ? TSelectedFields extends undefined ? Array<{
20
20
  name: string;
21
21
  }> : TSelectedFields extends readonly ["*"] ? Array<z.infer<DocModelListEntryType<TModel>>> : TSelectedFields extends readonly TFieldOptions[] ? Array<PickWithAliases<TModel, TSelectedFields>> : any : any>;
22
22
  export declare const LoadDocumentWrapper: <T extends AnyZodObject>(BaseModel: T) => z.ZodObject<{
@@ -130,13 +130,13 @@ export declare const ReturnItemInput: z.ZodObject<{
130
130
  return_fee: z.ZodDefault<z.ZodNumber>;
131
131
  return_label: z.ZodNullable<z.ZodOptional<z.ZodString>>;
132
132
  } & {
133
- name: z.ZodString;
133
+ name: z.ZodOptional<z.ZodString>;
134
134
  }, "strip", z.ZodTypeAny, {
135
- name: string;
136
135
  item: string;
137
136
  return_quantity: number;
138
137
  is_complaint: 0 | 1;
139
138
  return_fee: number;
139
+ name?: string | undefined;
140
140
  attachments?: string | null | undefined;
141
141
  internal_reasons?: string | null | undefined;
142
142
  line_item_id?: string | null | undefined;
@@ -149,9 +149,9 @@ export declare const ReturnItemInput: z.ZodObject<{
149
149
  complaint_description?: string | null | undefined;
150
150
  return_label?: string | null | undefined;
151
151
  }, {
152
- name: string;
153
152
  item: string;
154
153
  return_quantity: number;
154
+ name?: string | undefined;
155
155
  attachments?: string | null | undefined;
156
156
  internal_reasons?: string | null | undefined;
157
157
  line_item_id?: string | null | undefined;
@@ -494,13 +494,13 @@ export declare const ServicecaseInput: import("../../utils/zodContextOptionals")
494
494
  return_fee: z.ZodDefault<z.ZodNumber>;
495
495
  return_label: z.ZodNullable<z.ZodOptional<z.ZodString>>;
496
496
  } & {
497
- name: z.ZodString;
497
+ name: z.ZodOptional<z.ZodString>;
498
498
  }, "strip", z.ZodTypeAny, {
499
- name: string;
500
499
  item: string;
501
500
  return_quantity: number;
502
501
  is_complaint: 0 | 1;
503
502
  return_fee: number;
503
+ name?: string | undefined;
504
504
  attachments?: string | null | undefined;
505
505
  internal_reasons?: string | null | undefined;
506
506
  line_item_id?: string | null | undefined;
@@ -513,9 +513,9 @@ export declare const ServicecaseInput: import("../../utils/zodContextOptionals")
513
513
  complaint_description?: string | null | undefined;
514
514
  return_label?: string | null | undefined;
515
515
  }, {
516
- name: string;
517
516
  item: string;
518
517
  return_quantity: number;
518
+ name?: string | undefined;
519
519
  attachments?: string | null | undefined;
520
520
  internal_reasons?: string | null | undefined;
521
521
  line_item_id?: string | null | undefined;
@@ -565,11 +565,11 @@ export declare const ServicecaseInput: import("../../utils/zodContextOptionals")
565
565
  is_sent_to_cc: 0 | 1;
566
566
  created_with: "Amazon FBA" | "Amazon FBM" | "Serviceportal" | "Missive Sidebar";
567
567
  return_items: {
568
- name: string;
569
568
  item: string;
570
569
  return_quantity: number;
571
570
  is_complaint: 0 | 1;
572
571
  return_fee: number;
572
+ name?: string | undefined;
573
573
  attachments?: string | null | undefined;
574
574
  internal_reasons?: string | null | undefined;
575
575
  line_item_id?: string | null | undefined;
@@ -602,9 +602,9 @@ export declare const ServicecaseInput: import("../../utils/zodContextOptionals")
602
602
  order_number: string;
603
603
  shop: "Shopify" | "Amazon FBA" | "Amazon FBM" | "Otto" | "Amazon" | "WordPress";
604
604
  return_items: {
605
- name: string;
606
605
  item: string;
607
606
  return_quantity: number;
607
+ name?: string | undefined;
608
608
  attachments?: string | null | undefined;
609
609
  internal_reasons?: string | null | undefined;
610
610
  line_item_id?: string | null | undefined;
@@ -61,7 +61,7 @@ exports.ReturnItem = zod_1.z
61
61
  })
62
62
  .describe("ReturnItem");
63
63
  exports.ReturnItemInput = exports.ReturnItem.extend({
64
- name: zod_1.z.string(),
64
+ name: zod_1.z.string().optional(),
65
65
  }).describe("ReturnItemInput");
66
66
  exports.ReturnItemExtended = (0, DocTypeHelpers_1.DocModel)(exports.ReturnItem.extend({
67
67
  attachments: zod_1.z.array(zod_1.z.object({ url: zod_1.z.string(), type: zod_1.z.enum(["image", "video"]) })),
@@ -4,12 +4,13 @@ import { Prettify } from "../utils/utils";
4
4
  import { DocModelType, GetListReturnValue, KeysOfModel } from "./model/DocTypeHelpers";
5
5
  import { DeleteResponseModel } from "./model/ERPNextResponse";
6
6
  import { ResourceInputType } from "../utils/zodContextOptionals";
7
+ type GetListFieldOptions<TModel extends AnyZodObject | undefined> = TModel extends AnyZodObject ? KeysOfModel<TModel> : string;
7
8
  export declare const stringifyFiltersForParams: (filters?: (string | string[])[][]) => string;
8
9
  export declare class ERPNextResourceRequest {
9
10
  protected temporalClient: TemporalClient;
10
11
  constructor(temporalClient: TemporalClient);
11
12
  private getParams;
12
- getList<TFieldOptions extends KeysOfModel<TModel>, TSelectedFields extends readonly TFieldOptions[] | readonly ["*"] | undefined = undefined, TModel extends AnyZodObject | undefined = undefined, TAsDict extends boolean | undefined = undefined>({ resourceName, fields, filters, resourceModel, skip, limit, priority, asDict, params, }: {
13
+ getList<TModel extends AnyZodObject | undefined = undefined, TFieldOptions extends GetListFieldOptions<TModel> = GetListFieldOptions<TModel>, TSelectedFields extends readonly TFieldOptions[] | readonly ["*"] | undefined = undefined, TAsDict extends boolean | undefined = undefined>({ resourceName, fields, filters, resourceModel, skip, limit, priority, asDict, params, }: {
13
14
  resourceName: string;
14
15
  fields?: TSelectedFields;
15
16
  filters?: (string | string[])[][];
@@ -49,3 +50,4 @@ export declare class ERPNextResourceRequest {
49
50
  priority?: number;
50
51
  }): Promise<z.TypeOf<typeof DeleteResponseModel>>;
51
52
  }
53
+ export {};
@@ -9,12 +9,20 @@ const DocTypeHelpers_1 = require("./model/DocTypeHelpers");
9
9
  const ERPNextResponse_1 = require("./model/ERPNextResponse");
10
10
  const zodContextOptionals_1 = require("../utils/zodContextOptionals");
11
11
  const stringifyFiltersForParams = (filters) => {
12
- return JSON.stringify(filters, (_key, value) => {
13
- if (value !== null && typeof value === "object" && !Array.isArray(value)) {
14
- return JSON.stringify(value).replace(/"/g, "'");
15
- }
16
- return value;
17
- });
12
+ try {
13
+ return JSON.stringify(filters, (_key, value) => {
14
+ if (value !== null &&
15
+ typeof value === "object" &&
16
+ !Array.isArray(value)) {
17
+ return JSON.stringify(value).replace(/"/g, "'");
18
+ }
19
+ return value;
20
+ });
21
+ }
22
+ catch (err) {
23
+ const message = err instanceof Error ? err.message : String(err);
24
+ throw new Error(`Failed to serialize ERPNext filters for query params: ${message}`);
25
+ }
18
26
  };
19
27
  exports.stringifyFiltersForParams = stringifyFiltersForParams;
20
28
  class ERPNextResourceRequest {
@@ -1,24 +1,63 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const vitest_1 = require("vitest");
4
3
  const resourceRequest_1 = require("./resourceRequest");
5
- (0, vitest_1.describe)("stringifyFiltersForParams", () => {
6
- (0, vitest_1.test)("stringifies nested objects with single quotes", () => {
4
+ describe("stringifyFiltersForParams", () => {
5
+ test("stringifies nested objects with single quotes", () => {
7
6
  const filters = [
8
7
  ["status", "=", "Open"],
9
8
  ["custom", "=", { foo: "bar", count: 2 }],
10
9
  ];
11
10
  const result = (0, resourceRequest_1.stringifyFiltersForParams)(filters);
12
- (0, vitest_1.expect)(result).toBe(`[["status","=","Open"],["custom","=","{'foo':'bar','count':2}"]]`);
11
+ expect(result).toBe(`[["status","=","Open"],["custom","=","{'foo':'bar','count':2}"]]`);
13
12
  });
14
- (0, vitest_1.test)("keeps array values as normal arrays", () => {
13
+ test("keeps array values as normal arrays", () => {
15
14
  const filters = [
16
15
  ["name", "in", ["ITEM-0001", "ITEM-0002"]],
17
16
  ];
18
17
  const result = (0, resourceRequest_1.stringifyFiltersForParams)(filters);
19
- (0, vitest_1.expect)(result).toBe(`[["name","in",["ITEM-0001","ITEM-0002"]]]`);
18
+ expect(result).toBe(`[["name","in",["ITEM-0001","ITEM-0002"]]]`);
20
19
  });
21
- (0, vitest_1.test)("returns undefined when filters are undefined", () => {
22
- (0, vitest_1.expect)((0, resourceRequest_1.stringifyFiltersForParams)(undefined)).toBeUndefined();
20
+ test("escapes backslashes in filter values as valid JSON", () => {
21
+ const filters = [
22
+ ["phone", "=", "+49 160\\123456"],
23
+ ];
24
+ const result = (0, resourceRequest_1.stringifyFiltersForParams)(filters);
25
+ const decodedQueryParam = decodeURIComponent(encodeURIComponent(result));
26
+ expect(result).toBe(`[["phone","=","+49 160\\\\123456"]]`);
27
+ expect(JSON.parse(decodedQueryParam)).toEqual(filters);
28
+ });
29
+ test("adds context when filter serialization fails", () => {
30
+ const cyclicFilterValue = {};
31
+ cyclicFilterValue.self = cyclicFilterValue;
32
+ const filters = [
33
+ ["custom", "=", cyclicFilterValue],
34
+ ];
35
+ expect(() => (0, resourceRequest_1.stringifyFiltersForParams)(filters)).toThrow("Failed to serialize ERPNext filters for query params");
36
+ });
37
+ test("passes typed getList filters as encoded JSON query params", async () => {
38
+ const executeERPNextRequestWorkflow = vi.fn().mockResolvedValue({
39
+ data: [],
40
+ });
41
+ const resourceRequest = new resourceRequest_1.ERPNextResourceRequest({
42
+ executeERPNextRequestWorkflow,
43
+ });
44
+ const filters = [
45
+ ["address_line1", "=", "Client\\Warehouse 1"],
46
+ ["phone", "=", "0049\\1573"],
47
+ ["Contact", "email_id", "=", "client@example.com"],
48
+ ];
49
+ await resourceRequest.getList({
50
+ resourceName: "Address",
51
+ fields: ["name"],
52
+ filters,
53
+ limit: 1,
54
+ });
55
+ const options = executeERPNextRequestWorkflow.mock.calls[0]?.[1];
56
+ const params = new URLSearchParams(options.params.slice(1));
57
+ expect(params.get("filters")).toBe(JSON.stringify(filters));
58
+ expect(JSON.parse(params.get("filters") ?? "")).toEqual(filters);
59
+ });
60
+ test("returns undefined when filters are undefined", () => {
61
+ expect((0, resourceRequest_1.stringifyFiltersForParams)(undefined)).toBeUndefined();
23
62
  });
24
63
  });
package/package.json CHANGED
@@ -34,7 +34,7 @@
34
34
  "winston": "^3.15.0",
35
35
  "zod": "3.25.76"
36
36
  },
37
- "version": "2.6.3",
37
+ "version": "2.6.4",
38
38
  "devDependencies": {
39
39
  "@types/crypto-js": "^4.2.2",
40
40
  "@types/lodash": "^4.17.13",