@labdigital/commercetools-mock 0.6.5 → 0.7.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 (113) hide show
  1. package/package.json +26 -13
  2. package/src/ctMock.ts +5 -0
  3. package/src/helpers.ts +15 -0
  4. package/src/lib/projectionSearchFilter.test.ts +177 -0
  5. package/src/lib/projectionSearchFilter.ts +248 -0
  6. package/src/priceSelector.test.ts +96 -0
  7. package/src/priceSelector.ts +109 -0
  8. package/src/product-projection-search.ts +149 -0
  9. package/src/projectAPI.ts +19 -20
  10. package/src/repositories/category.ts +36 -0
  11. package/src/repositories/channel.ts +104 -0
  12. package/src/repositories/customer-group.ts +37 -0
  13. package/src/repositories/discount-code.ts +37 -0
  14. package/src/repositories/helpers.ts +46 -4
  15. package/src/repositories/product-discount.ts +181 -0
  16. package/src/repositories/product-projection.ts +29 -59
  17. package/src/repositories/product-type.ts +88 -6
  18. package/src/repositories/product.ts +49 -9
  19. package/src/repositories/shipping-method.ts +31 -0
  20. package/src/repositories/store.ts +43 -3
  21. package/src/repositories/type.ts +19 -0
  22. package/src/services/custom-object.test.ts +2 -2
  23. package/src/services/product-discount.ts +33 -0
  24. package/src/services/product-projection.test.ts +171 -116
  25. package/src/services/product.test.ts +12 -0
  26. package/src/storage.ts +116 -58
  27. package/src/types.ts +9 -2
  28. package/dist/commercetools-mock.cjs.development.js +0 -4382
  29. package/dist/commercetools-mock.cjs.development.js.map +0 -1
  30. package/dist/commercetools-mock.cjs.production.min.js +0 -2
  31. package/dist/commercetools-mock.cjs.production.min.js.map +0 -1
  32. package/dist/commercetools-mock.esm.js +0 -4374
  33. package/dist/commercetools-mock.esm.js.map +0 -1
  34. package/dist/constants.d.ts +0 -2
  35. package/dist/ctMock.d.ts +0 -32
  36. package/dist/exceptions.d.ts +0 -12
  37. package/dist/helpers.d.ts +0 -6
  38. package/dist/index.d.ts +0 -3
  39. package/dist/index.js +0 -8
  40. package/dist/lib/expandParser.d.ts +0 -15
  41. package/dist/lib/filterParser.d.ts +0 -1
  42. package/dist/lib/haversine.d.ts +0 -8
  43. package/dist/lib/masking.d.ts +0 -1
  44. package/dist/lib/predicateParser.d.ts +0 -11
  45. package/dist/lib/proxy.d.ts +0 -1
  46. package/dist/oauth/errors.d.ts +0 -8
  47. package/dist/oauth/helpers.d.ts +0 -2
  48. package/dist/oauth/server.d.ts +0 -12
  49. package/dist/oauth/store.d.ts +0 -14
  50. package/dist/projectAPI.d.ts +0 -12
  51. package/dist/repositories/abstract.d.ts +0 -33
  52. package/dist/repositories/cart-discount.d.ts +0 -9
  53. package/dist/repositories/cart.d.ts +0 -21
  54. package/dist/repositories/category.d.ts +0 -18
  55. package/dist/repositories/channel.d.ts +0 -6
  56. package/dist/repositories/custom-object.d.ts +0 -8
  57. package/dist/repositories/customer-group.d.ts +0 -11
  58. package/dist/repositories/customer.d.ts +0 -11
  59. package/dist/repositories/discount-code.d.ts +0 -8
  60. package/dist/repositories/errors.d.ts +0 -2
  61. package/dist/repositories/extension.d.ts +0 -8
  62. package/dist/repositories/helpers.d.ts +0 -10
  63. package/dist/repositories/inventory-entry.d.ts +0 -14
  64. package/dist/repositories/my-order.d.ts +0 -6
  65. package/dist/repositories/order.d.ts +0 -26
  66. package/dist/repositories/payment.d.ts +0 -23
  67. package/dist/repositories/product-projection.d.ts +0 -10
  68. package/dist/repositories/product-type.d.ts +0 -10
  69. package/dist/repositories/product.d.ts +0 -11
  70. package/dist/repositories/project.d.ts +0 -8
  71. package/dist/repositories/shipping-method.d.ts +0 -10
  72. package/dist/repositories/shopping-list.d.ts +0 -6
  73. package/dist/repositories/state.d.ts +0 -8
  74. package/dist/repositories/store.d.ts +0 -10
  75. package/dist/repositories/subscription.d.ts +0 -6
  76. package/dist/repositories/tax-category.d.ts +0 -10
  77. package/dist/repositories/type.d.ts +0 -8
  78. package/dist/repositories/zone.d.ts +0 -8
  79. package/dist/server.d.ts +0 -1
  80. package/dist/services/abstract.d.ts +0 -20
  81. package/dist/services/cart-discount.d.ts +0 -9
  82. package/dist/services/cart.d.ts +0 -12
  83. package/dist/services/category.d.ts +0 -9
  84. package/dist/services/channel.d.ts +0 -9
  85. package/dist/services/custom-object.d.ts +0 -13
  86. package/dist/services/customer-group.d.ts +0 -9
  87. package/dist/services/customer.d.ts +0 -10
  88. package/dist/services/discount-code.d.ts +0 -9
  89. package/dist/services/extension.d.ts +0 -9
  90. package/dist/services/inventory-entry.d.ts +0 -9
  91. package/dist/services/my-cart.d.ts +0 -11
  92. package/dist/services/my-customer.d.ts +0 -13
  93. package/dist/services/my-order.d.ts +0 -10
  94. package/dist/services/my-payment.d.ts +0 -9
  95. package/dist/services/order.d.ts +0 -12
  96. package/dist/services/payment.d.ts +0 -9
  97. package/dist/services/product-projection.d.ts +0 -11
  98. package/dist/services/product-type.d.ts +0 -11
  99. package/dist/services/product.d.ts +0 -9
  100. package/dist/services/project.d.ts +0 -11
  101. package/dist/services/shipping-method.d.ts +0 -10
  102. package/dist/services/shopping-list.d.ts +0 -9
  103. package/dist/services/state.d.ts +0 -9
  104. package/dist/services/store.d.ts +0 -11
  105. package/dist/services/subscription.d.ts +0 -9
  106. package/dist/services/tax-category.d.ts +0 -11
  107. package/dist/services/type.d.ts +0 -9
  108. package/dist/services/zone.d.ts +0 -9
  109. package/dist/storage.d.ts +0 -56
  110. package/dist/types.d.ts +0 -89
  111. package/dist/validate.d.ts +0 -7482
  112. package/src/lib/filterParser.test.ts +0 -15
  113. package/src/lib/filterParser.ts +0 -17
@@ -1,11 +1,15 @@
1
1
  import { v4 as uuidv4 } from 'uuid'
2
2
  import {
3
+ Address,
4
+ BaseAddress,
3
5
  CustomFields,
4
6
  CustomFieldsDraft,
7
+ InvalidJsonInputError,
5
8
  Money,
6
9
  Price,
7
10
  PriceDraft,
8
11
  Reference,
12
+ ReferencedResourceNotFoundError,
9
13
  ResourceIdentifier,
10
14
  Store,
11
15
  StoreKeyReference,
@@ -13,9 +17,26 @@ import {
13
17
  Type,
14
18
  TypedMoney,
15
19
  } from '@commercetools/platform-sdk'
20
+ import { Request } from 'express'
16
21
  import { AbstractStorage } from '../storage'
17
22
  import { RepositoryContext } from './abstract'
18
- import { Request } from 'express'
23
+ import { CommercetoolsError } from '../exceptions'
24
+
25
+ export const createAddress = (
26
+ base: BaseAddress | undefined,
27
+ projectKey: string,
28
+ storage: AbstractStorage
29
+ ): Address | undefined => {
30
+ if (!base) return undefined
31
+
32
+ if (!base?.country) {
33
+ throw new Error('Country is required')
34
+ }
35
+
36
+ return {
37
+ ...base,
38
+ }
39
+ }
19
40
 
20
41
  export const createCustomFields = (
21
42
  draft: CustomFieldsDraft | undefined,
@@ -84,14 +105,35 @@ export const getReferenceFromResourceIdentifier = <T extends Reference>(
84
105
  projectKey: string,
85
106
  storage: AbstractStorage
86
107
  ): T => {
108
+ if (!resourceIdentifier.id && !resourceIdentifier.key) {
109
+ throw new CommercetoolsError<InvalidJsonInputError>(
110
+ {
111
+ code: 'InvalidJsonInput',
112
+ message: `${resourceIdentifier.typeId}: ResourceIdentifier requires an 'id' xor a 'key'`,
113
+ },
114
+ 400
115
+ )
116
+ }
117
+
87
118
  const resource = storage.getByResourceIdentifier(
88
119
  projectKey,
89
120
  resourceIdentifier
90
121
  )
91
- if (!resource)
92
- throw new Error(
93
- `resource type ${resourceIdentifier.typeId} with id ${resourceIdentifier.id} and key ${resourceIdentifier.key} not found`
122
+ if (!resource) {
123
+ const errIdentifier = resourceIdentifier.key
124
+ ? `key '${resourceIdentifier.key}'`
125
+ : `identifier '${resourceIdentifier.key}'`
126
+
127
+ throw new CommercetoolsError<ReferencedResourceNotFoundError>(
128
+ {
129
+ code: 'ReferencedResourceNotFound',
130
+ // @ts-ignore
131
+ typeId: resourceIdentifier.typeId,
132
+ message: `The referenced object of type '${resourceIdentifier.typeId}' with '${errIdentifier}' was not found. It either doesn't exist, or it can't be accessed from this endpoint (e.g., if the endpoint filters by store or customer account).`,
133
+ },
134
+ 400
94
135
  )
136
+ }
95
137
 
96
138
  return ({
97
139
  typeId: resourceIdentifier.typeId,
@@ -0,0 +1,181 @@
1
+ import {
2
+ ProductDiscount,
3
+ ProductDiscountChangeIsActiveAction,
4
+ ProductDiscountChangeNameAction,
5
+ ProductDiscountChangePredicateAction,
6
+ ProductDiscountChangeSortOrderAction,
7
+ ProductDiscountChangeValueAction,
8
+ ProductDiscountDraft,
9
+ ProductDiscountSetDescriptionAction,
10
+ ProductDiscountSetKeyAction,
11
+ ProductDiscountSetValidFromAction,
12
+ ProductDiscountSetValidFromAndUntilAction,
13
+ ProductDiscountSetValidUntilAction,
14
+ ProductDiscountUpdateAction,
15
+ ProductDiscountValue,
16
+ ProductDiscountValueAbsolute,
17
+ ProductDiscountValueDraft,
18
+ ProductDiscountValueExternal,
19
+ ProductDiscountValueRelative,
20
+ ReferenceTypeId,
21
+ } from '@commercetools/platform-sdk'
22
+ import { Writable } from 'types'
23
+ import { getBaseResourceProperties } from '../helpers'
24
+ import { AbstractResourceRepository, RepositoryContext } from './abstract'
25
+ import { createTypedMoney } from './helpers'
26
+
27
+ export class ProductDiscountRepository extends AbstractResourceRepository {
28
+ getTypeId(): ReferenceTypeId {
29
+ return 'product-discount'
30
+ }
31
+
32
+ create(
33
+ context: RepositoryContext,
34
+ draft: ProductDiscountDraft
35
+ ): ProductDiscount {
36
+ const resource: ProductDiscount = {
37
+ ...getBaseResourceProperties(),
38
+ key: draft.key,
39
+ name: draft.name,
40
+ description: draft.description,
41
+ value: this.transformValueDraft(draft.value),
42
+ predicate: draft.predicate,
43
+ sortOrder: draft.sortOrder,
44
+ isActive: draft.isActive || false,
45
+ validFrom: draft.validFrom,
46
+ validUntil: draft.validUntil,
47
+ references: [],
48
+ }
49
+ this.save(context, resource)
50
+ return resource
51
+ }
52
+
53
+ private transformValueDraft(
54
+ value: ProductDiscountValueDraft
55
+ ): ProductDiscountValue {
56
+ switch (value.type) {
57
+ case 'absolute': {
58
+ return {
59
+ type: 'absolute',
60
+ money: value.money.map(createTypedMoney),
61
+ } as ProductDiscountValueAbsolute
62
+ }
63
+ case 'external': {
64
+ return {
65
+ type: 'external',
66
+ } as ProductDiscountValueExternal
67
+ }
68
+ case 'relative': {
69
+ return {
70
+ ...value,
71
+ } as ProductDiscountValueRelative
72
+ }
73
+ }
74
+ }
75
+
76
+ getWithKey(
77
+ context: RepositoryContext,
78
+ key: string
79
+ ): ProductDiscount | undefined {
80
+ const result = this._storage.query(context.projectKey, this.getTypeId(), {
81
+ where: [`key="${key}"`],
82
+ })
83
+ if (result.count === 1) {
84
+ return result.results[0] as ProductDiscount
85
+ }
86
+
87
+ // Catch this for now, should be checked when creating/updating
88
+ if (result.count > 1) {
89
+ throw new Error('Duplicate product discount key')
90
+ }
91
+
92
+ return
93
+ }
94
+
95
+ actions: Partial<
96
+ Record<
97
+ ProductDiscountUpdateAction['action'],
98
+ (
99
+ context: RepositoryContext,
100
+ resource: Writable<ProductDiscount>,
101
+ action: any
102
+ ) => void
103
+ >
104
+ > = {
105
+ setKey: (
106
+ context: RepositoryContext,
107
+ resource: Writable<ProductDiscount>,
108
+ { key }: ProductDiscountSetKeyAction
109
+ ) => {
110
+ resource.key = key
111
+ },
112
+ setDescription: (
113
+ context: RepositoryContext,
114
+ resource: Writable<ProductDiscount>,
115
+ { description }: ProductDiscountSetDescriptionAction
116
+ ) => {
117
+ if (description && Object.keys(description).length > 0) {
118
+ resource.description = description
119
+ } else {
120
+ resource.description = undefined
121
+ }
122
+ },
123
+ changeName: (
124
+ context: RepositoryContext,
125
+ resource: Writable<ProductDiscount>,
126
+ { name }: ProductDiscountChangeNameAction
127
+ ) => {
128
+ resource.name = name
129
+ },
130
+ changeValue: (
131
+ context: RepositoryContext,
132
+ resource: Writable<ProductDiscount>,
133
+ { value }: ProductDiscountChangeValueAction
134
+ ) => {
135
+ resource.value = this.transformValueDraft(value)
136
+ },
137
+ changePredicate: (
138
+ context: RepositoryContext,
139
+ resource: Writable<ProductDiscount>,
140
+ { predicate }: ProductDiscountChangePredicateAction
141
+ ) => {
142
+ resource.predicate = predicate
143
+ },
144
+ changeSortOrder: (
145
+ context: RepositoryContext,
146
+ resource: Writable<ProductDiscount>,
147
+ { sortOrder }: ProductDiscountChangeSortOrderAction
148
+ ) => {
149
+ resource.sortOrder = sortOrder
150
+ },
151
+ changeIsActive: (
152
+ context: RepositoryContext,
153
+ resource: Writable<ProductDiscount>,
154
+ { isActive }: ProductDiscountChangeIsActiveAction
155
+ ) => {
156
+ resource.isActive = isActive
157
+ },
158
+ setValidFrom: (
159
+ context: RepositoryContext,
160
+ resource: Writable<ProductDiscount>,
161
+ { validFrom }: ProductDiscountSetValidFromAction
162
+ ) => {
163
+ resource.validFrom = validFrom
164
+ },
165
+ setValidUntil: (
166
+ context: RepositoryContext,
167
+ resource: Writable<ProductDiscount>,
168
+ { validUntil }: ProductDiscountSetValidUntilAction
169
+ ) => {
170
+ resource.validUntil = validUntil
171
+ },
172
+ setValidFromAndUntil: (
173
+ context: RepositoryContext,
174
+ resource: Writable<ProductDiscount>,
175
+ { validFrom, validUntil }: ProductDiscountSetValidFromAndUntilAction
176
+ ) => {
177
+ resource.validFrom = validFrom
178
+ resource.validUntil = validUntil
179
+ },
180
+ }
181
+ }
@@ -1,81 +1,51 @@
1
1
  import { ParsedQs } from 'qs'
2
+ import { ProductDraft, ProductProjection } from '@commercetools/platform-sdk'
2
3
  import {
3
- ProductDraft,
4
- ProductProjection,
5
- ProductVariant,
6
- ProductVariantDraft,
7
- } from '@commercetools/platform-sdk'
8
- import { getBaseResourceProperties } from '../helpers'
9
- import { AbstractResourceRepository, RepositoryContext } from './abstract'
4
+ AbstractResourceRepository,
5
+ QueryParams,
6
+ RepositoryContext,
7
+ } from './abstract'
10
8
  import { RepositoryTypes } from '../types'
11
- import { parseFilterExpression } from '../lib/filterParser'
9
+ import { AbstractStorage } from '../storage'
10
+ import { ProductProjectionSearch } from '../product-projection-search'
11
+ import { QueryParamsAsArray } from '../helpers'
12
12
 
13
13
  export class ProductProjectionRepository extends AbstractResourceRepository {
14
+ protected _searchService: ProductProjectionSearch
15
+
16
+ constructor(storage: AbstractStorage) {
17
+ super(storage)
18
+ this._searchService = new ProductProjectionSearch(storage)
19
+ }
20
+
14
21
  getTypeId(): RepositoryTypes {
15
22
  return 'product-projection'
16
23
  }
17
24
 
18
25
  create(context: RepositoryContext, draft: ProductDraft): ProductProjection {
19
- if (!draft.masterVariant) {
20
- throw new Error(
21
- `must provider mastervariant for product projection with key ${draft.key}`
22
- )
23
- }
24
-
25
- if (!draft.productType.id) {
26
- throw new Error(
27
- `must provider product type id for product projection with key ${draft.key}`
28
- )
29
- }
30
-
31
- const resource: ProductProjection = {
32
- ...getBaseResourceProperties(),
33
- name: draft.name,
34
- slug: draft.slug,
35
- categories: [],
36
- productType: { ...draft.productType, id: draft.productType.id! },
37
- masterVariant: variantFromDraft(0, draft.masterVariant!),
38
- variants:
39
- draft.variants?.map((variant, index) => {
40
- return variantFromDraft(index + 1, variant)
41
- }) ?? [],
42
-
43
- // @ts-ignore
44
- searchKeywords: draft.searchKeywords,
45
- }
46
-
47
- this.save(context, resource)
26
+ throw new Error('No valid action')
27
+ }
48
28
 
49
- return resource
29
+ query(context: RepositoryContext, params: QueryParams = {}) {
30
+ return this._storage.query(context.projectKey, 'product', {
31
+ expand: params.expand,
32
+ where: params.where,
33
+ offset: params.offset,
34
+ limit: params.limit,
35
+ })
50
36
  }
51
37
 
52
38
  search(context: RepositoryContext, query: ParsedQs) {
53
- const expand = query.expand
54
- ? (query.expand as string | string[])
55
- : undefined
56
- const filter = (query['filter.query'] ?? query.filter) as any
57
- const wherePredicate = filter ? parseFilterExpression(filter) : undefined
58
-
59
- const results = this._storage.query(context.projectKey, this.getTypeId(), {
60
- where: wherePredicate,
39
+ const results = this._searchService.search(context.projectKey, {
40
+ filter: QueryParamsAsArray(query.filter),
41
+ 'filter.query': QueryParamsAsArray(query['filter.query']),
61
42
  offset: query.offset ? Number(query.offset) : undefined,
62
43
  limit: query.limit ? Number(query.limit) : undefined,
63
- expand,
64
- }) //TODO: this is a partial implementation, but I don't really have the time to implement an actual search API right now
44
+ expand: QueryParamsAsArray(query.expand),
45
+ })
65
46
 
66
47
  return results
67
48
  }
68
49
 
69
50
  actions = {}
70
51
  }
71
-
72
- const variantFromDraft = (
73
- variantId: number,
74
- variant: ProductVariantDraft
75
- ): ProductVariant => {
76
- return {
77
- id: variantId,
78
- sku: variant?.sku,
79
- attributes: variant?.attributes,
80
- }
81
- }
@@ -4,9 +4,13 @@ import {
4
4
  AttributeDefinitionDraft,
5
5
  AttributeType,
6
6
  ProductType,
7
+ ProductTypeAddAttributeDefinitionAction,
8
+ ProductTypeChangeAttributeOrderAction,
7
9
  ProductTypeChangeLabelAction,
8
10
  ProductTypeChangeLocalizedEnumValueLabelAction,
9
11
  ProductTypeDraft,
12
+ ProductTypeRemoveAttributeDefinitionAction,
13
+ ProductTypeRemoveEnumValuesAction,
10
14
  ProductTypeUpdateAction,
11
15
  ReferenceTypeId,
12
16
  } from '@commercetools/platform-sdk'
@@ -36,12 +40,18 @@ export class ProductTypeRepository extends AbstractResourceRepository {
36
40
  attributeDefinitionFromAttributeDefinitionDraft = (
37
41
  _context: RepositoryContext,
38
42
  draft: AttributeDefinitionDraft
39
- ): AttributeDefinition => ({
40
- ...draft,
41
- attributeConstraint: draft.attributeConstraint ?? 'None',
42
- inputHint: draft.inputHint ?? 'SingleLine',
43
- isSearchable: draft.isSearchable ?? true,
44
- })
43
+ ): AttributeDefinition => {
44
+ return {
45
+ ...draft,
46
+ attributeConstraint: draft.attributeConstraint ?? 'None',
47
+ inputHint: draft.inputHint ?? 'SingleLine',
48
+ inputTip:
49
+ draft.inputTip && Object.keys(draft.inputTip).length > 0
50
+ ? draft.inputTip
51
+ : undefined,
52
+ isSearchable: draft.isSearchable ?? true,
53
+ }
54
+ }
45
55
 
46
56
  getWithKey(context: RepositoryContext, key: string): ProductType | undefined {
47
57
  const result = this._storage.query(context.projectKey, this.getTypeId(), {
@@ -109,5 +119,77 @@ export class ProductTypeRepository extends AbstractResourceRepository {
109
119
  }
110
120
  })
111
121
  },
122
+ addAttributeDefinition: (
123
+ context: RepositoryContext,
124
+ resource: Writable<ProductType>,
125
+ { attribute }: ProductTypeAddAttributeDefinitionAction
126
+ ) => {
127
+ resource.attributes?.push(
128
+ this.attributeDefinitionFromAttributeDefinitionDraft(context, attribute)
129
+ )
130
+ },
131
+ changeAttributeOrder: (
132
+ context: RepositoryContext,
133
+ resource: Writable<ProductType>,
134
+ { attributes }: ProductTypeChangeAttributeOrderAction
135
+ ) => {
136
+ const attrs = new Map(resource.attributes?.map(item => [item.name, item]))
137
+ const result: AttributeDefinition[] = []
138
+ let current = resource.attributes
139
+
140
+ attributes.forEach(iAttr => {
141
+ const attr = attrs.get(iAttr.name)
142
+ if (attr === undefined) {
143
+ throw new Error('New attr')
144
+ }
145
+ result.push(attr)
146
+
147
+ // Remove from current items
148
+ current = current?.filter(f => {
149
+ return f.name !== iAttr.name
150
+ })
151
+ })
152
+
153
+ resource.attributes = result
154
+ // Add attrs which were not specified in the order as last items. Not
155
+ // sure if this follows commercetools
156
+ if (current) {
157
+ resource.attributes.push(...current)
158
+ }
159
+ },
160
+ removeAttributeDefinition: (
161
+ context: RepositoryContext,
162
+ resource: Writable<ProductType>,
163
+ { name }: ProductTypeRemoveAttributeDefinitionAction
164
+ ) => {
165
+ resource.attributes = resource.attributes?.filter(f => {
166
+ return f.name !== name
167
+ })
168
+ },
169
+ removeEnumValues: (
170
+ context: RepositoryContext,
171
+ resource: Writable<ProductType>,
172
+ { attributeName, keys }: ProductTypeRemoveEnumValuesAction
173
+ ) => {
174
+ resource.attributes?.forEach(attr => {
175
+ if (attr.name == attributeName) {
176
+ if (attr.type.name == 'enum') {
177
+ attr.type.values = attr.type.values.filter(v => {
178
+ return !keys.includes(v.key)
179
+ })
180
+ }
181
+
182
+ if (attr.type.name == 'set') {
183
+ if (attr.type.elementType.name == 'enum') {
184
+ attr.type.elementType.values = attr.type.elementType.values.filter(
185
+ v => {
186
+ return !keys.includes(v.key)
187
+ }
188
+ )
189
+ }
190
+ }
191
+ }
192
+ })
193
+ },
112
194
  }
113
195
  }
@@ -1,17 +1,22 @@
1
1
  import {
2
2
  Price,
3
+ PriceDraft,
3
4
  Product,
4
5
  ProductData,
5
6
  ProductDraft,
6
7
  ProductPublishAction,
7
8
  ProductSetAttributeAction,
9
+ ProductType,
10
+ ProductTypeReference,
8
11
  ProductVariant,
9
12
  ProductVariantDraft,
10
13
  ReferenceTypeId,
11
14
  } from '@commercetools/platform-sdk'
15
+ import { v4 as uuidv4 } from 'uuid'
12
16
  import { getBaseResourceProperties } from '../helpers'
13
17
  import { AbstractResourceRepository, RepositoryContext } from './abstract'
14
18
  import { Writable } from '../types'
19
+ import { getReferenceFromResourceIdentifier } from './helpers'
15
20
 
16
21
  export class ProductRepository extends AbstractResourceRepository {
17
22
  getTypeId(): ReferenceTypeId {
@@ -19,17 +24,37 @@ export class ProductRepository extends AbstractResourceRepository {
19
24
  }
20
25
 
21
26
  create(context: RepositoryContext, draft: ProductDraft): Product {
22
- const productData = {
27
+ if (!draft.masterVariant) {
28
+ throw new Error('Missing master variant')
29
+ }
30
+
31
+ let productType: ProductTypeReference | undefined = undefined
32
+ try {
33
+ productType = getReferenceFromResourceIdentifier<ProductTypeReference>(
34
+ draft.productType,
35
+ context.projectKey,
36
+ this._storage
37
+ )
38
+ } catch (err) {
39
+ // For now accept missing product types (but warn)
40
+ console.warn(
41
+ `Error resolving product-type '${draft.productType.id}'. This will be throw an error in later releases.`
42
+ )
43
+ productType = {
44
+ typeId: 'product-type',
45
+ id: draft.productType.id || '',
46
+ }
47
+ }
48
+
49
+ const productData: ProductData = {
23
50
  name: draft.name,
24
51
  slug: draft.slug,
25
52
  categories: [],
26
- masterVariant:
27
- draft.masterVariant && variantFromDraft(0, draft.masterVariant!),
53
+ masterVariant: variantFromDraft(1, draft.masterVariant),
28
54
  variants:
29
- draft.variants &&
30
- draft.variants.map((variant, index) => {
31
- return variantFromDraft(index + 1, variant)
32
- }),
55
+ draft.variants?.map((variant, index) => {
56
+ return variantFromDraft(index + 2, variant)
57
+ }) ?? [],
33
58
 
34
59
  // @ts-ignore
35
60
  searchKeywords: draft.searchKeywords,
@@ -37,6 +62,7 @@ export class ProductRepository extends AbstractResourceRepository {
37
62
 
38
63
  const resource: Product = {
39
64
  ...getBaseResourceProperties(),
65
+ productType: productType,
40
66
  masterData: {
41
67
  // @ts-ignore
42
68
  current: draft.publish ? productData : undefined,
@@ -207,7 +233,21 @@ const variantFromDraft = (
207
233
  return {
208
234
  id: variantId,
209
235
  sku: variant?.sku,
210
- attributes: variant?.attributes,
211
- prices: variant?.prices as Price[],
236
+ attributes: variant?.attributes ?? [],
237
+ prices: variant?.prices?.map(priceFromDraft),
238
+ assets: [],
239
+ images: [],
240
+ }
241
+ }
242
+
243
+ const priceFromDraft = (draft: PriceDraft): Price => {
244
+ return {
245
+ id: uuidv4(),
246
+ value: {
247
+ currencyCode: draft.value.currencyCode,
248
+ centAmount: draft.value.centAmount,
249
+ fractionDigits: 2,
250
+ type: 'centPrecision',
251
+ },
212
252
  }
213
253
  }
@@ -12,6 +12,8 @@ import {
12
12
  ShippingMethodChangeNameAction,
13
13
  ShippingMethodDraft,
14
14
  ShippingMethodRemoveZoneAction,
15
+ ShippingMethodSetCustomFieldAction,
16
+ ShippingMethodSetCustomTypeAction,
15
17
  ShippingMethodSetDescriptionAction,
16
18
  ShippingMethodSetKeyAction,
17
19
  ShippingMethodSetLocalizedDescriptionAction,
@@ -196,5 +198,34 @@ export class ShippingMethodRepository extends AbstractResourceRepository {
196
198
  ) => {
197
199
  resource.name = name
198
200
  },
201
+ setCustomType: (
202
+ context: RepositoryContext,
203
+ resource: Writable<ShippingMethod>,
204
+ { type, fields }: ShippingMethodSetCustomTypeAction
205
+ ) => {
206
+ if (type) {
207
+ resource.custom = createCustomFields(
208
+ { type, fields },
209
+ context.projectKey,
210
+ this._storage
211
+ )
212
+ } else {
213
+ resource.custom = undefined
214
+ }
215
+ },
216
+ setCustomField: (
217
+ context: RepositoryContext,
218
+ resource: Writable<ShippingMethod>,
219
+ { name, value }: ShippingMethodSetCustomFieldAction
220
+ ) => {
221
+ if (!resource.custom) {
222
+ return
223
+ }
224
+ if (value === null) {
225
+ delete resource.custom.fields[name]
226
+ } else {
227
+ resource.custom.fields[name] = value
228
+ }
229
+ },
199
230
  }
200
231
  }