zudello-integration-sdk 1.0.14 → 1.0.16

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zudello-integration-sdk",
3
- "version": "1.0.14",
3
+ "version": "1.0.16",
4
4
  "description": "Zudello Integrations SDK",
5
5
  "main": "./src/index.js",
6
6
  "repository": {
package/src/index.js CHANGED
@@ -1,64 +1,68 @@
1
- 'use strict'
1
+ "use strict";
2
2
 
3
- const Auth = require('./sdk/Auth')
4
- const ZudelloSDK = require('./sdk/Zudello')
5
- const NetsuiteSDK = require('./sdk/Netsuite')
6
- const NetsuiteSoapSDK = require('./sdk/NetsuiteSOAP')
7
- const IntacctSDK = require('./sdk/Intacct')
8
- const BusinessCentralSDK = require('./sdk/BusinessCentral')
9
- const ZenotiSDK = require('./sdk/Zenoti')
10
- const DearSDK = require('./sdk/Dear')
11
- const NexviaSDK = require('./sdk/Nexvia')
12
- const FoSDK = require('./sdk/Fo')
13
- const RetailExpressSDK = require('./sdk/RetailExpress')
14
- const MYOBAcumaticaSDK = require('./sdk/MYOBAcumatica')
15
- const SybizSDK = require('./sdk/Sybiz')
16
- const JobReadySDK = require('./sdk/JobReady')
3
+ const Auth = require("./sdk/Auth");
4
+ const ZudelloSDK = require("./sdk/Zudello");
5
+ const NetsuiteSDK = require("./sdk/Netsuite");
6
+ const NetsuiteSoapSDK = require("./sdk/NetsuiteSOAP");
7
+ const IntacctSDK = require("./sdk/Intacct");
8
+ const BusinessCentralSDK = require("./sdk/BusinessCentral");
9
+ const ZenotiSDK = require("./sdk/Zenoti");
10
+ const DearSDK = require("./sdk/Dear");
11
+ const NexviaSDK = require("./sdk/Nexvia");
12
+ const FoSDK = require("./sdk/Fo");
13
+ const RetailExpressSDK = require("./sdk/RetailExpress");
14
+ const MYOBAcumaticaSDK = require("./sdk/MYOBAcumatica");
15
+ const SybizSDK = require("./sdk/Sybiz");
16
+ const XeroSDK = require("./sdk/Xero");
17
+ const JobReadySDK = require("./sdk/JobReady");
17
18
 
18
- const Logger = require('./utils/logger')
19
- const Metadata = require('./utils/metadata')
20
- const Tags = require('./utils/tags')
21
- const Trigger = require('./utils/trigger')
22
- const Properties = require('./utils/properties')
23
- const MiscHelper = require('./utils/miscHelper')
24
- const ModelHelper = require('./utils/modelHelper')
19
+ const Logger = require("./utils/logger");
20
+ const Metadata = require("./utils/metadata");
21
+ const Tags = require("./utils/tags");
22
+ const Trigger = require("./utils/trigger");
23
+ const Properties = require("./utils/properties");
24
+ const MiscHelper = require("./utils/miscHelper");
25
+ const ModelHelper = require("./utils/modelHelper");
26
+ const DatasetHelper = require("./utils/datasetHelper");
25
27
  const {
26
- getFileContent,
27
- uploadFile,
28
- listFiles,
29
- deleteFile,
30
- deleteFiles
31
- } = require('./utils/s3Client')
28
+ getFileContent,
29
+ uploadFile,
30
+ listFiles,
31
+ deleteFile,
32
+ deleteFiles,
33
+ } = require("./utils/s3Client");
32
34
 
33
35
  const S3Client = {
34
- getFileContent,
35
- uploadFile,
36
- listFiles,
37
- deleteFile,
38
- deleteFiles
39
- }
36
+ getFileContent,
37
+ uploadFile,
38
+ listFiles,
39
+ deleteFile,
40
+ deleteFiles,
41
+ };
40
42
 
41
43
  module.exports = {
42
- Auth,
43
- ZudelloSDK,
44
- NetsuiteSDK,
45
- NetsuiteSoapSDK,
46
- IntacctSDK,
47
- BusinessCentralSDK,
48
- ZenotiSDK,
49
- DearSDK,
50
- NexviaSDK,
51
- FoSDK,
52
- RetailExpressSDK,
53
- MYOBAcumaticaSDK,
54
- SybizSDK,
55
- JobReadySDK,
56
- Logger,
57
- Metadata,
58
- Tags,
59
- Trigger,
60
- Properties,
61
- MiscHelper,
62
- ModelHelper,
63
- S3Client
64
- }
44
+ Auth,
45
+ ZudelloSDK,
46
+ NetsuiteSDK,
47
+ NetsuiteSoapSDK,
48
+ IntacctSDK,
49
+ BusinessCentralSDK,
50
+ ZenotiSDK,
51
+ DearSDK,
52
+ NexviaSDK,
53
+ FoSDK,
54
+ RetailExpressSDK,
55
+ MYOBAcumaticaSDK,
56
+ SybizSDK,
57
+ XeroSDK,
58
+ JobReadySDK,
59
+ Logger,
60
+ Metadata,
61
+ Tags,
62
+ Trigger,
63
+ Properties,
64
+ MiscHelper,
65
+ ModelHelper,
66
+ DatasetHelper,
67
+ S3Client,
68
+ };
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+
3
+ const BaseSDK = require("./Base");
4
+ const UniversalModule = require("./submodules/xero/Universal");
5
+
6
+ class Xero extends BaseSDK {
7
+ /**
8
+ * Constructor.
9
+ * @param {class} auth Auth class object with authorized api instance.
10
+ * @param {string} connectionUUID The UUID of the Connection we're working on.
11
+ */
12
+ constructor(auth, connectionUUID, organizationUUID, apiURL, apiVersion, loggerClass = null) {
13
+ super({
14
+ auth,
15
+ connectionUUID,
16
+ organizationUUID,
17
+ apiURL,
18
+ apiVersion,
19
+ appUUIDKey: "xero",
20
+ integrationName: "xero",
21
+ loggerClass,
22
+ });
23
+
24
+ /**
25
+ * Create submodule instances.
26
+ */
27
+ this.universal = new UniversalModule(this);
28
+ }
29
+ }
30
+
31
+ module.exports = Xero;
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+
3
+ class UniversalModule {
4
+ /**
5
+ * Constructor.
6
+ * @param {class} parentModule Object of Xero class.
7
+ */
8
+ constructor(parentModule) {
9
+ this.module = parentModule;
10
+ }
11
+
12
+ /**
13
+ * Universal Request By URL and Method.
14
+ * @param {string} url URL of request.
15
+ * @param {string} method Method of request.
16
+ * @param {object} header Headers to pass to the block
17
+ * @param {object} qs Some available filters inside: offset, limit.
18
+ * @param {object} body Some available data inside.
19
+ * @returns {object} Universal Request Response.
20
+ */
21
+ async request({ url, method, header = {}, qs = {}, body = {} }) {
22
+ const validateIsEmpty = this.module.validator.isEmpty({ url, method });
23
+
24
+ if (!validateIsEmpty.valid) {
25
+ return this.module.responseHandler.error(validateIsEmpty.errors);
26
+ }
27
+
28
+ return await this.module.makeRequest(
29
+ "POST",
30
+ `${this.module.apiURL}/zintegrations/action/9939030a-2670-4b80-a4fb-6ca030d26043`,
31
+ {
32
+ mappable_parameters: {
33
+ url: {
34
+ value: url,
35
+ },
36
+ method: {
37
+ value: method,
38
+ },
39
+ header: {
40
+ value: JSON.stringify(header),
41
+ },
42
+ qs: {
43
+ isMap: true,
44
+ value: JSON.stringify(qs),
45
+ },
46
+ body: {
47
+ isMap: true,
48
+ value: JSON.stringify(body),
49
+ },
50
+ },
51
+ }
52
+ );
53
+ }
54
+
55
+ /**
56
+ * Universal List By URL and Method.
57
+ * @param {string} url URL of listed data.
58
+ * @param {string} method Method of listed data.
59
+ * @param {object} header Headers to pass to the block
60
+ * @param {object} qs Some available filters inside: Page, Limit.
61
+ * @param {object} body Some available data inside.
62
+ * @returns {object} Universal List Response.
63
+ */
64
+ async list({ url, method, header = {}, qs = {}, body = {} }) {
65
+ const validateIsEmpty = this.module.validator.isEmpty({ url, method });
66
+
67
+ if (!validateIsEmpty.valid) {
68
+ return this.module.responseHandler.error(validateIsEmpty.errors);
69
+ }
70
+
71
+ if (!qs.page) {
72
+ qs.page = 1;
73
+ }
74
+
75
+ return await this.request({ url, method, header, qs, body });
76
+ }
77
+
78
+ /**
79
+ * Universal Auto Pagination Listing By URL and Method.
80
+ * @param {string} url URL of listed data.
81
+ * @param {string} method Method of listed data.
82
+ * @param {object} header Headers to pass to the block
83
+ * @param {object} qs Some available filters inside: Page, Limit.
84
+ * @param {object} body Some available data inside.
85
+ * @returns {object} Auto Pagination responses.
86
+ */
87
+ async *autoPaginationList({ url, method, header = {}, qs = {}, body = {} }) {
88
+ if (!qs.page) {
89
+ qs.page = 1;
90
+ }
91
+
92
+ let response = await this.list({ url, method, header, qs, body });
93
+ let currentPageCount = response?.data?.length;
94
+
95
+ yield response;
96
+
97
+ if (currentPageCount && currentPageCount === qs.limit) {
98
+ while (currentPageCount === qs.limit) {
99
+ qs.page = qs.page + 1;
100
+
101
+ response = await this.list({ url, method, header, qs, body });
102
+ currentPageCount = response?.data?.length;
103
+
104
+ yield response;
105
+ }
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Upload Attachment
111
+ * @param {object} header Headers to pass to the block
112
+ * @param {object} qs Some available filters inside: Page, Limit.
113
+ * @param {object} body Some available data inside.
114
+ * @returns {object} Universal List Response.
115
+ */
116
+ async addAttachment({ header = {}, qs = {}, body = {} }) {
117
+ return await this.module.makeRequest(
118
+ "POST",
119
+ `${this.module.apiURL}/zintegrations/action/2e52bb12-dcee-4011-848c-b1828182fbcf`,
120
+ {
121
+ mappable_parameters: {
122
+ header: {
123
+ value: JSON.stringify(header),
124
+ },
125
+ body: {
126
+ isMap: true,
127
+ value: JSON.stringify(body),
128
+ },
129
+ },
130
+ }
131
+ );
132
+ }
133
+ }
134
+
135
+ module.exports = UniversalModule;
@@ -9,6 +9,7 @@ class ApiInstance {
9
9
  */
10
10
  constructor () {
11
11
  this.bearerToken = null
12
+ this.retryStatuses = [502, 504]
12
13
 
13
14
  this.responseHandler = new ResponseHandler()
14
15
 
@@ -39,7 +40,7 @@ class ApiInstance {
39
40
  * @param {object} headers Request Headers.
40
41
  * @returns {object} Response Data.
41
42
  */
42
- async get (url, params, headers, returnHeaders = false, callback = () => {}) {
43
+ async get (url, params, headers, returnHeaders = false, callback = () => {}, retryCount = 0) {
43
44
  try {
44
45
  const requestBody = { params, headers }
45
46
 
@@ -67,6 +68,11 @@ class ApiInstance {
67
68
  headers
68
69
  })
69
70
 
71
+ if (this.retryStatuses.includes(error?.response?.status) && retryCount === 0) {
72
+ await this.sleep(20000)
73
+ return await this.get(url, params, headers, returnHeaders, callback, retryCount + 1)
74
+ }
75
+
70
76
  if (error?.response?.status === 302) {
71
77
  return this.responseHandler.success(error?.response?.headers?.location)
72
78
  }
@@ -93,7 +99,7 @@ class ApiInstance {
93
99
  * @param {object} params Request Params.
94
100
  * @returns {object} Response Data.
95
101
  */
96
- async post (url, data, headers, params = {}, callback = () => {}) {
102
+ async post (url, data, headers, params = {}, callback = () => {}, retryCount = 0) {
97
103
  try {
98
104
  const response = await this.axiosInstance.post(url, data, { headers, params })
99
105
 
@@ -119,6 +125,11 @@ class ApiInstance {
119
125
  body: data
120
126
  })
121
127
 
128
+ if (this.retryStatuses.includes(error?.response?.status) && retryCount === 0) {
129
+ await this.sleep(20000)
130
+ return await this.post(url, data, headers, params, callback, retryCount + 1)
131
+ }
132
+
122
133
  if (error?.response?.status === 500) {
123
134
  return this.responseHandler.error(['Something went wrong.'])
124
135
  }
@@ -135,7 +146,7 @@ class ApiInstance {
135
146
  * @param {object} data PUT Data.
136
147
  * @returns {object} Response Data.
137
148
  */
138
- async put (url, data, headers, params = {}, callback = () => {}) {
149
+ async put (url, data, headers, params = {}, callback = () => {}, retryCount = 0) {
139
150
  try {
140
151
  const response = await this.axiosInstance.put(url, data, { headers, params })
141
152
 
@@ -157,6 +168,11 @@ class ApiInstance {
157
168
  body: data
158
169
  })
159
170
 
171
+ if (this.retryStatuses.includes(error?.response?.status) && retryCount === 0) {
172
+ await this.sleep(20000)
173
+ return await this.put(url, data, headers, params, callback, retryCount + 1)
174
+ }
175
+
160
176
  if (error?.response?.data) {
161
177
  return this.responseHandler.error([error?.response?.data])
162
178
  }
@@ -170,7 +186,7 @@ class ApiInstance {
170
186
  * @param {string} url Request URL.
171
187
  * @returns {object} Response Data.
172
188
  */
173
- async delete (url, callback = () => {}) {
189
+ async delete (url, callback = () => {}, retryCount = 0) {
174
190
  try {
175
191
  const response = await this.axiosInstance.delete(url)
176
192
 
@@ -186,6 +202,11 @@ class ApiInstance {
186
202
  response: error?.response?.data
187
203
  })
188
204
 
205
+ if (this.retryStatuses.includes(error?.response?.status) && retryCount === 0) {
206
+ await this.sleep(20000)
207
+ return await this.delete(url, callback, retryCount + 1)
208
+ }
209
+
189
210
  if (error?.response?.data) {
190
211
  return this.responseHandler.error([error?.response?.data])
191
212
  }
@@ -193,6 +214,10 @@ class ApiInstance {
193
214
  return this.responseHandler.error(['Something went wrong.'])
194
215
  }
195
216
  }
217
+
218
+ async sleep(ms) {
219
+ return new Promise(resolve => setTimeout(resolve, ms))
220
+ }
196
221
  }
197
222
 
198
223
  module.exports = ApiInstance
@@ -1,18 +1,19 @@
1
- 'use strict'
1
+ "use strict";
2
2
 
3
3
  module.exports = {
4
- appUUIDs: {
5
- zudello: 'c698c4a5-ee07-44cb-a0e0-a3a1d0e683ec',
6
- netsuite: '010d0262-fa01-43eb-9e35-1b49e131c1ba',
7
- intacct: 'a8bbbc60-2409-49e8-adfb-72fc79658dd6',
8
- bc: 'ee6f62f5-9dda-48aa-bb8d-44c8b8455472',
9
- zenoti: '967a0844-6a9d-4979-a298-427259eafad8',
10
- dear: '0e456359-fe0d-4b01-9662-08bba1bdce63',
11
- nexvia: '5f693545-3be0-4798-bb3b-3af0b7ee2e96',
12
- fo: '524e1173-6d73-42ea-9d9c-0c728c6f24ea',
13
- retailExpress: '49584664-65a5-4b76-ba62-a73f7b7b3885',
14
- myobAcumatica: '8fd5015c-a200-4675-9e03-2047807c5693',
15
- sybiz: 'ead57add-301e-4b29-881b-1bc331c101a5',
16
- jobready: '14d16371-3e56-40c8-9efa-8578a8f334fc'
17
- }
18
- }
4
+ appUUIDs: {
5
+ zudello: "c698c4a5-ee07-44cb-a0e0-a3a1d0e683ec",
6
+ netsuite: "010d0262-fa01-43eb-9e35-1b49e131c1ba",
7
+ intacct: "a8bbbc60-2409-49e8-adfb-72fc79658dd6",
8
+ bc: "ee6f62f5-9dda-48aa-bb8d-44c8b8455472",
9
+ zenoti: "967a0844-6a9d-4979-a298-427259eafad8",
10
+ dear: "0e456359-fe0d-4b01-9662-08bba1bdce63",
11
+ nexvia: "5f693545-3be0-4798-bb3b-3af0b7ee2e96",
12
+ fo: "524e1173-6d73-42ea-9d9c-0c728c6f24ea",
13
+ retailExpress: "49584664-65a5-4b76-ba62-a73f7b7b3885",
14
+ myobAcumatica: "8fd5015c-a200-4675-9e03-2047807c5693",
15
+ sybiz: "ead57add-301e-4b29-881b-1bc331c101a5",
16
+ xero: "71648f29-7867-40d8-ac68-651b53cb3c49",
17
+ jobready: "14d16371-3e56-40c8-9efa-8578a8f334fc",
18
+ },
19
+ };
@@ -0,0 +1,81 @@
1
+ 'use strict'
2
+
3
+ const _ = require('lodash')
4
+
5
+ class DatasetHelper {
6
+ constructor(zudello, logger, data = null, uuid = null) {
7
+ this.zudello = zudello
8
+ this.logger = logger
9
+
10
+ this.data = data
11
+ this.uuid = uuid
12
+ }
13
+
14
+ async load(uuid, failCallback) {
15
+ failCallback = failCallback || ((data) => this.defaultFailCallback(data))
16
+
17
+ this.logger.info('DatasetUUID', uuid)
18
+
19
+ return await this.get(uuid, failCallback)
20
+ }
21
+
22
+ async get(uuid, failCallback) {
23
+ failCallback = failCallback || ((data) => this.defaultFailCallback(data))
24
+
25
+ if (!uuid) {
26
+ return failCallback({ uuid })
27
+ }
28
+
29
+ const fetchedDataset = await this.zudello.search({
30
+ model: 'DataSetRow',
31
+ offset: 0,
32
+ limit: 10000000,
33
+ select: ['uuid', 'custom'],
34
+ order_by: ['ordering'],
35
+ filter: {
36
+ dataset_uuid: uuid
37
+ }
38
+ })
39
+
40
+ this.logger.debug('Fetched Dataset', fetchedDataset)
41
+
42
+ if (fetchedDataset && fetchedDataset.data) {
43
+ const data = fetchedDataset.data?.data || null
44
+
45
+ if (data) {
46
+ return new DatasetHelper(this.zudello, this.logger, data, uuid)
47
+ }
48
+ }
49
+
50
+ return failCallback({ uuid })
51
+ }
52
+
53
+ length() {
54
+ return this.data ? this.data.length : 0
55
+ }
56
+
57
+ rows(mapping = null, filter = null) {
58
+ let data = this.data
59
+
60
+ if (!data) {
61
+ return []
62
+ }
63
+
64
+ if (filter) {
65
+ data = _.filter(data, filter)
66
+ }
67
+
68
+ if (mapping) {
69
+ data = _.map(data, mapping)
70
+ }
71
+
72
+ return data
73
+ }
74
+
75
+ defaultFailCallback(data) {
76
+ this.logger.error('Unable to find Dataset', data)
77
+ throw new Error('Unable to find Dataset')
78
+ }
79
+ }
80
+
81
+ module.exports = DatasetHelper