@merchi/sdk 1.40.2 → 1.42.1

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 (171) hide show
  1. package/dist/entities/cart.js +40 -0
  2. package/dist/entities/cart.test.js +21 -0
  3. package/dist/entities/domain.js +4 -0
  4. package/dist/entities/domain.test.js +10 -0
  5. package/dist/entities/invoice.js +4 -0
  6. package/dist/entities/job.js +40 -0
  7. package/dist/entities/job.test.js +25 -0
  8. package/dist/entity.js +6 -0
  9. package/dist/request.js +11 -3
  10. package/dist/request.test.js +21 -2
  11. package/package.json +1 -1
  12. package/src/entities/cart.test.ts +23 -0
  13. package/src/entities/cart.ts +30 -0
  14. package/src/entities/domain.test.ts +14 -0
  15. package/src/entities/domain.ts +3 -0
  16. package/src/entities/invoice.ts +3 -0
  17. package/src/entities/job.test.ts +27 -0
  18. package/src/entities/job.ts +30 -0
  19. package/src/entity.ts +8 -0
  20. package/src/request.test.ts +23 -2
  21. package/src/request.ts +12 -3
  22. package/.turbo/turbo-test.log +0 -849
  23. package/coverage/clover.xml +0 -5057
  24. package/coverage/coverage-final.json +0 -133
  25. package/coverage/lcov-report/base.css +0 -224
  26. package/coverage/lcov-report/block-navigation.js +0 -87
  27. package/coverage/lcov-report/favicon.png +0 -0
  28. package/coverage/lcov-report/index.html +0 -191
  29. package/coverage/lcov-report/prettify.css +0 -1
  30. package/coverage/lcov-report/prettify.js +0 -2
  31. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  32. package/coverage/lcov-report/sorter.js +0 -210
  33. package/coverage/lcov-report/src/constants/auto_assign_production_on_actions.ts.html +0 -103
  34. package/coverage/lcov-report/src/constants/call_to_actions.ts.html +0 -127
  35. package/coverage/lcov-report/src/constants/discount_types.ts.html +0 -100
  36. package/coverage/lcov-report/src/constants/domain_types.ts.html +0 -121
  37. package/coverage/lcov-report/src/constants/errors.ts.html +0 -181
  38. package/coverage/lcov-report/src/constants/event_types.ts.html +0 -100
  39. package/coverage/lcov-report/src/constants/field_types.ts.html +0 -133
  40. package/coverage/lcov-report/src/constants/index.html +0 -551
  41. package/coverage/lcov-report/src/constants/index.ts.html +0 -238
  42. package/coverage/lcov-report/src/constants/input_types.ts.html +0 -124
  43. package/coverage/lcov-report/src/constants/inventory_statuses.ts.html +0 -103
  44. package/coverage/lcov-report/src/constants/invoice_types.ts.html +0 -100
  45. package/coverage/lcov-report/src/constants/item_types.ts.html +0 -100
  46. package/coverage/lcov-report/src/constants/job/drafting_status.ts.html +0 -106
  47. package/coverage/lcov-report/src/constants/job/index.html +0 -176
  48. package/coverage/lcov-report/src/constants/job/payment_status.ts.html +0 -106
  49. package/coverage/lcov-report/src/constants/job/production_status.ts.html +0 -121
  50. package/coverage/lcov-report/src/constants/job/shipment_status.ts.html +0 -118
  51. package/coverage/lcov-report/src/constants/job/supply_chain_request_status.ts.html +0 -103
  52. package/coverage/lcov-report/src/constants/job_priorities.ts.html +0 -103
  53. package/coverage/lcov-report/src/constants/job_status.ts.html +0 -232
  54. package/coverage/lcov-report/src/constants/job_types.ts.html +0 -133
  55. package/coverage/lcov-report/src/constants/notification_sections.ts.html +0 -124
  56. package/coverage/lcov-report/src/constants/notification_types.ts.html +0 -385
  57. package/coverage/lcov-report/src/constants/notification_urgencies.ts.html +0 -106
  58. package/coverage/lcov-report/src/constants/payment_types.ts.html +0 -115
  59. package/coverage/lcov-report/src/constants/platform.ts.html +0 -103
  60. package/coverage/lcov-report/src/constants/product_types.ts.html +0 -163
  61. package/coverage/lcov-report/src/constants/rights.ts.html +0 -100
  62. package/coverage/lcov-report/src/constants/robots_meta_directives.ts.html +0 -118
  63. package/coverage/lcov-report/src/constants/roles.ts.html +0 -223
  64. package/coverage/lcov-report/src/constants/shipment_companies.ts.html +0 -142
  65. package/coverage/lcov-report/src/constants/shipment_services.ts.html +0 -94
  66. package/coverage/lcov-report/src/constants/system_roles.ts.html +0 -94
  67. package/coverage/lcov-report/src/constants/theme_status.ts.html +0 -100
  68. package/coverage/lcov-report/src/constants/user_types.ts.html +0 -136
  69. package/coverage/lcov-report/src/constants/white_label_accessibilities.ts.html +0 -103
  70. package/coverage/lcov-report/src/cookie.ts.html +0 -133
  71. package/coverage/lcov-report/src/entities/address.ts.html +0 -280
  72. package/coverage/lcov-report/src/entities/agent_conversation.ts.html +0 -202
  73. package/coverage/lcov-report/src/entities/agent_skill.ts.html +0 -382
  74. package/coverage/lcov-report/src/entities/agent_skill_approval.ts.html +0 -163
  75. package/coverage/lcov-report/src/entities/agent_skill_version.ts.html +0 -277
  76. package/coverage/lcov-report/src/entities/agent_token_usage.ts.html +0 -349
  77. package/coverage/lcov-report/src/entities/assignment.ts.html +0 -382
  78. package/coverage/lcov-report/src/entities/automatic_payment_relationship.ts.html +0 -172
  79. package/coverage/lcov-report/src/entities/bank.ts.html +0 -220
  80. package/coverage/lcov-report/src/entities/cart.ts.html +0 -391
  81. package/coverage/lcov-report/src/entities/cart_item.ts.html +0 -340
  82. package/coverage/lcov-report/src/entities/cart_shipment_group.ts.html +0 -148
  83. package/coverage/lcov-report/src/entities/cart_shipment_quote.ts.html +0 -184
  84. package/coverage/lcov-report/src/entities/category.ts.html +0 -262
  85. package/coverage/lcov-report/src/entities/company.ts.html +0 -1276
  86. package/coverage/lcov-report/src/entities/company_invitation.ts.html +0 -184
  87. package/coverage/lcov-report/src/entities/country_tax.ts.html +0 -223
  88. package/coverage/lcov-report/src/entities/discount.ts.html +0 -235
  89. package/coverage/lcov-report/src/entities/discount_group.ts.html +0 -214
  90. package/coverage/lcov-report/src/entities/domain.ts.html +0 -3349
  91. package/coverage/lcov-report/src/entities/domain_chat_settings.ts.html +0 -331
  92. package/coverage/lcov-report/src/entities/domain_invitation.ts.html +0 -193
  93. package/coverage/lcov-report/src/entities/domain_tag.ts.html +0 -211
  94. package/coverage/lcov-report/src/entities/draft.ts.html +0 -322
  95. package/coverage/lcov-report/src/entities/draft_comment.ts.html +0 -274
  96. package/coverage/lcov-report/src/entities/draft_preview.ts.html +0 -196
  97. package/coverage/lcov-report/src/entities/draft_preview_layer.ts.html +0 -148
  98. package/coverage/lcov-report/src/entities/draft_template.ts.html +0 -328
  99. package/coverage/lcov-report/src/entities/email_address.ts.html +0 -157
  100. package/coverage/lcov-report/src/entities/email_counter.ts.html +0 -145
  101. package/coverage/lcov-report/src/entities/enrolled_domain.ts.html +0 -205
  102. package/coverage/lcov-report/src/entities/exchange_rate.ts.html +0 -151
  103. package/coverage/lcov-report/src/entities/file.ts.html +0 -580
  104. package/coverage/lcov-report/src/entities/index.html +0 -1271
  105. package/coverage/lcov-report/src/entities/internal_tag.ts.html +0 -238
  106. package/coverage/lcov-report/src/entities/inventory.ts.html +0 -274
  107. package/coverage/lcov-report/src/entities/inventory_group.ts.html +0 -193
  108. package/coverage/lcov-report/src/entities/inventory_unit_variation.ts.html +0 -172
  109. package/coverage/lcov-report/src/entities/invoice.ts.html +0 -661
  110. package/coverage/lcov-report/src/entities/item.ts.html +0 -262
  111. package/coverage/lcov-report/src/entities/job.ts.html +0 -1288
  112. package/coverage/lcov-report/src/entities/job_comment.ts.html +0 -244
  113. package/coverage/lcov-report/src/entities/job_note.ts.html +0 -205
  114. package/coverage/lcov-report/src/entities/job_operation_log.ts.html +0 -208
  115. package/coverage/lcov-report/src/entities/matching_inventory.ts.html +0 -172
  116. package/coverage/lcov-report/src/entities/notification.ts.html +0 -403
  117. package/coverage/lcov-report/src/entities/payment.ts.html +0 -316
  118. package/coverage/lcov-report/src/entities/payment_device.ts.html +0 -175
  119. package/coverage/lcov-report/src/entities/phone_number.ts.html +0 -193
  120. package/coverage/lcov-report/src/entities/product.ts.html +0 -1543
  121. package/coverage/lcov-report/src/entities/product_form.ts.html +0 -238
  122. package/coverage/lcov-report/src/entities/product_form_version.ts.html +0 -238
  123. package/coverage/lcov-report/src/entities/product_review.ts.html +0 -748
  124. package/coverage/lcov-report/src/entities/production_comment.ts.html +0 -244
  125. package/coverage/lcov-report/src/entities/quote.ts.html +0 -505
  126. package/coverage/lcov-report/src/entities/quote_item.ts.html +0 -298
  127. package/coverage/lcov-report/src/entities/reminder.ts.html +0 -307
  128. package/coverage/lcov-report/src/entities/session.ts.html +0 -169
  129. package/coverage/lcov-report/src/entities/shipment.ts.html +0 -673
  130. package/coverage/lcov-report/src/entities/shipment_item.ts.html +0 -130
  131. package/coverage/lcov-report/src/entities/shipment_item_fulfillment.ts.html +0 -130
  132. package/coverage/lcov-report/src/entities/shipment_log.ts.html +0 -196
  133. package/coverage/lcov-report/src/entities/shipment_method.ts.html +0 -268
  134. package/coverage/lcov-report/src/entities/shipment_method_variation.ts.html +0 -202
  135. package/coverage/lcov-report/src/entities/short_url.ts.html +0 -193
  136. package/coverage/lcov-report/src/entities/subscription_plan.ts.html +0 -304
  137. package/coverage/lcov-report/src/entities/supply_domain.ts.html +0 -166
  138. package/coverage/lcov-report/src/entities/support_conversation.ts.html +0 -280
  139. package/coverage/lcov-report/src/entities/support_message.ts.html +0 -175
  140. package/coverage/lcov-report/src/entities/system_role.ts.html +0 -136
  141. package/coverage/lcov-report/src/entities/theme.ts.html +0 -331
  142. package/coverage/lcov-report/src/entities/theme_css_setting.ts.html +0 -154
  143. package/coverage/lcov-report/src/entities/user.ts.html +0 -1369
  144. package/coverage/lcov-report/src/entities/user_company.ts.html +0 -166
  145. package/coverage/lcov-report/src/entities/variation.ts.html +0 -277
  146. package/coverage/lcov-report/src/entities/variation_field.ts.html +0 -889
  147. package/coverage/lcov-report/src/entities/variation_fields_option.ts.html +0 -406
  148. package/coverage/lcov-report/src/entities/variation_option.ts.html +0 -259
  149. package/coverage/lcov-report/src/entities/variations_group.ts.html +0 -208
  150. package/coverage/lcov-report/src/entity.ts.html +0 -3379
  151. package/coverage/lcov-report/src/index.html +0 -221
  152. package/coverage/lcov-report/src/index.ts.html +0 -652
  153. package/coverage/lcov-report/src/merchi.ts.html +0 -1420
  154. package/coverage/lcov-report/src/pricing/discount.ts.html +0 -136
  155. package/coverage/lcov-report/src/pricing/estimate.ts.html +0 -1015
  156. package/coverage/lcov-report/src/pricing/index.html +0 -206
  157. package/coverage/lcov-report/src/pricing/index.ts.html +0 -106
  158. package/coverage/lcov-report/src/pricing/inventory.ts.html +0 -352
  159. package/coverage/lcov-report/src/pricing/matrix.ts.html +0 -736
  160. package/coverage/lcov-report/src/pricing/round.ts.html +0 -166
  161. package/coverage/lcov-report/src/pricing/visibility.ts.html +0 -418
  162. package/coverage/lcov-report/src/request.ts.html +0 -673
  163. package/coverage/lcov-report/src/test_util.ts.html +0 -139
  164. package/coverage/lcov-report/src/toasts.ts.html +0 -187
  165. package/coverage/lcov-report/src/util/float.ts.html +0 -121
  166. package/coverage/lcov-report/src/util/index.html +0 -161
  167. package/coverage/lcov-report/src/util/index.ts.html +0 -106
  168. package/coverage/lcov-report/src/util/query_string.ts.html +0 -124
  169. package/coverage/lcov-report/src/util/validation.ts.html +0 -91
  170. package/coverage/lcov-report/src/uuid.ts.html +0 -109
  171. package/coverage/lcov.info +0 -7758
@@ -136,6 +136,46 @@ var Cart = /** @class */ (function (_super) {
136
136
  Cart.property(),
137
137
  __metadata("design:type", Boolean)
138
138
  ], Cart.prototype, "sendWhatsapp", void 0);
139
+ __decorate([
140
+ Cart.property(),
141
+ __metadata("design:type", Boolean)
142
+ ], Cart.prototype, "isTest", void 0);
143
+ __decorate([
144
+ Cart.property({ type: String }),
145
+ __metadata("design:type", Object)
146
+ ], Cart.prototype, "sourceChannel", void 0);
147
+ __decorate([
148
+ Cart.property({ type: String }),
149
+ __metadata("design:type", Object)
150
+ ], Cart.prototype, "utmSource", void 0);
151
+ __decorate([
152
+ Cart.property({ type: String }),
153
+ __metadata("design:type", Object)
154
+ ], Cart.prototype, "utmMedium", void 0);
155
+ __decorate([
156
+ Cart.property({ type: String }),
157
+ __metadata("design:type", Object)
158
+ ], Cart.prototype, "utmCampaign", void 0);
159
+ __decorate([
160
+ Cart.property({ type: String }),
161
+ __metadata("design:type", Object)
162
+ ], Cart.prototype, "utmContent", void 0);
163
+ __decorate([
164
+ Cart.property({ type: String }),
165
+ __metadata("design:type", Object)
166
+ ], Cart.prototype, "utmTerm", void 0);
167
+ __decorate([
168
+ Cart.property({ type: String }),
169
+ __metadata("design:type", Object)
170
+ ], Cart.prototype, "sourceClickId", void 0);
171
+ __decorate([
172
+ Cart.property({ type: String }),
173
+ __metadata("design:type", Object)
174
+ ], Cart.prototype, "sourceLanding", void 0);
175
+ __decorate([
176
+ Cart.property({ type: String }),
177
+ __metadata("design:type", Object)
178
+ ], Cart.prototype, "sourceReferrer", void 0);
139
179
  __decorate([
140
180
  Cart.property({ type: 'User' }),
141
181
  __metadata("design:type", Object)
@@ -49,3 +49,24 @@ test('preserves server payment engine hint', function () {
49
49
  entity.fromJson({ id: 1, stripePaymentEngine: 'wallet' });
50
50
  expect(entity.toJson()).toMatchObject({ stripePaymentEngine: 'wallet' });
51
51
  });
52
+ test('preserves isTest', function () {
53
+ var merchi = new Merchi();
54
+ var entity = new merchi.Cart();
55
+ entity.fromJson({ id: 1, isTest: true });
56
+ expect(entity.toJson()).toMatchObject({ isTest: true });
57
+ });
58
+ test('preserves source attribution', function () {
59
+ var merchi = new Merchi();
60
+ var entity = new merchi.Cart();
61
+ entity.fromJson({
62
+ id: 1,
63
+ sourceChannel: 'meta',
64
+ utmSource: 'facebook',
65
+ sourceClickId: 'IwAR',
66
+ });
67
+ expect(entity.toJson()).toMatchObject({
68
+ sourceChannel: 'meta',
69
+ utmSource: 'facebook',
70
+ sourceClickId: 'IwAR',
71
+ });
72
+ });
@@ -362,6 +362,10 @@ var Domain = /** @class */ (function (_super) {
362
362
  Domain.property({ type: String }),
363
363
  __metadata("design:type", Object)
364
364
  ], Domain.prototype, "apiSecret", void 0);
365
+ __decorate([
366
+ Domain.property({ type: jsonPropertyType }),
367
+ __metadata("design:type", Object)
368
+ ], Domain.prototype, "apiAllowedOrigins", void 0);
365
369
  __decorate([
366
370
  Domain.property({ type: String }),
367
371
  __metadata("design:type", Object)
@@ -28,6 +28,16 @@ test('can create domain on server', function () {
28
28
  var sentToServer = Array.from(fetch.mock.calls[0][1]['body'].entries());
29
29
  expect(sentToServer).toEqual(data);
30
30
  });
31
+ test('serialises apiAllowedOrigins JSON for form data', function () {
32
+ var merchi = new Merchi();
33
+ var domain = new merchi.Domain();
34
+ domain.id = 7;
35
+ domain.apiAllowedOrigins = ['https://shop.example.com', 'https://preview.example.com'];
36
+ var entries = Array.from(domain.toFormData().entries());
37
+ var data = Object.fromEntries(entries);
38
+ expect(data.apiAllowedOrigins).toBe(JSON.stringify(['https://shop.example.com', 'https://preview.example.com']));
39
+ expect(data.apiAllowedOrigins).not.toBe('[object Object]');
40
+ });
31
41
  test('serialises jobAgentPolicy JSON for form data', function () {
32
42
  var merchi = new Merchi();
33
43
  var domain = new merchi.Domain();
@@ -119,6 +119,10 @@ var Invoice = /** @class */ (function (_super) {
119
119
  Invoice.property({ type: Boolean }),
120
120
  __metadata("design:type", Object)
121
121
  ], Invoice.prototype, "unpaid", void 0);
122
+ __decorate([
123
+ Invoice.property({ type: Boolean }),
124
+ __metadata("design:type", Object)
125
+ ], Invoice.prototype, "isTest", void 0);
122
126
  __decorate([
123
127
  Invoice.property(),
124
128
  __metadata("design:type", String)
@@ -374,6 +374,42 @@ var Job = /** @class */ (function (_super) {
374
374
  Job.property(),
375
375
  __metadata("design:type", String)
376
376
  ], Job.prototype, "clientOrigin", void 0);
377
+ __decorate([
378
+ Job.property({ type: String }),
379
+ __metadata("design:type", Object)
380
+ ], Job.prototype, "sourceChannel", void 0);
381
+ __decorate([
382
+ Job.property({ type: String }),
383
+ __metadata("design:type", Object)
384
+ ], Job.prototype, "utmSource", void 0);
385
+ __decorate([
386
+ Job.property({ type: String }),
387
+ __metadata("design:type", Object)
388
+ ], Job.prototype, "utmMedium", void 0);
389
+ __decorate([
390
+ Job.property({ type: String }),
391
+ __metadata("design:type", Object)
392
+ ], Job.prototype, "utmCampaign", void 0);
393
+ __decorate([
394
+ Job.property({ type: String }),
395
+ __metadata("design:type", Object)
396
+ ], Job.prototype, "utmContent", void 0);
397
+ __decorate([
398
+ Job.property({ type: String }),
399
+ __metadata("design:type", Object)
400
+ ], Job.prototype, "utmTerm", void 0);
401
+ __decorate([
402
+ Job.property({ type: String }),
403
+ __metadata("design:type", Object)
404
+ ], Job.prototype, "sourceClickId", void 0);
405
+ __decorate([
406
+ Job.property({ type: String }),
407
+ __metadata("design:type", Object)
408
+ ], Job.prototype, "sourceLanding", void 0);
409
+ __decorate([
410
+ Job.property({ type: String }),
411
+ __metadata("design:type", Object)
412
+ ], Job.prototype, "sourceReferrer", void 0);
377
413
  __decorate([
378
414
  Job.property({ type: User }),
379
415
  __metadata("design:type", Object)
@@ -514,6 +550,10 @@ var Job = /** @class */ (function (_super) {
514
550
  Job.property(),
515
551
  __metadata("design:type", Boolean)
516
552
  ], Job.prototype, "isNewClient", void 0);
553
+ __decorate([
554
+ Job.property(),
555
+ __metadata("design:type", Boolean)
556
+ ], Job.prototype, "isTest", void 0);
517
557
  return Job;
518
558
  }(Entity));
519
559
  export { Job };
@@ -7,6 +7,31 @@ test('can make Job', function () {
7
7
  var job = new merchi.Job();
8
8
  expect(job).toBeTruthy();
9
9
  });
10
+ test('preserves isTest', function () {
11
+ var merchi = new Merchi();
12
+ var job = new merchi.Job();
13
+ job.fromJson({ id: 1, isTest: true });
14
+ expect(job.toJson()).toMatchObject({ isTest: true });
15
+ });
16
+ test('preserves source attribution', function () {
17
+ var merchi = new Merchi();
18
+ var job = new merchi.Job();
19
+ job.fromJson({
20
+ id: 1,
21
+ sourceChannel: 'google_ads',
22
+ utmSource: 'google',
23
+ utmMedium: 'cpc',
24
+ utmCampaign: 'wristbands',
25
+ sourceClickId: 'EAIa',
26
+ });
27
+ expect(job.toJson()).toMatchObject({
28
+ sourceChannel: 'google_ads',
29
+ utmSource: 'google',
30
+ utmMedium: 'cpc',
31
+ utmCampaign: 'wristbands',
32
+ sourceClickId: 'EAIa',
33
+ });
34
+ });
10
35
  test('Job deadline serialised to milliseconds in form data', function () {
11
36
  var merchi = new Merchi();
12
37
  var job = new merchi.Job();
package/dist/entity.js CHANGED
@@ -688,6 +688,12 @@ var Entity = /** @class */ (function () {
688
688
  if (options.isDraft !== undefined) {
689
689
  fetchOptions.query.push(['is_draft', options.isDraft.toString()]);
690
690
  }
691
+ if (options.isTest !== undefined) {
692
+ fetchOptions.query.push(['is_test', options.isTest.toString()]);
693
+ }
694
+ if (options.sourceChannel !== undefined) {
695
+ fetchOptions.query.push(['source_channel', options.sourceChannel.toString()]);
696
+ }
691
697
  if (options.managedOnly !== undefined) {
692
698
  fetchOptions.query.push(['managed_only',
693
699
  options.managedOnly.toString()]);
package/dist/request.js CHANGED
@@ -26,17 +26,25 @@ var __values = (this && this.__values) || function(o) {
26
26
  };
27
27
  // eslint-disable-next-line no-unused-vars
28
28
  import { getErrorFromCode } from './constants/errors.js';
29
+ function resolveApiErrorMessage(err) {
30
+ if (err && typeof err === 'object' && typeof err.message === 'string' && err.message) {
31
+ return err.message;
32
+ }
33
+ if (typeof err === 'string' && err) {
34
+ return err;
35
+ }
36
+ return 'No error message';
37
+ }
29
38
  var ApiError = /** @class */ (function (_super) {
30
39
  __extends(ApiError, _super);
31
40
  function ApiError(err) {
32
41
  var _this = this;
33
- var message = JSON.stringify(err);
42
+ var message = resolveApiErrorMessage(err);
34
43
  /* istanbul ignore next */
35
44
  _this = _super.call(this, message) || this;
36
45
  _this.statusCode = err.statusCode;
37
46
  _this.errorCode = getErrorFromCode(err.errorCode);
38
- _this.errorMessage = err.message ?
39
- err.message : 'No error message';
47
+ _this.errorMessage = message;
40
48
  _this.details = err.details;
41
49
  _this.name = 'ApiError';
42
50
  _this.original = err;
@@ -1,4 +1,4 @@
1
- import { apiFetch } from './request.js';
1
+ import { apiFetch, ApiError } from './request.js';
2
2
  import { ErrorType } from './constants/errors.js';
3
3
  import { setup, mockFetch } from './test_util.js';
4
4
  setup();
@@ -28,11 +28,30 @@ test('will get default errorCode', function () {
28
28
  mockFetch(false, { 'statusCode': 404,
29
29
  'errorCode': -1,
30
30
  'message': 'just a test' }, 404);
31
- apiFetch('https://api.merchi.co/', '/test').catch(function (e) {
31
+ return apiFetch('https://api.merchi.co/', '/test').catch(function (e) {
32
32
  expect(e.statusCode).toBe(404);
33
33
  expect(e.name).toBe('ApiError');
34
34
  expect(e.errorCode).toBe(ErrorType.UNKNOWN_ERROR);
35
35
  expect(e.errorMessage).toBe('just a test');
36
+ expect(e.message).toBe('just a test');
37
+ });
38
+ });
39
+ test('ApiError keeps plain string messages', function () {
40
+ var e = new ApiError('empty response');
41
+ expect(e.message).toBe('empty response');
42
+ expect(e.errorMessage).toBe('empty response');
43
+ });
44
+ test('ApiError.message is the human-readable text, not serialized JSON', function () {
45
+ mockFetch(false, {
46
+ 'statusCode': 403,
47
+ 'errorCode': ErrorType.UNKNOWN_ERROR,
48
+ 'message': 'cannot set referrer',
49
+ }, 403);
50
+ return apiFetch('https://api.merchi.co/', '/test').catch(function (e) {
51
+ expect(e.message).toBe('cannot set referrer');
52
+ expect(e.errorMessage).toBe('cannot set referrer');
53
+ expect(e.message).not.toContain('errorCode');
54
+ expect(e.message).not.toContain('statusCode');
36
55
  });
37
56
  });
38
57
  test('ApiError exposes details when the server supplies them', function () {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@merchi/sdk",
3
- "version": "1.40.2",
3
+ "version": "1.42.1",
4
4
  "main": "dist/index.js",
5
5
  "type": "module",
6
6
  "repository": {
@@ -55,3 +55,26 @@ test('preserves server payment engine hint', () => {
55
55
  entity.fromJson({ id: 1, stripePaymentEngine: 'wallet' });
56
56
  expect(entity.toJson()).toMatchObject({ stripePaymentEngine: 'wallet' });
57
57
  });
58
+
59
+ test('preserves isTest', () => {
60
+ const merchi = new Merchi();
61
+ const entity = new merchi.Cart();
62
+ entity.fromJson({ id: 1, isTest: true });
63
+ expect(entity.toJson()).toMatchObject({ isTest: true });
64
+ });
65
+
66
+ test('preserves source attribution', () => {
67
+ const merchi = new Merchi();
68
+ const entity = new merchi.Cart();
69
+ entity.fromJson({
70
+ id: 1,
71
+ sourceChannel: 'meta',
72
+ utmSource: 'facebook',
73
+ sourceClickId: 'IwAR',
74
+ });
75
+ expect(entity.toJson()).toMatchObject({
76
+ sourceChannel: 'meta',
77
+ utmSource: 'facebook',
78
+ sourceClickId: 'IwAR',
79
+ });
80
+ });
@@ -64,6 +64,36 @@ export class Cart extends Entity {
64
64
  @Cart.property()
65
65
  public sendWhatsapp?: boolean;
66
66
 
67
+ @Cart.property()
68
+ public isTest?: boolean;
69
+
70
+ @Cart.property({type: String})
71
+ public sourceChannel?: string | null;
72
+
73
+ @Cart.property({type: String})
74
+ public utmSource?: string | null;
75
+
76
+ @Cart.property({type: String})
77
+ public utmMedium?: string | null;
78
+
79
+ @Cart.property({type: String})
80
+ public utmCampaign?: string | null;
81
+
82
+ @Cart.property({type: String})
83
+ public utmContent?: string | null;
84
+
85
+ @Cart.property({type: String})
86
+ public utmTerm?: string | null;
87
+
88
+ @Cart.property({type: String})
89
+ public sourceClickId?: string | null;
90
+
91
+ @Cart.property({type: String})
92
+ public sourceLanding?: string | null;
93
+
94
+ @Cart.property({type: String})
95
+ public sourceReferrer?: string | null;
96
+
67
97
  @Cart.property({type: 'User'})
68
98
  public client?: User | null;
69
99
 
@@ -34,6 +34,20 @@ test('can create domain on server', () => {
34
34
  expect(sentToServer).toEqual(data);
35
35
  });
36
36
 
37
+ test('serialises apiAllowedOrigins JSON for form data', () => {
38
+ const merchi = new Merchi();
39
+ const domain = new merchi.Domain();
40
+ domain.id = 7;
41
+ domain.apiAllowedOrigins = ['https://shop.example.com', 'https://preview.example.com'];
42
+ const entries = Array.from((domain.toFormData() as any).entries()) as
43
+ Array<[string, string]>;
44
+ const data = Object.fromEntries(entries);
45
+ expect(data.apiAllowedOrigins).toBe(
46
+ JSON.stringify(['https://shop.example.com', 'https://preview.example.com'])
47
+ );
48
+ expect(data.apiAllowedOrigins).not.toBe('[object Object]');
49
+ });
50
+
37
51
  test('serialises jobAgentPolicy JSON for form data', () => {
38
52
  const merchi = new Merchi();
39
53
  const domain = new merchi.Domain();
@@ -558,6 +558,9 @@ export class Domain extends Entity {
558
558
  @Domain.property({type: String})
559
559
  public apiSecret?: string | null;
560
560
 
561
+ @Domain.property({type: jsonPropertyType})
562
+ public apiAllowedOrigins?: string[] | null;
563
+
561
564
  @Domain.property({type: String})
562
565
  public webflowApiKey?: string | null;
563
566
 
@@ -82,6 +82,9 @@ export class Invoice extends Entity {
82
82
  @Invoice.property({type: Boolean})
83
83
  public unpaid?: boolean | null;
84
84
 
85
+ @Invoice.property({type: Boolean})
86
+ public isTest?: boolean | null;
87
+
85
88
  @Invoice.property()
86
89
  public currency?: string;
87
90
 
@@ -10,6 +10,33 @@ test('can make Job', () => {
10
10
  expect(job).toBeTruthy();
11
11
  });
12
12
 
13
+ test('preserves isTest', () => {
14
+ const merchi = new Merchi();
15
+ const job = new merchi.Job();
16
+ job.fromJson({ id: 1, isTest: true });
17
+ expect(job.toJson()).toMatchObject({ isTest: true });
18
+ });
19
+
20
+ test('preserves source attribution', () => {
21
+ const merchi = new Merchi();
22
+ const job = new merchi.Job();
23
+ job.fromJson({
24
+ id: 1,
25
+ sourceChannel: 'google_ads',
26
+ utmSource: 'google',
27
+ utmMedium: 'cpc',
28
+ utmCampaign: 'wristbands',
29
+ sourceClickId: 'EAIa',
30
+ });
31
+ expect(job.toJson()).toMatchObject({
32
+ sourceChannel: 'google_ads',
33
+ utmSource: 'google',
34
+ utmMedium: 'cpc',
35
+ utmCampaign: 'wristbands',
36
+ sourceClickId: 'EAIa',
37
+ });
38
+ });
39
+
13
40
  test('Job deadline serialised to milliseconds in form data', () => {
14
41
  const merchi = new Merchi();
15
42
  const job = new merchi.Job();
@@ -249,6 +249,33 @@ export class Job extends Entity {
249
249
  @Job.property()
250
250
  public clientOrigin?: string;
251
251
 
252
+ @Job.property({type: String})
253
+ public sourceChannel?: string | null;
254
+
255
+ @Job.property({type: String})
256
+ public utmSource?: string | null;
257
+
258
+ @Job.property({type: String})
259
+ public utmMedium?: string | null;
260
+
261
+ @Job.property({type: String})
262
+ public utmCampaign?: string | null;
263
+
264
+ @Job.property({type: String})
265
+ public utmContent?: string | null;
266
+
267
+ @Job.property({type: String})
268
+ public utmTerm?: string | null;
269
+
270
+ @Job.property({type: String})
271
+ public sourceClickId?: string | null;
272
+
273
+ @Job.property({type: String})
274
+ public sourceLanding?: string | null;
275
+
276
+ @Job.property({type: String})
277
+ public sourceReferrer?: string | null;
278
+
252
279
  @Job.property({type: User})
253
280
  public manager?: User | null;
254
281
 
@@ -354,6 +381,9 @@ export class Job extends Entity {
354
381
  @Job.property()
355
382
  public isNewClient?: boolean;
356
383
 
384
+ @Job.property()
385
+ public isTest?: boolean;
386
+
357
387
  public getQuote = () => {
358
388
  const resource = '/specialised-order-estimate/';
359
389
  const data = this.toFormData({excludeOld: false});
package/src/entity.ts CHANGED
@@ -130,6 +130,8 @@ interface ListOptions {
130
130
  productTypes?: ProductType[];
131
131
  publicOnly?: boolean;
132
132
  isDraft?: boolean;
133
+ isTest?: boolean;
134
+ sourceChannel?: string;
133
135
  q?: string;
134
136
  receiverId?: number;
135
137
  userAsReceiver?: number;
@@ -498,6 +500,12 @@ export class Entity {
498
500
  if (options.isDraft !== undefined) {
499
501
  fetchOptions.query.push(['is_draft', options.isDraft.toString()]);
500
502
  }
503
+ if (options.isTest !== undefined) {
504
+ fetchOptions.query.push(['is_test', options.isTest.toString()]);
505
+ }
506
+ if (options.sourceChannel !== undefined) {
507
+ fetchOptions.query.push(['source_channel', options.sourceChannel.toString()]);
508
+ }
501
509
  if (options.managedOnly !== undefined) {
502
510
  fetchOptions.query.push(['managed_only',
503
511
  options.managedOnly.toString()]);
@@ -1,4 +1,4 @@
1
- import { apiFetch } from './request.js';
1
+ import { apiFetch, ApiError } from './request.js';
2
2
  import { ErrorType } from './constants/errors.js';
3
3
  import { setup, mockFetch } from './test_util.js';
4
4
 
@@ -34,11 +34,32 @@ test('will get default errorCode', () => {
34
34
  {'statusCode': 404,
35
35
  'errorCode': -1,
36
36
  'message': 'just a test'}, 404);
37
- apiFetch('https://api.merchi.co/', '/test').catch(e => {
37
+ return apiFetch('https://api.merchi.co/', '/test').catch(e => {
38
38
  expect(e.statusCode).toBe(404);
39
39
  expect(e.name).toBe('ApiError');
40
40
  expect(e.errorCode).toBe(ErrorType.UNKNOWN_ERROR);
41
41
  expect(e.errorMessage).toBe('just a test');
42
+ expect(e.message).toBe('just a test');
43
+ });
44
+ });
45
+
46
+ test('ApiError keeps plain string messages', () => {
47
+ const e = new ApiError('empty response');
48
+ expect(e.message).toBe('empty response');
49
+ expect(e.errorMessage).toBe('empty response');
50
+ });
51
+
52
+ test('ApiError.message is the human-readable text, not serialized JSON', () => {
53
+ mockFetch(false, {
54
+ 'statusCode': 403,
55
+ 'errorCode': ErrorType.UNKNOWN_ERROR,
56
+ 'message': 'cannot set referrer',
57
+ }, 403);
58
+ return apiFetch('https://api.merchi.co/', '/test').catch(e => {
59
+ expect(e.message).toBe('cannot set referrer');
60
+ expect(e.errorMessage).toBe('cannot set referrer');
61
+ expect(e.message).not.toContain('errorCode');
62
+ expect(e.message).not.toContain('statusCode');
42
63
  });
43
64
  });
44
65
 
package/src/request.ts CHANGED
@@ -38,6 +38,16 @@ export interface ApiErrorDetails {
38
38
  [key: string]: any;
39
39
  }
40
40
 
41
+ function resolveApiErrorMessage(err: any): string {
42
+ if (err && typeof err === 'object' && typeof err.message === 'string' && err.message) {
43
+ return err.message;
44
+ }
45
+ if (typeof err === 'string' && err) {
46
+ return err;
47
+ }
48
+ return 'No error message';
49
+ }
50
+
41
51
  export class ApiError extends Error {
42
52
  public statusCode?: number;
43
53
  public errorCode?: ErrorType;
@@ -52,13 +62,12 @@ export class ApiError extends Error {
52
62
  public details?: ApiErrorDetails;
53
63
  public original: any;
54
64
  public constructor(err: any) {
55
- const message = JSON.stringify(err);
65
+ const message = resolveApiErrorMessage(err);
56
66
  /* istanbul ignore next */
57
67
  super(message);
58
68
  this.statusCode = err.statusCode;
59
69
  this.errorCode = getErrorFromCode(err.errorCode);
60
- this.errorMessage = err.message ?
61
- err.message : 'No error message';
70
+ this.errorMessage = message;
62
71
  this.details = err.details;
63
72
  this.name = 'ApiError';
64
73
  this.original = err;