@labdigital/commercetools-mock 0.9.0 → 0.10.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 (95) hide show
  1. package/README.md +8 -0
  2. package/dist/index.d.ts +18 -17
  3. package/dist/index.global.js +1751 -1664
  4. package/dist/index.global.js.map +1 -1
  5. package/dist/index.js +1773 -1684
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +1966 -1877
  8. package/dist/index.mjs.map +1 -1
  9. package/package.json +28 -20
  10. package/src/constants.ts +4 -2
  11. package/src/ctMock.ts +19 -84
  12. package/src/helpers.ts +9 -10
  13. package/src/index.test.ts +1 -1
  14. package/src/lib/haversine.ts +2 -2
  15. package/src/lib/masking.ts +3 -1
  16. package/src/lib/predicateParser.test.ts +16 -0
  17. package/src/lib/predicateParser.ts +94 -86
  18. package/src/lib/projectionSearchFilter.test.ts +28 -36
  19. package/src/lib/projectionSearchFilter.ts +86 -102
  20. package/src/oauth/store.ts +3 -3
  21. package/src/priceSelector.test.ts +18 -35
  22. package/src/priceSelector.ts +6 -9
  23. package/src/product-projection-search.ts +51 -57
  24. package/src/repositories/abstract.ts +85 -41
  25. package/src/repositories/cart-discount.ts +1 -1
  26. package/src/repositories/cart.ts +36 -31
  27. package/src/repositories/category.ts +17 -19
  28. package/src/repositories/channel.ts +1 -1
  29. package/src/repositories/custom-object.ts +35 -22
  30. package/src/repositories/customer-group.ts +1 -1
  31. package/src/repositories/customer.ts +39 -1
  32. package/src/repositories/discount-code.ts +1 -1
  33. package/src/repositories/errors.ts +9 -11
  34. package/src/repositories/extension.ts +13 -11
  35. package/src/repositories/helpers.ts +8 -13
  36. package/src/repositories/index.ts +59 -0
  37. package/src/repositories/inventory-entry.ts +1 -1
  38. package/src/repositories/order.ts +6 -6
  39. package/src/repositories/payment.ts +3 -3
  40. package/src/repositories/product-discount.ts +1 -1
  41. package/src/repositories/product-projection.ts +1 -0
  42. package/src/repositories/product-type.ts +29 -34
  43. package/src/repositories/product.ts +124 -80
  44. package/src/repositories/project.ts +10 -27
  45. package/src/repositories/shipping-method.ts +15 -17
  46. package/src/repositories/shopping-list.ts +2 -2
  47. package/src/repositories/state.ts +9 -9
  48. package/src/repositories/store.ts +2 -2
  49. package/src/repositories/subscription.ts +1 -1
  50. package/src/repositories/tax-category.ts +4 -4
  51. package/src/repositories/type.ts +12 -14
  52. package/src/repositories/zone.ts +5 -6
  53. package/src/server.ts +5 -0
  54. package/src/services/abstract.ts +44 -11
  55. package/src/services/cart-discount.ts +2 -3
  56. package/src/services/cart.test.ts +8 -10
  57. package/src/services/cart.ts +8 -11
  58. package/src/services/category.test.ts +1 -2
  59. package/src/services/category.ts +2 -3
  60. package/src/services/channel.ts +2 -3
  61. package/src/services/custom-object.test.ts +5 -5
  62. package/src/services/custom-object.ts +2 -3
  63. package/src/services/customer-group.ts +2 -3
  64. package/src/services/customer.test.ts +136 -0
  65. package/src/services/customer.ts +2 -3
  66. package/src/services/discount-code.ts +2 -3
  67. package/src/services/extension.ts +2 -3
  68. package/src/services/index.ts +74 -0
  69. package/src/services/inventory-entry.test.ts +8 -12
  70. package/src/services/inventory-entry.ts +2 -3
  71. package/src/services/my-cart.ts +3 -4
  72. package/src/services/my-customer.ts +2 -3
  73. package/src/services/my-order.ts +3 -4
  74. package/src/services/my-payment.ts +2 -3
  75. package/src/services/order.test.ts +4 -6
  76. package/src/services/order.ts +2 -3
  77. package/src/services/payment.ts +2 -3
  78. package/src/services/product-discount.ts +2 -3
  79. package/src/services/product-projection.test.ts +76 -8
  80. package/src/services/product-projection.ts +2 -3
  81. package/src/services/product-type.ts +2 -3
  82. package/src/services/product.test.ts +199 -89
  83. package/src/services/product.ts +2 -3
  84. package/src/services/project.ts +3 -3
  85. package/src/services/shipping-method.ts +2 -3
  86. package/src/services/shopping-list.ts +2 -3
  87. package/src/services/state.ts +2 -3
  88. package/src/services/store.test.ts +11 -2
  89. package/src/services/store.ts +2 -3
  90. package/src/services/subscription.ts +2 -3
  91. package/src/services/tax-category.ts +2 -3
  92. package/src/services/type.ts +2 -3
  93. package/src/services/zone.ts +2 -3
  94. package/src/storage.ts +23 -30
  95. package/src/types.ts +46 -6
package/dist/index.mjs CHANGED
@@ -37,8 +37,8 @@ var haversineDistance = (src, dst) => {
37
37
  const toRadian = (deg) => deg * (Math.PI / 180);
38
38
  const dLat = toRadian(dst.latitude - src.latitude);
39
39
  const dLon = toRadian(dst.longitude - src.longitude);
40
- var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(toRadian(src.latitude)) * Math.cos(toRadian(dst.latitude)) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
41
- var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
40
+ const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(toRadian(src.latitude)) * Math.cos(toRadian(dst.latitude)) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
41
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
42
42
  return RADIUS_OF_EARTH_IN_KM * c * 1e3;
43
43
  };
44
44
 
@@ -51,9 +51,7 @@ var PredicateError = class {
51
51
  var parseQueryExpression = (predicate) => {
52
52
  if (Array.isArray(predicate)) {
53
53
  const callbacks = predicate.map((item) => generateMatchFunc(item));
54
- return (target, variables) => {
55
- return callbacks.every((callback) => callback(target, variables));
56
- };
54
+ return (target, variables) => callbacks.every((callback) => callback(target, variables));
57
55
  } else {
58
56
  return generateMatchFunc(predicate);
59
57
  }
@@ -93,60 +91,66 @@ var resolveValue = (obj, val) => {
93
91
  }
94
92
  return obj[val.value];
95
93
  };
96
- var getLexer = (value) => {
97
- return new perplex(value).token("AND", /and(?![-_a-z0-9]+)/i).token("OR", /or(?![-_a-z0-9]+)/i).token("NOT", /not(?![-_a-z0-9]+)/i).token("WITHIN", /within(?![-_a-z0-9]+)/i).token("IN", /in(?![-_a-z0-9]+)/i).token("MATCHES_IGNORE_CASE", /matches\s+ignore\s+case(?![-_a-z0-9]+)/i).token("CONTAINS", /contains(?![-_a-z0-9]+)/i).token("ALL", /all(?![-_a-z0-9]+)/i).token("ANY", /any(?![-_a-z0-9]+)/i).token("EMPTY", /empty(?![-_a-z0-9]+)/i).token("IS", /is(?![-_a-z0-9]+)/i).token("DEFINED", /defined(?![-_a-z0-9]+)/i).token("FLOAT", /\d+\.\d+/).token("INT", /\d+/).token("VARIABLE", /:([-_A-Za-z0-9]+)/).token("IDENTIFIER", /[-_A-Za-z0-9]+/).token("STRING", /"((?:\\.|[^"\\])*)"/).token("STRING", /'((?:\\.|[^'\\])*)'/).token("COMMA", ",").token("(", "(").token(")", ")").token(">=", ">=").token("<=", "<=").token(">", ">").token("<", "<").token("!=", "!=").token("=", "=").token('"', '"').token("WS", /\s+/, true);
98
- };
94
+ var getLexer = (value) => new perplex(value).token("AND", /and(?![-_a-z0-9]+)/i).token("OR", /or(?![-_a-z0-9]+)/i).token("NOT", /not(?![-_a-z0-9]+)/i).token("WITHIN", /within(?![-_a-z0-9]+)/i).token("IN", /in(?![-_a-z0-9]+)/i).token("MATCHES_IGNORE_CASE", /matches\s+ignore\s+case(?![-_a-z0-9]+)/i).token("CONTAINS", /contains(?![-_a-z0-9]+)/i).token("ALL", /all(?![-_a-z0-9]+)/i).token("ANY", /any(?![-_a-z0-9]+)/i).token("EMPTY", /empty(?![-_a-z0-9]+)/i).token("IS", /is(?![-_a-z0-9]+)/i).token("DEFINED", /defined(?![-_a-z0-9]+)/i).token("FLOAT", /\d+\.\d+/).token("INT", /\d+/).token("VARIABLE", /:([-_A-Za-z0-9]+)/).token("BOOLEAN", /(true|false)/).token("IDENTIFIER", /[-_A-Za-z0-9]+/).token("STRING", /"((?:\\.|[^"\\])*)"/).token("STRING", /'((?:\\.|[^'\\])*)'/).token("COMMA", ",").token("(", "(").token(")", ")").token(">=", ">=").token("<=", "<=").token(">", ">").token("<", "<").token("!=", "!=").token("=", "=").token('"', '"').token("WS", /\s+/, true);
99
95
  var generateMatchFunc = (predicate) => {
100
96
  const lexer = getLexer(predicate);
101
- const parser = new Parser(lexer).builder().nud("IDENTIFIER", 100, (t) => {
102
- return {
97
+ const parser = new Parser(lexer).builder().nud(
98
+ "IDENTIFIER",
99
+ 100,
100
+ (t) => ({
103
101
  type: "identifier",
104
102
  value: t.token.match,
105
103
  pos: t.token.strpos()
106
- };
107
- }).nud("VARIABLE", 100, (t) => {
108
- return {
104
+ })
105
+ ).nud(
106
+ "BOOLEAN",
107
+ 1,
108
+ (t) => ({
109
+ type: "boolean",
110
+ value: t.token.match === "true" ? true : false,
111
+ pos: t.token.strpos()
112
+ })
113
+ ).nud(
114
+ "VARIABLE",
115
+ 100,
116
+ (t) => ({
109
117
  type: "var",
110
118
  value: t.token.groups[1],
111
119
  pos: t.token.strpos()
112
- };
113
- }).nud("STRING", 100, (t) => {
114
- return {
120
+ })
121
+ ).nud(
122
+ "STRING",
123
+ 100,
124
+ (t) => ({
115
125
  type: "string",
116
126
  value: t.token.groups[1],
117
127
  pos: t.token.strpos()
118
- };
119
- }).nud("INT", 1, (t) => {
120
- return {
128
+ })
129
+ ).nud(
130
+ "INT",
131
+ 1,
132
+ (t) => ({
121
133
  type: "int",
122
134
  value: parseInt(t.token.match, 10),
123
135
  pos: t.token.strpos()
124
- };
125
- }).nud("FLOAT", 1, (t) => {
126
- return {
136
+ })
137
+ ).nud(
138
+ "FLOAT",
139
+ 1,
140
+ (t) => ({
127
141
  type: "float",
128
142
  value: parseFloat(t.token.match),
129
143
  pos: t.token.strpos()
130
- };
131
- }).nud("NOT", 100, ({ bp }) => {
144
+ })
145
+ ).nud("NOT", 100, ({ bp }) => {
132
146
  const expr = parser.parse({ terminals: [bp - 1] });
133
- return (obj) => {
134
- return !expr(obj);
135
- };
136
- }).nud("EMPTY", 10, ({ bp }) => {
137
- return "empty";
138
- }).nud("DEFINED", 10, ({ bp }) => {
139
- return "defined";
140
- }).led("AND", 5, ({ left, bp }) => {
147
+ return (obj) => !expr(obj);
148
+ }).nud("EMPTY", 10, ({ bp }) => "empty").nud("DEFINED", 10, ({ bp }) => "defined").led("AND", 5, ({ left, bp }) => {
141
149
  const expr = parser.parse({ terminals: [bp - 1] });
142
- return (obj) => {
143
- return left(obj) && expr(obj);
144
- };
150
+ return (obj) => left(obj) && expr(obj);
145
151
  }).led("OR", 5, ({ left, token, bp }) => {
146
152
  const expr = parser.parse({ terminals: [bp - 1] });
147
- return (obj, vars) => {
148
- return left(obj, vars) || expr(obj, vars);
149
- };
153
+ return (obj, vars) => left(obj, vars) || expr(obj, vars);
150
154
  }).led("COMMA", 1, ({ left, token, bp }) => {
151
155
  const expr = parser.parse({ terminals: [bp - 1] });
152
156
  if (Array.isArray(expr)) {
@@ -181,33 +185,23 @@ var generateMatchFunc = (predicate) => {
181
185
  }).led("!=", 20, ({ left, bp }) => {
182
186
  const expr = parser.parse({ terminals: [bp - 1] });
183
187
  validateSymbol(expr);
184
- return (obj, vars) => {
185
- return resolveValue(obj, left) !== resolveSymbol(expr, vars);
186
- };
188
+ return (obj, vars) => resolveValue(obj, left) !== resolveSymbol(expr, vars);
187
189
  }).led(">", 20, ({ left, bp }) => {
188
190
  const expr = parser.parse({ terminals: [bp - 1] });
189
191
  validateSymbol(expr);
190
- return (obj, vars) => {
191
- return resolveValue(obj, left) > resolveSymbol(expr, vars);
192
- };
192
+ return (obj, vars) => resolveValue(obj, left) > resolveSymbol(expr, vars);
193
193
  }).led(">=", 20, ({ left, bp }) => {
194
194
  const expr = parser.parse({ terminals: [bp - 1] });
195
195
  validateSymbol(expr);
196
- return (obj, vars) => {
197
- return resolveValue(obj, left) >= resolveSymbol(expr, vars);
198
- };
196
+ return (obj, vars) => resolveValue(obj, left) >= resolveSymbol(expr, vars);
199
197
  }).led("<", 20, ({ left, bp }) => {
200
198
  const expr = parser.parse({ terminals: [bp - 1] });
201
199
  validateSymbol(expr);
202
- return (obj, vars) => {
203
- return resolveValue(obj, left) < resolveSymbol(expr, vars);
204
- };
200
+ return (obj, vars) => resolveValue(obj, left) < resolveSymbol(expr, vars);
205
201
  }).led("<=", 20, ({ left, bp }) => {
206
202
  const expr = parser.parse({ terminals: [bp - 1] });
207
203
  validateSymbol(expr);
208
- return (obj, vars) => {
209
- return resolveValue(obj, left) <= resolveSymbol(expr, vars);
210
- };
204
+ return (obj, vars) => resolveValue(obj, left) <= resolveSymbol(expr, vars);
211
205
  }).led("IS", 20, ({ left, bp }) => {
212
206
  let invert = false;
213
207
  const next = lexer.peek();
@@ -339,6 +333,40 @@ var CommercetoolsError = class extends Error {
339
333
  }
340
334
  };
341
335
 
336
+ // src/helpers.ts
337
+ import { v4 as uuidv4 } from "uuid";
338
+ var getBaseResourceProperties = () => ({
339
+ id: uuidv4(),
340
+ createdAt: new Date().toISOString(),
341
+ lastModifiedAt: new Date().toISOString(),
342
+ version: 0
343
+ });
344
+ var nestedLookup = (obj, path) => {
345
+ if (!path || path === "") {
346
+ return obj;
347
+ }
348
+ const parts = path.split(".");
349
+ let val = obj;
350
+ for (let i = 0; i < parts.length; i++) {
351
+ const part = parts[i];
352
+ if (val == void 0) {
353
+ return void 0;
354
+ }
355
+ val = val[part];
356
+ }
357
+ return val;
358
+ };
359
+ var QueryParamsAsArray = (input) => {
360
+ if (input == void 0) {
361
+ return [];
362
+ }
363
+ if (Array.isArray(input)) {
364
+ return input;
365
+ }
366
+ return [input];
367
+ };
368
+ var cloneObject = (o) => JSON.parse(JSON.stringify(o));
369
+
342
370
  // src/storage.ts
343
371
  var AbstractStorage = class {
344
372
  };
@@ -381,13 +409,11 @@ var InMemoryStorage = class extends AbstractStorage {
381
409
  this.projects[project.key] = project;
382
410
  return project;
383
411
  };
384
- this.getProject = (projectKey) => {
385
- return this.addProject(projectKey);
386
- };
412
+ this.getProject = (projectKey) => this.addProject(projectKey);
387
413
  this.expand = (projectKey, obj, clause) => {
388
414
  if (!clause)
389
415
  return obj;
390
- const newObj = JSON.parse(JSON.stringify(obj));
416
+ const newObj = cloneObject(obj);
391
417
  if (Array.isArray(clause)) {
392
418
  clause.forEach((c) => {
393
419
  this._resolveResource(projectKey, newObj, c);
@@ -465,12 +491,10 @@ var InMemoryStorage = class extends AbstractStorage {
465
491
  }
466
492
  }
467
493
  }
468
- assertStorage(typeId) {
469
- }
470
494
  all(projectKey, typeId) {
471
495
  const store = this.forProjectKey(projectKey)[typeId];
472
496
  if (store) {
473
- return Array.from(store.values());
497
+ return Array.from(store.values()).map(cloneObject);
474
498
  }
475
499
  return [];
476
500
  }
@@ -480,13 +504,14 @@ var InMemoryStorage = class extends AbstractStorage {
480
504
  (_a = store[typeId]) == null ? void 0 : _a.set(obj.id, obj);
481
505
  const resource = this.get(projectKey, typeId, obj.id, params);
482
506
  assert(resource, `resource of type ${typeId} with id ${obj.id} not created`);
483
- return resource;
507
+ return cloneObject(resource);
484
508
  }
485
509
  get(projectKey, typeId, id, params = {}) {
486
510
  var _a;
487
511
  const resource = (_a = this.forProjectKey(projectKey)[typeId]) == null ? void 0 : _a.get(id);
488
512
  if (resource) {
489
- return this.expand(projectKey, resource, params.expand);
513
+ const clone = cloneObject(resource);
514
+ return this.expand(projectKey, clone, params.expand);
490
515
  }
491
516
  return null;
492
517
  }
@@ -499,7 +524,8 @@ var InMemoryStorage = class extends AbstractStorage {
499
524
  const resources = Array.from(resourceStore.values());
500
525
  const resource = resources.find((e) => e.key === key);
501
526
  if (resource) {
502
- return this.expand(projectKey, resource, params.expand);
527
+ const clone = cloneObject(resource);
528
+ return this.expand(projectKey, clone, params.expand);
503
529
  }
504
530
  return null;
505
531
  }
@@ -537,24 +563,20 @@ var InMemoryStorage = class extends AbstractStorage {
537
563
  const limit = params.limit || 20;
538
564
  resources = resources.slice(offset, offset + limit);
539
565
  if (params.expand !== void 0) {
540
- resources = resources.map((resource) => {
541
- return this.expand(projectKey, resource, params.expand);
542
- });
566
+ resources = resources.map(
567
+ (resource) => this.expand(projectKey, resource, params.expand)
568
+ );
543
569
  }
544
570
  return {
545
571
  count: totalResources,
546
572
  total: resources.length,
547
573
  offset,
548
574
  limit,
549
- results: resources
575
+ results: resources.map(cloneObject)
550
576
  };
551
577
  }
552
578
  search(projectKey, typeId, params) {
553
- const store = this.forProjectKey(projectKey)[typeId];
554
- if (!store) {
555
- throw new Error("No type");
556
- }
557
- let resources = Array.from(store.values());
579
+ let resources = this.all(projectKey, typeId);
558
580
  if (params.where) {
559
581
  try {
560
582
  const filterFunc = parseQueryExpression(params.where);
@@ -574,9 +596,9 @@ var InMemoryStorage = class extends AbstractStorage {
574
596
  const limit = params.limit || 20;
575
597
  resources = resources.slice(offset, offset + limit);
576
598
  if (params.expand !== void 0) {
577
- resources = resources.map((resource) => {
578
- return this.expand(projectKey, resource, params.expand);
579
- });
599
+ resources = resources.map(
600
+ (resource) => this.expand(projectKey, resource, params.expand)
601
+ );
580
602
  }
581
603
  return {
582
604
  count: totalResources,
@@ -777,41 +799,6 @@ var OAuth2Server = class {
777
799
  }
778
800
  };
779
801
 
780
- // src/helpers.ts
781
- import { v4 as uuidv4 } from "uuid";
782
- var getBaseResourceProperties = () => {
783
- return {
784
- id: uuidv4(),
785
- createdAt: new Date().toISOString(),
786
- lastModifiedAt: new Date().toISOString(),
787
- version: 0
788
- };
789
- };
790
- var nestedLookup = (obj, path) => {
791
- if (!path || path === "") {
792
- return obj;
793
- }
794
- const parts = path.split(".");
795
- let val = obj;
796
- for (let i = 0; i < parts.length; i++) {
797
- const part = parts[i];
798
- if (val == void 0) {
799
- return void 0;
800
- }
801
- val = val[part];
802
- }
803
- return val;
804
- };
805
- var QueryParamsAsArray = (input) => {
806
- if (input == void 0) {
807
- return [];
808
- }
809
- if (Array.isArray(input)) {
810
- return input;
811
- }
812
- return [input];
813
- };
814
-
815
802
  // src/projectAPI.ts
816
803
  var ProjectAPI = class {
817
804
  constructor(projectKey, services, storage) {
@@ -863,9 +850,6 @@ var copyHeaders = (headers) => {
863
850
  var DEFAULT_API_HOSTNAME = /^https:\/\/api\..*?\.commercetools.com:443$/;
864
851
  var DEFAULT_AUTH_HOSTNAME = /^https:\/\/auth\..*?\.commercetools.com:443$/;
865
852
 
866
- // src/services/abstract.ts
867
- import { Router } from "express";
868
-
869
853
  // src/repositories/helpers.ts
870
854
  import { v4 as uuidv42 } from "uuid";
871
855
  var createAddress = (base, projectKey, storage) => {
@@ -904,12 +888,10 @@ var createCustomFields = (draft, projectKey, storage) => {
904
888
  fields: draft.fields
905
889
  };
906
890
  };
907
- var createPrice = (draft) => {
908
- return {
909
- id: uuidv42(),
910
- value: createTypedMoney(draft.value)
911
- };
912
- };
891
+ var createPrice = (draft) => ({
892
+ id: uuidv42(),
893
+ value: createTypedMoney(draft.value)
894
+ });
913
895
  var createTypedMoney = (value) => {
914
896
  let fractionDigits = 2;
915
897
  switch (value.currencyCode.toUpperCase()) {
@@ -991,143 +973,58 @@ var getReferenceFromResourceIdentifier = (resourceIdentifier, projectKey, storag
991
973
  id: resource == null ? void 0 : resource.id
992
974
  };
993
975
  };
994
- var getRepositoryContext = (request) => {
995
- return {
996
- projectKey: request.params.projectKey,
997
- storeKey: request.params.storeKey
998
- };
999
- };
976
+ var getRepositoryContext = (request) => ({
977
+ projectKey: request.params.projectKey,
978
+ storeKey: request.params.storeKey
979
+ });
1000
980
 
1001
- // src/services/abstract.ts
1002
- var AbstractService = class {
1003
- constructor(parent) {
1004
- this.createStatusCode = 201;
981
+ // src/services/project.ts
982
+ var ProjectService = class {
983
+ constructor(parent, repository) {
984
+ this.repository = repository;
1005
985
  this.registerRoutes(parent);
1006
986
  }
1007
- extraRoutes(router) {
1008
- }
1009
987
  registerRoutes(parent) {
1010
- const basePath = this.getBasePath();
1011
- const router = Router({ mergeParams: true });
1012
- this.extraRoutes(router);
1013
- router.get("/", this.get.bind(this));
1014
- router.get("/key=:key", this.getWithKey.bind(this));
1015
- router.get("/:id", this.getWithId.bind(this));
1016
- router.delete("/key=:key", this.deletewithKey.bind(this));
1017
- router.delete("/:id", this.deletewithId.bind(this));
1018
- router.post("/", this.post.bind(this));
1019
- router.post("/key=:key", this.postWithKey.bind(this));
1020
- router.post("/:id", this.postWithId.bind(this));
1021
- parent.use(`/${basePath}`, router);
988
+ parent.get("", this.get.bind(this));
989
+ parent.post("", this.post.bind(this));
1022
990
  }
1023
991
  get(request, response) {
1024
- const limit = this._parseParam(request.query.limit);
1025
- const offset = this._parseParam(request.query.offset);
1026
- const result = this.repository.query(getRepositoryContext(request), {
1027
- expand: this._parseParam(request.query.expand),
1028
- where: this._parseParam(request.query.where),
1029
- limit: limit !== void 0 ? Number(limit) : void 0,
1030
- offset: offset !== void 0 ? Number(offset) : void 0
1031
- });
1032
- return response.status(200).send(result);
1033
- }
1034
- getWithId(request, response) {
1035
- const result = this._expandWithId(request, request.params["id"]);
1036
- if (!result) {
1037
- return response.status(404).send();
1038
- }
1039
- return response.status(200).send(result);
1040
- }
1041
- getWithKey(request, response) {
1042
- const result = this.repository.getByKey(
1043
- getRepositoryContext(request),
1044
- request.params["key"],
1045
- { expand: this._parseParam(request.query.expand) }
1046
- );
1047
- if (!result)
1048
- return response.status(404).send();
1049
- return response.status(200).send(result);
1050
- }
1051
- deletewithId(request, response) {
1052
- const result = this.repository.delete(
1053
- getRepositoryContext(request),
1054
- request.params["id"],
1055
- {
1056
- expand: this._parseParam(request.query.expand)
1057
- }
1058
- );
1059
- if (!result) {
1060
- return response.status(404).send("Not found");
1061
- }
1062
- return response.status(200).send(result);
1063
- }
1064
- deletewithKey(request, response) {
1065
- return response.status(500).send("Not implemented");
992
+ const project = this.repository.get(getRepositoryContext(request));
993
+ return response.status(200).send(project);
1066
994
  }
1067
995
  post(request, response) {
1068
- const draft = request.body;
1069
- const resource = this.repository.create(
1070
- getRepositoryContext(request),
1071
- draft
1072
- );
1073
- const result = this._expandWithId(request, resource.id);
1074
- return response.status(this.createStatusCode).send(result);
1075
- }
1076
- postWithId(request, response) {
1077
996
  const updateRequest = request.body;
1078
- const resource = this.repository.get(
1079
- getRepositoryContext(request),
1080
- request.params["id"]
1081
- );
1082
- if (!resource) {
1083
- return response.status(404).send("Not found");
1084
- }
1085
- if (resource.version !== updateRequest.version) {
1086
- return response.status(409).send("Concurrent modification");
997
+ const project = this.repository.get(getRepositoryContext(request));
998
+ if (!project) {
999
+ return response.status(404).send({});
1087
1000
  }
1088
- const updatedResource = this.repository.processUpdateActions(
1001
+ this.repository.processUpdateActions(
1089
1002
  getRepositoryContext(request),
1090
- resource,
1003
+ project,
1004
+ updateRequest.version,
1091
1005
  updateRequest.actions
1092
1006
  );
1093
- const result = this._expandWithId(request, updatedResource.id);
1094
- return response.status(200).send(result);
1095
- }
1096
- postWithKey(request, response) {
1097
- return response.status(500).send("Not implemented");
1098
- }
1099
- _expandWithId(request, resourceId) {
1100
- const result = this.repository.get(
1101
- getRepositoryContext(request),
1102
- resourceId,
1103
- {
1104
- expand: this._parseParam(request.query.expand)
1105
- }
1106
- );
1107
- return result;
1108
- }
1109
- _parseParam(value) {
1110
- if (Array.isArray(value)) {
1111
- return value;
1112
- } else if (value !== void 0) {
1113
- return [`${value}`];
1114
- }
1115
- return void 0;
1007
+ return response.status(200).send({});
1116
1008
  }
1117
1009
  };
1118
1010
 
1011
+ // src/repositories/cart.ts
1012
+ import { v4 as uuidv43 } from "uuid";
1013
+
1119
1014
  // src/repositories/abstract.ts
1120
1015
  import deepEqual from "deep-equal";
1121
1016
 
1122
1017
  // src/repositories/errors.ts
1123
- var checkConcurrentModification = (resource, expectedVersion) => {
1124
- if (resource.version === expectedVersion)
1018
+ var checkConcurrentModification = (currentVersion, expectedVersion, identifier) => {
1019
+ if (currentVersion === expectedVersion)
1125
1020
  return;
1126
- const identifier = resource.id ? resource.id : resource.key;
1021
+ console.error(
1022
+ `Object ${identifier} has a different version than expected. Expected: ${expectedVersion} - Actual: ${currentVersion}.`
1023
+ );
1127
1024
  throw new CommercetoolsError(
1128
1025
  {
1129
- message: `Object ${identifier} has a different version than expected. Expected: ${expectedVersion} - Actual: ${resource.version}.`,
1130
- currentVersion: resource.version,
1026
+ message: `Object ${identifier} has a different version than expected. Expected: ${expectedVersion} - Actual: ${currentVersion}.`,
1027
+ currentVersion,
1131
1028
  code: "ConcurrentModification"
1132
1029
  },
1133
1030
  409
@@ -1140,20 +1037,28 @@ var AbstractRepository = class {
1140
1037
  this.actions = {};
1141
1038
  this._storage = storage;
1142
1039
  }
1143
- processUpdateActions(context, resource, actions) {
1144
- const modifiedResource = JSON.parse(JSON.stringify(resource));
1040
+ processUpdateActions(context, resource, version, actions) {
1041
+ const updatedResource = cloneObject(resource);
1042
+ const identifier = resource.id ? resource.id : resource.key;
1145
1043
  actions.forEach((action) => {
1146
1044
  const updateFunc = this.actions[action.action];
1147
1045
  if (!updateFunc) {
1148
1046
  console.error(`No mock implemented for update action ${action.action}`);
1149
- return;
1047
+ throw new Error(
1048
+ `No mock implemented for update action ${action.action}`
1049
+ );
1050
+ }
1051
+ const beforeUpdate = cloneObject(resource);
1052
+ updateFunc(context, updatedResource, action);
1053
+ if (!deepEqual(beforeUpdate, updatedResource)) {
1054
+ checkConcurrentModification(resource.version, version, identifier);
1055
+ updatedResource.version += 1;
1150
1056
  }
1151
- updateFunc(context, modifiedResource, action);
1152
1057
  });
1153
- if (!deepEqual(modifiedResource, resource)) {
1154
- this.save(context, modifiedResource);
1058
+ if (resource.version != updatedResource.version) {
1059
+ this.saveUpdate(context, version, updatedResource);
1155
1060
  }
1156
- const result = this.postProcessResource(modifiedResource);
1061
+ const result = this.postProcessResource(updatedResource);
1157
1062
  if (!result) {
1158
1063
  throw new Error("invalid post process action");
1159
1064
  }
@@ -1166,7 +1071,6 @@ var AbstractRepository = class {
1166
1071
  var AbstractResourceRepository = class extends AbstractRepository {
1167
1072
  constructor(storage) {
1168
1073
  super(storage);
1169
- this._storage.assertStorage(this.getTypeId());
1170
1074
  }
1171
1075
  query(context, params = {}) {
1172
1076
  const result = this._storage.query(context.projectKey, this.getTypeId(), {
@@ -1179,8 +1083,13 @@ var AbstractResourceRepository = class extends AbstractRepository {
1179
1083
  return result;
1180
1084
  }
1181
1085
  get(context, id, params = {}) {
1182
- const resource = this._storage.get(context.projectKey, this.getTypeId(), id, params);
1183
- return this.postProcessResource(resource);
1086
+ const resource = this._storage.get(
1087
+ context.projectKey,
1088
+ this.getTypeId(),
1089
+ id,
1090
+ params
1091
+ );
1092
+ return resource ? this.postProcessResource(resource) : null;
1184
1093
  }
1185
1094
  getByKey(context, key, params = {}) {
1186
1095
  const resource = this._storage.getByKey(
@@ -1189,7 +1098,7 @@ var AbstractResourceRepository = class extends AbstractRepository {
1189
1098
  key,
1190
1099
  params
1191
1100
  );
1192
- return this.postProcessResource(resource);
1101
+ return resource ? this.postProcessResource(resource) : null;
1193
1102
  }
1194
1103
  delete(context, id, params = {}) {
1195
1104
  const resource = this._storage.delete(
@@ -1198,130 +1107,45 @@ var AbstractResourceRepository = class extends AbstractRepository {
1198
1107
  id,
1199
1108
  params
1200
1109
  );
1201
- return this.postProcessResource(resource);
1110
+ return resource ? this.postProcessResource(resource) : null;
1202
1111
  }
1203
- save(context, resource) {
1204
- const current = this.get(context, resource.id);
1205
- if (current) {
1206
- checkConcurrentModification(current, resource.version);
1207
- } else {
1208
- if (resource.version !== 0) {
1209
- throw new CommercetoolsError(
1210
- {
1211
- code: "InvalidOperation",
1212
- message: "version on create must be 0"
1213
- },
1214
- 400
1215
- );
1216
- }
1112
+ saveNew(context, resource) {
1113
+ resource.version = 1;
1114
+ this._storage.add(context.projectKey, this.getTypeId(), resource);
1115
+ }
1116
+ saveUpdate(context, version, resource) {
1117
+ const current = this._storage.get(
1118
+ context.projectKey,
1119
+ this.getTypeId(),
1120
+ resource.id
1121
+ );
1122
+ if (!current) {
1123
+ throw new CommercetoolsError(
1124
+ {
1125
+ code: "ResourceNotFound",
1126
+ message: "Resource not found while updating"
1127
+ },
1128
+ 400
1129
+ );
1130
+ }
1131
+ checkConcurrentModification(current.version, version, resource.id);
1132
+ if (current.version === resource.version) {
1133
+ throw new Error("Internal error: no changes to save");
1217
1134
  }
1218
- resource.version += 1;
1135
+ resource.lastModifiedAt = new Date().toISOString();
1219
1136
  this._storage.add(context.projectKey, this.getTypeId(), resource);
1137
+ return resource;
1220
1138
  }
1221
1139
  };
1222
1140
 
1223
- // src/repositories/cart-discount.ts
1224
- var CartDiscountRepository = class extends AbstractResourceRepository {
1225
- constructor() {
1226
- super(...arguments);
1227
- this.actions = {
1228
- setKey: (context, resource, { key }) => {
1229
- resource.key = key;
1230
- },
1231
- setDescription: (context, resource, { description }) => {
1232
- resource.description = description;
1233
- },
1234
- setValidFrom: (context, resource, { validFrom }) => {
1235
- resource.validFrom = validFrom;
1236
- },
1237
- setValidUntil: (context, resource, { validUntil }) => {
1238
- resource.validUntil = validUntil;
1239
- },
1240
- setValidFromAndUntil: (context, resource, { validFrom, validUntil }) => {
1241
- resource.validFrom = validFrom;
1242
- resource.validUntil = validUntil;
1243
- },
1244
- changeSortOrder: (context, resource, { sortOrder }) => {
1245
- resource.sortOrder = sortOrder;
1246
- },
1247
- changeIsActive: (context, resource, { isActive }) => {
1248
- resource.isActive = isActive;
1249
- }
1250
- };
1251
- }
1252
- getTypeId() {
1253
- return "cart-discount";
1254
- }
1255
- create(context, draft) {
1256
- const resource = {
1257
- ...getBaseResourceProperties(),
1258
- key: draft.key,
1259
- description: draft.description,
1260
- cartPredicate: draft.cartPredicate,
1261
- isActive: draft.isActive || false,
1262
- name: draft.name,
1263
- references: [],
1264
- target: draft.target,
1265
- requiresDiscountCode: draft.requiresDiscountCode || false,
1266
- sortOrder: draft.sortOrder,
1267
- stackingMode: draft.stackingMode || "Stacking",
1268
- validFrom: draft.validFrom,
1269
- validUntil: draft.validUntil,
1270
- value: this.transformValueDraft(draft.value)
1271
- };
1272
- this.save(context, resource);
1273
- return resource;
1274
- }
1275
- transformValueDraft(value) {
1276
- switch (value.type) {
1277
- case "absolute": {
1278
- return {
1279
- type: "absolute",
1280
- money: value.money.map(createTypedMoney)
1281
- };
1282
- }
1283
- case "fixed": {
1284
- return {
1285
- type: "fixed",
1286
- money: value.money.map(createTypedMoney)
1287
- };
1288
- }
1289
- case "giftLineItem": {
1290
- return {
1291
- ...value
1292
- };
1293
- }
1294
- case "relative": {
1295
- return {
1296
- ...value
1297
- };
1298
- }
1299
- }
1300
- return value;
1301
- }
1302
- };
1303
-
1304
- // src/services/cart-discount.ts
1305
- var CartDiscountService = class extends AbstractService {
1306
- constructor(parent, storage) {
1307
- super(parent);
1308
- this.repository = new CartDiscountRepository(storage);
1309
- }
1310
- getBasePath() {
1311
- return "cart-discounts";
1312
- }
1313
- };
1314
-
1315
- // src/repositories/cart.ts
1316
- import { v4 as uuidv43 } from "uuid";
1317
- var CartRepository = class extends AbstractResourceRepository {
1141
+ // src/repositories/cart.ts
1142
+ var CartRepository = class extends AbstractResourceRepository {
1318
1143
  constructor() {
1319
1144
  super(...arguments);
1320
1145
  this.actions = {
1321
1146
  addLineItem: (context, resource, { productId, variantId, sku, quantity = 1 }) => {
1322
1147
  var _a;
1323
1148
  let product = null;
1324
- let variant;
1325
1149
  if (productId && variantId) {
1326
1150
  product = this._storage.get(
1327
1151
  context.projectKey,
@@ -1345,7 +1169,7 @@ var CartRepository = class extends AbstractResourceRepository {
1345
1169
  message: sku ? `A product containing a variant with SKU '${sku}' not found.` : `A product with ID '${productId}' not found.`
1346
1170
  });
1347
1171
  }
1348
- variant = [
1172
+ const variant = [
1349
1173
  product.masterData.current.masterVariant,
1350
1174
  ...product.masterData.current.variants
1351
1175
  ].find((x) => {
@@ -1422,7 +1246,9 @@ var CartRepository = class extends AbstractResourceRepository {
1422
1246
  }
1423
1247
  const shouldDelete = !quantity || quantity >= lineItem.quantity;
1424
1248
  if (shouldDelete) {
1425
- resource.lineItems = resource.lineItems.filter((x) => x.id !== lineItemId);
1249
+ resource.lineItems = resource.lineItems.filter(
1250
+ (x) => x.id !== lineItemId
1251
+ );
1426
1252
  } else {
1427
1253
  resource.lineItems.map((x) => {
1428
1254
  if (x.id === lineItemId && quantity) {
@@ -1438,19 +1264,24 @@ var CartRepository = class extends AbstractResourceRepository {
1438
1264
  resource.billingAddress = address;
1439
1265
  },
1440
1266
  setShippingMethod: (context, resource, { shippingMethod }) => {
1441
- const resolvedType = this._storage.getByResourceIdentifier(
1442
- context.projectKey,
1443
- shippingMethod
1444
- );
1445
- if (!resolvedType) {
1446
- throw new Error(`Type ${shippingMethod} not found`);
1447
- }
1448
- resource.shippingInfo = {
1449
- shippingMethod: {
1450
- typeId: "shipping-method",
1451
- id: resolvedType.id
1267
+ if (shippingMethod) {
1268
+ const method = this._storage.getByResourceIdentifier(
1269
+ context.projectKey,
1270
+ shippingMethod
1271
+ );
1272
+ if (!method) {
1273
+ throw new Error(`Type ${shippingMethod} not found`);
1452
1274
  }
1453
- };
1275
+ resource.shippingInfo = {
1276
+ shippingMethod: {
1277
+ typeId: "shipping-method",
1278
+ id: method.id
1279
+ },
1280
+ shippingMethodName: method.name
1281
+ };
1282
+ } else {
1283
+ resource.shippingInfo = void 0;
1284
+ }
1454
1285
  },
1455
1286
  setCountry: (context, resource, { country }) => {
1456
1287
  resource.country = country;
@@ -1494,7 +1325,6 @@ var CartRepository = class extends AbstractResourceRepository {
1494
1325
  this.draftLineItemtoLineItem = (projectKey, draftLineItem, currency, country) => {
1495
1326
  const { productId, quantity, variantId, sku } = draftLineItem;
1496
1327
  let product = null;
1497
- let variant;
1498
1328
  if (productId && variantId) {
1499
1329
  product = this._storage.get(projectKey, "product", productId, {});
1500
1330
  } else if (sku) {
@@ -1513,7 +1343,7 @@ var CartRepository = class extends AbstractResourceRepository {
1513
1343
  message: sku ? `A product containing a variant with SKU '${sku}' not found.` : `A product with ID '${productId}' not found.`
1514
1344
  });
1515
1345
  }
1516
- variant = [
1346
+ const variant = [
1517
1347
  product.masterData.current.masterVariant,
1518
1348
  ...product.masterData.current.variants
1519
1349
  ].find((x) => {
@@ -1594,7 +1424,7 @@ var CartRepository = class extends AbstractResourceRepository {
1594
1424
  )
1595
1425
  };
1596
1426
  resource.totalPrice.centAmount = calculateCartTotalPrice(resource);
1597
- this.save(context, resource);
1427
+ this.saveNew(context, resource);
1598
1428
  return resource;
1599
1429
  }
1600
1430
  getActiveCart(projectKey) {
@@ -1624,313 +1454,84 @@ var selectPrice = ({
1624
1454
  var calculateLineItemTotalPrice = (lineItem) => lineItem.price.value.centAmount * lineItem.quantity;
1625
1455
  var calculateCartTotalPrice = (cart) => cart.lineItems.reduce((cur, item) => cur + item.totalPrice.centAmount, 0);
1626
1456
 
1627
- // src/repositories/order.ts
1628
- import assert2 from "assert";
1629
- var OrderRepository = class extends AbstractResourceRepository {
1457
+ // src/repositories/cart-discount.ts
1458
+ var CartDiscountRepository = class extends AbstractResourceRepository {
1630
1459
  constructor() {
1631
1460
  super(...arguments);
1632
1461
  this.actions = {
1633
- addPayment: (context, resource, { payment }) => {
1634
- const resolvedPayment = this._storage.getByResourceIdentifier(
1635
- context.projectKey,
1636
- payment
1637
- );
1638
- if (!resolvedPayment) {
1639
- throw new Error(`Payment ${payment.id} not found`);
1640
- }
1641
- if (!resource.paymentInfo) {
1642
- resource.paymentInfo = {
1643
- payments: []
1644
- };
1645
- }
1646
- resource.paymentInfo.payments.push({
1647
- typeId: "payment",
1648
- id: payment.id
1649
- });
1650
- },
1651
- changeOrderState: (context, resource, { orderState }) => {
1652
- resource.orderState = orderState;
1653
- },
1654
- changePaymentState: (context, resource, { paymentState }) => {
1655
- resource.paymentState = paymentState;
1656
- },
1657
- transitionState: (context, resource, { state }) => {
1658
- const resolvedType = this._storage.getByResourceIdentifier(
1659
- context.projectKey,
1660
- state
1661
- );
1662
- if (!resolvedType) {
1663
- throw new Error(
1664
- `No state found with key=${state.key} or id=${state.key}`
1665
- );
1666
- }
1667
- resource.state = { typeId: "state", id: resolvedType.id };
1668
- },
1669
- setBillingAddress: (context, resource, { address }) => {
1670
- resource.billingAddress = address;
1671
- },
1672
- setCustomerEmail: (context, resource, { email }) => {
1673
- resource.customerEmail = email;
1462
+ setKey: (context, resource, { key }) => {
1463
+ resource.key = key;
1674
1464
  },
1675
- setCustomField: (context, resource, { name, value }) => {
1676
- if (!resource.custom) {
1677
- throw new Error("Resource has no custom field");
1678
- }
1679
- resource.custom.fields[name] = value;
1465
+ setDescription: (context, resource, { description }) => {
1466
+ resource.description = description;
1680
1467
  },
1681
- setCustomType: (context, resource, { type, fields }) => {
1682
- if (!type) {
1683
- resource.custom = void 0;
1684
- } else {
1685
- const resolvedType = this._storage.getByResourceIdentifier(
1686
- context.projectKey,
1687
- type
1688
- );
1689
- if (!resolvedType) {
1690
- throw new Error(`Type ${type} not found`);
1691
- }
1692
- resource.custom = {
1693
- type: {
1694
- typeId: "type",
1695
- id: resolvedType.id
1696
- },
1697
- fields: fields || []
1698
- };
1699
- }
1468
+ setValidFrom: (context, resource, { validFrom }) => {
1469
+ resource.validFrom = validFrom;
1700
1470
  },
1701
- setLocale: (context, resource, { locale }) => {
1702
- resource.locale = locale;
1471
+ setValidUntil: (context, resource, { validUntil }) => {
1472
+ resource.validUntil = validUntil;
1703
1473
  },
1704
- setOrderNumber: (context, resource, { orderNumber }) => {
1705
- resource.orderNumber = orderNumber;
1474
+ setValidFromAndUntil: (context, resource, { validFrom, validUntil }) => {
1475
+ resource.validFrom = validFrom;
1476
+ resource.validUntil = validUntil;
1706
1477
  },
1707
- setShippingAddress: (context, resource, { address }) => {
1708
- resource.shippingAddress = address;
1478
+ changeSortOrder: (context, resource, { sortOrder }) => {
1479
+ resource.sortOrder = sortOrder;
1709
1480
  },
1710
- setStore: (context, resource, { store }) => {
1711
- if (!store)
1712
- return;
1713
- const resolvedType = this._storage.getByResourceIdentifier(
1714
- context.projectKey,
1715
- store
1716
- );
1717
- if (!resolvedType) {
1718
- throw new Error(`No store found with key=${store.key}`);
1719
- }
1720
- const storeReference = resolvedType;
1721
- resource.store = {
1722
- typeId: "store",
1723
- key: storeReference.key
1724
- };
1481
+ changeIsActive: (context, resource, { isActive }) => {
1482
+ resource.isActive = isActive;
1725
1483
  }
1726
1484
  };
1727
1485
  }
1728
1486
  getTypeId() {
1729
- return "order";
1487
+ return "cart-discount";
1730
1488
  }
1731
1489
  create(context, draft) {
1732
- assert2(draft.cart, "draft.cart is missing");
1733
- return this.createFromCart(
1734
- context,
1735
- {
1736
- id: draft.cart.id,
1737
- typeId: "cart"
1738
- },
1739
- draft.orderNumber
1740
- );
1741
- }
1742
- createFromCart(context, cartReference, orderNumber) {
1743
- const cart = this._storage.getByResourceIdentifier(
1744
- context.projectKey,
1745
- cartReference
1746
- );
1747
- if (!cart) {
1748
- throw new Error("Cannot find cart");
1749
- }
1750
1490
  const resource = {
1751
1491
  ...getBaseResourceProperties(),
1752
- orderNumber,
1753
- cart: cartReference,
1754
- orderState: "Open",
1755
- lineItems: [],
1756
- customLineItems: [],
1757
- totalPrice: cart.totalPrice,
1758
- refusedGifts: [],
1759
- origin: "Customer",
1760
- syncInfo: [],
1761
- store: context.storeKey ? {
1762
- key: context.storeKey,
1763
- typeId: "store"
1764
- } : void 0,
1765
- lastMessageSequenceNumber: 0
1492
+ key: draft.key,
1493
+ description: draft.description,
1494
+ cartPredicate: draft.cartPredicate,
1495
+ isActive: draft.isActive || false,
1496
+ name: draft.name,
1497
+ references: [],
1498
+ target: draft.target,
1499
+ requiresDiscountCode: draft.requiresDiscountCode || false,
1500
+ sortOrder: draft.sortOrder,
1501
+ stackingMode: draft.stackingMode || "Stacking",
1502
+ validFrom: draft.validFrom,
1503
+ validUntil: draft.validUntil,
1504
+ value: this.transformValueDraft(draft.value)
1766
1505
  };
1767
- this.save(context, resource);
1506
+ this.saveNew(context, resource);
1768
1507
  return resource;
1769
1508
  }
1770
- import(context, draft) {
1771
- var _a, _b;
1772
- assert2(this, "OrderRepository not valid");
1773
- const resource = {
1774
- ...getBaseResourceProperties(),
1775
- billingAddress: draft.billingAddress,
1776
- shippingAddress: draft.shippingAddress,
1777
- custom: createCustomFields(
1778
- draft.custom,
1779
- context.projectKey,
1780
- this._storage
1781
- ),
1782
- customerEmail: draft.customerEmail,
1783
- lastMessageSequenceNumber: 0,
1784
- orderNumber: draft.orderNumber,
1785
- orderState: draft.orderState || "Open",
1786
- origin: draft.origin || "Customer",
1787
- paymentState: draft.paymentState,
1788
- refusedGifts: [],
1789
- store: resolveStoreReference(
1790
- draft.store,
1791
- context.projectKey,
1792
- this._storage
1793
- ),
1794
- syncInfo: [],
1795
- lineItems: ((_a = draft.lineItems) == null ? void 0 : _a.map(
1796
- (item) => this.lineItemFromImportDraft.bind(this)(context, item)
1797
- )) || [],
1798
- customLineItems: ((_b = draft.customLineItems) == null ? void 0 : _b.map(
1799
- (item) => this.customLineItemFromImportDraft.bind(this)(context, item)
1800
- )) || [],
1801
- totalPrice: {
1802
- type: "centPrecision",
1803
- ...draft.totalPrice,
1804
- fractionDigits: 2
1805
- }
1806
- };
1807
- this.save(context, resource);
1808
- return resource;
1809
- }
1810
- lineItemFromImportDraft(context, draft) {
1811
- let product;
1812
- let variant;
1813
- if (draft.variant.sku) {
1814
- variant = {
1815
- id: 0,
1816
- sku: draft.variant.sku
1817
- };
1818
- var items = this._storage.query(context.projectKey, "product", {
1819
- where: [
1820
- `masterData(current(masterVariant(sku="${draft.variant.sku}"))) or masterData(current(variants(sku="${draft.variant.sku}")))`
1821
- ]
1822
- });
1823
- if (items.count !== 1) {
1824
- throw new CommercetoolsError({
1825
- code: "General",
1826
- message: `A product containing a variant with SKU '${draft.variant.sku}' not found.`
1827
- });
1509
+ transformValueDraft(value) {
1510
+ switch (value.type) {
1511
+ case "absolute": {
1512
+ return {
1513
+ type: "absolute",
1514
+ money: value.money.map(createTypedMoney)
1515
+ };
1828
1516
  }
1829
- product = items.results[0];
1830
- if (product.masterData.current.masterVariant.sku === draft.variant.sku) {
1831
- variant = product.masterData.current.masterVariant;
1832
- } else {
1833
- variant = product.masterData.current.variants.find(
1834
- (v) => v.sku === draft.variant.sku
1835
- );
1517
+ case "fixed": {
1518
+ return {
1519
+ type: "fixed",
1520
+ money: value.money.map(createTypedMoney)
1521
+ };
1836
1522
  }
1837
- if (!variant) {
1838
- throw new Error("Internal state error");
1523
+ case "giftLineItem": {
1524
+ return {
1525
+ ...value
1526
+ };
1839
1527
  }
1840
- } else {
1841
- throw new Error("No product found");
1842
- }
1843
- const lineItem = {
1844
- ...getBaseResourceProperties(),
1845
- custom: createCustomFields(
1846
- draft.custom,
1847
- context.projectKey,
1848
- this._storage
1849
- ),
1850
- discountedPricePerQuantity: [],
1851
- lineItemMode: "Standard",
1852
- name: draft.name,
1853
- price: createPrice(draft.price),
1854
- priceMode: "Platform",
1855
- productId: product.id,
1856
- productType: product.productType,
1857
- quantity: draft.quantity,
1858
- state: draft.state || [],
1859
- taxRate: draft.taxRate,
1860
- totalPrice: createTypedMoney(draft.price.value),
1861
- variant: {
1862
- id: variant.id,
1863
- sku: variant.sku,
1864
- price: createPrice(draft.price)
1528
+ case "relative": {
1529
+ return {
1530
+ ...value
1531
+ };
1865
1532
  }
1866
- };
1867
- return lineItem;
1868
- }
1869
- customLineItemFromImportDraft(context, draft) {
1870
- const lineItem = {
1871
- ...getBaseResourceProperties(),
1872
- custom: createCustomFields(
1873
- draft.custom,
1874
- context.projectKey,
1875
- this._storage
1876
- ),
1877
- discountedPricePerQuantity: [],
1878
- money: createTypedMoney(draft.money),
1879
- name: draft.name,
1880
- quantity: draft.quantity,
1881
- slug: draft.slug,
1882
- state: [],
1883
- totalPrice: createTypedMoney(draft.money)
1884
- };
1885
- return lineItem;
1886
- }
1887
- getWithOrderNumber(context, orderNumber, params = {}) {
1888
- const result = this._storage.query(context.projectKey, this.getTypeId(), {
1889
- ...params,
1890
- where: [`orderNumber="${orderNumber}"`]
1891
- });
1892
- if (result.count === 1) {
1893
- return result.results[0];
1894
- }
1895
- if (result.count > 1) {
1896
- throw new Error("Duplicate order numbers");
1897
1533
  }
1898
- return;
1899
- }
1900
- };
1901
-
1902
- // src/services/cart.ts
1903
- var CartService = class extends AbstractService {
1904
- constructor(parent, storage) {
1905
- super(parent);
1906
- this.repository = new CartRepository(storage);
1907
- this.orderRepository = new OrderRepository(storage);
1908
- }
1909
- getBasePath() {
1910
- return "carts";
1911
- }
1912
- extraRoutes(parent) {
1913
- parent.post("/replicate", (request, response) => {
1914
- const context = getRepositoryContext(request);
1915
- const cartOrOrder = request.body.reference.typeId === "order" ? this.orderRepository.get(context, request.body.reference.id) : this.repository.get(context, request.body.reference.id);
1916
- if (!cartOrOrder) {
1917
- return response.status(400).send();
1918
- }
1919
- const cartDraft = {
1920
- ...cartOrOrder,
1921
- currency: cartOrOrder.totalPrice.currencyCode,
1922
- discountCodes: [],
1923
- lineItems: cartOrOrder.lineItems.map((lineItem) => {
1924
- return {
1925
- ...lineItem,
1926
- variantId: lineItem.variant.id,
1927
- sku: lineItem.variant.sku
1928
- };
1929
- })
1930
- };
1931
- const newCart = this.repository.create(context, cartDraft);
1932
- return response.status(200).send(newCart);
1933
- });
1534
+ return value;
1934
1535
  }
1935
1536
  };
1936
1537
 
@@ -2028,43 +1629,30 @@ var CategoryRepository = class extends AbstractResourceRepository {
2028
1629
  externalId: draft.externalId || "",
2029
1630
  parent: draft.parent ? { typeId: "category", id: draft.parent.id } : void 0,
2030
1631
  ancestors: [],
2031
- assets: ((_a = draft.assets) == null ? void 0 : _a.map((d) => {
2032
- return {
2033
- id: uuidv44(),
2034
- name: d.name,
2035
- description: d.description,
2036
- sources: d.sources,
2037
- tags: d.tags,
2038
- key: d.key,
2039
- custom: createCustomFields(
2040
- draft.custom,
2041
- context.projectKey,
2042
- this._storage
2043
- )
2044
- };
2045
- })) || [],
1632
+ assets: ((_a = draft.assets) == null ? void 0 : _a.map((d) => ({
1633
+ id: uuidv44(),
1634
+ name: d.name,
1635
+ description: d.description,
1636
+ sources: d.sources,
1637
+ tags: d.tags,
1638
+ key: d.key,
1639
+ custom: createCustomFields(
1640
+ draft.custom,
1641
+ context.projectKey,
1642
+ this._storage
1643
+ )
1644
+ }))) || [],
2046
1645
  custom: createCustomFields(
2047
1646
  draft.custom,
2048
1647
  context.projectKey,
2049
1648
  this._storage
2050
1649
  )
2051
1650
  };
2052
- this.save(context, resource);
1651
+ this.saveNew(context, resource);
2053
1652
  return resource;
2054
1653
  }
2055
1654
  };
2056
1655
 
2057
- // src/services/category.ts
2058
- var CategoryServices = class extends AbstractService {
2059
- constructor(parent, storage) {
2060
- super(parent);
2061
- this.repository = new CategoryRepository(storage);
2062
- }
2063
- getBasePath() {
2064
- return "categories";
2065
- }
2066
- };
2067
-
2068
1656
  // src/repositories/channel.ts
2069
1657
  var ChannelRepository = class extends AbstractResourceRepository {
2070
1658
  constructor() {
@@ -2130,93 +1718,103 @@ var ChannelRepository = class extends AbstractResourceRepository {
2130
1718
  this._storage
2131
1719
  )
2132
1720
  };
2133
- this.save(context, resource);
1721
+ this.saveNew(context, resource);
2134
1722
  return resource;
2135
1723
  }
2136
1724
  };
2137
1725
 
2138
- // src/services/channel.ts
2139
- var ChannelService = class extends AbstractService {
2140
- constructor(parent, storage) {
2141
- super(parent);
2142
- this.repository = new ChannelRepository(storage);
1726
+ // src/repositories/custom-object.ts
1727
+ var CustomObjectRepository = class extends AbstractResourceRepository {
1728
+ getTypeId() {
1729
+ return "key-value-document";
2143
1730
  }
2144
- getBasePath() {
2145
- return "channels";
1731
+ create(context, draft) {
1732
+ const current = this.getWithContainerAndKey(
1733
+ context,
1734
+ draft.container,
1735
+ draft.key
1736
+ );
1737
+ if (current) {
1738
+ if (draft.version) {
1739
+ checkConcurrentModification(current.version, draft.version, current.id);
1740
+ } else {
1741
+ draft.version = current.version;
1742
+ }
1743
+ if (draft.value !== current.value) {
1744
+ const updated = cloneObject(current);
1745
+ updated.value = draft.value;
1746
+ updated.version += 1;
1747
+ this.saveUpdate(context, draft.version, updated);
1748
+ return updated;
1749
+ }
1750
+ return current;
1751
+ } else {
1752
+ if (draft.version) {
1753
+ throw new CommercetoolsError(
1754
+ {
1755
+ code: "InvalidOperation",
1756
+ message: "version on create must be 0"
1757
+ },
1758
+ 400
1759
+ );
1760
+ }
1761
+ const baseProperties = getBaseResourceProperties();
1762
+ const resource = {
1763
+ ...baseProperties,
1764
+ container: draft.container,
1765
+ key: draft.key,
1766
+ value: draft.value
1767
+ };
1768
+ this.saveNew(context, resource);
1769
+ return resource;
1770
+ }
1771
+ }
1772
+ getWithContainerAndKey(context, container, key) {
1773
+ const items = this._storage.all(
1774
+ context.projectKey,
1775
+ this.getTypeId()
1776
+ );
1777
+ return items.find(
1778
+ (item) => item.container === container && item.key === key
1779
+ );
2146
1780
  }
2147
1781
  };
2148
1782
 
2149
- // src/repositories/customer-group.ts
2150
- var CustomerGroupRepository = class extends AbstractResourceRepository {
1783
+ // src/repositories/customer.ts
1784
+ var CustomerRepository = class extends AbstractResourceRepository {
2151
1785
  constructor() {
2152
1786
  super(...arguments);
2153
1787
  this.actions = {
2154
- setKey: (context, resource, { key }) => {
2155
- resource.key = key;
2156
- },
2157
- changeName: (context, resource, { name }) => {
2158
- resource.name = name;
1788
+ changeEmail: (_context, resource, { email }) => {
1789
+ resource.email = email;
2159
1790
  },
2160
- setCustomType: (context, resource, { type, fields }) => {
2161
- if (type) {
2162
- resource.custom = createCustomFields(
2163
- { type, fields },
2164
- context.projectKey,
2165
- this._storage
1791
+ setAuthenticationMode: (_context, resource, { authMode, password }) => {
1792
+ if (resource.authenticationMode === authMode) {
1793
+ throw new CommercetoolsError(
1794
+ {
1795
+ code: "InvalidInput",
1796
+ message: `The customer is already using the '${resource.authenticationMode}' authentication mode.`
1797
+ },
1798
+ 400
2166
1799
  );
2167
- } else {
2168
- resource.custom = void 0;
2169
1800
  }
2170
- },
2171
- setCustomField: (context, resource, { name, value }) => {
2172
- if (!resource.custom) {
1801
+ resource.authenticationMode = authMode;
1802
+ if (authMode === "ExternalAuth") {
1803
+ delete resource.password;
2173
1804
  return;
2174
1805
  }
2175
- if (value === null) {
2176
- delete resource.custom.fields[name];
2177
- } else {
2178
- resource.custom.fields[name] = value;
1806
+ if (authMode === "Password") {
1807
+ resource.password = password ? Buffer.from(password).toString("base64") : void 0;
1808
+ return;
2179
1809
  }
2180
- }
2181
- };
2182
- }
2183
- getTypeId() {
2184
- return "customer";
2185
- }
2186
- create(context, draft) {
2187
- const resource = {
2188
- ...getBaseResourceProperties(),
2189
- key: draft.key,
2190
- name: draft.groupName,
2191
- custom: createCustomFields(
2192
- draft.custom,
2193
- context.projectKey,
2194
- this._storage
2195
- )
2196
- };
2197
- this.save(context, resource);
2198
- return resource;
2199
- }
2200
- };
2201
-
2202
- // src/services/customer-group.ts
2203
- var CustomerGroupService = class extends AbstractService {
2204
- constructor(parent, storage) {
2205
- super(parent);
2206
- this.repository = new CustomerGroupRepository(storage);
2207
- }
2208
- getBasePath() {
2209
- return "customer-groups";
2210
- }
2211
- };
2212
-
2213
- // src/repositories/customer.ts
2214
- var CustomerRepository = class extends AbstractResourceRepository {
2215
- constructor() {
2216
- super(...arguments);
2217
- this.actions = {
2218
- changeEmail: (_context, resource, { email }) => {
2219
- resource.email = email;
1810
+ throw new CommercetoolsError(
1811
+ {
1812
+ code: "InvalidJsonInput",
1813
+ message: "Request body does not contain valid JSON.",
1814
+ detailedErrorMessage: `actions -> authMode: Invalid enum value: '${authMode}'. Expected one of: 'Password','ExternalAuth'`
1815
+ },
1816
+ 400
1817
+ );
2220
1818
  }
2221
1819
  };
2222
1820
  }
@@ -2231,7 +1829,7 @@ var CustomerRepository = class extends AbstractResourceRepository {
2231
1829
  isEmailVerified: draft.isEmailVerified || false,
2232
1830
  addresses: []
2233
1831
  };
2234
- this.save(context, resource);
1832
+ this.saveNew(context, resource);
2235
1833
  return resource;
2236
1834
  }
2237
1835
  getMe(context) {
@@ -2247,127 +1845,57 @@ var CustomerRepository = class extends AbstractResourceRepository {
2247
1845
  }
2248
1846
  };
2249
1847
 
2250
- // src/services/customer.ts
2251
- import { v4 as uuidv45 } from "uuid";
2252
- var CustomerService = class extends AbstractService {
2253
- constructor(parent, storage) {
2254
- super(parent);
2255
- this.repository = new CustomerRepository(storage);
2256
- }
2257
- getBasePath() {
2258
- return "customers";
2259
- }
2260
- extraRoutes(parent) {
2261
- parent.post("/password-token", (request, response) => {
2262
- const customer = this.repository.query(getRepositoryContext(request), {
2263
- where: [`email="${request.body.email}"`]
2264
- });
2265
- const ttlMinutes = request.params.ttlMinutes ? +request.params.ttlMinutes : 34560;
2266
- const { version, ...rest } = getBaseResourceProperties();
2267
- return response.status(200).send({
2268
- ...rest,
2269
- customerId: customer.results[0].id,
2270
- expiresAt: new Date(Date.now() + ttlMinutes * 60).toISOString(),
2271
- value: uuidv45()
2272
- });
2273
- });
1848
+ // src/repositories/customer-group.ts
1849
+ var CustomerGroupRepository = class extends AbstractResourceRepository {
1850
+ constructor() {
1851
+ super(...arguments);
1852
+ this.actions = {
1853
+ setKey: (context, resource, { key }) => {
1854
+ resource.key = key;
1855
+ },
1856
+ changeName: (context, resource, { name }) => {
1857
+ resource.name = name;
1858
+ },
1859
+ setCustomType: (context, resource, { type, fields }) => {
1860
+ if (type) {
1861
+ resource.custom = createCustomFields(
1862
+ { type, fields },
1863
+ context.projectKey,
1864
+ this._storage
1865
+ );
1866
+ } else {
1867
+ resource.custom = void 0;
1868
+ }
1869
+ },
1870
+ setCustomField: (context, resource, { name, value }) => {
1871
+ if (!resource.custom) {
1872
+ return;
1873
+ }
1874
+ if (value === null) {
1875
+ delete resource.custom.fields[name];
1876
+ } else {
1877
+ resource.custom.fields[name] = value;
1878
+ }
1879
+ }
1880
+ };
2274
1881
  }
2275
- };
2276
-
2277
- // src/repositories/custom-object.ts
2278
- var CustomObjectRepository = class extends AbstractResourceRepository {
2279
1882
  getTypeId() {
2280
- return "key-value-document";
1883
+ return "customer";
2281
1884
  }
2282
1885
  create(context, draft) {
2283
- const current = this.getWithContainerAndKey(
2284
- context,
2285
- draft.container,
2286
- draft.key
2287
- );
2288
- const baseProperties = getBaseResourceProperties();
2289
- if (current) {
2290
- baseProperties.id = current.id;
2291
- if (!draft.version) {
2292
- draft.version = current.version;
2293
- }
2294
- checkConcurrentModification(current, draft.version);
2295
- if (draft.value === current.value) {
2296
- return current;
2297
- }
2298
- baseProperties.version = current.version;
2299
- } else {
2300
- if (draft.version) {
2301
- baseProperties.version = draft.version;
2302
- }
2303
- }
2304
1886
  const resource = {
2305
- ...baseProperties,
2306
- container: draft.container,
1887
+ ...getBaseResourceProperties(),
2307
1888
  key: draft.key,
2308
- value: draft.value
1889
+ name: draft.groupName,
1890
+ custom: createCustomFields(
1891
+ draft.custom,
1892
+ context.projectKey,
1893
+ this._storage
1894
+ )
2309
1895
  };
2310
- this.save(context, resource);
1896
+ this.saveNew(context, resource);
2311
1897
  return resource;
2312
1898
  }
2313
- getWithContainerAndKey(context, container, key) {
2314
- const items = this._storage.all(
2315
- context.projectKey,
2316
- this.getTypeId()
2317
- );
2318
- return items.find((item) => item.container === container && item.key === key);
2319
- }
2320
- };
2321
-
2322
- // src/services/custom-object.ts
2323
- var CustomObjectService = class extends AbstractService {
2324
- constructor(parent, storage) {
2325
- super(parent);
2326
- this.repository = new CustomObjectRepository(storage);
2327
- }
2328
- getBasePath() {
2329
- return "custom-objects";
2330
- }
2331
- extraRoutes(router) {
2332
- router.get("/:container/:key", this.getWithContainerAndKey.bind(this));
2333
- router.post("/:container/:key", this.createWithContainerAndKey.bind(this));
2334
- router.delete("/:container/:key", this.deleteWithContainerAndKey.bind(this));
2335
- }
2336
- getWithContainerAndKey(request, response) {
2337
- const result = this.repository.getWithContainerAndKey(
2338
- getRepositoryContext(request),
2339
- request.params.container,
2340
- request.params.key
2341
- );
2342
- if (!result) {
2343
- return response.status(404).send("Not Found");
2344
- }
2345
- return response.status(200).send(result);
2346
- }
2347
- createWithContainerAndKey(request, response) {
2348
- const draft = {
2349
- ...request.body,
2350
- key: request.params.key,
2351
- container: request.params.container
2352
- };
2353
- const result = this.repository.create(getRepositoryContext(request), draft);
2354
- return response.status(200).send(result);
2355
- }
2356
- deleteWithContainerAndKey(request, response) {
2357
- const current = this.repository.getWithContainerAndKey(
2358
- getRepositoryContext(request),
2359
- request.params.container,
2360
- request.params.key
2361
- );
2362
- if (!current) {
2363
- return response.status(404).send("Not Found");
2364
- }
2365
- const result = this.repository.delete(
2366
- getRepositoryContext(request),
2367
- current.id
2368
- );
2369
- return response.status(200).send(result);
2370
- }
2371
1899
  };
2372
1900
 
2373
1901
  // src/repositories/discount-code.ts
@@ -2466,26 +1994,15 @@ var DiscountCodeRepository = class extends AbstractResourceRepository {
2466
1994
  this._storage
2467
1995
  )
2468
1996
  };
2469
- this.save(context, resource);
1997
+ this.saveNew(context, resource);
2470
1998
  return resource;
2471
1999
  }
2472
2000
  };
2473
2001
 
2474
- // src/services/discount-code.ts
2475
- var DiscountCodeService = class extends AbstractService {
2476
- constructor(parent, storage) {
2477
- super(parent);
2478
- this.repository = new DiscountCodeRepository(storage);
2479
- }
2480
- getBasePath() {
2481
- return "discount-codes";
2482
- }
2483
- };
2484
-
2485
2002
  // src/lib/masking.ts
2486
2003
  var maskSecretValue = (resource, path) => {
2487
2004
  const parts = path.split(".");
2488
- const clone = JSON.parse(JSON.stringify(resource));
2005
+ const clone = cloneObject(resource);
2489
2006
  let val = clone;
2490
2007
  const target = parts.pop();
2491
2008
  for (let i = 0; i < parts.length; i++) {
@@ -2526,16 +2043,14 @@ var ExtensionRepository = class extends AbstractResourceRepository {
2526
2043
  postProcessResource(resource) {
2527
2044
  var _a;
2528
2045
  if (resource) {
2529
- if (resource.destination.type === "HTTP" && ((_a = resource.destination.authentication) == null ? void 0 : _a.type) === "AuthorizationHeader") {
2046
+ const extension = resource;
2047
+ if (extension.destination.type === "HTTP" && ((_a = extension.destination.authentication) == null ? void 0 : _a.type) === "AuthorizationHeader") {
2530
2048
  return maskSecretValue(
2531
- resource,
2049
+ extension,
2532
2050
  "destination.authentication.headerValue"
2533
2051
  );
2534
- } else if (resource.destination.type == "AWSLambda") {
2535
- return maskSecretValue(
2536
- resource,
2537
- "destination.accessSecret"
2538
- );
2052
+ } else if (extension.destination.type == "AWSLambda") {
2053
+ return maskSecretValue(resource, "destination.accessSecret");
2539
2054
  }
2540
2055
  }
2541
2056
  return resource;
@@ -2548,22 +2063,11 @@ var ExtensionRepository = class extends AbstractResourceRepository {
2548
2063
  destination: draft.destination,
2549
2064
  triggers: draft.triggers
2550
2065
  };
2551
- this.save(context, resource);
2066
+ this.saveNew(context, resource);
2552
2067
  return resource;
2553
2068
  }
2554
2069
  };
2555
2070
 
2556
- // src/services/extension.ts
2557
- var ExtensionServices = class extends AbstractService {
2558
- constructor(parent, storage) {
2559
- super(parent);
2560
- this.repository = new ExtensionRepository(storage);
2561
- }
2562
- getBasePath() {
2563
- return "extensions";
2564
- }
2565
- };
2566
-
2567
2071
  // src/repositories/inventory-entry.ts
2568
2072
  var InventoryEntryRepository = class extends AbstractResourceRepository {
2569
2073
  constructor() {
@@ -2630,74 +2134,71 @@ var InventoryEntryRepository = class extends AbstractResourceRepository {
2630
2134
  this._storage
2631
2135
  )
2632
2136
  };
2633
- this.save(context, resource);
2137
+ this.saveNew(context, resource);
2634
2138
  return resource;
2635
2139
  }
2636
2140
  };
2637
2141
 
2638
- // src/services/inventory-entry.ts
2639
- var InventoryEntryService = class extends AbstractService {
2640
- constructor(parent, storage) {
2641
- super(parent);
2642
- this.repository = new InventoryEntryRepository(storage);
2643
- }
2644
- getBasePath() {
2645
- return "inventory";
2646
- }
2647
- };
2648
-
2649
- // src/services/my-cart.ts
2650
- import { Router as Router2 } from "express";
2651
- var MyCartService = class extends AbstractService {
2652
- constructor(parent, storage) {
2653
- super(parent);
2654
- this.repository = new CartRepository(storage);
2655
- }
2656
- getBasePath() {
2657
- return "me";
2658
- }
2659
- registerRoutes(parent) {
2660
- const basePath = this.getBasePath();
2661
- const router = Router2({ mergeParams: true });
2662
- this.extraRoutes(router);
2663
- router.get("/active-cart", this.activeCart.bind(this));
2664
- router.get("/carts/", this.get.bind(this));
2665
- router.get("/carts/:id", this.getWithId.bind(this));
2666
- router.delete("/carts/:id", this.deletewithId.bind(this));
2667
- router.post("/carts/", this.post.bind(this));
2668
- router.post("/carts/:id", this.postWithId.bind(this));
2669
- parent.use(`/${basePath}`, router);
2670
- }
2671
- activeCart(request, response) {
2672
- const resource = this.repository.getActiveCart(request.params.projectKey);
2673
- if (!resource) {
2674
- return response.status(404).send("Not found");
2675
- }
2676
- return response.status(200).send(resource);
2677
- }
2678
- };
2142
+ // src/repositories/my-order.ts
2143
+ import assert3 from "assert";
2679
2144
 
2680
- // src/repositories/payment.ts
2681
- import { v4 as uuidv46 } from "uuid";
2682
- var PaymentRepository = class extends AbstractResourceRepository {
2145
+ // src/repositories/order.ts
2146
+ import assert2 from "assert";
2147
+ var OrderRepository = class extends AbstractResourceRepository {
2683
2148
  constructor() {
2684
2149
  super(...arguments);
2685
- this.transactionFromTransactionDraft = (draft, context) => ({
2686
- ...draft,
2687
- id: uuidv46(),
2688
- amount: createTypedMoney(draft.amount),
2689
- custom: createCustomFields(draft.custom, context.projectKey, this._storage)
2690
- });
2691
2150
  this.actions = {
2692
- setCustomField: (context, resource, { name, value }) => {
2693
- if (!resource.custom) {
2694
- throw new Error("Resource has no custom field");
2695
- }
2696
- resource.custom.fields[name] = value;
2697
- },
2698
- setCustomType: (context, resource, { type, fields }) => {
2699
- if (!type) {
2700
- resource.custom = void 0;
2151
+ addPayment: (context, resource, { payment }) => {
2152
+ const resolvedPayment = this._storage.getByResourceIdentifier(
2153
+ context.projectKey,
2154
+ payment
2155
+ );
2156
+ if (!resolvedPayment) {
2157
+ throw new Error(`Payment ${payment.id} not found`);
2158
+ }
2159
+ if (!resource.paymentInfo) {
2160
+ resource.paymentInfo = {
2161
+ payments: []
2162
+ };
2163
+ }
2164
+ resource.paymentInfo.payments.push({
2165
+ typeId: "payment",
2166
+ id: payment.id
2167
+ });
2168
+ },
2169
+ changeOrderState: (context, resource, { orderState }) => {
2170
+ resource.orderState = orderState;
2171
+ },
2172
+ changePaymentState: (context, resource, { paymentState }) => {
2173
+ resource.paymentState = paymentState;
2174
+ },
2175
+ transitionState: (context, resource, { state }) => {
2176
+ const resolvedType = this._storage.getByResourceIdentifier(
2177
+ context.projectKey,
2178
+ state
2179
+ );
2180
+ if (!resolvedType) {
2181
+ throw new Error(
2182
+ `No state found with key=${state.key} or id=${state.key}`
2183
+ );
2184
+ }
2185
+ resource.state = { typeId: "state", id: resolvedType.id };
2186
+ },
2187
+ setBillingAddress: (context, resource, { address }) => {
2188
+ resource.billingAddress = address;
2189
+ },
2190
+ setCustomerEmail: (context, resource, { email }) => {
2191
+ resource.customerEmail = email;
2192
+ },
2193
+ setCustomField: (context, resource, { name, value }) => {
2194
+ if (!resource.custom) {
2195
+ throw new Error("Resource has no custom field");
2196
+ }
2197
+ resource.custom.fields[name] = value;
2198
+ },
2199
+ setCustomType: (context, resource, { type, fields }) => {
2200
+ if (!type) {
2201
+ resource.custom = void 0;
2701
2202
  } else {
2702
2203
  const resolvedType = this._storage.getByResourceIdentifier(
2703
2204
  context.projectKey,
@@ -2715,198 +2216,562 @@ var PaymentRepository = class extends AbstractResourceRepository {
2715
2216
  };
2716
2217
  }
2717
2218
  },
2718
- addTransaction: (context, resource, { transaction }) => {
2719
- resource.transactions = [
2720
- ...resource.transactions,
2721
- this.transactionFromTransactionDraft(transaction, context)
2722
- ];
2219
+ setLocale: (context, resource, { locale }) => {
2220
+ resource.locale = locale;
2723
2221
  },
2724
- changeTransactionState: (_context, resource, { transactionId, state }) => {
2725
- const index = resource.transactions.findIndex(
2726
- (e) => e.id === transactionId
2727
- );
2728
- const updatedTransaction = {
2729
- ...resource.transactions[index],
2730
- state
2731
- };
2732
- resource.transactions[index] = updatedTransaction;
2222
+ setOrderNumber: (context, resource, { orderNumber }) => {
2223
+ resource.orderNumber = orderNumber;
2733
2224
  },
2734
- transitionState: (context, resource, { state }) => {
2735
- const stateObj = this._storage.getByResourceIdentifier(
2225
+ setShippingAddress: (context, resource, { address }) => {
2226
+ resource.shippingAddress = address;
2227
+ },
2228
+ setStore: (context, resource, { store }) => {
2229
+ if (!store)
2230
+ return;
2231
+ const resolvedType = this._storage.getByResourceIdentifier(
2736
2232
  context.projectKey,
2737
- state
2233
+ store
2738
2234
  );
2739
- if (!stateObj) {
2740
- throw new Error(`State ${state} not found`);
2235
+ if (!resolvedType) {
2236
+ throw new Error(`No store found with key=${store.key}`);
2741
2237
  }
2742
- resource.paymentStatus.state = {
2743
- typeId: "state",
2744
- id: stateObj.id,
2745
- obj: stateObj
2238
+ const storeReference = resolvedType;
2239
+ resource.store = {
2240
+ typeId: "store",
2241
+ key: storeReference.key
2746
2242
  };
2747
2243
  }
2748
2244
  };
2749
2245
  }
2750
2246
  getTypeId() {
2751
- return "payment";
2247
+ return "order";
2752
2248
  }
2753
2249
  create(context, draft) {
2250
+ assert2(draft.cart, "draft.cart is missing");
2251
+ return this.createFromCart(
2252
+ context,
2253
+ {
2254
+ id: draft.cart.id,
2255
+ typeId: "cart"
2256
+ },
2257
+ draft.orderNumber
2258
+ );
2259
+ }
2260
+ createFromCart(context, cartReference, orderNumber) {
2261
+ const cart = this._storage.getByResourceIdentifier(
2262
+ context.projectKey,
2263
+ cartReference
2264
+ );
2265
+ if (!cart) {
2266
+ throw new Error("Cannot find cart");
2267
+ }
2754
2268
  const resource = {
2755
2269
  ...getBaseResourceProperties(),
2756
- amountPlanned: createTypedMoney(draft.amountPlanned),
2757
- paymentMethodInfo: draft.paymentMethodInfo,
2758
- paymentStatus: draft.paymentStatus ? {
2759
- ...draft.paymentStatus,
2760
- state: draft.paymentStatus.state ? getReferenceFromResourceIdentifier(
2761
- draft.paymentStatus.state,
2762
- context.projectKey,
2763
- this._storage
2764
- ) : void 0
2765
- } : {},
2766
- transactions: (draft.transactions || []).map(
2767
- (t) => this.transactionFromTransactionDraft(t, context)
2270
+ orderNumber,
2271
+ cart: cartReference,
2272
+ orderState: "Open",
2273
+ lineItems: [],
2274
+ customLineItems: [],
2275
+ totalPrice: cart.totalPrice,
2276
+ refusedGifts: [],
2277
+ origin: "Customer",
2278
+ syncInfo: [],
2279
+ store: context.storeKey ? {
2280
+ key: context.storeKey,
2281
+ typeId: "store"
2282
+ } : void 0,
2283
+ lastMessageSequenceNumber: 0
2284
+ };
2285
+ this.saveNew(context, resource);
2286
+ return resource;
2287
+ }
2288
+ import(context, draft) {
2289
+ var _a, _b;
2290
+ assert2(this, "OrderRepository not valid");
2291
+ const resource = {
2292
+ ...getBaseResourceProperties(),
2293
+ billingAddress: draft.billingAddress,
2294
+ shippingAddress: draft.shippingAddress,
2295
+ custom: createCustomFields(
2296
+ draft.custom,
2297
+ context.projectKey,
2298
+ this._storage
2768
2299
  ),
2769
- interfaceInteractions: (draft.interfaceInteractions || []).map(
2770
- (interaction) => createCustomFields(interaction, context.projectKey, this._storage)
2300
+ customerEmail: draft.customerEmail,
2301
+ lastMessageSequenceNumber: 0,
2302
+ orderNumber: draft.orderNumber,
2303
+ orderState: draft.orderState || "Open",
2304
+ origin: draft.origin || "Customer",
2305
+ paymentState: draft.paymentState,
2306
+ refusedGifts: [],
2307
+ store: resolveStoreReference(
2308
+ draft.store,
2309
+ context.projectKey,
2310
+ this._storage
2771
2311
  ),
2312
+ syncInfo: [],
2313
+ lineItems: ((_a = draft.lineItems) == null ? void 0 : _a.map(
2314
+ (item) => this.lineItemFromImportDraft.bind(this)(context, item)
2315
+ )) || [],
2316
+ customLineItems: ((_b = draft.customLineItems) == null ? void 0 : _b.map(
2317
+ (item) => this.customLineItemFromImportDraft.bind(this)(context, item)
2318
+ )) || [],
2319
+ totalPrice: {
2320
+ type: "centPrecision",
2321
+ ...draft.totalPrice,
2322
+ fractionDigits: 2
2323
+ }
2324
+ };
2325
+ this.saveNew(context, resource);
2326
+ return resource;
2327
+ }
2328
+ lineItemFromImportDraft(context, draft) {
2329
+ let product;
2330
+ let variant;
2331
+ if (draft.variant.sku) {
2332
+ variant = {
2333
+ id: 0,
2334
+ sku: draft.variant.sku
2335
+ };
2336
+ const items = this._storage.query(context.projectKey, "product", {
2337
+ where: [
2338
+ `masterData(current(masterVariant(sku="${draft.variant.sku}"))) or masterData(current(variants(sku="${draft.variant.sku}")))`
2339
+ ]
2340
+ });
2341
+ if (items.count !== 1) {
2342
+ throw new CommercetoolsError({
2343
+ code: "General",
2344
+ message: `A product containing a variant with SKU '${draft.variant.sku}' not found.`
2345
+ });
2346
+ }
2347
+ product = items.results[0];
2348
+ if (product.masterData.current.masterVariant.sku === draft.variant.sku) {
2349
+ variant = product.masterData.current.masterVariant;
2350
+ } else {
2351
+ variant = product.masterData.current.variants.find(
2352
+ (v) => v.sku === draft.variant.sku
2353
+ );
2354
+ }
2355
+ if (!variant) {
2356
+ throw new Error("Internal state error");
2357
+ }
2358
+ } else {
2359
+ throw new Error("No product found");
2360
+ }
2361
+ const lineItem = {
2362
+ ...getBaseResourceProperties(),
2772
2363
  custom: createCustomFields(
2773
2364
  draft.custom,
2774
2365
  context.projectKey,
2775
2366
  this._storage
2776
- )
2367
+ ),
2368
+ discountedPricePerQuantity: [],
2369
+ lineItemMode: "Standard",
2370
+ name: draft.name,
2371
+ price: createPrice(draft.price),
2372
+ priceMode: "Platform",
2373
+ productId: product.id,
2374
+ productType: product.productType,
2375
+ quantity: draft.quantity,
2376
+ state: draft.state || [],
2377
+ taxRate: draft.taxRate,
2378
+ totalPrice: createTypedMoney(draft.price.value),
2379
+ variant: {
2380
+ id: variant.id,
2381
+ sku: variant.sku,
2382
+ price: createPrice(draft.price)
2383
+ }
2777
2384
  };
2778
- this.save(context, resource);
2779
- return resource;
2385
+ return lineItem;
2780
2386
  }
2781
- };
2782
-
2783
- // src/services/my-payment.ts
2784
- var MyPaymentService = class extends AbstractService {
2785
- constructor(parent, storage) {
2786
- super(parent);
2787
- this.repository = new PaymentRepository(storage);
2387
+ customLineItemFromImportDraft(context, draft) {
2388
+ const lineItem = {
2389
+ ...getBaseResourceProperties(),
2390
+ custom: createCustomFields(
2391
+ draft.custom,
2392
+ context.projectKey,
2393
+ this._storage
2394
+ ),
2395
+ discountedPricePerQuantity: [],
2396
+ money: createTypedMoney(draft.money),
2397
+ name: draft.name,
2398
+ quantity: draft.quantity,
2399
+ slug: draft.slug,
2400
+ state: [],
2401
+ totalPrice: createTypedMoney(draft.money)
2402
+ };
2403
+ return lineItem;
2788
2404
  }
2789
- getBasePath() {
2790
- return "me/payments";
2791
- }
2792
- };
2793
-
2794
- // src/services/order.ts
2795
- var OrderService = class extends AbstractService {
2796
- constructor(parent, storage) {
2797
- super(parent);
2798
- this.repository = new OrderRepository(storage);
2799
- }
2800
- getBasePath() {
2801
- return "orders";
2802
- }
2803
- extraRoutes(router) {
2804
- router.post("/import", this.import.bind(this));
2805
- router.get("/order-number=:orderNumber", this.getWithOrderNumber.bind(this));
2806
- }
2807
- import(request, response) {
2808
- const importDraft = request.body;
2809
- const resource = this.repository.import(
2810
- getRepositoryContext(request),
2811
- importDraft
2812
- );
2813
- return response.status(200).send(resource);
2814
- }
2815
- getWithOrderNumber(request, response) {
2816
- const resource = this.repository.getWithOrderNumber(
2817
- getRepositoryContext(request),
2818
- request.params.orderNumber,
2819
- request.query
2820
- );
2821
- if (resource) {
2822
- return response.status(200).send(resource);
2405
+ getWithOrderNumber(context, orderNumber, params = {}) {
2406
+ const result = this._storage.query(context.projectKey, this.getTypeId(), {
2407
+ ...params,
2408
+ where: [`orderNumber="${orderNumber}"`]
2409
+ });
2410
+ if (result.count === 1) {
2411
+ return result.results[0];
2823
2412
  }
2824
- return response.status(404).send("Not found");
2413
+ if (result.count > 1) {
2414
+ throw new Error("Duplicate order numbers");
2415
+ }
2416
+ return;
2825
2417
  }
2826
2418
  };
2827
2419
 
2828
- // src/services/payment.ts
2829
- var PaymentService = class extends AbstractService {
2830
- constructor(parent, storage) {
2831
- super(parent);
2832
- this.repository = new PaymentRepository(storage);
2833
- }
2834
- getBasePath() {
2835
- return "payments";
2420
+ // src/repositories/my-order.ts
2421
+ var MyOrderRepository = class extends OrderRepository {
2422
+ create(context, draft) {
2423
+ assert3(draft.id, "draft.id is missing");
2424
+ const cartIdentifier = {
2425
+ id: draft.id,
2426
+ typeId: "cart"
2427
+ };
2428
+ return this.createFromCart(context, cartIdentifier);
2836
2429
  }
2837
2430
  };
2838
2431
 
2839
- // src/repositories/product-discount.ts
2840
- var ProductDiscountRepository = class extends AbstractResourceRepository {
2432
+ // src/repositories/payment.ts
2433
+ import { v4 as uuidv45 } from "uuid";
2434
+ var PaymentRepository = class extends AbstractResourceRepository {
2841
2435
  constructor() {
2842
2436
  super(...arguments);
2437
+ this.transactionFromTransactionDraft = (draft, context) => ({
2438
+ ...draft,
2439
+ id: uuidv45(),
2440
+ amount: createTypedMoney(draft.amount),
2441
+ custom: createCustomFields(draft.custom, context.projectKey, this._storage)
2442
+ });
2843
2443
  this.actions = {
2844
- setKey: (context, resource, { key }) => {
2845
- resource.key = key;
2444
+ setCustomField: (context, resource, { name, value }) => {
2445
+ if (!resource.custom) {
2446
+ throw new Error("Resource has no custom field");
2447
+ }
2448
+ resource.custom.fields[name] = value;
2846
2449
  },
2847
- setDescription: (context, resource, { description }) => {
2848
- if (description && Object.keys(description).length > 0) {
2849
- resource.description = description;
2450
+ setCustomType: (context, resource, { type, fields }) => {
2451
+ if (!type) {
2452
+ resource.custom = void 0;
2850
2453
  } else {
2851
- resource.description = void 0;
2454
+ const resolvedType = this._storage.getByResourceIdentifier(
2455
+ context.projectKey,
2456
+ type
2457
+ );
2458
+ if (!resolvedType) {
2459
+ throw new Error(`Type ${type} not found`);
2460
+ }
2461
+ resource.custom = {
2462
+ type: {
2463
+ typeId: "type",
2464
+ id: resolvedType.id
2465
+ },
2466
+ fields: fields || []
2467
+ };
2852
2468
  }
2853
2469
  },
2854
- changeName: (context, resource, { name }) => {
2855
- resource.name = name;
2856
- },
2857
- changeValue: (context, resource, { value }) => {
2858
- resource.value = this.transformValueDraft(value);
2470
+ addTransaction: (context, resource, { transaction }) => {
2471
+ resource.transactions = [
2472
+ ...resource.transactions,
2473
+ this.transactionFromTransactionDraft(transaction, context)
2474
+ ];
2859
2475
  },
2860
- changePredicate: (context, resource, { predicate }) => {
2861
- resource.predicate = predicate;
2476
+ changeTransactionState: (_context, resource, { transactionId, state }) => {
2477
+ const index = resource.transactions.findIndex(
2478
+ (e) => e.id === transactionId
2479
+ );
2480
+ const updatedTransaction = {
2481
+ ...resource.transactions[index],
2482
+ state
2483
+ };
2484
+ resource.transactions[index] = updatedTransaction;
2862
2485
  },
2863
- changeSortOrder: (context, resource, { sortOrder }) => {
2864
- resource.sortOrder = sortOrder;
2486
+ transitionState: (context, resource, { state }) => {
2487
+ const stateObj = this._storage.getByResourceIdentifier(
2488
+ context.projectKey,
2489
+ state
2490
+ );
2491
+ if (!stateObj) {
2492
+ throw new Error(`State ${state} not found`);
2493
+ }
2494
+ resource.paymentStatus.state = {
2495
+ typeId: "state",
2496
+ id: stateObj.id,
2497
+ obj: stateObj
2498
+ };
2499
+ }
2500
+ };
2501
+ }
2502
+ getTypeId() {
2503
+ return "payment";
2504
+ }
2505
+ create(context, draft) {
2506
+ const resource = {
2507
+ ...getBaseResourceProperties(),
2508
+ amountPlanned: createTypedMoney(draft.amountPlanned),
2509
+ paymentMethodInfo: draft.paymentMethodInfo,
2510
+ paymentStatus: draft.paymentStatus ? {
2511
+ ...draft.paymentStatus,
2512
+ state: draft.paymentStatus.state ? getReferenceFromResourceIdentifier(
2513
+ draft.paymentStatus.state,
2514
+ context.projectKey,
2515
+ this._storage
2516
+ ) : void 0
2517
+ } : {},
2518
+ transactions: (draft.transactions || []).map(
2519
+ (t) => this.transactionFromTransactionDraft(t, context)
2520
+ ),
2521
+ interfaceInteractions: (draft.interfaceInteractions || []).map(
2522
+ (interaction) => createCustomFields(interaction, context.projectKey, this._storage)
2523
+ ),
2524
+ custom: createCustomFields(
2525
+ draft.custom,
2526
+ context.projectKey,
2527
+ this._storage
2528
+ )
2529
+ };
2530
+ this.saveNew(context, resource);
2531
+ return resource;
2532
+ }
2533
+ };
2534
+
2535
+ // src/repositories/product.ts
2536
+ import { v4 as uuidv46 } from "uuid";
2537
+ import deepEqual2 from "deep-equal";
2538
+ var ProductRepository = class extends AbstractResourceRepository {
2539
+ constructor() {
2540
+ super(...arguments);
2541
+ this.actions = {
2542
+ publish: (context, resource, { scope }) => {
2543
+ resource.masterData.current = resource.masterData.staged;
2544
+ resource.masterData.published = true;
2545
+ checkForStagedChanges(resource);
2865
2546
  },
2866
- changeIsActive: (context, resource, { isActive }) => {
2867
- resource.isActive = isActive;
2547
+ unpublish: (context, resource) => {
2548
+ resource.masterData.published = false;
2549
+ checkForStagedChanges(resource);
2868
2550
  },
2869
- setValidFrom: (context, resource, { validFrom }) => {
2870
- resource.validFrom = validFrom;
2551
+ setAttribute: (context, resource, { variantId, sku, name, value, staged }) => {
2552
+ const setAttr = (data) => {
2553
+ const { variant, isMasterVariant, variantIndex } = getVariant(
2554
+ data,
2555
+ variantId,
2556
+ sku
2557
+ );
2558
+ if (!variant) {
2559
+ throw new Error(
2560
+ `Variant with id ${variantId} or sku ${sku} not found on product ${resource.id}`
2561
+ );
2562
+ }
2563
+ if (!variant.attributes) {
2564
+ variant.attributes = [];
2565
+ }
2566
+ const existingAttr = variant.attributes.find(
2567
+ (attr) => attr.name === name
2568
+ );
2569
+ if (existingAttr) {
2570
+ existingAttr.value = value;
2571
+ } else {
2572
+ variant.attributes.push({
2573
+ name,
2574
+ value
2575
+ });
2576
+ }
2577
+ if (isMasterVariant) {
2578
+ data.masterVariant = variant;
2579
+ } else {
2580
+ data.variants[variantIndex] = variant;
2581
+ }
2582
+ };
2583
+ const onlyStaged = staged !== void 0 ? staged : true;
2584
+ setAttr(resource.masterData.staged);
2585
+ if (!onlyStaged) {
2586
+ setAttr(resource.masterData.current);
2587
+ }
2588
+ checkForStagedChanges(resource);
2589
+ return resource;
2871
2590
  },
2872
- setValidUntil: (context, resource, { validUntil }) => {
2873
- resource.validUntil = validUntil;
2591
+ "setDescription": (context, resource, { description, staged }) => {
2592
+ const onlyStaged = staged !== void 0 ? staged : true;
2593
+ resource.masterData.staged.description = description;
2594
+ if (!onlyStaged) {
2595
+ resource.masterData.current.description = description;
2596
+ }
2597
+ checkForStagedChanges(resource);
2598
+ return resource;
2874
2599
  },
2875
- setValidFromAndUntil: (context, resource, { validFrom, validUntil }) => {
2876
- resource.validFrom = validFrom;
2877
- resource.validUntil = validUntil;
2600
+ "setKey": (context, resource, { key }) => {
2601
+ resource.key = key;
2602
+ return resource;
2878
2603
  }
2879
2604
  };
2880
2605
  }
2881
2606
  getTypeId() {
2882
- return "product-discount";
2607
+ return "product";
2883
2608
  }
2884
2609
  create(context, draft) {
2610
+ var _a;
2611
+ if (!draft.masterVariant) {
2612
+ throw new Error("Missing master variant");
2613
+ }
2614
+ let productType = void 0;
2615
+ try {
2616
+ productType = getReferenceFromResourceIdentifier(
2617
+ draft.productType,
2618
+ context.projectKey,
2619
+ this._storage
2620
+ );
2621
+ } catch (err) {
2622
+ console.warn(
2623
+ `Error resolving product-type '${draft.productType.id}'. This will be throw an error in later releases.`
2624
+ );
2625
+ productType = {
2626
+ typeId: "product-type",
2627
+ id: draft.productType.id || ""
2628
+ };
2629
+ }
2630
+ const productData = {
2631
+ name: draft.name,
2632
+ slug: draft.slug,
2633
+ categories: [],
2634
+ masterVariant: variantFromDraft(1, draft.masterVariant),
2635
+ variants: ((_a = draft.variants) == null ? void 0 : _a.map(
2636
+ (variant, index) => variantFromDraft(index + 2, variant)
2637
+ )) ?? [],
2638
+ searchKeywords: draft.searchKeywords ?? {}
2639
+ };
2885
2640
  const resource = {
2886
2641
  ...getBaseResourceProperties(),
2887
2642
  key: draft.key,
2888
- name: draft.name,
2889
- description: draft.description,
2890
- value: this.transformValueDraft(draft.value),
2891
- predicate: draft.predicate,
2892
- sortOrder: draft.sortOrder,
2893
- isActive: draft.isActive || false,
2894
- validFrom: draft.validFrom,
2895
- validUntil: draft.validUntil,
2896
- references: []
2643
+ productType,
2644
+ masterData: {
2645
+ current: productData,
2646
+ staged: productData,
2647
+ hasStagedChanges: false,
2648
+ published: draft.publish ?? false
2649
+ }
2897
2650
  };
2898
- this.save(context, resource);
2651
+ this.saveNew(context, resource);
2899
2652
  return resource;
2900
2653
  }
2901
- transformValueDraft(value) {
2902
- switch (value.type) {
2903
- case "absolute": {
2904
- return {
2905
- type: "absolute",
2906
- money: value.money.map(createTypedMoney)
2907
- };
2908
- }
2909
- case "external": {
2654
+ };
2655
+ var checkForStagedChanges = (product) => {
2656
+ if (!product.masterData.staged) {
2657
+ product.masterData.staged = product.masterData.current;
2658
+ }
2659
+ if (deepEqual2(product.masterData.current, product.masterData.staged)) {
2660
+ product.masterData.hasStagedChanges = false;
2661
+ } else {
2662
+ product.masterData.hasStagedChanges = true;
2663
+ }
2664
+ };
2665
+ var getVariant = (productData, variantId, sku) => {
2666
+ const variants = [productData.masterVariant, ...productData.variants];
2667
+ const foundVariant = variants.find((variant) => {
2668
+ if (variantId) {
2669
+ return variant.id === variantId;
2670
+ }
2671
+ if (sku) {
2672
+ return variant.sku === sku;
2673
+ }
2674
+ return false;
2675
+ });
2676
+ const isMasterVariant = foundVariant === productData.masterVariant;
2677
+ return {
2678
+ variant: foundVariant,
2679
+ isMasterVariant,
2680
+ variantIndex: !isMasterVariant && foundVariant ? productData.variants.indexOf(foundVariant) : -1
2681
+ };
2682
+ };
2683
+ var variantFromDraft = (variantId, variant) => {
2684
+ var _a;
2685
+ return {
2686
+ id: variantId,
2687
+ sku: variant == null ? void 0 : variant.sku,
2688
+ attributes: (variant == null ? void 0 : variant.attributes) ?? [],
2689
+ prices: (_a = variant == null ? void 0 : variant.prices) == null ? void 0 : _a.map(priceFromDraft),
2690
+ assets: [],
2691
+ images: []
2692
+ };
2693
+ };
2694
+ var priceFromDraft = (draft) => ({
2695
+ id: uuidv46(),
2696
+ value: {
2697
+ currencyCode: draft.value.currencyCode,
2698
+ centAmount: draft.value.centAmount,
2699
+ fractionDigits: 2,
2700
+ type: "centPrecision"
2701
+ }
2702
+ });
2703
+
2704
+ // src/repositories/product-discount.ts
2705
+ var ProductDiscountRepository = class extends AbstractResourceRepository {
2706
+ constructor() {
2707
+ super(...arguments);
2708
+ this.actions = {
2709
+ setKey: (context, resource, { key }) => {
2710
+ resource.key = key;
2711
+ },
2712
+ setDescription: (context, resource, { description }) => {
2713
+ if (description && Object.keys(description).length > 0) {
2714
+ resource.description = description;
2715
+ } else {
2716
+ resource.description = void 0;
2717
+ }
2718
+ },
2719
+ changeName: (context, resource, { name }) => {
2720
+ resource.name = name;
2721
+ },
2722
+ changeValue: (context, resource, { value }) => {
2723
+ resource.value = this.transformValueDraft(value);
2724
+ },
2725
+ changePredicate: (context, resource, { predicate }) => {
2726
+ resource.predicate = predicate;
2727
+ },
2728
+ changeSortOrder: (context, resource, { sortOrder }) => {
2729
+ resource.sortOrder = sortOrder;
2730
+ },
2731
+ changeIsActive: (context, resource, { isActive }) => {
2732
+ resource.isActive = isActive;
2733
+ },
2734
+ setValidFrom: (context, resource, { validFrom }) => {
2735
+ resource.validFrom = validFrom;
2736
+ },
2737
+ setValidUntil: (context, resource, { validUntil }) => {
2738
+ resource.validUntil = validUntil;
2739
+ },
2740
+ setValidFromAndUntil: (context, resource, { validFrom, validUntil }) => {
2741
+ resource.validFrom = validFrom;
2742
+ resource.validUntil = validUntil;
2743
+ }
2744
+ };
2745
+ }
2746
+ getTypeId() {
2747
+ return "product-discount";
2748
+ }
2749
+ create(context, draft) {
2750
+ const resource = {
2751
+ ...getBaseResourceProperties(),
2752
+ key: draft.key,
2753
+ name: draft.name,
2754
+ description: draft.description,
2755
+ value: this.transformValueDraft(draft.value),
2756
+ predicate: draft.predicate,
2757
+ sortOrder: draft.sortOrder,
2758
+ isActive: draft.isActive || false,
2759
+ validFrom: draft.validFrom,
2760
+ validUntil: draft.validUntil,
2761
+ references: []
2762
+ };
2763
+ this.saveNew(context, resource);
2764
+ return resource;
2765
+ }
2766
+ transformValueDraft(value) {
2767
+ switch (value.type) {
2768
+ case "absolute": {
2769
+ return {
2770
+ type: "absolute",
2771
+ money: value.money.map(createTypedMoney)
2772
+ };
2773
+ }
2774
+ case "external": {
2910
2775
  return {
2911
2776
  type: "external"
2912
2777
  };
@@ -2932,52 +2797,23 @@ var ProductDiscountRepository = class extends AbstractResourceRepository {
2932
2797
  }
2933
2798
  };
2934
2799
 
2935
- // src/services/product-discount.ts
2936
- var ProductDiscountService = class extends AbstractService {
2937
- constructor(parent, storage) {
2938
- super(parent);
2939
- this.repository = new ProductDiscountRepository(storage);
2940
- }
2941
- getBasePath() {
2942
- return "product-discounts";
2943
- }
2944
- extraRoutes(router) {
2945
- router.get("/key=:key", this.getWithKey.bind(this));
2946
- }
2947
- getWithKey(request, response) {
2948
- const resource = this.repository.getWithKey(
2949
- getRepositoryContext(request),
2950
- request.params.key
2951
- );
2952
- if (resource) {
2953
- return response.status(200).send(resource);
2954
- }
2955
- return response.status(404).send("Not found");
2956
- }
2957
- };
2958
-
2959
2800
  // src/lib/projectionSearchFilter.ts
2960
2801
  import perplex2 from "perplex";
2961
2802
  import Parser2 from "pratt";
2962
- var parseFilterExpression = (filter, staged) => {
2803
+ var parseFilterExpression = (filter) => {
2963
2804
  const exprFunc = generateMatchFunc2(filter);
2964
2805
  const [source] = filter.split(":", 1);
2965
2806
  if (source.startsWith("variants.")) {
2966
- return filterVariants(source, staged, exprFunc);
2807
+ return filterVariants(source, exprFunc);
2967
2808
  }
2968
2809
  return filterProduct(source, exprFunc);
2969
2810
  };
2970
- var getLexer2 = (value) => {
2971
- return new perplex2(value).token("MISSING", /missing(?![-_a-z0-9]+)/i).token("EXISTS", /exists(?![-_a-z0-9]+)/i).token("RANGE", /range(?![-_a-z0-9]+)/i).token("TO", /to(?![-_a-z0-9]+)/i).token("IDENTIFIER", /[-_\.a-z]+/i).token("FLOAT", /\d+\.\d+/).token("INT", /\d+/).token("STRING", /"((?:\\.|[^"\\])*)"/).token("STRING", /'((?:\\.|[^'\\])*)'/).token("COMMA", ",").token("STAR", "*").token("(", "(").token(":", ":").token(")", ")").token('"', '"').token("WS", /\s+/, true);
2972
- };
2811
+ var getLexer2 = (value) => new perplex2(value).token("MISSING", /missing(?![-_a-z0-9]+)/i).token("EXISTS", /exists(?![-_a-z0-9]+)/i).token("RANGE", /range(?![-_a-z0-9]+)/i).token("TO", /to(?![-_a-z0-9]+)/i).token("IDENTIFIER", /[-_.a-z]+/i).token("FLOAT", /\d+\.\d+/).token("INT", /\d+/).token("STRING", /"((?:\\.|[^"\\])*)"/).token("STRING", /'((?:\\.|[^'\\])*)'/).token("COMMA", ",").token("STAR", "*").token("(", "(").token(":", ":").token(")", ")").token('"', '"').token("WS", /\s+/, true);
2973
2812
  var parseFilter = (filter) => {
2974
2813
  const lexer = getLexer2(filter);
2975
- const parser = new Parser2(lexer).builder().nud("IDENTIFIER", 100, (t) => {
2976
- return t.token.match;
2977
- }).led(":", 100, ({ left, bp }) => {
2978
- let parsed = parser.parse({ terminals: [bp - 1] });
2979
- let expressions;
2980
- expressions = !Array.isArray(parsed) ? [parsed] : parsed;
2814
+ const parser = new Parser2(lexer).builder().nud("IDENTIFIER", 100, (t) => t.token.match).led(":", 100, ({ left, bp }) => {
2815
+ const parsed = parser.parse({ terminals: [bp - 1] });
2816
+ const expressions = !Array.isArray(parsed) ? [parsed] : parsed;
2981
2817
  const unique = new Set(expressions.map((expr) => expr.type));
2982
2818
  if (unique.size > 1) {
2983
2819
  throw new Error("Invalid expression");
@@ -2992,9 +2828,7 @@ var parseFilter = (filter) => {
2992
2828
  }
2993
2829
  return {
2994
2830
  type: "FilterExpression",
2995
- match: (obj) => {
2996
- return obj === e.value;
2997
- }
2831
+ match: (obj) => obj === e.value
2998
2832
  };
2999
2833
  })
3000
2834
  };
@@ -3004,39 +2838,41 @@ var parseFilter = (filter) => {
3004
2838
  type: expressions[0].type,
3005
2839
  children: expressions
3006
2840
  };
3007
- }).nud("STRING", 20, (t) => {
3008
- return {
2841
+ }).nud(
2842
+ "STRING",
2843
+ 20,
2844
+ (t) => ({
3009
2845
  type: "Symbol",
3010
2846
  kind: "string",
3011
2847
  value: t.token.groups[1]
3012
- };
3013
- }).nud("INT", 5, (t) => {
3014
- return {
2848
+ })
2849
+ ).nud(
2850
+ "INT",
2851
+ 5,
2852
+ (t) => ({
3015
2853
  type: "Symbol",
3016
2854
  kind: "int",
3017
2855
  value: parseInt(t.token.match, 10)
3018
- };
3019
- }).nud("STAR", 5, (t) => {
3020
- return {
3021
- type: "Symbol",
3022
- kind: "any",
3023
- value: null
3024
- };
3025
- }).nud("EXISTS", 10, ({ bp }) => {
3026
- return {
2856
+ })
2857
+ ).nud("STAR", 5, (_) => ({
2858
+ type: "Symbol",
2859
+ kind: "any",
2860
+ value: null
2861
+ })).nud(
2862
+ "EXISTS",
2863
+ 10,
2864
+ ({ bp }) => ({
3027
2865
  type: "FilterExpression",
3028
- match: (obj) => {
3029
- return obj !== void 0;
3030
- }
3031
- };
3032
- }).nud("MISSING", 10, ({ bp }) => {
3033
- return {
2866
+ match: (obj) => obj !== void 0
2867
+ })
2868
+ ).nud(
2869
+ "MISSING",
2870
+ 10,
2871
+ ({ bp }) => ({
3034
2872
  type: "FilterExpression",
3035
- match: (obj) => {
3036
- return obj === void 0;
3037
- }
3038
- };
3039
- }).led("COMMA", 200, ({ left, token, bp }) => {
2873
+ match: (obj) => obj === void 0
2874
+ })
2875
+ ).led("COMMA", 200, ({ left, token, bp }) => {
3040
2876
  const expr = parser.parse({ terminals: [bp - 1] });
3041
2877
  if (Array.isArray(expr)) {
3042
2878
  return [left, ...expr];
@@ -3061,21 +2897,13 @@ var parseFilter = (filter) => {
3061
2897
  return ranges.map((range) => {
3062
2898
  let func = void 0;
3063
2899
  if (range.start !== null && range.stop !== null) {
3064
- func = (obj) => {
3065
- return obj >= range.start && obj <= range.stop;
3066
- };
2900
+ func = (obj) => obj >= range.start && obj <= range.stop;
3067
2901
  } else if (range.start === null && range.stop !== null) {
3068
- func = (obj) => {
3069
- return obj <= range.stop;
3070
- };
2902
+ func = (obj) => obj <= range.stop;
3071
2903
  } else if (range.start !== null && range.stop === null) {
3072
- func = (obj) => {
3073
- return obj >= range.start;
3074
- };
2904
+ func = (obj) => obj >= range.start;
3075
2905
  } else {
3076
- func = (obj) => {
3077
- return true;
3078
- };
2906
+ func = (obj) => true;
3079
2907
  }
3080
2908
  return {
3081
2909
  type: "RangeExpression",
@@ -3090,8 +2918,6 @@ var parseFilter = (filter) => {
3090
2918
  var generateMatchFunc2 = (filter) => {
3091
2919
  const result = parseFilter(filter);
3092
2920
  if (!result) {
3093
- const lines = filter.split("\n");
3094
- const column = lines[lines.length - 1].length;
3095
2921
  throw new Error(`Syntax error while parsing '${filter}'.`);
3096
2922
  }
3097
2923
  if (result.type == "TermExpression") {
@@ -3112,29 +2938,25 @@ var generateFacetFunc = (filter) => {
3112
2938
  }
3113
2939
  return parseFilter(filter);
3114
2940
  };
3115
- var filterProduct = (source, exprFunc) => {
3116
- return (p, markMatchingVariants) => {
3117
- const value = nestedLookup(p, source);
3118
- return exprFunc(value);
3119
- };
2941
+ var filterProduct = (source, exprFunc) => (p, markMatchingVariants) => {
2942
+ const value = nestedLookup(p, source);
2943
+ return exprFunc(value);
3120
2944
  };
3121
- var filterVariants = (source, staged, exprFunc) => {
3122
- return (p, markMatchingVariants) => {
3123
- const [, ...paths] = source.split(".");
3124
- const path = paths.join(".");
3125
- const variants = getVariants(p, staged);
3126
- for (const variant of variants) {
3127
- const value = resolveVariantValue(variant, path);
3128
- if (exprFunc(value)) {
3129
- if (markMatchingVariants) {
3130
- variants.forEach((v) => v.isMatchingVariant = false);
3131
- variant.isMatchingVariant = true;
3132
- }
3133
- return true;
2945
+ var filterVariants = (source, exprFunc) => (p, markMatchingVariants) => {
2946
+ const [, ...paths] = source.split(".");
2947
+ const path = paths.join(".");
2948
+ const variants = getVariants(p);
2949
+ for (const variant of variants) {
2950
+ const value = resolveVariantValue(variant, path);
2951
+ if (exprFunc(value)) {
2952
+ if (markMatchingVariants) {
2953
+ variants.forEach((v) => v.isMatchingVariant = false);
2954
+ variant.isMatchingVariant = true;
3134
2955
  }
2956
+ return true;
3135
2957
  }
3136
- return false;
3137
- };
2958
+ }
2959
+ return false;
3138
2960
  };
3139
2961
  var resolveVariantValue = (obj, path) => {
3140
2962
  if (path === void 0) {
@@ -3159,27 +2981,22 @@ var resolveVariantValue = (obj, path) => {
3159
2981
  }
3160
2982
  return nestedLookup(obj, path);
3161
2983
  };
3162
- var getVariants = (p, staged) => {
3163
- var _a, _b, _c, _d;
3164
- return [
3165
- staged ? (_a = p.masterData.staged) == null ? void 0 : _a.masterVariant : (_b = p.masterData.current) == null ? void 0 : _b.masterVariant,
3166
- ...staged ? (_c = p.masterData.staged) == null ? void 0 : _c.variants : (_d = p.masterData.current) == null ? void 0 : _d.variants
3167
- ];
3168
- };
2984
+ var getVariants = (p) => [
2985
+ p.masterVariant,
2986
+ ...p.variants ?? []
2987
+ ];
3169
2988
 
3170
2989
  // src/priceSelector.ts
3171
2990
  var applyPriceSelector = (products, selector) => {
3172
- var _a, _b, _c, _d, _e;
2991
+ var _a;
3173
2992
  validatePriceSelector(selector);
3174
2993
  for (const product of products) {
3175
2994
  const variants = [
3176
- (_a = product.masterData.staged) == null ? void 0 : _a.masterVariant,
3177
- ...((_b = product.masterData.staged) == null ? void 0 : _b.variants) || [],
3178
- (_c = product.masterData.current) == null ? void 0 : _c.masterVariant,
3179
- ...((_d = product.masterData.current) == null ? void 0 : _d.variants) || []
2995
+ product.masterVariant,
2996
+ ...product.variants ?? []
3180
2997
  ].filter((x) => x != void 0);
3181
2998
  for (const variant of variants) {
3182
- const scopedPrices = ((_e = variant.prices) == null ? void 0 : _e.filter((p) => priceSelectorFilter(p, selector))) ?? [];
2999
+ const scopedPrices = ((_a = variant.prices) == null ? void 0 : _a.filter((p) => priceSelectorFilter(p, selector))) ?? [];
3183
3000
  if (scopedPrices.length > 0) {
3184
3001
  const price = scopedPrices[0];
3185
3002
  variant.scopedPriceDiscounted = false;
@@ -3225,8 +3042,13 @@ var ProductProjectionSearch = class {
3225
3042
  this._storage = storage;
3226
3043
  }
3227
3044
  search(projectKey, params) {
3228
- let resources = this._storage.all(projectKey, "product").map((r) => JSON.parse(JSON.stringify(r)));
3229
- let markMatchingVariant = params.markMatchingVariants ?? false;
3045
+ let resources = this._storage.all(projectKey, "product").map((r) => this.transform(r, params.staged ?? false)).filter((p) => p !== null).filter((p) => {
3046
+ if (!params.staged) {
3047
+ return p.published;
3048
+ }
3049
+ return true;
3050
+ });
3051
+ const markMatchingVariant = params.markMatchingVariants ?? false;
3230
3052
  applyPriceSelector(resources, {
3231
3053
  country: params.priceCountry,
3232
3054
  channel: params.priceChannel,
@@ -3235,13 +3057,12 @@ var ProductProjectionSearch = class {
3235
3057
  });
3236
3058
  if (params.filter) {
3237
3059
  try {
3238
- const filters = params.filter.map(
3239
- (f) => parseFilterExpression(f, params.staged ?? false)
3240
- );
3060
+ const filters = params.filter.map(parseFilterExpression);
3241
3061
  resources = resources.filter(
3242
3062
  (resource) => filters.every((f) => f(resource, markMatchingVariant))
3243
3063
  );
3244
3064
  } catch (err) {
3065
+ console.error(err);
3245
3066
  throw new CommercetoolsError(
3246
3067
  {
3247
3068
  code: "InvalidInput",
@@ -3254,9 +3075,7 @@ var ProductProjectionSearch = class {
3254
3075
  const facets = this.getFacets(params, resources);
3255
3076
  if (params["filter.query"]) {
3256
3077
  try {
3257
- const filters = params["filter.query"].map(
3258
- (f) => parseFilterExpression(f, params.staged ?? false)
3259
- );
3078
+ const filters = params["filter.query"].map(parseFilterExpression);
3260
3079
  resources = resources.filter(
3261
3080
  (resource) => filters.every((f) => f(resource, markMatchingVariant))
3262
3081
  );
@@ -3270,26 +3089,28 @@ var ProductProjectionSearch = class {
3270
3089
  );
3271
3090
  }
3272
3091
  }
3273
- const totalResources = resources.length;
3274
- const offset = params.offset || 0;
3275
- const limit = params.limit || 20;
3276
- resources = resources.slice(offset, offset + limit);
3277
3092
  if (params.expand !== void 0) {
3278
- resources = resources.map((resource) => {
3279
- return this._storage.expand(projectKey, resource, params.expand);
3280
- });
3093
+ resources = resources.map(
3094
+ (resource) => this._storage.expand(projectKey, resource, params.expand)
3095
+ );
3281
3096
  }
3097
+ const totalResults = resources.length;
3098
+ const offset = params.offset || 0;
3099
+ const limit = params.limit || 20;
3100
+ const results = resources.slice(offset, offset + limit);
3282
3101
  return {
3283
- count: totalResources,
3284
- total: resources.length,
3102
+ count: totalResults,
3103
+ total: results.length,
3285
3104
  offset,
3286
3105
  limit,
3287
- results: resources.map(this.transform),
3106
+ results,
3288
3107
  facets
3289
3108
  };
3290
3109
  }
3291
- transform(product) {
3292
- const obj = product.masterData.current;
3110
+ transform(product, staged) {
3111
+ const obj = !staged ? product.masterData.current : product.masterData.staged;
3112
+ if (!obj)
3113
+ return null;
3293
3114
  return {
3294
3115
  id: product.id,
3295
3116
  createdAt: product.createdAt,
@@ -3303,7 +3124,9 @@ var ProductProjectionSearch = class {
3303
3124
  categories: obj.categories,
3304
3125
  masterVariant: obj.masterVariant,
3305
3126
  variants: obj.variants,
3306
- productType: product.productType
3127
+ productType: product.productType,
3128
+ hasStagedChanges: product.masterData.hasStagedChanges,
3129
+ published: product.masterData.published
3307
3130
  };
3308
3131
  }
3309
3132
  getFacets(params, products) {
@@ -3314,28 +3137,26 @@ var ProductProjectionSearch = class {
3314
3137
  for (const facet of params.facet) {
3315
3138
  const expression = generateFacetFunc(facet);
3316
3139
  if (expression.type === "TermExpression") {
3317
- result[facet] = this.termFacet(expression.source, products, staged);
3140
+ result[facet] = this.termFacet(expression.source, products);
3318
3141
  }
3319
3142
  if (expression.type === "RangeExpression") {
3320
3143
  result[expression.source] = this.rangeFacet(
3321
3144
  expression.source,
3322
3145
  expression.children,
3323
- products,
3324
- staged
3146
+ products
3325
3147
  );
3326
3148
  }
3327
3149
  if (expression.type === "FilterExpression") {
3328
3150
  result[expression.source] = this.filterFacet(
3329
3151
  expression.source,
3330
3152
  expression.children,
3331
- products,
3332
- staged
3153
+ products
3333
3154
  );
3334
3155
  }
3335
3156
  }
3336
3157
  return result;
3337
3158
  }
3338
- termFacet(facet, products, staged) {
3159
+ termFacet(facet, products) {
3339
3160
  const result = {
3340
3161
  type: "terms",
3341
3162
  dataType: "text",
@@ -3347,7 +3168,7 @@ var ProductProjectionSearch = class {
3347
3168
  const terms = {};
3348
3169
  if (facet.startsWith("variants.")) {
3349
3170
  products.forEach((p) => {
3350
- const variants = getVariants(p, staged);
3171
+ const variants = getVariants(p);
3351
3172
  variants.forEach((v) => {
3352
3173
  result.total++;
3353
3174
  let value = resolveVariantValue(v, facet);
@@ -3380,11 +3201,11 @@ var ProductProjectionSearch = class {
3380
3201
  }
3381
3202
  return result;
3382
3203
  }
3383
- filterFacet(source, filters, products, staged) {
3204
+ filterFacet(source, filters, products) {
3384
3205
  let count = 0;
3385
3206
  if (source.startsWith("variants.")) {
3386
3207
  for (const p of products) {
3387
- for (const v of getVariants(p, staged)) {
3208
+ for (const v of getVariants(p)) {
3388
3209
  const val = resolveVariantValue(v, source);
3389
3210
  if (filters == null ? void 0 : filters.some((f) => f.match(val))) {
3390
3211
  count++;
@@ -3399,12 +3220,12 @@ var ProductProjectionSearch = class {
3399
3220
  count
3400
3221
  };
3401
3222
  }
3402
- rangeFacet(source, ranges, products, staged) {
3223
+ rangeFacet(source, ranges, products) {
3403
3224
  const counts = (ranges == null ? void 0 : ranges.map((range) => {
3404
3225
  if (source.startsWith("variants.")) {
3405
3226
  const values = [];
3406
3227
  for (const p of products) {
3407
- for (const v of getVariants(p, staged)) {
3228
+ for (const v of getVariants(p)) {
3408
3229
  const val = resolveVariantValue(v, source);
3409
3230
  if (val === void 0) {
3410
3231
  continue;
@@ -3475,233 +3296,47 @@ var ProductProjectionRepository = class extends AbstractResourceRepository {
3475
3296
  facet: QueryParamsAsArray(query.facet),
3476
3297
  offset: query.offset ? Number(query.offset) : void 0,
3477
3298
  limit: query.limit ? Number(query.limit) : void 0,
3478
- expand: QueryParamsAsArray(query.expand)
3299
+ expand: QueryParamsAsArray(query.expand),
3300
+ staged: query.staged === "true"
3479
3301
  });
3480
3302
  return results;
3481
3303
  }
3482
3304
  };
3483
3305
 
3484
- // src/services/product-projection.ts
3485
- var ProductProjectionService = class extends AbstractService {
3486
- constructor(parent, storage) {
3487
- super(parent);
3488
- this.repository = new ProductProjectionRepository(storage);
3489
- }
3490
- getBasePath() {
3491
- return "product-projections";
3492
- }
3493
- extraRoutes(router) {
3494
- router.get("/search", this.search.bind(this));
3495
- }
3496
- search(request, response) {
3497
- const resource = this.repository.search(
3498
- getRepositoryContext(request),
3499
- request.query
3500
- );
3501
- return response.status(200).send(resource);
3502
- }
3503
- };
3504
-
3505
- // src/repositories/product.ts
3506
- import { v4 as uuidv47 } from "uuid";
3507
- var ProductRepository = class extends AbstractResourceRepository {
3306
+ // src/repositories/product-type.ts
3307
+ var ProductTypeRepository = class extends AbstractResourceRepository {
3508
3308
  constructor() {
3509
3309
  super(...arguments);
3310
+ this.attributeDefinitionFromAttributeDefinitionDraft = (_context, draft) => ({
3311
+ ...draft,
3312
+ attributeConstraint: draft.attributeConstraint ?? "None",
3313
+ inputHint: draft.inputHint ?? "SingleLine",
3314
+ inputTip: draft.inputTip && Object.keys(draft.inputTip).length > 0 ? draft.inputTip : void 0,
3315
+ isSearchable: draft.isSearchable ?? true
3316
+ });
3510
3317
  this.actions = {
3511
- publish: (context, resource, { scope }) => {
3512
- if (resource.masterData.staged) {
3513
- resource.masterData.current = resource.masterData.staged;
3514
- resource.masterData.staged = void 0;
3515
- }
3516
- resource.masterData.hasStagedChanges = false;
3517
- resource.masterData.published = true;
3518
- },
3519
- setAttribute: (context, resource, { variantId, sku, name, value, staged }) => {
3520
- const isStaged = staged !== void 0 ? staged : false;
3521
- const productData = getProductData(resource, isStaged);
3522
- const { variant, isMasterVariant, variantIndex } = getVariant(
3523
- productData,
3524
- variantId,
3525
- sku
3526
- );
3527
- if (!variant) {
3528
- throw new Error(
3529
- `Variant with id ${variantId} or sku ${sku} not found on product ${resource.id}`
3530
- );
3531
- }
3532
- if (!variant.attributes) {
3533
- variant.attributes = [];
3534
- }
3535
- const existingAttr = variant.attributes.find((attr) => attr.name === name);
3536
- if (existingAttr) {
3537
- existingAttr.value = value;
3538
- } else {
3539
- variant.attributes.push({
3540
- name,
3541
- value
3542
- });
3543
- }
3544
- if (isStaged) {
3545
- resource.masterData.staged = productData;
3546
- if (isMasterVariant) {
3547
- resource.masterData.staged.masterVariant = variant;
3548
- } else {
3549
- resource.masterData.staged.variants[variantIndex] = variant;
3318
+ changeLocalizedEnumValueLabel: (context, resource, {
3319
+ attributeName,
3320
+ newValue
3321
+ }) => {
3322
+ var _a;
3323
+ const updateAttributeType = (type) => {
3324
+ switch (type.name) {
3325
+ case "lenum":
3326
+ type.values.forEach((v) => {
3327
+ if (v.key === newValue.key) {
3328
+ v.label = newValue.label;
3329
+ }
3330
+ });
3331
+ return;
3332
+ case "set":
3333
+ updateAttributeType(type.elementType);
3334
+ return;
3550
3335
  }
3551
- resource.masterData.hasStagedChanges = true;
3552
- } else {
3553
- resource.masterData.current = productData;
3554
- if (isMasterVariant) {
3555
- resource.masterData.current.masterVariant = variant;
3556
- } else {
3557
- resource.masterData.current.variants[variantIndex] = variant;
3558
- }
3559
- }
3560
- }
3561
- };
3562
- }
3563
- getTypeId() {
3564
- return "product";
3565
- }
3566
- create(context, draft) {
3567
- var _a;
3568
- if (!draft.masterVariant) {
3569
- throw new Error("Missing master variant");
3570
- }
3571
- let productType = void 0;
3572
- try {
3573
- productType = getReferenceFromResourceIdentifier(
3574
- draft.productType,
3575
- context.projectKey,
3576
- this._storage
3577
- );
3578
- } catch (err) {
3579
- console.warn(
3580
- `Error resolving product-type '${draft.productType.id}'. This will be throw an error in later releases.`
3581
- );
3582
- productType = {
3583
- typeId: "product-type",
3584
- id: draft.productType.id || ""
3585
- };
3586
- }
3587
- const productData = {
3588
- name: draft.name,
3589
- slug: draft.slug,
3590
- categories: [],
3591
- masterVariant: variantFromDraft(1, draft.masterVariant),
3592
- variants: ((_a = draft.variants) == null ? void 0 : _a.map((variant, index) => {
3593
- return variantFromDraft(index + 2, variant);
3594
- })) ?? [],
3595
- searchKeywords: draft.searchKeywords
3596
- };
3597
- const resource = {
3598
- ...getBaseResourceProperties(),
3599
- productType,
3600
- masterData: {
3601
- current: draft.publish ? productData : void 0,
3602
- staged: draft.publish ? void 0 : productData,
3603
- hasStagedChanges: draft.publish ?? true,
3604
- published: draft.publish ?? false
3605
- }
3606
- };
3607
- this.save(context, resource);
3608
- return resource;
3609
- }
3610
- };
3611
- var getProductData = (product, staged) => {
3612
- if (!staged && product.masterData.current) {
3613
- return product.masterData.current;
3614
- }
3615
- return product.masterData.staged;
3616
- };
3617
- var getVariant = (productData, variantId, sku) => {
3618
- const variants = [productData.masterVariant, ...productData.variants];
3619
- const foundVariant = variants.find((variant) => {
3620
- if (variantId) {
3621
- return variant.id === variantId;
3622
- }
3623
- if (sku) {
3624
- return variant.sku === sku;
3625
- }
3626
- return false;
3627
- });
3628
- const isMasterVariant = foundVariant === productData.masterVariant;
3629
- return {
3630
- variant: foundVariant,
3631
- isMasterVariant,
3632
- variantIndex: !isMasterVariant && foundVariant ? productData.variants.indexOf(foundVariant) : -1
3633
- };
3634
- };
3635
- var variantFromDraft = (variantId, variant) => {
3636
- var _a;
3637
- return {
3638
- id: variantId,
3639
- sku: variant == null ? void 0 : variant.sku,
3640
- attributes: (variant == null ? void 0 : variant.attributes) ?? [],
3641
- prices: (_a = variant == null ? void 0 : variant.prices) == null ? void 0 : _a.map(priceFromDraft),
3642
- assets: [],
3643
- images: []
3644
- };
3645
- };
3646
- var priceFromDraft = (draft) => {
3647
- return {
3648
- id: uuidv47(),
3649
- value: {
3650
- currencyCode: draft.value.currencyCode,
3651
- centAmount: draft.value.centAmount,
3652
- fractionDigits: 2,
3653
- type: "centPrecision"
3654
- }
3655
- };
3656
- };
3657
-
3658
- // src/services/product.ts
3659
- var ProductService = class extends AbstractService {
3660
- constructor(parent, storage) {
3661
- super(parent);
3662
- this.repository = new ProductRepository(storage);
3663
- }
3664
- getBasePath() {
3665
- return "products";
3666
- }
3667
- };
3668
-
3669
- // src/repositories/product-type.ts
3670
- var ProductTypeRepository = class extends AbstractResourceRepository {
3671
- constructor() {
3672
- super(...arguments);
3673
- this.attributeDefinitionFromAttributeDefinitionDraft = (_context, draft) => {
3674
- return {
3675
- ...draft,
3676
- attributeConstraint: draft.attributeConstraint ?? "None",
3677
- inputHint: draft.inputHint ?? "SingleLine",
3678
- inputTip: draft.inputTip && Object.keys(draft.inputTip).length > 0 ? draft.inputTip : void 0,
3679
- isSearchable: draft.isSearchable ?? true
3680
- };
3681
- };
3682
- this.actions = {
3683
- changeLocalizedEnumValueLabel: (context, resource, {
3684
- attributeName,
3685
- newValue
3686
- }) => {
3687
- var _a;
3688
- const updateAttributeType = (type) => {
3689
- switch (type.name) {
3690
- case "lenum":
3691
- type.values.forEach((v) => {
3692
- if (v.key === newValue.key) {
3693
- v.label = newValue.label;
3694
- }
3695
- });
3696
- return;
3697
- case "set":
3698
- updateAttributeType(type.elementType);
3699
- return;
3700
- }
3701
- };
3702
- (_a = resource.attributes) == null ? void 0 : _a.forEach((value) => {
3703
- if (value.name === attributeName) {
3704
- updateAttributeType(value.type);
3336
+ };
3337
+ (_a = resource.attributes) == null ? void 0 : _a.forEach((value) => {
3338
+ if (value.name === attributeName) {
3339
+ updateAttributeType(value.type);
3705
3340
  }
3706
3341
  });
3707
3342
  },
@@ -3721,7 +3356,9 @@ var ProductTypeRepository = class extends AbstractResourceRepository {
3721
3356
  },
3722
3357
  changeAttributeOrder: (context, resource, { attributes }) => {
3723
3358
  var _a;
3724
- const attrs = new Map((_a = resource.attributes) == null ? void 0 : _a.map((item) => [item.name, item]));
3359
+ const attrs = new Map(
3360
+ (_a = resource.attributes) == null ? void 0 : _a.map((item) => [item.name, item])
3361
+ );
3725
3362
  const result = [];
3726
3363
  let current = resource.attributes;
3727
3364
  attributes.forEach((iAttr) => {
@@ -3730,9 +3367,7 @@ var ProductTypeRepository = class extends AbstractResourceRepository {
3730
3367
  throw new Error("New attr");
3731
3368
  }
3732
3369
  result.push(attr);
3733
- current = current == null ? void 0 : current.filter((f) => {
3734
- return f.name !== iAttr.name;
3735
- });
3370
+ current = current == null ? void 0 : current.filter((f) => f.name !== iAttr.name);
3736
3371
  });
3737
3372
  resource.attributes = result;
3738
3373
  if (current) {
@@ -3741,25 +3376,21 @@ var ProductTypeRepository = class extends AbstractResourceRepository {
3741
3376
  },
3742
3377
  removeAttributeDefinition: (context, resource, { name }) => {
3743
3378
  var _a;
3744
- resource.attributes = (_a = resource.attributes) == null ? void 0 : _a.filter((f) => {
3745
- return f.name !== name;
3746
- });
3379
+ resource.attributes = (_a = resource.attributes) == null ? void 0 : _a.filter((f) => f.name !== name);
3747
3380
  },
3748
3381
  removeEnumValues: (context, resource, { attributeName, keys }) => {
3749
3382
  var _a;
3750
3383
  (_a = resource.attributes) == null ? void 0 : _a.forEach((attr) => {
3751
3384
  if (attr.name == attributeName) {
3752
3385
  if (attr.type.name == "enum") {
3753
- attr.type.values = attr.type.values.filter((v) => {
3754
- return !keys.includes(v.key);
3755
- });
3386
+ attr.type.values = attr.type.values.filter(
3387
+ (v) => !keys.includes(v.key)
3388
+ );
3756
3389
  }
3757
3390
  if (attr.type.name == "set") {
3758
3391
  if (attr.type.elementType.name == "enum") {
3759
3392
  attr.type.elementType.values = attr.type.elementType.values.filter(
3760
- (v) => {
3761
- return !keys.includes(v.key);
3762
- }
3393
+ (v) => !keys.includes(v.key)
3763
3394
  );
3764
3395
  }
3765
3396
  }
@@ -3781,7 +3412,7 @@ var ProductTypeRepository = class extends AbstractResourceRepository {
3781
3412
  (a) => this.attributeDefinitionFromAttributeDefinitionDraft(context, a)
3782
3413
  )
3783
3414
  };
3784
- this.save(context, resource);
3415
+ this.saveNew(context, resource);
3785
3416
  return resource;
3786
3417
  }
3787
3418
  getWithKey(context, key) {
@@ -3798,30 +3429,6 @@ var ProductTypeRepository = class extends AbstractResourceRepository {
3798
3429
  }
3799
3430
  };
3800
3431
 
3801
- // src/services/product-type.ts
3802
- var ProductTypeService = class extends AbstractService {
3803
- constructor(parent, storage) {
3804
- super(parent);
3805
- this.repository = new ProductTypeRepository(storage);
3806
- }
3807
- getBasePath() {
3808
- return "product-types";
3809
- }
3810
- extraRoutes(router) {
3811
- router.get("/key=:key", this.getWithKey.bind(this));
3812
- }
3813
- getWithKey(request, response) {
3814
- const resource = this.repository.getWithKey(
3815
- getRepositoryContext(request),
3816
- request.params.key
3817
- );
3818
- if (resource) {
3819
- return response.status(200).send(resource);
3820
- }
3821
- return response.status(404).send("Not found");
3822
- }
3823
- };
3824
-
3825
3432
  // src/repositories/project.ts
3826
3433
  var ProjectRepository = class extends AbstractRepository {
3827
3434
  constructor() {
@@ -3883,64 +3490,21 @@ var ProjectRepository = class extends AbstractRepository {
3883
3490
  }
3884
3491
  postProcessResource(resource) {
3885
3492
  if (resource) {
3886
- return maskSecretValue(
3887
- resource,
3888
- "externalOAuth.authorizationHeader"
3889
- );
3493
+ return maskSecretValue(resource, "externalOAuth.authorizationHeader");
3890
3494
  }
3891
3495
  return resource;
3892
3496
  }
3893
- save(context, resource) {
3894
- const current = this.get(context);
3895
- if (current) {
3896
- checkConcurrentModification(current, resource.version);
3897
- } else {
3898
- if (resource.version !== 0) {
3899
- throw new CommercetoolsError(
3900
- {
3901
- code: "InvalidOperation",
3902
- message: "version on create must be 0"
3903
- },
3904
- 400
3905
- );
3906
- }
3907
- }
3908
- resource.version += 1;
3497
+ saveNew(context, resource) {
3498
+ resource.version = 1;
3909
3499
  this._storage.saveProject(resource);
3910
3500
  }
3911
- };
3912
-
3913
- // src/services/project.ts
3914
- var ProjectService = class {
3915
- constructor(parent, storage) {
3916
- this.repository = new ProjectRepository(storage);
3917
- this.registerRoutes(parent);
3918
- }
3919
- registerRoutes(parent) {
3920
- parent.get("", this.get.bind(this));
3921
- parent.post("", this.post.bind(this));
3922
- }
3923
- get(request, response) {
3924
- const project = this.repository.get(getRepositoryContext(request));
3925
- return response.status(200).send(project);
3926
- }
3927
- post(request, response) {
3928
- const updateRequest = request.body;
3929
- const project = this.repository.get(getRepositoryContext(request));
3930
- if (!project) {
3931
- return response.status(404).send({});
3932
- }
3933
- this.repository.processUpdateActions(
3934
- getRepositoryContext(request),
3935
- project,
3936
- updateRequest.actions
3937
- );
3938
- return response.status(200).send({});
3501
+ saveUpdate(context, version, resource) {
3502
+ this._storage.saveProject(resource);
3939
3503
  }
3940
3504
  };
3941
3505
 
3942
3506
  // src/repositories/shipping-method.ts
3943
- import deepEqual2 from "deep-equal";
3507
+ import deepEqual3 from "deep-equal";
3944
3508
  var ShippingMethodRepository = class extends AbstractResourceRepository {
3945
3509
  constructor() {
3946
3510
  super(...arguments);
@@ -3956,13 +3520,11 @@ var ShippingMethodRepository = class extends AbstractResourceRepository {
3956
3520
  shippingRates: (_a = draft.shippingRates) == null ? void 0 : _a.map(this._transformShippingRate)
3957
3521
  };
3958
3522
  };
3959
- this._transformShippingRate = (rate) => {
3960
- return {
3961
- price: createTypedMoney(rate.price),
3962
- freeAbove: rate.freeAbove && createTypedMoney(rate.freeAbove),
3963
- tiers: rate.tiers || []
3964
- };
3965
- };
3523
+ this._transformShippingRate = (rate) => ({
3524
+ price: createTypedMoney(rate.price),
3525
+ freeAbove: rate.freeAbove && createTypedMoney(rate.freeAbove),
3526
+ tiers: rate.tiers || []
3527
+ });
3966
3528
  this.actions = {
3967
3529
  addShippingRate: (_context, resource, { shippingRate, zone }) => {
3968
3530
  const rate = this._transformShippingRate(shippingRate);
@@ -3984,9 +3546,9 @@ var ShippingMethodRepository = class extends AbstractResourceRepository {
3984
3546
  const rate = this._transformShippingRate(shippingRate);
3985
3547
  resource.zoneRates.forEach((zoneRate) => {
3986
3548
  if (zoneRate.zone.id === zone.id) {
3987
- zoneRate.shippingRates = zoneRate.shippingRates.filter((otherRate) => {
3988
- return !deepEqual2(rate, otherRate);
3989
- });
3549
+ zoneRate.shippingRates = zoneRate.shippingRates.filter(
3550
+ (otherRate) => !deepEqual3(rate, otherRate)
3551
+ );
3990
3552
  }
3991
3553
  });
3992
3554
  },
@@ -4005,9 +3567,9 @@ var ShippingMethodRepository = class extends AbstractResourceRepository {
4005
3567
  });
4006
3568
  },
4007
3569
  removeZone: (_context, resource, { zone }) => {
4008
- resource.zoneRates = resource.zoneRates.filter((zoneRate) => {
4009
- return zoneRate.zone.id !== zone.id;
4010
- });
3570
+ resource.zoneRates = resource.zoneRates.filter(
3571
+ (zoneRate) => zoneRate.zone.id !== zone.id
3572
+ );
4011
3573
  },
4012
3574
  setKey: (_context, resource, { key }) => {
4013
3575
  resource.key = key;
@@ -4072,26 +3634,11 @@ var ShippingMethodRepository = class extends AbstractResourceRepository {
4072
3634
  this._storage
4073
3635
  )
4074
3636
  };
4075
- this.save(context, resource);
3637
+ this.saveNew(context, resource);
4076
3638
  return resource;
4077
3639
  }
4078
3640
  };
4079
3641
 
4080
- // src/services/shipping-method.ts
4081
- var ShippingMethodService = class extends AbstractService {
4082
- constructor(parent, storage) {
4083
- super(parent);
4084
- this.repository = new ShippingMethodRepository(storage);
4085
- this.registerRoutes(parent);
4086
- }
4087
- getBasePath() {
4088
- return "shipping-methods";
4089
- }
4090
- extraRoutes(parent) {
4091
- parent.get("/matching-cart", this.get.bind(this));
4092
- }
4093
- };
4094
-
4095
3642
  // src/repositories/shopping-list.ts
4096
3643
  var ShoppingListRepository = class extends AbstractResourceRepository {
4097
3644
  getTypeId() {
@@ -4125,22 +3672,11 @@ var ShoppingListRepository = class extends AbstractResourceRepository {
4125
3672
  ) : void 0,
4126
3673
  store: ((_b = draft.store) == null ? void 0 : _b.key) ? { typeId: "store", key: draft.store.key } : void 0
4127
3674
  };
4128
- this.save(context, resource);
3675
+ this.saveNew(context, resource);
4129
3676
  return resource;
4130
3677
  }
4131
3678
  };
4132
3679
 
4133
- // src/services/shopping-list.ts
4134
- var ShoppingListService = class extends AbstractService {
4135
- constructor(parent, storage) {
4136
- super(parent);
4137
- this.repository = new ShoppingListRepository(storage);
4138
- }
4139
- getBasePath() {
4140
- return "shopping-lists";
4141
- }
4142
- };
4143
-
4144
3680
  // src/repositories/state.ts
4145
3681
  var StateRepository = class extends AbstractResourceRepository {
4146
3682
  constructor() {
@@ -4159,12 +3695,12 @@ var StateRepository = class extends AbstractResourceRepository {
4159
3695
  resource.roles = roles;
4160
3696
  },
4161
3697
  setTransitions: (context, resource, { transitions }) => {
4162
- resource.transitions = transitions == null ? void 0 : transitions.map((resourceId) => {
4163
- return {
3698
+ resource.transitions = transitions == null ? void 0 : transitions.map(
3699
+ (resourceId) => ({
4164
3700
  id: resourceId.id || "",
4165
3701
  typeId: "state"
4166
- };
4167
- });
3702
+ })
3703
+ );
4168
3704
  }
4169
3705
  };
4170
3706
  }
@@ -4181,22 +3717,11 @@ var StateRepository = class extends AbstractResourceRepository {
4181
3717
  (t) => getReferenceFromResourceIdentifier(t, context.projectKey, this._storage)
4182
3718
  )
4183
3719
  };
4184
- this.save(context, resource);
3720
+ this.saveNew(context, resource);
4185
3721
  return resource;
4186
3722
  }
4187
3723
  };
4188
3724
 
4189
- // src/services/state.ts
4190
- var StateService = class extends AbstractService {
4191
- constructor(parent, storage) {
4192
- super(parent);
4193
- this.repository = new StateRepository(storage);
4194
- }
4195
- getBasePath() {
4196
- return "states";
4197
- }
4198
- };
4199
-
4200
3725
  // src/repositories/store.ts
4201
3726
  var StoreRepository = class extends AbstractResourceRepository {
4202
3727
  constructor() {
@@ -4258,7 +3783,7 @@ var StoreRepository = class extends AbstractResourceRepository {
4258
3783
  this._storage
4259
3784
  )
4260
3785
  };
4261
- this.save(context, resource);
3786
+ this.saveNew(context, resource);
4262
3787
  return resource;
4263
3788
  }
4264
3789
  transformChannels(context, channels) {
@@ -4286,30 +3811,6 @@ var StoreRepository = class extends AbstractResourceRepository {
4286
3811
  }
4287
3812
  };
4288
3813
 
4289
- // src/services/store.ts
4290
- var StoreService = class extends AbstractService {
4291
- constructor(parent, storage) {
4292
- super(parent);
4293
- this.repository = new StoreRepository(storage);
4294
- }
4295
- getBasePath() {
4296
- return "stores";
4297
- }
4298
- extraRoutes(router) {
4299
- router.get("/key=:key", this.getWithKey.bind(this));
4300
- }
4301
- getWithKey(request, response) {
4302
- const resource = this.repository.getWithKey(
4303
- getRepositoryContext(request),
4304
- request.params.key
4305
- );
4306
- if (resource) {
4307
- return response.status(200).send(resource);
4308
- }
4309
- return response.status(404).send("Not found");
4310
- }
4311
- };
4312
-
4313
3814
  // src/repositories/subscription.ts
4314
3815
  var SubscriptionRepository = class extends AbstractResourceRepository {
4315
3816
  getTypeId() {
@@ -4341,30 +3842,19 @@ var SubscriptionRepository = class extends AbstractResourceRepository {
4341
3842
  messages: draft.messages || [],
4342
3843
  status: "Healthy"
4343
3844
  };
4344
- this.save(context, resource);
3845
+ this.saveNew(context, resource);
4345
3846
  return resource;
4346
3847
  }
4347
3848
  };
4348
3849
 
4349
- // src/services/subscription.ts
4350
- var SubscriptionService = class extends AbstractService {
4351
- constructor(parent, storage) {
4352
- super(parent);
4353
- this.repository = new SubscriptionRepository(storage);
4354
- }
4355
- getBasePath() {
4356
- return "subscriptions";
4357
- }
4358
- };
4359
-
4360
3850
  // src/repositories/tax-category.ts
4361
- import { v4 as uuidv48 } from "uuid";
3851
+ import { v4 as uuidv47 } from "uuid";
4362
3852
  var TaxCategoryRepository = class extends AbstractResourceRepository {
4363
3853
  constructor() {
4364
3854
  super(...arguments);
4365
3855
  this.taxRateFromTaxRateDraft = (draft) => ({
4366
3856
  ...draft,
4367
- id: uuidv48(),
3857
+ id: uuidv47(),
4368
3858
  amount: draft.amount || 0
4369
3859
  });
4370
3860
  this.actions = {
@@ -4378,9 +3868,9 @@ var TaxCategoryRepository = class extends AbstractResourceRepository {
4378
3868
  if (resource.rates === void 0) {
4379
3869
  resource.rates = [];
4380
3870
  }
4381
- resource.rates = resource.rates.filter((taxRate) => {
4382
- return taxRate.id !== taxRateId;
4383
- });
3871
+ resource.rates = resource.rates.filter(
3872
+ (taxRate) => taxRate.id !== taxRateId
3873
+ );
4384
3874
  },
4385
3875
  replaceTaxRate: (context, resource, { taxRateId, taxRate }) => {
4386
3876
  if (resource.rates === void 0) {
@@ -4415,220 +3905,573 @@ var TaxCategoryRepository = class extends AbstractResourceRepository {
4415
3905
  ...draft,
4416
3906
  rates: ((_a = draft.rates) == null ? void 0 : _a.map(this.taxRateFromTaxRateDraft)) || []
4417
3907
  };
4418
- this.save(context, resource);
3908
+ this.saveNew(context, resource);
4419
3909
  return resource;
4420
3910
  }
4421
- getWithKey(context, key) {
4422
- const result = this._storage.query(context.projectKey, this.getTypeId(), {
4423
- where: [`key="${key}"`]
4424
- });
4425
- if (result.count === 1) {
4426
- return result.results[0];
4427
- }
4428
- if (result.count > 1) {
4429
- throw new Error("Duplicate tax category key");
4430
- }
4431
- return;
3911
+ getWithKey(context, key) {
3912
+ const result = this._storage.query(context.projectKey, this.getTypeId(), {
3913
+ where: [`key="${key}"`]
3914
+ });
3915
+ if (result.count === 1) {
3916
+ return result.results[0];
3917
+ }
3918
+ if (result.count > 1) {
3919
+ throw new Error("Duplicate tax category key");
3920
+ }
3921
+ return;
3922
+ }
3923
+ };
3924
+
3925
+ // src/repositories/type.ts
3926
+ import { isEqual } from "lodash";
3927
+ var TypeRepository = class extends AbstractResourceRepository {
3928
+ constructor() {
3929
+ super(...arguments);
3930
+ this.actions = {
3931
+ addFieldDefinition: (context, resource, { fieldDefinition }) => {
3932
+ resource.fieldDefinitions.push(fieldDefinition);
3933
+ },
3934
+ removeFieldDefinition: (context, resource, { fieldName }) => {
3935
+ resource.fieldDefinitions = resource.fieldDefinitions.filter(
3936
+ (f) => f.name !== fieldName
3937
+ );
3938
+ },
3939
+ setDescription: (context, resource, { description }) => {
3940
+ resource.description = description;
3941
+ },
3942
+ changeName: (context, resource, { name }) => {
3943
+ resource.name = name;
3944
+ },
3945
+ changeFieldDefinitionOrder: (context, resource, { fieldNames }) => {
3946
+ const fields = new Map(
3947
+ resource.fieldDefinitions.map((item) => [item.name, item])
3948
+ );
3949
+ const result = [];
3950
+ let current = resource.fieldDefinitions;
3951
+ fieldNames.forEach((fieldName) => {
3952
+ const field = fields.get(fieldName);
3953
+ if (field === void 0) {
3954
+ throw new Error("New field");
3955
+ }
3956
+ result.push(field);
3957
+ current = current.filter((f) => f.name !== fieldName);
3958
+ });
3959
+ if (isEqual(
3960
+ fieldNames,
3961
+ resource.fieldDefinitions.map((item) => item.name)
3962
+ )) {
3963
+ throw new CommercetoolsError({
3964
+ code: "InvalidOperation",
3965
+ message: "'fieldDefinitions' has no changes.",
3966
+ action: {
3967
+ action: "changeFieldDefinitionOrder",
3968
+ fieldNames
3969
+ }
3970
+ });
3971
+ }
3972
+ resource.fieldDefinitions = result;
3973
+ resource.fieldDefinitions.push(...current);
3974
+ },
3975
+ addEnumValue: (context, resource, { fieldName, value }) => {
3976
+ resource.fieldDefinitions.forEach((field) => {
3977
+ if (field.name === fieldName) {
3978
+ if (field.type.name === "Enum") {
3979
+ field.type.values.push(value);
3980
+ } else if (field.type.name === "Set" && field.type.elementType.name === "Enum") {
3981
+ field.type.elementType.values.push(value);
3982
+ } else {
3983
+ throw new Error("Type is not a Enum (or Set of Enum)");
3984
+ }
3985
+ }
3986
+ });
3987
+ },
3988
+ changeEnumValueLabel: (context, resource, { fieldName, value }) => {
3989
+ resource.fieldDefinitions.forEach((field) => {
3990
+ if (field.name === fieldName) {
3991
+ if (field.type.name === "Enum") {
3992
+ field.type.values.forEach((v) => {
3993
+ if (v.key === value.key) {
3994
+ v.label = value.label;
3995
+ }
3996
+ });
3997
+ } else if (field.type.name === "Set" && field.type.elementType.name === "Enum") {
3998
+ field.type.elementType.values.forEach((v) => {
3999
+ if (v.key === value.key) {
4000
+ v.label = value.label;
4001
+ }
4002
+ });
4003
+ } else {
4004
+ throw new Error("Type is not a Enum (or Set of Enum)");
4005
+ }
4006
+ }
4007
+ });
4008
+ }
4009
+ };
4010
+ }
4011
+ getTypeId() {
4012
+ return "type";
4013
+ }
4014
+ create(context, draft) {
4015
+ const resource = {
4016
+ ...getBaseResourceProperties(),
4017
+ key: draft.key,
4018
+ name: draft.name,
4019
+ resourceTypeIds: draft.resourceTypeIds,
4020
+ fieldDefinitions: draft.fieldDefinitions || [],
4021
+ description: draft.description
4022
+ };
4023
+ this.saveNew(context, resource);
4024
+ return resource;
4025
+ }
4026
+ };
4027
+
4028
+ // src/repositories/zone.ts
4029
+ var ZoneRepository = class extends AbstractResourceRepository {
4030
+ constructor() {
4031
+ super(...arguments);
4032
+ this.actions = {
4033
+ addLocation: (context, resource, { location }) => {
4034
+ resource.locations.push(location);
4035
+ },
4036
+ removeLocation: (context, resource, { location }) => {
4037
+ resource.locations = resource.locations.filter(
4038
+ (loc) => !(loc.country === location.country && loc.state === location.state)
4039
+ );
4040
+ },
4041
+ changeName: (context, resource, { name }) => {
4042
+ resource.name = name;
4043
+ },
4044
+ setDescription: (context, resource, { description }) => {
4045
+ resource.description = description;
4046
+ },
4047
+ setKey: (context, resource, { key }) => {
4048
+ resource.key = key;
4049
+ }
4050
+ };
4051
+ }
4052
+ getTypeId() {
4053
+ return "zone";
4054
+ }
4055
+ create(context, draft) {
4056
+ const resource = {
4057
+ ...getBaseResourceProperties(),
4058
+ key: draft.key,
4059
+ locations: draft.locations || [],
4060
+ name: draft.name,
4061
+ description: draft.description
4062
+ };
4063
+ this.saveNew(context, resource);
4064
+ return resource;
4065
+ }
4066
+ };
4067
+
4068
+ // src/repositories/index.ts
4069
+ var createRepositories = (storage) => ({
4070
+ category: new CategoryRepository(storage),
4071
+ cart: new CartRepository(storage),
4072
+ "cart-discount": new CartDiscountRepository(storage),
4073
+ customer: new CustomerRepository(storage),
4074
+ channel: new ChannelRepository(storage),
4075
+ "customer-group": new CustomerGroupRepository(storage),
4076
+ "discount-code": new DiscountCodeRepository(storage),
4077
+ extension: new ExtensionRepository(storage),
4078
+ "inventory-entry": new InventoryEntryRepository(storage),
4079
+ "key-value-document": new CustomObjectRepository(storage),
4080
+ order: new OrderRepository(storage),
4081
+ payment: new PaymentRepository(storage),
4082
+ "my-cart": new CartRepository(storage),
4083
+ "my-order": new MyOrderRepository(storage),
4084
+ "my-customer": new CustomerRepository(storage),
4085
+ "my-payment": new PaymentRepository(storage),
4086
+ "shipping-method": new ShippingMethodRepository(storage),
4087
+ "product-type": new ProductTypeRepository(storage),
4088
+ product: new ProductRepository(storage),
4089
+ project: new ProjectRepository(storage),
4090
+ "product-discount": new ProductDiscountRepository(storage),
4091
+ "product-projection": new ProductProjectionRepository(storage),
4092
+ "shopping-list": new ShoppingListRepository(storage),
4093
+ state: new StateRepository(storage),
4094
+ store: new StoreRepository(storage),
4095
+ subscription: new SubscriptionRepository(storage),
4096
+ "tax-category": new TaxCategoryRepository(storage),
4097
+ type: new TypeRepository(storage),
4098
+ zone: new ZoneRepository(storage)
4099
+ });
4100
+
4101
+ // src/services/abstract.ts
4102
+ import { Router } from "express";
4103
+ var AbstractService = class {
4104
+ constructor(parent) {
4105
+ this.createStatusCode = 201;
4106
+ this.registerRoutes(parent);
4107
+ }
4108
+ extraRoutes(router) {
4109
+ }
4110
+ registerRoutes(parent) {
4111
+ const basePath = this.getBasePath();
4112
+ const router = Router({ mergeParams: true });
4113
+ this.extraRoutes(router);
4114
+ router.get("/", this.get.bind(this));
4115
+ router.get("/key=:key", this.getWithKey.bind(this));
4116
+ router.get("/:id", this.getWithId.bind(this));
4117
+ router.delete("/key=:key", this.deleteWithKey.bind(this));
4118
+ router.delete("/:id", this.deleteWithId.bind(this));
4119
+ router.post("/", this.post.bind(this));
4120
+ router.post("/key=:key", this.postWithKey.bind(this));
4121
+ router.post("/:id", this.postWithId.bind(this));
4122
+ parent.use(`/${basePath}`, router);
4123
+ }
4124
+ get(request, response) {
4125
+ const limit = this._parseParam(request.query.limit);
4126
+ const offset = this._parseParam(request.query.offset);
4127
+ const result = this.repository.query(getRepositoryContext(request), {
4128
+ expand: this._parseParam(request.query.expand),
4129
+ where: this._parseParam(request.query.where),
4130
+ limit: limit !== void 0 ? Number(limit) : void 0,
4131
+ offset: offset !== void 0 ? Number(offset) : void 0
4132
+ });
4133
+ return response.status(200).send(result);
4134
+ }
4135
+ getWithId(request, response) {
4136
+ const result = this._expandWithId(request, request.params["id"]);
4137
+ if (!result) {
4138
+ return response.status(404).send();
4139
+ }
4140
+ return response.status(200).send(result);
4141
+ }
4142
+ getWithKey(request, response) {
4143
+ const result = this.repository.getByKey(
4144
+ getRepositoryContext(request),
4145
+ request.params["key"],
4146
+ { expand: this._parseParam(request.query.expand) }
4147
+ );
4148
+ if (!result)
4149
+ return response.status(404).send();
4150
+ return response.status(200).send(result);
4151
+ }
4152
+ deleteWithId(request, response) {
4153
+ const result = this.repository.delete(
4154
+ getRepositoryContext(request),
4155
+ request.params["id"],
4156
+ {
4157
+ expand: this._parseParam(request.query.expand)
4158
+ }
4159
+ );
4160
+ if (!result) {
4161
+ return response.status(404).send("Not found");
4162
+ }
4163
+ return response.status(200).send(result);
4164
+ }
4165
+ deleteWithKey(request, response) {
4166
+ const resource = this.repository.getByKey(
4167
+ getRepositoryContext(request),
4168
+ request.params["key"]
4169
+ );
4170
+ if (!resource) {
4171
+ return response.status(404).send("Not found");
4172
+ }
4173
+ const result = this.repository.delete(
4174
+ getRepositoryContext(request),
4175
+ resource.id,
4176
+ {
4177
+ expand: this._parseParam(request.query.expand)
4178
+ }
4179
+ );
4180
+ if (!result) {
4181
+ return response.status(404).send("Not found");
4182
+ }
4183
+ return response.status(200).send(result);
4184
+ }
4185
+ post(request, response) {
4186
+ const draft = request.body;
4187
+ const resource = this.repository.create(
4188
+ getRepositoryContext(request),
4189
+ draft
4190
+ );
4191
+ const result = this._expandWithId(request, resource.id);
4192
+ return response.status(this.createStatusCode).send(result);
4193
+ }
4194
+ postWithId(request, response) {
4195
+ const updateRequest = request.body;
4196
+ const resource = this.repository.get(
4197
+ getRepositoryContext(request),
4198
+ request.params["id"]
4199
+ );
4200
+ if (!resource) {
4201
+ return response.status(404).send("Not found");
4202
+ }
4203
+ const updatedResource = this.repository.processUpdateActions(
4204
+ getRepositoryContext(request),
4205
+ resource,
4206
+ updateRequest.version,
4207
+ updateRequest.actions
4208
+ );
4209
+ const result = this._expandWithId(request, updatedResource.id);
4210
+ return response.status(200).send(result);
4211
+ }
4212
+ postWithKey(request, response) {
4213
+ const updateRequest = request.body;
4214
+ const resource = this.repository.getByKey(
4215
+ getRepositoryContext(request),
4216
+ request.params["key"]
4217
+ );
4218
+ if (!resource) {
4219
+ return response.status(404).send("Not found");
4220
+ }
4221
+ const updatedResource = this.repository.processUpdateActions(
4222
+ getRepositoryContext(request),
4223
+ resource,
4224
+ updateRequest.version,
4225
+ updateRequest.actions
4226
+ );
4227
+ const result = this._expandWithId(request, updatedResource.id);
4228
+ return response.status(200).send(result);
4229
+ }
4230
+ _expandWithId(request, resourceId) {
4231
+ const result = this.repository.get(
4232
+ getRepositoryContext(request),
4233
+ resourceId,
4234
+ {
4235
+ expand: this._parseParam(request.query.expand)
4236
+ }
4237
+ );
4238
+ return result;
4239
+ }
4240
+ _parseParam(value) {
4241
+ if (Array.isArray(value)) {
4242
+ return value;
4243
+ } else if (value !== void 0) {
4244
+ return [`${value}`];
4245
+ }
4246
+ return void 0;
4247
+ }
4248
+ };
4249
+
4250
+ // src/services/cart.ts
4251
+ var CartService = class extends AbstractService {
4252
+ constructor(parent, cartRepository, orderRepository) {
4253
+ super(parent);
4254
+ this.repository = cartRepository;
4255
+ this.orderRepository = orderRepository;
4256
+ }
4257
+ getBasePath() {
4258
+ return "carts";
4259
+ }
4260
+ extraRoutes(parent) {
4261
+ parent.post("/replicate", (request, response) => {
4262
+ const context = getRepositoryContext(request);
4263
+ const cartOrOrder = request.body.reference.typeId === "order" ? this.orderRepository.get(context, request.body.reference.id) : this.repository.get(context, request.body.reference.id);
4264
+ if (!cartOrOrder) {
4265
+ return response.status(400).send();
4266
+ }
4267
+ const cartDraft = {
4268
+ ...cartOrOrder,
4269
+ currency: cartOrOrder.totalPrice.currencyCode,
4270
+ discountCodes: [],
4271
+ lineItems: cartOrOrder.lineItems.map((lineItem) => ({
4272
+ ...lineItem,
4273
+ variantId: lineItem.variant.id,
4274
+ sku: lineItem.variant.sku
4275
+ }))
4276
+ };
4277
+ const newCart = this.repository.create(context, cartDraft);
4278
+ return response.status(200).send(newCart);
4279
+ });
4280
+ }
4281
+ };
4282
+
4283
+ // src/services/cart-discount.ts
4284
+ var CartDiscountService = class extends AbstractService {
4285
+ constructor(parent, repository) {
4286
+ super(parent);
4287
+ this.repository = repository;
4288
+ }
4289
+ getBasePath() {
4290
+ return "cart-discounts";
4291
+ }
4292
+ };
4293
+
4294
+ // src/services/category.ts
4295
+ var CategoryServices = class extends AbstractService {
4296
+ constructor(parent, repository) {
4297
+ super(parent);
4298
+ this.repository = repository;
4299
+ }
4300
+ getBasePath() {
4301
+ return "categories";
4302
+ }
4303
+ };
4304
+
4305
+ // src/services/channel.ts
4306
+ var ChannelService = class extends AbstractService {
4307
+ constructor(parent, repository) {
4308
+ super(parent);
4309
+ this.repository = repository;
4310
+ }
4311
+ getBasePath() {
4312
+ return "channels";
4432
4313
  }
4433
4314
  };
4434
4315
 
4435
- // src/services/tax-category.ts
4436
- var TaxCategoryService = class extends AbstractService {
4437
- constructor(parent, storage) {
4316
+ // src/services/custom-object.ts
4317
+ var CustomObjectService = class extends AbstractService {
4318
+ constructor(parent, repository) {
4438
4319
  super(parent);
4439
- this.repository = new TaxCategoryRepository(storage);
4320
+ this.repository = repository;
4440
4321
  }
4441
4322
  getBasePath() {
4442
- return "tax-categories";
4323
+ return "custom-objects";
4443
4324
  }
4444
4325
  extraRoutes(router) {
4445
- router.get("/key=:key", this.getWithKey.bind(this));
4326
+ router.get("/:container/:key", this.getWithContainerAndKey.bind(this));
4327
+ router.post("/:container/:key", this.createWithContainerAndKey.bind(this));
4328
+ router.delete("/:container/:key", this.deleteWithContainerAndKey.bind(this));
4446
4329
  }
4447
- getWithKey(request, response) {
4448
- const resource = this.repository.getWithKey(
4330
+ getWithContainerAndKey(request, response) {
4331
+ const result = this.repository.getWithContainerAndKey(
4449
4332
  getRepositoryContext(request),
4333
+ request.params.container,
4450
4334
  request.params.key
4451
4335
  );
4452
- if (resource) {
4453
- return response.status(200).send(resource);
4336
+ if (!result) {
4337
+ return response.status(404).send("Not Found");
4454
4338
  }
4455
- return response.status(404).send("Not found");
4339
+ return response.status(200).send(result);
4340
+ }
4341
+ createWithContainerAndKey(request, response) {
4342
+ const draft = {
4343
+ ...request.body,
4344
+ key: request.params.key,
4345
+ container: request.params.container
4346
+ };
4347
+ const result = this.repository.create(getRepositoryContext(request), draft);
4348
+ return response.status(200).send(result);
4349
+ }
4350
+ deleteWithContainerAndKey(request, response) {
4351
+ const current = this.repository.getWithContainerAndKey(
4352
+ getRepositoryContext(request),
4353
+ request.params.container,
4354
+ request.params.key
4355
+ );
4356
+ if (!current) {
4357
+ return response.status(404).send("Not Found");
4358
+ }
4359
+ const result = this.repository.delete(
4360
+ getRepositoryContext(request),
4361
+ current.id
4362
+ );
4363
+ return response.status(200).send(result);
4456
4364
  }
4457
4365
  };
4458
4366
 
4459
- // src/repositories/type.ts
4460
- import { isEqual } from "lodash";
4461
- var TypeRepository = class extends AbstractResourceRepository {
4462
- constructor() {
4463
- super(...arguments);
4464
- this.actions = {
4465
- addFieldDefinition: (context, resource, { fieldDefinition }) => {
4466
- resource.fieldDefinitions.push(fieldDefinition);
4467
- },
4468
- removeFieldDefinition: (context, resource, { fieldName }) => {
4469
- resource.fieldDefinitions = resource.fieldDefinitions.filter((f) => {
4470
- return f.name !== fieldName;
4471
- });
4472
- },
4473
- setDescription: (context, resource, { description }) => {
4474
- resource.description = description;
4475
- },
4476
- changeName: (context, resource, { name }) => {
4477
- resource.name = name;
4478
- },
4479
- changeFieldDefinitionOrder: (context, resource, { fieldNames }) => {
4480
- const fields = new Map(
4481
- resource.fieldDefinitions.map((item) => [item.name, item])
4482
- );
4483
- const result = [];
4484
- let current = resource.fieldDefinitions;
4485
- fieldNames.forEach((fieldName) => {
4486
- const field = fields.get(fieldName);
4487
- if (field === void 0) {
4488
- throw new Error("New field");
4489
- }
4490
- result.push(field);
4491
- current = current.filter((f) => {
4492
- return f.name !== fieldName;
4493
- });
4494
- });
4495
- if (isEqual(
4496
- fieldNames,
4497
- resource.fieldDefinitions.map((item) => item.name)
4498
- )) {
4499
- throw new CommercetoolsError({
4500
- code: "InvalidOperation",
4501
- message: "'fieldDefinitions' has no changes.",
4502
- action: {
4503
- action: "changeFieldDefinitionOrder",
4504
- fieldNames
4505
- }
4506
- });
4507
- }
4508
- resource.fieldDefinitions = result;
4509
- resource.fieldDefinitions.push(...current);
4510
- },
4511
- addEnumValue: (context, resource, { fieldName, value }) => {
4512
- resource.fieldDefinitions.forEach((field) => {
4513
- if (field.name === fieldName) {
4514
- if (field.type.name === "Enum") {
4515
- field.type.values.push(value);
4516
- } else if (field.type.name === "Set" && field.type.elementType.name === "Enum") {
4517
- field.type.elementType.values.push(value);
4518
- } else {
4519
- throw new Error("Type is not a Enum (or Set of Enum)");
4520
- }
4521
- }
4522
- });
4523
- },
4524
- changeEnumValueLabel: (context, resource, { fieldName, value }) => {
4525
- resource.fieldDefinitions.forEach((field) => {
4526
- if (field.name === fieldName) {
4527
- if (field.type.name === "Enum") {
4528
- field.type.values.forEach((v) => {
4529
- if (v.key === value.key) {
4530
- v.label = value.label;
4531
- }
4532
- });
4533
- } else if (field.type.name === "Set" && field.type.elementType.name === "Enum") {
4534
- field.type.elementType.values.forEach((v) => {
4535
- if (v.key === value.key) {
4536
- v.label = value.label;
4537
- }
4538
- });
4539
- } else {
4540
- throw new Error("Type is not a Enum (or Set of Enum)");
4541
- }
4542
- }
4543
- });
4544
- }
4545
- };
4367
+ // src/services/customer.ts
4368
+ import { v4 as uuidv48 } from "uuid";
4369
+ var CustomerService = class extends AbstractService {
4370
+ constructor(parent, repository) {
4371
+ super(parent);
4372
+ this.repository = repository;
4546
4373
  }
4547
- getTypeId() {
4548
- return "type";
4374
+ getBasePath() {
4375
+ return "customers";
4549
4376
  }
4550
- create(context, draft) {
4551
- const resource = {
4552
- ...getBaseResourceProperties(),
4553
- key: draft.key,
4554
- name: draft.name,
4555
- resourceTypeIds: draft.resourceTypeIds,
4556
- fieldDefinitions: draft.fieldDefinitions || [],
4557
- description: draft.description
4558
- };
4559
- this.save(context, resource);
4560
- return resource;
4377
+ extraRoutes(parent) {
4378
+ parent.post("/password-token", (request, response) => {
4379
+ const customer = this.repository.query(getRepositoryContext(request), {
4380
+ where: [`email="${request.body.email}"`]
4381
+ });
4382
+ const ttlMinutes = request.params.ttlMinutes ? +request.params.ttlMinutes : 34560;
4383
+ const { version, ...rest } = getBaseResourceProperties();
4384
+ return response.status(200).send({
4385
+ ...rest,
4386
+ customerId: customer.results[0].id,
4387
+ expiresAt: new Date(Date.now() + ttlMinutes * 60).toISOString(),
4388
+ value: uuidv48()
4389
+ });
4390
+ });
4561
4391
  }
4562
4392
  };
4563
4393
 
4564
- // src/services/type.ts
4565
- var TypeService = class extends AbstractService {
4566
- constructor(parent, storage) {
4394
+ // src/services/customer-group.ts
4395
+ var CustomerGroupService = class extends AbstractService {
4396
+ constructor(parent, repository) {
4567
4397
  super(parent);
4568
- this.repository = new TypeRepository(storage);
4398
+ this.repository = repository;
4569
4399
  }
4570
4400
  getBasePath() {
4571
- return "types";
4401
+ return "customer-groups";
4572
4402
  }
4573
4403
  };
4574
4404
 
4575
- // src/repositories/zone.ts
4576
- var ZoneRepository = class extends AbstractResourceRepository {
4577
- constructor() {
4578
- super(...arguments);
4579
- this.actions = {
4580
- addLocation: (context, resource, { location }) => {
4581
- resource.locations.push(location);
4582
- },
4583
- removeLocation: (context, resource, { location }) => {
4584
- resource.locations = resource.locations.filter((loc) => {
4585
- return !(loc.country === location.country && loc.state === location.state);
4586
- });
4587
- },
4588
- changeName: (context, resource, { name }) => {
4589
- resource.name = name;
4590
- },
4591
- setDescription: (context, resource, { description }) => {
4592
- resource.description = description;
4593
- },
4594
- setKey: (context, resource, { key }) => {
4595
- resource.key = key;
4596
- }
4597
- };
4405
+ // src/services/discount-code.ts
4406
+ var DiscountCodeService = class extends AbstractService {
4407
+ constructor(parent, repository) {
4408
+ super(parent);
4409
+ this.repository = repository;
4598
4410
  }
4599
- getTypeId() {
4600
- return "zone";
4411
+ getBasePath() {
4412
+ return "discount-codes";
4601
4413
  }
4602
- create(context, draft) {
4603
- const resource = {
4604
- ...getBaseResourceProperties(),
4605
- key: draft.key,
4606
- locations: draft.locations || [],
4607
- name: draft.name,
4608
- description: draft.description
4609
- };
4610
- this.save(context, resource);
4611
- return resource;
4414
+ };
4415
+
4416
+ // src/services/extension.ts
4417
+ var ExtensionServices = class extends AbstractService {
4418
+ constructor(parent, repository) {
4419
+ super(parent);
4420
+ this.repository = repository;
4421
+ }
4422
+ getBasePath() {
4423
+ return "extensions";
4612
4424
  }
4613
4425
  };
4614
4426
 
4615
- // src/services/zone.ts
4616
- var ZoneService = class extends AbstractService {
4617
- constructor(parent, storage) {
4427
+ // src/services/inventory-entry.ts
4428
+ var InventoryEntryService = class extends AbstractService {
4429
+ constructor(parent, repository) {
4618
4430
  super(parent);
4619
- this.repository = new ZoneRepository(storage);
4431
+ this.repository = repository;
4620
4432
  }
4621
4433
  getBasePath() {
4622
- return "zones";
4434
+ return "inventory";
4435
+ }
4436
+ };
4437
+
4438
+ // src/services/my-cart.ts
4439
+ import { Router as Router2 } from "express";
4440
+ var MyCartService = class extends AbstractService {
4441
+ constructor(parent, repository) {
4442
+ super(parent);
4443
+ this.repository = repository;
4444
+ }
4445
+ getBasePath() {
4446
+ return "me";
4447
+ }
4448
+ registerRoutes(parent) {
4449
+ const basePath = this.getBasePath();
4450
+ const router = Router2({ mergeParams: true });
4451
+ this.extraRoutes(router);
4452
+ router.get("/active-cart", this.activeCart.bind(this));
4453
+ router.get("/carts/", this.get.bind(this));
4454
+ router.get("/carts/:id", this.getWithId.bind(this));
4455
+ router.delete("/carts/:id", this.deleteWithId.bind(this));
4456
+ router.post("/carts/", this.post.bind(this));
4457
+ router.post("/carts/:id", this.postWithId.bind(this));
4458
+ parent.use(`/${basePath}`, router);
4459
+ }
4460
+ activeCart(request, response) {
4461
+ const resource = this.repository.getActiveCart(request.params.projectKey);
4462
+ if (!resource) {
4463
+ return response.status(404).send("Not found");
4464
+ }
4465
+ return response.status(200).send(resource);
4623
4466
  }
4624
4467
  };
4625
4468
 
4626
4469
  // src/services/my-customer.ts
4627
4470
  import { Router as Router3 } from "express";
4628
4471
  var MyCustomerService = class extends AbstractService {
4629
- constructor(parent, storage) {
4472
+ constructor(parent, repository) {
4630
4473
  super(parent);
4631
- this.repository = new CustomerRepository(storage);
4474
+ this.repository = repository;
4632
4475
  }
4633
4476
  getBasePath() {
4634
4477
  return "me";
@@ -4681,25 +4524,10 @@ var MyCustomerService = class extends AbstractService {
4681
4524
 
4682
4525
  // src/services/my-order.ts
4683
4526
  import { Router as Router4 } from "express";
4684
-
4685
- // src/repositories/my-order.ts
4686
- import assert3 from "assert";
4687
- var MyOrderRepository = class extends OrderRepository {
4688
- create(context, draft) {
4689
- assert3(draft.id, "draft.id is missing");
4690
- const cartIdentifier = {
4691
- id: draft.id,
4692
- typeId: "cart"
4693
- };
4694
- return this.createFromCart(context, cartIdentifier);
4695
- }
4696
- };
4697
-
4698
- // src/services/my-order.ts
4699
4527
  var MyOrderService = class extends AbstractService {
4700
- constructor(parent, storage) {
4528
+ constructor(parent, repository) {
4701
4529
  super(parent);
4702
- this.repository = new MyOrderRepository(storage);
4530
+ this.repository = repository;
4703
4531
  }
4704
4532
  getBasePath() {
4705
4533
  return "me";
@@ -4710,13 +4538,314 @@ var MyOrderService = class extends AbstractService {
4710
4538
  this.extraRoutes(router);
4711
4539
  router.get("/orders/", this.get.bind(this));
4712
4540
  router.get("/orders/:id", this.getWithId.bind(this));
4713
- router.delete("/orders/:id", this.deletewithId.bind(this));
4541
+ router.delete("/orders/:id", this.deleteWithId.bind(this));
4714
4542
  router.post("/orders/", this.post.bind(this));
4715
4543
  router.post("/orders/:id", this.postWithId.bind(this));
4716
4544
  parent.use(`/${basePath}`, router);
4717
4545
  }
4718
4546
  };
4719
4547
 
4548
+ // src/services/my-payment.ts
4549
+ var MyPaymentService = class extends AbstractService {
4550
+ constructor(parent, repository) {
4551
+ super(parent);
4552
+ this.repository = repository;
4553
+ }
4554
+ getBasePath() {
4555
+ return "me/payments";
4556
+ }
4557
+ };
4558
+
4559
+ // src/services/order.ts
4560
+ var OrderService = class extends AbstractService {
4561
+ constructor(parent, repository) {
4562
+ super(parent);
4563
+ this.repository = repository;
4564
+ }
4565
+ getBasePath() {
4566
+ return "orders";
4567
+ }
4568
+ extraRoutes(router) {
4569
+ router.post("/import", this.import.bind(this));
4570
+ router.get("/order-number=:orderNumber", this.getWithOrderNumber.bind(this));
4571
+ }
4572
+ import(request, response) {
4573
+ const importDraft = request.body;
4574
+ const resource = this.repository.import(
4575
+ getRepositoryContext(request),
4576
+ importDraft
4577
+ );
4578
+ return response.status(200).send(resource);
4579
+ }
4580
+ getWithOrderNumber(request, response) {
4581
+ const resource = this.repository.getWithOrderNumber(
4582
+ getRepositoryContext(request),
4583
+ request.params.orderNumber,
4584
+ request.query
4585
+ );
4586
+ if (resource) {
4587
+ return response.status(200).send(resource);
4588
+ }
4589
+ return response.status(404).send("Not found");
4590
+ }
4591
+ };
4592
+
4593
+ // src/services/payment.ts
4594
+ var PaymentService = class extends AbstractService {
4595
+ constructor(parent, repository) {
4596
+ super(parent);
4597
+ this.repository = repository;
4598
+ }
4599
+ getBasePath() {
4600
+ return "payments";
4601
+ }
4602
+ };
4603
+
4604
+ // src/services/product.ts
4605
+ var ProductService = class extends AbstractService {
4606
+ constructor(parent, repository) {
4607
+ super(parent);
4608
+ this.repository = repository;
4609
+ }
4610
+ getBasePath() {
4611
+ return "products";
4612
+ }
4613
+ };
4614
+
4615
+ // src/services/product-discount.ts
4616
+ var ProductDiscountService = class extends AbstractService {
4617
+ constructor(parent, repository) {
4618
+ super(parent);
4619
+ this.repository = repository;
4620
+ }
4621
+ getBasePath() {
4622
+ return "product-discounts";
4623
+ }
4624
+ extraRoutes(router) {
4625
+ router.get("/key=:key", this.getWithKey.bind(this));
4626
+ }
4627
+ getWithKey(request, response) {
4628
+ const resource = this.repository.getWithKey(
4629
+ getRepositoryContext(request),
4630
+ request.params.key
4631
+ );
4632
+ if (resource) {
4633
+ return response.status(200).send(resource);
4634
+ }
4635
+ return response.status(404).send("Not found");
4636
+ }
4637
+ };
4638
+
4639
+ // src/services/product-projection.ts
4640
+ var ProductProjectionService = class extends AbstractService {
4641
+ constructor(parent, repository) {
4642
+ super(parent);
4643
+ this.repository = repository;
4644
+ }
4645
+ getBasePath() {
4646
+ return "product-projections";
4647
+ }
4648
+ extraRoutes(router) {
4649
+ router.get("/search", this.search.bind(this));
4650
+ }
4651
+ search(request, response) {
4652
+ const resource = this.repository.search(
4653
+ getRepositoryContext(request),
4654
+ request.query
4655
+ );
4656
+ return response.status(200).send(resource);
4657
+ }
4658
+ };
4659
+
4660
+ // src/services/product-type.ts
4661
+ var ProductTypeService = class extends AbstractService {
4662
+ constructor(parent, repository) {
4663
+ super(parent);
4664
+ this.repository = repository;
4665
+ }
4666
+ getBasePath() {
4667
+ return "product-types";
4668
+ }
4669
+ extraRoutes(router) {
4670
+ router.get("/key=:key", this.getWithKey.bind(this));
4671
+ }
4672
+ getWithKey(request, response) {
4673
+ const resource = this.repository.getWithKey(
4674
+ getRepositoryContext(request),
4675
+ request.params.key
4676
+ );
4677
+ if (resource) {
4678
+ return response.status(200).send(resource);
4679
+ }
4680
+ return response.status(404).send("Not found");
4681
+ }
4682
+ };
4683
+
4684
+ // src/services/shipping-method.ts
4685
+ var ShippingMethodService = class extends AbstractService {
4686
+ constructor(parent, repository) {
4687
+ super(parent);
4688
+ this.repository = repository;
4689
+ this.registerRoutes(parent);
4690
+ }
4691
+ getBasePath() {
4692
+ return "shipping-methods";
4693
+ }
4694
+ extraRoutes(parent) {
4695
+ parent.get("/matching-cart", this.get.bind(this));
4696
+ }
4697
+ };
4698
+
4699
+ // src/services/shopping-list.ts
4700
+ var ShoppingListService = class extends AbstractService {
4701
+ constructor(parent, repository) {
4702
+ super(parent);
4703
+ this.repository = repository;
4704
+ }
4705
+ getBasePath() {
4706
+ return "shopping-lists";
4707
+ }
4708
+ };
4709
+
4710
+ // src/services/state.ts
4711
+ var StateService = class extends AbstractService {
4712
+ constructor(parent, repository) {
4713
+ super(parent);
4714
+ this.repository = repository;
4715
+ }
4716
+ getBasePath() {
4717
+ return "states";
4718
+ }
4719
+ };
4720
+
4721
+ // src/services/store.ts
4722
+ var StoreService = class extends AbstractService {
4723
+ constructor(parent, repository) {
4724
+ super(parent);
4725
+ this.repository = repository;
4726
+ }
4727
+ getBasePath() {
4728
+ return "stores";
4729
+ }
4730
+ extraRoutes(router) {
4731
+ router.get("/key=:key", this.getWithKey.bind(this));
4732
+ }
4733
+ getWithKey(request, response) {
4734
+ const resource = this.repository.getWithKey(
4735
+ getRepositoryContext(request),
4736
+ request.params.key
4737
+ );
4738
+ if (resource) {
4739
+ return response.status(200).send(resource);
4740
+ }
4741
+ return response.status(404).send("Not found");
4742
+ }
4743
+ };
4744
+
4745
+ // src/services/subscription.ts
4746
+ var SubscriptionService = class extends AbstractService {
4747
+ constructor(parent, repository) {
4748
+ super(parent);
4749
+ this.repository = repository;
4750
+ }
4751
+ getBasePath() {
4752
+ return "subscriptions";
4753
+ }
4754
+ };
4755
+
4756
+ // src/services/tax-category.ts
4757
+ var TaxCategoryService = class extends AbstractService {
4758
+ constructor(parent, repository) {
4759
+ super(parent);
4760
+ this.repository = repository;
4761
+ }
4762
+ getBasePath() {
4763
+ return "tax-categories";
4764
+ }
4765
+ extraRoutes(router) {
4766
+ router.get("/key=:key", this.getWithKey.bind(this));
4767
+ }
4768
+ getWithKey(request, response) {
4769
+ const resource = this.repository.getWithKey(
4770
+ getRepositoryContext(request),
4771
+ request.params.key
4772
+ );
4773
+ if (resource) {
4774
+ return response.status(200).send(resource);
4775
+ }
4776
+ return response.status(404).send("Not found");
4777
+ }
4778
+ };
4779
+
4780
+ // src/services/type.ts
4781
+ var TypeService = class extends AbstractService {
4782
+ constructor(parent, repository) {
4783
+ super(parent);
4784
+ this.repository = repository;
4785
+ }
4786
+ getBasePath() {
4787
+ return "types";
4788
+ }
4789
+ };
4790
+
4791
+ // src/services/zone.ts
4792
+ var ZoneService = class extends AbstractService {
4793
+ constructor(parent, repository) {
4794
+ super(parent);
4795
+ this.repository = repository;
4796
+ }
4797
+ getBasePath() {
4798
+ return "zones";
4799
+ }
4800
+ };
4801
+
4802
+ // src/services/index.ts
4803
+ var createServices = (router, repos) => ({
4804
+ category: new CategoryServices(router, repos["category"]),
4805
+ cart: new CartService(router, repos["cart"], repos["order"]),
4806
+ "cart-discount": new CartDiscountService(router, repos["cart-discount"]),
4807
+ customer: new CustomerService(router, repos["customer"]),
4808
+ channel: new ChannelService(router, repos["channel"]),
4809
+ "customer-group": new CustomerGroupService(router, repos["customer-group"]),
4810
+ "discount-code": new DiscountCodeService(router, repos["discount-code"]),
4811
+ extension: new ExtensionServices(router, repos["extension"]),
4812
+ "inventory-entry": new InventoryEntryService(
4813
+ router,
4814
+ repos["inventory-entry"]
4815
+ ),
4816
+ "key-value-document": new CustomObjectService(
4817
+ router,
4818
+ repos["key-value-document"]
4819
+ ),
4820
+ order: new OrderService(router, repos["order"]),
4821
+ payment: new PaymentService(router, repos["payment"]),
4822
+ "my-cart": new MyCartService(router, repos["my-cart"]),
4823
+ "my-order": new MyOrderService(router, repos["my-order"]),
4824
+ "my-customer": new MyCustomerService(router, repos["my-customer"]),
4825
+ "my-payment": new MyPaymentService(router, repos["my-payment"]),
4826
+ "shipping-method": new ShippingMethodService(
4827
+ router,
4828
+ repos["shipping-method"]
4829
+ ),
4830
+ "product-type": new ProductTypeService(router, repos["product-type"]),
4831
+ product: new ProductService(router, repos["product"]),
4832
+ "product-discount": new ProductDiscountService(
4833
+ router,
4834
+ repos["product-discount"]
4835
+ ),
4836
+ "product-projection": new ProductProjectionService(
4837
+ router,
4838
+ repos["product-projection"]
4839
+ ),
4840
+ "shopping-list": new ShoppingListService(router, repos["shopping-list"]),
4841
+ state: new StateService(router, repos["state"]),
4842
+ store: new StoreService(router, repos["store"]),
4843
+ subscription: new SubscriptionService(router, repos["subscription"]),
4844
+ "tax-category": new TaxCategoryService(router, repos["tax-category"]),
4845
+ type: new TypeService(router, repos["type"]),
4846
+ zone: new ZoneService(router, repos["zone"])
4847
+ });
4848
+
4720
4849
  // src/ctMock.ts
4721
4850
  var DEFAULT_OPTIONS = {
4722
4851
  enableAuthentication: false,
@@ -4731,6 +4860,7 @@ var CommercetoolsMock = class {
4731
4860
  this._nockScopes = { auth: void 0, api: void 0 };
4732
4861
  this.options = { ...DEFAULT_OPTIONS, ...options };
4733
4862
  this._services = {};
4863
+ this._repositories = {};
4734
4864
  this._projectService = void 0;
4735
4865
  this._storage = new InMemoryStorage();
4736
4866
  this._oauth2 = new OAuth2Server({
@@ -4764,9 +4894,8 @@ var CommercetoolsMock = class {
4764
4894
  );
4765
4895
  }
4766
4896
  runServer(port = 3e3, options) {
4767
- const app = this.createApp(options);
4768
- const server = app.listen(port, () => {
4769
- console.log(`Mock server listening at http://localhost:${port}`);
4897
+ const server = this.app.listen(port, () => {
4898
+ console.info(`Mock server listening at http://localhost:${port}`);
4770
4899
  });
4771
4900
  server.keepAliveTimeout = 60 * 1e3;
4772
4901
  }
@@ -4789,52 +4918,12 @@ var CommercetoolsMock = class {
4789
4918
  app.use("/:projectKey", projectRouter);
4790
4919
  app.use("/:projectKey/in-store/key=:storeKey", projectRouter);
4791
4920
  }
4792
- this._projectService = new ProjectService(projectRouter, this._storage);
4793
- this._services = {
4794
- category: new CategoryServices(projectRouter, this._storage),
4795
- cart: new CartService(projectRouter, this._storage),
4796
- "cart-discount": new CartDiscountService(projectRouter, this._storage),
4797
- customer: new CustomerService(projectRouter, this._storage),
4798
- channel: new ChannelService(projectRouter, this._storage),
4799
- "customer-group": new CustomerGroupService(projectRouter, this._storage),
4800
- "discount-code": new DiscountCodeService(projectRouter, this._storage),
4801
- extension: new ExtensionServices(projectRouter, this._storage),
4802
- "inventory-entry": new InventoryEntryService(
4803
- projectRouter,
4804
- this._storage
4805
- ),
4806
- "key-value-document": new CustomObjectService(
4807
- projectRouter,
4808
- this._storage
4809
- ),
4810
- order: new OrderService(projectRouter, this._storage),
4811
- payment: new PaymentService(projectRouter, this._storage),
4812
- "my-cart": new MyCartService(projectRouter, this._storage),
4813
- "my-order": new MyOrderService(projectRouter, this._storage),
4814
- "my-customer": new MyCustomerService(projectRouter, this._storage),
4815
- "my-payment": new MyPaymentService(projectRouter, this._storage),
4816
- "shipping-method": new ShippingMethodService(
4817
- projectRouter,
4818
- this._storage
4819
- ),
4820
- "product-type": new ProductTypeService(projectRouter, this._storage),
4821
- product: new ProductService(projectRouter, this._storage),
4822
- "product-discount": new ProductDiscountService(
4823
- projectRouter,
4824
- this._storage
4825
- ),
4826
- "product-projection": new ProductProjectionService(
4827
- projectRouter,
4828
- this._storage
4829
- ),
4830
- "shopping-list": new ShoppingListService(projectRouter, this._storage),
4831
- state: new StateService(projectRouter, this._storage),
4832
- store: new StoreService(projectRouter, this._storage),
4833
- subscription: new SubscriptionService(projectRouter, this._storage),
4834
- "tax-category": new TaxCategoryService(projectRouter, this._storage),
4835
- type: new TypeService(projectRouter, this._storage),
4836
- zone: new ZoneService(projectRouter, this._storage)
4837
- };
4921
+ this._repositories = createRepositories(this._storage);
4922
+ this._projectService = new ProjectService(
4923
+ projectRouter,
4924
+ this._repositories.project
4925
+ );
4926
+ this._services = createServices(projectRouter, this._repositories);
4838
4927
  app.use((err, req, resp, next) => {
4839
4928
  if (err instanceof CommercetoolsError) {
4840
4929
  return resp.status(err.statusCode).send({