erpnext-queue-client 2.4.3 → 2.4.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.
- package/dist/client.js +87 -105
- package/dist/constants.js +1 -0
- package/dist/dataConverter.js +4 -13
- package/dist/erpnext/decryptFromErpNext.server.js +1 -1
- package/dist/erpnext/decryptFromErpNext.server.test.js +2 -11
- package/dist/erpnext/doctypeResourceRequest.js +44 -37
- package/dist/erpnext/doctypeSubmittableResourceRequest.js +19 -33
- package/dist/erpnext/doctypes/address.js +40 -41
- package/dist/erpnext/doctypes/consolidatedCustomsInvoice.js +18 -20
- package/dist/erpnext/doctypes/contact.js +30 -30
- package/dist/erpnext/doctypes/deliveryNote.js +13 -12
- package/dist/erpnext/doctypes/item.d.ts +10 -10
- package/dist/erpnext/doctypes/item.js +64 -63
- package/dist/erpnext/doctypes/paymentEntry.js +42 -43
- package/dist/erpnext/doctypes/productBundle.js +15 -17
- package/dist/erpnext/doctypes/purchaseInvoice.js +45 -49
- package/dist/erpnext/doctypes/purchaseReceipt.js +41 -43
- package/dist/erpnext/doctypes/salesInvoice.js +42 -43
- package/dist/erpnext/doctypes/servicecase.js +103 -114
- package/dist/erpnext/doctypes/shipment.js +30 -35
- package/dist/erpnext/doctypes/stock.js +94 -109
- package/dist/erpnext/doctypes/tags.js +58 -77
- package/dist/erpnext/erpnextRequestWrapper.js +83 -80
- package/dist/erpnext/fileRequests.js +28 -29
- package/dist/erpnext/methodRequest.js +37 -43
- package/dist/erpnext/model/DocTypeHelpers.js +2 -3
- package/dist/erpnext/model/Item.d.ts +6 -6
- package/dist/erpnext/model/Item.js +1 -1
- package/dist/erpnext/model/StockEntry.d.ts +63 -21
- package/dist/erpnext/model/StockEntry.js +22 -21
- package/dist/erpnext/reports.js +81 -89
- package/dist/erpnext/resourceRequest.js +142 -150
- package/dist/index.js +43 -3
- package/dist/index.test.js +69 -83
- package/dist/utils/fernet.server.js +24 -4
- package/dist/utils/request.js +59 -72
- package/dist/utils/zodContextOptionals.js +5 -3
- package/dist/utils/zodUtils.js +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -44,13 +44,50 @@ const Waitlist_1 = require("./erpnext/model/Waitlist");
|
|
|
44
44
|
const reports_1 = require("./erpnext/reports");
|
|
45
45
|
const resourceRequest_1 = require("./erpnext/resourceRequest");
|
|
46
46
|
class ERPNextQueueClient {
|
|
47
|
+
temporalClient;
|
|
48
|
+
credentials;
|
|
49
|
+
resourceRequest;
|
|
50
|
+
methodRequest;
|
|
51
|
+
account;
|
|
52
|
+
country;
|
|
53
|
+
address;
|
|
54
|
+
contact;
|
|
55
|
+
customer;
|
|
56
|
+
deliveryNote;
|
|
57
|
+
fileRequests;
|
|
58
|
+
shipment;
|
|
59
|
+
productBundle;
|
|
60
|
+
shippingProvider;
|
|
61
|
+
item;
|
|
62
|
+
purchaseOrder;
|
|
63
|
+
purchaseReceipt;
|
|
64
|
+
purchaseInvoice;
|
|
65
|
+
waitlist;
|
|
66
|
+
stockEntry;
|
|
67
|
+
supplier;
|
|
68
|
+
paymentEntry;
|
|
69
|
+
stockReconciliation;
|
|
70
|
+
stock;
|
|
71
|
+
reports;
|
|
72
|
+
compliance;
|
|
73
|
+
partList;
|
|
74
|
+
salesOrder;
|
|
75
|
+
salesInvoice;
|
|
76
|
+
servicecase;
|
|
77
|
+
serviceportalProductConfiguration;
|
|
78
|
+
servicecaseReason;
|
|
79
|
+
servicecaseSolution;
|
|
80
|
+
internalReason;
|
|
81
|
+
shippingLabel;
|
|
82
|
+
file;
|
|
83
|
+
itemTaxTemplate;
|
|
84
|
+
taxCategory;
|
|
85
|
+
tags;
|
|
86
|
+
consolidatedCustomsInvoice;
|
|
47
87
|
/**
|
|
48
88
|
* @description Provide either a temporal client or connection details to create a new client
|
|
49
89
|
*/
|
|
50
90
|
constructor(options) {
|
|
51
|
-
this.utils = {
|
|
52
|
-
decryptFromErpNext: (encryptedString) => (0, decryptFromErpNext_server_1.decryptFromErpNext)(this.credentials, encryptedString),
|
|
53
|
-
};
|
|
54
91
|
if (options.erpnextCredentials)
|
|
55
92
|
this.credentials = options.erpnextCredentials;
|
|
56
93
|
this.temporalClient = new client_1.TemporalClient(options.temporalCredentials);
|
|
@@ -94,6 +131,9 @@ class ERPNextQueueClient {
|
|
|
94
131
|
this.tags = new tags_1.ERPNextTags(this.temporalClient);
|
|
95
132
|
this.consolidatedCustomsInvoice = new consolidatedCustomsInvoice_1.ERPNextConsolidatedCustomsInvoice(this.temporalClient);
|
|
96
133
|
}
|
|
134
|
+
utils = {
|
|
135
|
+
decryptFromErpNext: (encryptedString) => (0, decryptFromErpNext_server_1.decryptFromErpNext)(this.credentials, encryptedString),
|
|
136
|
+
};
|
|
97
137
|
}
|
|
98
138
|
exports.ERPNextQueueClient = ERPNextQueueClient;
|
|
99
139
|
var ERPNextResponse_1 = require("./erpnext/model/ERPNextResponse");
|
package/dist/index.test.js
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
4
|
};
|
|
@@ -20,7 +11,7 @@ const zodContextOptionals_1 = require("./utils/zodContextOptionals");
|
|
|
20
11
|
const Item_1 = require("./erpnext/model/Item");
|
|
21
12
|
// Most tests are wrapped in async function blocks so they are declared statically but not run as tests.
|
|
22
13
|
// If we wanted to run the tests, a mocking system would need to be implemented.
|
|
23
|
-
describe.skipIf(constants_1.constants.TEMPORAL_HOST === "test")("Type tests", () =>
|
|
14
|
+
describe.skipIf(constants_1.constants.TEMPORAL_HOST === "test")("Type tests", async () => {
|
|
24
15
|
const erp = new _1.ERPNextQueueClient({
|
|
25
16
|
temporalCredentials: {
|
|
26
17
|
temporalHost: constants_1.constants.TEMPORAL_HOST,
|
|
@@ -29,21 +20,19 @@ describe.skipIf(constants_1.constants.TEMPORAL_HOST === "test")("Type tests", ()
|
|
|
29
20
|
temporalKey: constants_1.constants.TEMPORAL_KEY,
|
|
30
21
|
},
|
|
31
22
|
});
|
|
32
|
-
test("Single item fetch", () =>
|
|
23
|
+
test("Single item fetch", async () => {
|
|
33
24
|
// We use expect-error to statically test negative cases in typescript
|
|
34
|
-
() =>
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
expect(item
|
|
39
|
-
expect(item
|
|
40
|
-
expect(item
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
var _a, _b, _c;
|
|
46
|
-
const items = yield erp.resourceRequest.getList({
|
|
25
|
+
async () => {
|
|
26
|
+
const items = await erp.item.getList({ limit: 1 });
|
|
27
|
+
const item = await erp.item.getById({ resourceId: items[0].name });
|
|
28
|
+
expect(item?.name).toBeTypeOf("string");
|
|
29
|
+
expect(item?.doctype).toBeTypeOf("string");
|
|
30
|
+
expect(item?.description).toBeTypeOf("string");
|
|
31
|
+
expect(item?.barcodes.at(0)?.idx).toBeTypeOf("number");
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
test("List with aliases", async () => {
|
|
35
|
+
const items = await erp.resourceRequest.getList({
|
|
47
36
|
resourceName: "Item",
|
|
48
37
|
resourceModel: Item_1.Item.merge(zod_1.default.object({
|
|
49
38
|
"`tabItem Supplier`.supplier as supplier": zod_1.default
|
|
@@ -59,81 +48,78 @@ describe.skipIf(constants_1.constants.TEMPORAL_HOST === "test")("Type tests", ()
|
|
|
59
48
|
"item_name as item_title",
|
|
60
49
|
],
|
|
61
50
|
});
|
|
62
|
-
expect(
|
|
63
|
-
expect(
|
|
64
|
-
expect(
|
|
65
|
-
})
|
|
66
|
-
test("Item List with field description", () =>
|
|
67
|
-
() =>
|
|
68
|
-
var _a, _b, _c, _d, _e, _f;
|
|
51
|
+
expect(items.at(0)?.name).toBeTypeOf("string");
|
|
52
|
+
expect(items.at(0)?.supplier).toBeTypeOf("string");
|
|
53
|
+
expect(items.at(0)?.item_title).toBeTypeOf("string");
|
|
54
|
+
});
|
|
55
|
+
test("Item List with field description", async () => {
|
|
56
|
+
async () => {
|
|
69
57
|
// get list with field defined
|
|
70
|
-
const itemsOnlyFieldDescription =
|
|
58
|
+
const itemsOnlyFieldDescription = await erp.item.getList({
|
|
71
59
|
fields: ["description"],
|
|
72
60
|
limit: 10,
|
|
73
61
|
});
|
|
74
62
|
expect(
|
|
75
63
|
// @ts-expect-error
|
|
76
|
-
|
|
77
|
-
expect(
|
|
64
|
+
itemsOnlyFieldDescription.at(0)?.barcodes?.at(0)?.idx).toBeUndefined();
|
|
65
|
+
expect(itemsOnlyFieldDescription.at(0)?.description).toBeTypeOf("string");
|
|
78
66
|
// @ts-expect-error
|
|
79
|
-
expect(
|
|
67
|
+
expect(itemsOnlyFieldDescription.at(0)?.name).toBeUndefined(); // name not valid here
|
|
80
68
|
// @ts-expect-error
|
|
81
|
-
expect(
|
|
82
|
-
}
|
|
83
|
-
})
|
|
84
|
-
test("Item List with default field 'name'", () =>
|
|
85
|
-
() =>
|
|
86
|
-
var _a, _b;
|
|
69
|
+
expect(itemsOnlyFieldDescription.at(0)?.barcodes).toBeUndefined(); // barcodes not valid here}
|
|
70
|
+
};
|
|
71
|
+
});
|
|
72
|
+
test("Item List with default field 'name'", async () => {
|
|
73
|
+
async () => {
|
|
87
74
|
// get list without fields defined
|
|
88
|
-
const items2 =
|
|
89
|
-
expect(
|
|
75
|
+
const items2 = await erp.item.getList({ limit: 10 });
|
|
76
|
+
expect(items2.at(0)?.name).toBeTypeOf("string");
|
|
90
77
|
// @ts-expect-error
|
|
91
|
-
expect(
|
|
92
|
-
}
|
|
93
|
-
})
|
|
94
|
-
test("Item List with all fields", () =>
|
|
95
|
-
() =>
|
|
96
|
-
var _a, _b, _c, _d;
|
|
78
|
+
expect(items2.at(0)?.item_code).toBeUndefined(); // item_code not valid here
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
test("Item List with all fields", async () => {
|
|
82
|
+
async () => {
|
|
97
83
|
// get list without fields defined
|
|
98
|
-
const itemsWithAllFields =
|
|
84
|
+
const itemsWithAllFields = await erp.item.getList({
|
|
99
85
|
fields: ["*"],
|
|
100
86
|
limit: 10,
|
|
101
87
|
});
|
|
102
|
-
expect(
|
|
88
|
+
expect(itemsWithAllFields.at(0)?.name).toBeTypeOf("string");
|
|
103
89
|
// @ts-expect-error
|
|
104
|
-
expect(
|
|
105
|
-
expect(
|
|
90
|
+
expect(itemsWithAllFields.at(0)?.doctype).toBeUndefined(); // doctype omitted in list entries
|
|
91
|
+
expect(itemsWithAllFields.at(0)?.item_code).toBeTypeOf("string");
|
|
106
92
|
// @ts-expect-error
|
|
107
|
-
expect(
|
|
108
|
-
}
|
|
109
|
-
})
|
|
110
|
-
test("Submittable DocType", () =>
|
|
111
|
-
() =>
|
|
112
|
-
const dns =
|
|
93
|
+
expect(itemsWithAllFields.at(0)?.barcodes).toBeUndefined();
|
|
94
|
+
};
|
|
95
|
+
});
|
|
96
|
+
test("Submittable DocType", async () => {
|
|
97
|
+
async () => {
|
|
98
|
+
const dns = await erp.deliveryNote.getList({ limit: 1 });
|
|
113
99
|
if (!dns[0])
|
|
114
100
|
throw new Error("No Delivery Notes found in test instance");
|
|
115
|
-
const dn =
|
|
101
|
+
const dn = await erp.deliveryNote.getById({
|
|
116
102
|
resourceId: dns[0].name,
|
|
117
103
|
});
|
|
118
|
-
dn
|
|
119
|
-
}
|
|
120
|
-
})
|
|
121
|
-
test("Get Address by Supplier", () =>
|
|
122
|
-
() =>
|
|
123
|
-
const sup =
|
|
124
|
-
const address =
|
|
104
|
+
dn?.amended_from; // for static type analysis}
|
|
105
|
+
};
|
|
106
|
+
});
|
|
107
|
+
test("Get Address by Supplier", async () => {
|
|
108
|
+
async () => {
|
|
109
|
+
const sup = await erp.supplier.getList({ limit: 1 });
|
|
110
|
+
const address = await erp.address.getAddressesBySupplier(sup[0].name);
|
|
125
111
|
expect(address[0].city).toBeTypeOf("string");
|
|
126
|
-
}
|
|
127
|
-
})
|
|
128
|
-
test("Item List with invalid field list", () =>
|
|
112
|
+
};
|
|
113
|
+
});
|
|
114
|
+
test("Item List with invalid field list", async () => {
|
|
129
115
|
// don't execute, this is just for type testing statically
|
|
130
116
|
() => erp.item.getList({
|
|
131
117
|
// @ts-expect-error
|
|
132
118
|
fields: ["name", "barcode"],
|
|
133
119
|
limit: 10,
|
|
134
120
|
});
|
|
135
|
-
})
|
|
136
|
-
test("Create with DocModel Metafields should fail", () =>
|
|
121
|
+
});
|
|
122
|
+
test("Create with DocModel Metafields should fail", async () => {
|
|
137
123
|
// SHOULD NOT BE EXECUTED, ONLY FOR STATIC TYPE TESTING
|
|
138
124
|
// We use expect-error to statically test negative cases in typescript
|
|
139
125
|
() => erp.item.create({
|
|
@@ -179,8 +165,8 @@ describe.skipIf(constants_1.constants.TEMPORAL_HOST === "test")("Type tests", ()
|
|
|
179
165
|
// @ts-expect-error should not be empty
|
|
180
166
|
body: {},
|
|
181
167
|
});
|
|
182
|
-
})
|
|
183
|
-
test("Static Types with Input Optional", () =>
|
|
168
|
+
});
|
|
169
|
+
test("Static Types with Input Optional", async () => {
|
|
184
170
|
// DO NOT EXECUTE, ONLY FOR STATIC TYPE TESTING
|
|
185
171
|
// We use expect-error to statically test negative cases in typescript
|
|
186
172
|
const testModel = zod_1.default.object({
|
|
@@ -200,8 +186,8 @@ describe.skipIf(constants_1.constants.TEMPORAL_HOST === "test")("Type tests", ()
|
|
|
200
186
|
const testOutput = {
|
|
201
187
|
mandatory: "TEST",
|
|
202
188
|
};
|
|
203
|
-
})
|
|
204
|
-
test("Static Types with Nested Array Input Optional", () =>
|
|
189
|
+
});
|
|
190
|
+
test("Static Types with Nested Array Input Optional", async () => {
|
|
205
191
|
// DO NOT EXECUTE, ONLY FOR STATIC TYPE TESTING
|
|
206
192
|
// We use expect-error to statically test negative cases in typescript
|
|
207
193
|
const testModel = zod_1.default.object({
|
|
@@ -239,9 +225,9 @@ describe.skipIf(constants_1.constants.TEMPORAL_HOST === "test")("Type tests", ()
|
|
|
239
225
|
},
|
|
240
226
|
],
|
|
241
227
|
};
|
|
242
|
-
})
|
|
243
|
-
test("Input for updateById function", () =>
|
|
244
|
-
() =>
|
|
228
|
+
});
|
|
229
|
+
test("Input for updateById function", async () => {
|
|
230
|
+
async () => {
|
|
245
231
|
// This static type test ensures, that Input as inferred here
|
|
246
232
|
// conformes to the expected input type defined in doctypeResourceRequest -> updateById()
|
|
247
233
|
const AddressInput = (0, zodContextOptionals_1.ResourceInput)(Address_1.Address);
|
|
@@ -252,10 +238,10 @@ describe.skipIf(constants_1.constants.TEMPORAL_HOST === "test")("Type tests", ()
|
|
|
252
238
|
country: "Country",
|
|
253
239
|
pincode: "1234",
|
|
254
240
|
};
|
|
255
|
-
|
|
241
|
+
await erp.address.updateById({
|
|
256
242
|
resourceId: "TEST",
|
|
257
243
|
body: typedInputBody,
|
|
258
244
|
});
|
|
259
|
-
}
|
|
260
|
-
})
|
|
261
|
-
})
|
|
245
|
+
};
|
|
246
|
+
});
|
|
247
|
+
});
|
|
@@ -217,6 +217,10 @@ function createHmac(signingKey, time, iv, cipherText) {
|
|
|
217
217
|
* Instance of a Secret to be used for the token encryption
|
|
218
218
|
*/
|
|
219
219
|
class Secret {
|
|
220
|
+
signingKeyHex;
|
|
221
|
+
signingKey;
|
|
222
|
+
encryptionKeyHex;
|
|
223
|
+
encryptionKey;
|
|
220
224
|
/**
|
|
221
225
|
* Creates a Secret to be used for the token encryption
|
|
222
226
|
* @param {String} secret64 - base64 encoded secret string
|
|
@@ -248,21 +252,37 @@ exports.Secret = Secret;
|
|
|
248
252
|
* Token object to perform encryption/decryption
|
|
249
253
|
*/
|
|
250
254
|
class Token {
|
|
255
|
+
secret;
|
|
256
|
+
ttl;
|
|
257
|
+
message;
|
|
258
|
+
/** cipher text to decrypt */
|
|
259
|
+
cipherText;
|
|
260
|
+
cipherTextHex;
|
|
261
|
+
/** token string */
|
|
262
|
+
token;
|
|
263
|
+
/** version of token */
|
|
264
|
+
version;
|
|
265
|
+
/** the IV array */
|
|
266
|
+
optsIV;
|
|
267
|
+
maxClockSkew = 60;
|
|
268
|
+
time;
|
|
269
|
+
encoded;
|
|
270
|
+
iv;
|
|
271
|
+
ivHex;
|
|
272
|
+
hmacHex;
|
|
251
273
|
/**
|
|
252
274
|
* Token object to perform encryption/decryption
|
|
253
275
|
* @param {TokenOptions} opts - options for token initialization
|
|
254
276
|
*/
|
|
255
277
|
constructor(opts) {
|
|
256
|
-
var _a, _b;
|
|
257
|
-
this.maxClockSkew = 60;
|
|
258
278
|
opts = opts || {};
|
|
259
279
|
this.secret = opts.secret || defaults.secret;
|
|
260
280
|
this.ttl = opts.ttl || defaults.ttl;
|
|
261
281
|
if (opts.ttl === 0)
|
|
262
282
|
this.ttl = 0;
|
|
263
|
-
this.message =
|
|
283
|
+
this.message = opts.message ?? "";
|
|
264
284
|
this.cipherText = opts.cipherText;
|
|
265
|
-
this.token =
|
|
285
|
+
this.token = opts.token ?? "";
|
|
266
286
|
this.version = opts.version || parseHex(defaults.versionHex);
|
|
267
287
|
this.optsIV = opts.iv;
|
|
268
288
|
// @ts-ignore
|
package/dist/utils/request.js
CHANGED
|
@@ -1,30 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
12
|
-
var t = {};
|
|
13
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
14
|
-
t[p] = s[p];
|
|
15
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
16
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
17
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
18
|
-
t[p[i]] = s[p[i]];
|
|
19
|
-
}
|
|
20
|
-
return t;
|
|
21
|
-
};
|
|
22
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
3
|
exports.RequestError = void 0;
|
|
24
4
|
exports.request = request;
|
|
25
5
|
const zodUtils_1 = require("./zodUtils");
|
|
26
6
|
const logger_1 = require("./logger");
|
|
27
7
|
class RequestError extends Error {
|
|
8
|
+
status;
|
|
9
|
+
requestUrl;
|
|
10
|
+
statusText;
|
|
11
|
+
responseHeaders;
|
|
12
|
+
response;
|
|
28
13
|
constructor({ status, requestUrl, statusText, responseHeaders, response, }) {
|
|
29
14
|
super(`Request failed with status ${status}: ${statusText} for URL ${requestUrl}`); // Call the parent `Error` constructor with the message
|
|
30
15
|
// Manually set the prototype to ensure `instanceof` works
|
|
@@ -52,56 +37,58 @@ class RequestError extends Error {
|
|
|
52
37
|
}
|
|
53
38
|
}
|
|
54
39
|
exports.RequestError = RequestError;
|
|
55
|
-
function request(options) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
40
|
+
async function request(options) {
|
|
41
|
+
const { body, url, inputValidationModel, responseValidationModel, credentials, headers, ...requestOptions } = options || {};
|
|
42
|
+
// Validate the request body
|
|
43
|
+
const validatedBody = inputValidationModel
|
|
44
|
+
? (0, zodUtils_1.validateData)(body, inputValidationModel)
|
|
45
|
+
: body;
|
|
46
|
+
const contentType = options.headers &&
|
|
47
|
+
"Content-Type" in options.headers &&
|
|
48
|
+
options.headers?.["Content-Type"]
|
|
49
|
+
? options.headers?.["Content-Type"]
|
|
50
|
+
: undefined;
|
|
51
|
+
const stringifiedBody = options.method !== "GET" &&
|
|
52
|
+
contentType !== "text/xml" &&
|
|
53
|
+
contentType !== "application/xml" &&
|
|
54
|
+
contentType !== "application/x-www-form-urlencoded"
|
|
55
|
+
? JSON.stringify(validatedBody)
|
|
56
|
+
: undefined;
|
|
57
|
+
const convertedOptions = {
|
|
58
|
+
...requestOptions,
|
|
59
|
+
...(headers ? { headers } : {}),
|
|
60
|
+
...(credentials ? { credentials } : {}),
|
|
61
|
+
...(options.method !== "GET"
|
|
62
|
+
? { body: stringifiedBody ?? validatedBody }
|
|
63
|
+
: {}),
|
|
64
|
+
};
|
|
65
|
+
// Log requests
|
|
66
|
+
logger_1.lg.info(`${options.method}: ${url}`);
|
|
67
|
+
// Wrap fetch
|
|
68
|
+
const response = await fetch(url, convertedOptions);
|
|
69
|
+
const { status, url: requestUrl, statusText, ok } = response;
|
|
70
|
+
const textResult = await response.text();
|
|
71
|
+
let finalResult;
|
|
72
|
+
try {
|
|
73
|
+
finalResult = JSON.parse(textResult);
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
finalResult = textResult;
|
|
77
|
+
}
|
|
78
|
+
// Reject promise when status is expected or unexpected error. Allows use of try/catch to catch http errors
|
|
79
|
+
if (!ok) {
|
|
80
|
+
logger_1.lg.error(`Error in request to ${requestUrl} with status text ${statusText}`, JSON.stringify(finalResult, null, 2));
|
|
81
|
+
throw new RequestError({
|
|
82
|
+
status,
|
|
83
|
+
requestUrl,
|
|
84
|
+
statusText,
|
|
85
|
+
responseHeaders: response?.headers,
|
|
86
|
+
response: finalResult,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
// Validate the response body
|
|
90
|
+
const validatedResult = responseValidationModel
|
|
91
|
+
? (0, zodUtils_1.validateData)(finalResult, responseValidationModel)
|
|
92
|
+
: finalResult;
|
|
93
|
+
return validatedResult;
|
|
107
94
|
}
|
|
@@ -15,8 +15,10 @@ function isMarkedOptionalForInput(schema) {
|
|
|
15
15
|
}
|
|
16
16
|
// schema transformation
|
|
17
17
|
function ResourceInput(schema) {
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
const shape = {
|
|
19
|
+
...schema.shape,
|
|
20
|
+
docstatus: zod_1.z.number().optional().default(0),
|
|
21
|
+
};
|
|
20
22
|
function makeMarkedKeysOptional(shape) {
|
|
21
23
|
const newShape = zod_1.z.object({}).shape;
|
|
22
24
|
for (const [key, value] of Object.entries(shape)) {
|
|
@@ -52,5 +54,5 @@ function ResourceInput(schema) {
|
|
|
52
54
|
}
|
|
53
55
|
return zod_1.z
|
|
54
56
|
.object(makeMarkedKeysOptional(shape))
|
|
55
|
-
.describe((
|
|
57
|
+
.describe((schema.description ?? "Unnamed Model") + " Input");
|
|
56
58
|
}
|
package/dist/utils/zodUtils.js
CHANGED
|
@@ -30,12 +30,12 @@ function validateData(data, ValidationModel) {
|
|
|
30
30
|
typeof data.message === "string") {
|
|
31
31
|
throw new Error(data.message);
|
|
32
32
|
}
|
|
33
|
-
throw errorObject;
|
|
33
|
+
throw new Error(errorObject.message, { cause: errorObject.error });
|
|
34
34
|
}
|
|
35
35
|
return validationResult.data;
|
|
36
36
|
}
|
|
37
37
|
function pickFromSchema(schema, keys) {
|
|
38
|
-
const pickedShape = keys
|
|
38
|
+
const pickedShape = keys?.reduce((acc, key) => {
|
|
39
39
|
if (typeof key === "string" && key.includes("as")) {
|
|
40
40
|
const [field, alias] = key.split(" as ");
|
|
41
41
|
if (key in schema.shape) {
|