@sommpicks/sommpicks-shopify 24.12.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.
Files changed (71) hide show
  1. package/Logger.ts +18 -0
  2. package/README.md +258 -0
  3. package/addTypings.sh +2 -0
  4. package/bitbucket-pipelines.yml +38 -0
  5. package/index.ts +132 -0
  6. package/package.json +57 -0
  7. package/publish.sh +20 -0
  8. package/services/CacheWrapper.ts +30 -0
  9. package/services/CountryCodeService.ts +507 -0
  10. package/shopify/ShopifyAppService.ts +109 -0
  11. package/shopify/ShopifyAssetService.ts +20 -0
  12. package/shopify/ShopifyBillingService.ts +73 -0
  13. package/shopify/ShopifyCartTrasnformationService.ts +207 -0
  14. package/shopify/ShopifyCollectionService.ts +523 -0
  15. package/shopify/ShopifyCustomerService.ts +472 -0
  16. package/shopify/ShopifyDeliveryCustomisationService.ts +220 -0
  17. package/shopify/ShopifyDiscountService.ts +131 -0
  18. package/shopify/ShopifyDraftOrderService.ts +125 -0
  19. package/shopify/ShopifyFulfillmentService.ts +41 -0
  20. package/shopify/ShopifyFunctionsProductDiscountsService.ts +166 -0
  21. package/shopify/ShopifyInventoryService.ts +415 -0
  22. package/shopify/ShopifyLocationService.ts +29 -0
  23. package/shopify/ShopifyOrderRefundsService.ts +138 -0
  24. package/shopify/ShopifyOrderRiskService.ts +19 -0
  25. package/shopify/ShopifyOrderService.ts +1143 -0
  26. package/shopify/ShopifyPageService.ts +62 -0
  27. package/shopify/ShopifyProductService.ts +772 -0
  28. package/shopify/ShopifyShippingZonesService.ts +37 -0
  29. package/shopify/ShopifyShopService.ts +101 -0
  30. package/shopify/ShopifyTemplateService.ts +30 -0
  31. package/shopify/ShopifyThemeService.ts +33 -0
  32. package/shopify/ShopifyUtils.ts +56 -0
  33. package/shopify/ShopifyWebhookService.ts +110 -0
  34. package/shopify/base/APIVersion.ts +4 -0
  35. package/shopify/base/AbstractService.ts +152 -0
  36. package/shopify/base/ErrorHelper.ts +24 -0
  37. package/shopify/errors/InspiraShopifyCustomError.ts +7 -0
  38. package/shopify/errors/InspiraShopifyError.ts +15 -0
  39. package/shopify/errors/InspiraShopifyUnableToReserveInventoryError.ts +7 -0
  40. package/shopify/helpers/ShopifyProductServiceHelper.ts +450 -0
  41. package/shopify/product/ShopifyProductCountService.ts +110 -0
  42. package/shopify/product/ShopifyProductListService.ts +333 -0
  43. package/shopify/product/ShopifyProductMetafieldsService.ts +405 -0
  44. package/shopify/product/ShopifyProductPublicationsService.ts +112 -0
  45. package/shopify/product/ShopifyVariantService.ts +584 -0
  46. package/shopify/router/ShopifyMandatoryRouter.ts +37 -0
  47. package/shopify/router/ShopifyRouter.ts +85 -0
  48. package/shopify/router/ShopifyRouterBis.ts +85 -0
  49. package/shopify/router/ShopifyRouterBisBis.ts +85 -0
  50. package/shopify/router/ShopifyRouterBisBisBis.ts +85 -0
  51. package/shopify/router/ShopifyRouterBisBisBisBis.ts +85 -0
  52. package/shopify/router/WebhookSkipMiddleware.ts +73 -0
  53. package/shopify/router/services/CryptoService.ts +26 -0
  54. package/shopify/router/services/HmacValidator.ts +36 -0
  55. package/shopify/router/services/OauthService.ts +17 -0
  56. package/shopify/router/services/RestUtils.ts +13 -0
  57. package/shopify/router/services/rateLimiter/MemoryStores.ts +46 -0
  58. package/shopify/router/services/rateLimiter/StoreRateLimiter.ts +46 -0
  59. package/test/README.md +223 -0
  60. package/test/router/ShopifyRouter.test.ts +71 -0
  61. package/test/router/WebhookSkipMiddleware.test.ts +86 -0
  62. package/test/router/services/HmacValidator.test.ts +24 -0
  63. package/test/router/services/RestUtils.test.ts +13 -0
  64. package/test/router/services/rateLimiter/StoreRateLimiter.test.ts +62 -0
  65. package/test/services/CacheWrapper.test.ts +30 -0
  66. package/test/shopify/ShopifyOrderService.test.ts +29 -0
  67. package/test/shopify/ShopifyProductService.test.ts +118 -0
  68. package/test/shopify/ShopifyWebhookService.test.ts +105 -0
  69. package/tsconfig.json +10 -0
  70. package/typings/axios.d.ts +8 -0
  71. package/typings/index.d.ts +1682 -0
@@ -0,0 +1,472 @@
1
+ import { Logger } from '../Logger';
2
+ import { AxiosInstance } from 'axios';
3
+ import ErrorHelper from './base/ErrorHelper';
4
+ import InspiraShopifyError from './errors/InspiraShopifyError';
5
+ import moment = require('moment');
6
+ import { AbstractService } from './base/AbstractService';
7
+
8
+ export class ShopifyCustomerService extends AbstractService {
9
+
10
+ constructor(private axiosInstance: AxiosInstance) { super(); }
11
+
12
+ public getById = async (customerId: number): Promise<ICustomer> => {
13
+ return new Promise<ICustomer>(async (resolve, reject) => {
14
+ try {
15
+ Logger.info(`Get customer By Id ${customerId}`);
16
+ const response = await this.axiosInstance.get(`/customers/${customerId}.json`);
17
+ Logger.info('Customer found', response.data.customer);
18
+ resolve(response.data.customer);
19
+ } catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
20
+ });
21
+ };
22
+
23
+ public getByEmail = async (email: string): Promise<ICustomer[]> => {
24
+ return new Promise<ICustomer[]>(async (resolve, reject) => {
25
+ try {
26
+ Logger.info(`Get customers By Email ${email}`);
27
+ const response = await this.axiosInstance.get(`/customers/search.json?query=email:${email}`);
28
+ Logger.info('Customers found', response.data.customers);
29
+ resolve(response.data.customers);
30
+ } catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
31
+ });
32
+ };
33
+
34
+
35
+ /**
36
+ *
37
+ * Searches using /customers/search.json?query= and returns the customers that has the tag doing a filter on the endpoint results.
38
+ *
39
+ * @param {string} tag to search for.
40
+ * @returns Promise
41
+ */
42
+ public getByTag = async (tag: string): Promise<ICustomer[]> => {
43
+ return new Promise<ICustomer[]>(async (resolve, reject) => {
44
+ try {
45
+ Logger.info(`Get customers By Tag ${tag}`);
46
+ const response = await this.axiosInstance.get(`/customers/search.json?query=${tag.trim()}`);
47
+ const customers = response.data.customers;
48
+ Logger.info('Initial Customers found', response.data.customers);
49
+ const foundCustomers: ICustomer[] = [];
50
+ for (const customer of customers) {
51
+ if (customer.tags && (customer.tags as string).trim().toLowerCase().indexOf(tag.trim().toLowerCase()) > -1) {
52
+ foundCustomers.push(customer);
53
+ }
54
+ }
55
+ Logger.info('Customers found', response.data.customers);
56
+ resolve(foundCustomers);
57
+ } catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
58
+ });
59
+ };
60
+
61
+ /**
62
+ *
63
+ * Searches using /customers/search.json?query= and returns the customers that contains the string in the last name field.
64
+ *
65
+ * @param {string} text to search for.
66
+ * @returns Promise
67
+ */
68
+ public getByLastNameContains = async (text: string): Promise<ICustomer[]> => {
69
+ return new Promise<ICustomer[]>(async (resolve, reject) => {
70
+ try {
71
+ Logger.info(`Get customers By Last Name ${text}`);
72
+ const response = await this.axiosInstance.get(`/customers/search.json?query=${text.trim()}`);
73
+ const customers: ICustomer[] = response.data.customers;
74
+ Logger.info('Initial Customers found', response.data.customers);
75
+ const foundCustomers: ICustomer[] = [];
76
+ for (const customer of customers) {
77
+ if (customer.last_name && customer.last_name.trim().toLowerCase().indexOf(text.trim().toLowerCase()) > -1) {
78
+ foundCustomers.push(customer);
79
+ }
80
+ }
81
+ Logger.info('Customers found', response.data.customers);
82
+ resolve(foundCustomers);
83
+ } catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
84
+ });
85
+ };
86
+
87
+ public create = async (customer: ICustomer): Promise<ICustomer> => {
88
+ return new Promise<ICustomer>(async (resolve, reject) => {
89
+ try {
90
+ Logger.info('Create customers', customer);
91
+ const response = await this.axiosInstance.post('/customers.json', { customer: customer });
92
+ resolve(response.data.customer);
93
+ } catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
94
+ });
95
+ };
96
+
97
+ /**
98
+ *
99
+ * @param custormerId Customer Id in shopify
100
+ * @param {ICustomer} customer add fields that need to be updated. Id field is required
101
+ * @returns
102
+ */
103
+ public update = async (custormerId: number, customer: ICustomer): Promise<ICustomer> => {
104
+ return new Promise<ICustomer>(async (resolve, reject) => {
105
+ try {
106
+ Logger.info(`Update customers ${custormerId}`, customer);
107
+ const response = await this.axiosInstance.put(`/customers/${custormerId}.json`, { customer: customer });
108
+ resolve(response.data.customer);
109
+ } catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
110
+ });
111
+ };
112
+
113
+ /**
114
+ *
115
+ * Adds one or more tags to a customer. It does add them toghether with the existing ones.
116
+ *
117
+ * @param {number} customerId customer id number
118
+ * @param {tags: string; id: number;} customer customer to apply change to. Just tags and id fields
119
+ * @param {string[]} tags tags to add
120
+ * @returns Promise
121
+ */
122
+ public addTags = async (customerId: number, customer: { tags: string; id: number; }, tags: string[]): Promise<ICustomer> => {
123
+ return new Promise<ICustomer>(async (resolve, reject) => {
124
+ try {
125
+ if(customerId !== customer.id) {
126
+ throw new Error(`Trying to add tags to the wrong customer - ${customerId} vs ${customer.id}`);
127
+ }
128
+ Logger.info(`Added tags of (${tags.join(',')}) to customer with id of ${customerId}`);
129
+ customer.tags = [...new Set([...customer.tags.split(','), ...tags])].join();
130
+ const responsedCustomer: ICustomer = await this.update(customerId, customer as any);
131
+ resolve(responsedCustomer);
132
+ } catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
133
+ });
134
+ };
135
+
136
+ /**
137
+ *
138
+ * Removes one or more tags to a customer
139
+ *
140
+ * @param {number} customerId customer id number
141
+ * @param {tags: string; id: number;} customer customer to apply change to. Just tags and id fields
142
+ * @param {string[]} tags tags to remove
143
+ * @returns Promise
144
+ */
145
+ public removeTags = async (customerId: number, customer: { tags: string; id: number; }, tags: string[]): Promise<ICustomer> => {
146
+ return new Promise<ICustomer>(async (resolve, reject) => {
147
+ try {
148
+ if(customerId !== customer.id) {
149
+ throw new Error(`Trying to remove tags to the wrong customer - ${customerId} vs ${customer.id}`);
150
+ }
151
+ Logger.info(`Removing tags of (${tags.join(',')}) to customer with id of ${customerId}`);
152
+ customer.tags = (customer.tags).split(',').filter(function (x) {
153
+ return tags.indexOf(x.trim()) < 0;
154
+ }).join(',');
155
+ const responsedCustomer: ICustomer = await this.update(customerId, customer as any);
156
+ resolve(responsedCustomer);
157
+ } catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
158
+ });
159
+ };
160
+
161
+ public getInBatch = async (sinceId: number): Promise<ICustomerBatch> => {
162
+ return new Promise<ICustomerBatch>(async (resolve, reject) => {
163
+ try {
164
+ Logger.info(`Getting customer since id ${sinceId}`);
165
+ const response = await this.axiosInstance.get('/customers/count.json');
166
+ const count = response.data.count;
167
+ const batches = parseInt(((count / 250) + 1).toString());
168
+ const customerBatch: ICustomerBatch = { batches: batches, customers: [], nextSinceId: 0 };
169
+ const customersGetURL = `/customers.json?limit=250&since_id=${sinceId}`;
170
+ const customersRetrieved = await this.axiosInstance.get(customersGetURL);
171
+ customerBatch.customers = customersRetrieved.data.customers;
172
+ if (customerBatch.customers && customerBatch.customers.length > 249) {
173
+ customerBatch.nextSinceId = customerBatch.customers[customerBatch.customers.length - 1].id;
174
+ } else {
175
+ customerBatch.nextSinceId = null;
176
+ }
177
+ resolve(customerBatch);
178
+ } catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
179
+ });
180
+ };
181
+
182
+ public getCustomerEmails = async (ids: number[]): Promise<{ email: string; id: number; }[]> => {
183
+ return new Promise<{ email: string; id: number; }[]>(async (resolve, reject) => {
184
+ try {
185
+ let emails: { email: string; id: number; }[] = [];
186
+ const idsChunks: number[][] = this.sliceIntoChunks(ids, 250);
187
+
188
+ Logger.info(`Getting customer emails in ${idsChunks.length} chunks of 250`);
189
+
190
+ for (const idsChunk of idsChunks) {
191
+ const customersGetURL = `/customers.json?ids=${idsChunk.join(',')}&limit=250&fields=id, email`;
192
+ Logger.info(`idsChunk ... ${customersGetURL}`);
193
+ const customersRetrieved = await this.axiosInstance.get(customersGetURL);
194
+ if(customersRetrieved.data?.customers && customersRetrieved.data.customers.length > 0) {
195
+ Logger.info(`idsChunk - customersRetrieved ... ${JSON.stringify(customersRetrieved.data)}`);
196
+ emails = emails.concat(customersRetrieved.data.customers);
197
+ }
198
+ }
199
+ resolve(emails);
200
+ } catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
201
+ });
202
+ };
203
+
204
+ /**
205
+ *
206
+ * @param {number} num? Optional if you want to get a certain amount of products. Leave blank to get all.
207
+ * @returns Promise
208
+ */
209
+ public getAll = async (num?: number): Promise<ICustomer[]> => {
210
+ return new Promise<ICustomer[]>(async (resolve, reject) => {
211
+ try {
212
+ Logger.info('getting customers');
213
+ let customers: ICustomer[] = [];
214
+ const response = await this.axiosInstance.get('/customers/count.json');
215
+ const count = response.data.count > num && num !== undefined ? num : response.data.count;
216
+ while (customers.length < count) {
217
+ let customerGetURL = '/customers.json?limit=100&since_id=';
218
+ if (customers.length > 1) {
219
+ customerGetURL += customers[customers.length - 1].id;
220
+ } else {
221
+ customerGetURL += '0';
222
+ }
223
+ const customersRetrieved = await this.axiosInstance.get(customerGetURL);
224
+ customers = customers.concat(customersRetrieved.data.customers);
225
+ if (!customersRetrieved.data.customers || customersRetrieved.data.customers.length < 100) {
226
+ break;
227
+ }
228
+ }
229
+ resolve(customers.slice(0, count));
230
+ } catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
231
+ });
232
+ };
233
+
234
+ /**
235
+ * Adds an address to a customer.
236
+ *
237
+ * @param {number} customerId - Customer Id
238
+ * @param {IAddress} address
239
+ * @returns Promise
240
+ */
241
+ public addAddress = async (customerId: number, address: IAddress): Promise<IAddress> => {
242
+ return new Promise<IAddress>(async (resolve, reject) => {
243
+ try {
244
+ Logger.info(`Adding a address to customer ${customerId}`, address);
245
+ const response = await this.axiosInstance.post(`/customers/${customerId}/addresses.json`, { address: address });
246
+ resolve(response.data.customer_address);
247
+ } catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
248
+ });
249
+ };
250
+
251
+ /**
252
+ * Adds an address to a customer as its default.
253
+ *
254
+ * @param {number} customerId - Cusotmer Id
255
+ * @param {IAddress} address
256
+ * @returns Promise
257
+ */
258
+ public addAddressAsDefault = async (customerId: number, address: IAddress): Promise<IAddress> => {
259
+ return new Promise<IAddress>(async (resolve, reject) => {
260
+ try {
261
+ let addressCreated = await this.addAddress(customerId, address);
262
+ addressCreated = await this.addressAsDefault(customerId, addressCreated.id);
263
+ resolve(addressCreated);
264
+ } catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
265
+ });
266
+ };
267
+
268
+ /**
269
+ * Replaces the default address of a customer for the address provided.
270
+ *
271
+ * @param {number} customerId - Customer Id
272
+ * @param {IAddress} address
273
+ * @returns Promise
274
+ */
275
+ public replacesAddressAsDefault = async (customerId: number, address: IAddress): Promise<IAddress> => {
276
+ return new Promise<IAddress>(async (resolve, reject) => {
277
+ try {
278
+ const customer = await this.getById(customerId);
279
+ const defaultAddressId = customer.default_address ? customer.default_address.id : null;
280
+ let addressCreated = await this.addAddress(customerId, address);
281
+ addressCreated = await this.addressAsDefault(customerId, addressCreated.id);
282
+ if (defaultAddressId) {
283
+ await this.removeAddress(customerId, defaultAddressId);
284
+ } else {
285
+ Logger.info('There wasn\'t a default address');
286
+ }
287
+ resolve(addressCreated);
288
+ } catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
289
+ });
290
+ };
291
+
292
+ /**
293
+ * Converts an address of a customer to its default.
294
+ *
295
+ * @param {number} customerId - Customer Id
296
+ * @param {IAddress} addressId
297
+ * @returns Promise
298
+ */
299
+ public addressAsDefault = async (customerId: number, addressId: number): Promise<IAddress> => {
300
+ return new Promise<IAddress>(async (resolve, reject) => {
301
+ try {
302
+ Logger.info(`Address ${addressId} of customer ${customerId} as default`);
303
+ const response = await this.axiosInstance.put(`/customers/${customerId}/addresses/${addressId}/default.json`, {});
304
+ resolve(response.data.customer_address);
305
+ } catch (error) { Logger.error('Error setting address as default', error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
306
+ });
307
+ };
308
+
309
+ /**
310
+ * Updates an address to a customer.
311
+ *
312
+ * @param {number} id - Cusotmer Id
313
+ * @param {IAddress} address with id field in
314
+ * @returns Promise
315
+ */
316
+ public updateAddress = async (id: number, address: IAddress): Promise<IAddress> => {
317
+ return new Promise<IAddress>(async (resolve, reject) => {
318
+ try {
319
+ Logger.info(`Updating address ${address.id} to customer ${id}`, address);
320
+ const response = await this.axiosInstance.put(`/customers/${id}/addresses/${address.id}.json`, { address: address });
321
+ resolve(response.data.customer_address);
322
+ } catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
323
+ });
324
+ };
325
+
326
+ /**
327
+ * Removes an address to a customer.
328
+ *
329
+ * @param {number} customerId - Customer Id
330
+ * @param {number} addressId
331
+ * @returns Promise
332
+ */
333
+ public removeAddress = async (customerId: number, addressId: number): Promise<void> => {
334
+ return new Promise<void>(async (resolve, reject) => {
335
+ try {
336
+ Logger.info(`Removing address ${addressId} for customer ${customerId}`);
337
+ await this.axiosInstance.delete(`/customers/${customerId}/addresses/${addressId}.json`);
338
+ resolve();
339
+ } catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
340
+ });
341
+ };
342
+
343
+ /**
344
+ * Gets all metafields for a customer or empty array.
345
+ *
346
+ * @param {number} id - Cusotmer Id
347
+ * @returns Promise
348
+ */
349
+ public getMetafields = async (id: number): Promise<IMetafield[]> => {
350
+ return new Promise<IMetafield[]>(async (resolve, reject) => {
351
+ try {
352
+ Logger.info(`Getting metafields for customer id -> ${id}`);
353
+ const response = await this.axiosInstance.get(`/customers/${id}/metafields.json`);
354
+ resolve(response.data.metafields);
355
+ } catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
356
+ });
357
+ };
358
+
359
+ /**
360
+ * Count customers.
361
+ *
362
+ * @param {number} daysAgo - All customers created since that date.
363
+ * @returns Promise
364
+ */
365
+ public count = async (daysAgo: number): Promise<number> => {
366
+ return new Promise<number>(async (resolve, reject) => {
367
+ try {
368
+ Logger.info(`Count customers created after ${daysAgo} days ago`);
369
+ const response = await this.axiosInstance.get(`/customers/count.json?created_at_min=${moment().subtract(daysAgo, 'days').format()}`);
370
+ resolve(response.data.count);
371
+ } catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
372
+ });
373
+ };
374
+
375
+ /**
376
+ * Gets one concrete metafield for a customer or null if it does not exists.
377
+ *
378
+ * @param {number} id - Cusotmer Id
379
+ * @param {string} namespace
380
+ * @param {string} key
381
+ * @returns Promise
382
+ */
383
+ public getMetafield = async (id: number, namespace: string, key: string): Promise<IMetafield> => {
384
+ return new Promise<IMetafield>(async (resolve, reject) => {
385
+ try {
386
+ Logger.info(`Getting metafield for customer id -> ${id} and namespace ${namespace} and key ${key}`);
387
+ const metafields = await this.getMetafields(id);
388
+ let foundMetafield: IMetafield = null;
389
+ if (metafields && metafields.length > 0) {
390
+ foundMetafield = metafields.find(m => m.namespace === namespace && m.key === key);
391
+ }
392
+ resolve(foundMetafield);
393
+ } catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
394
+ });
395
+ };
396
+
397
+ /**
398
+ * Sends invite to a customer.
399
+ *
400
+ * @param {number} customerId
401
+ * @returns Promise
402
+ */
403
+ public sendInvite = async (customerId: number): Promise<void> => {
404
+ return new Promise<void>(async (resolve, reject) => {
405
+ try {
406
+ Logger.info(`Send invite to customer -> ${customerId}`);
407
+ await this.axiosInstance.post(`/customers/${customerId}/send_invite.json`);
408
+ resolve();
409
+ } catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
410
+ });
411
+ };
412
+
413
+ /**
414
+ * Creates a metafield for a customer and return the created metafield.
415
+ *
416
+ * @param {number} id
417
+ * @param {IMetafield} metafield
418
+ * @returns Promise
419
+ */
420
+ public postMetafield = async (id: number, metafield: IMetafield): Promise<IMetafield> => {
421
+ return new Promise<IMetafield>(async (resolve, reject) => {
422
+ try {
423
+ Logger.info(`Posting metafield for customer id -> ${id}`);
424
+ const response = await this.axiosInstance.post(`/customers/${id}/metafields.json`, { metafield: metafield });
425
+ resolve(response.data.metafield);
426
+ } catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
427
+ });
428
+ };
429
+
430
+ /**
431
+ * Updates a metafield for a customer and return the updated metafield. <br>
432
+ * The functionality first retrieves the customer metafield to get the ID and then updates it.
433
+ *
434
+ * @param {number} customerId
435
+ * @param {IMetafield} metafield.
436
+ * @returns Promise
437
+ */
438
+ public putMetafield = async (customerId: number, metafield: IMetafield): Promise<IMetafield> => {
439
+ return new Promise<IMetafield>(async (resolve, reject) => {
440
+ try {
441
+ Logger.info(`Updating a metafield for customer id -> ${customerId}`);
442
+ const metafieldSaved = await this.getMetafield(customerId, metafield.namespace, metafield.key);
443
+ if (metafieldSaved && metafieldSaved.id) {
444
+ Logger.info(`Existing Metafield. Updating a metafield for customer id -> ${customerId}`);
445
+ const response = await this.axiosInstance.put(`/customers/${customerId}/metafields/${metafieldSaved.id}.json`, { metafield: { id: metafieldSaved.id, value: metafield.value } });
446
+ resolve(response.data.metafield);
447
+ } else {
448
+ Logger.info(`Metafield not found. Updating the metafield for customer id -> ${customerId}`);
449
+ const createdMetafield = await this.postMetafield(customerId, metafield);
450
+ resolve(createdMetafield);
451
+ }
452
+ } catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
453
+ });
454
+ };
455
+
456
+ /**
457
+ * Deletes a metafield for a customer.
458
+ *
459
+ * @param {number} id - Customer Id
460
+ * @param {number} metafieldId
461
+ * @returns Promise
462
+ */
463
+ public deleteMetafield = async (id: number, metafieldId: number): Promise<void> => {
464
+ return new Promise<void>(async (resolve, reject) => {
465
+ try {
466
+ Logger.info(`Posting metafield for customer id -> ${id}`);
467
+ await this.axiosInstance.delete(`/customers/${id}/metafields/${metafieldId}.json`);
468
+ resolve();
469
+ } catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
470
+ });
471
+ };
472
+ }