@labdigital/commercetools-mock 0.6.4 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/dist/index.d.ts +385 -3
  2. package/dist/index.global.js +49770 -0
  3. package/dist/index.global.js.map +1 -0
  4. package/dist/index.js +4622 -6
  5. package/dist/index.js.map +1 -0
  6. package/dist/index.mjs +4590 -0
  7. package/dist/index.mjs.map +1 -0
  8. package/package.json +30 -17
  9. package/src/ctMock.ts +5 -0
  10. package/src/helpers.ts +15 -0
  11. package/src/lib/projectionSearchFilter.test.ts +177 -0
  12. package/src/lib/projectionSearchFilter.ts +248 -0
  13. package/src/priceSelector.test.ts +96 -0
  14. package/src/priceSelector.ts +109 -0
  15. package/src/product-projection-search.ts +149 -0
  16. package/src/projectAPI.ts +19 -20
  17. package/src/repositories/category.ts +36 -0
  18. package/src/repositories/channel.ts +104 -0
  19. package/src/repositories/customer-group.ts +37 -0
  20. package/src/repositories/discount-code.ts +37 -0
  21. package/src/repositories/helpers.ts +46 -4
  22. package/src/repositories/product-discount.ts +181 -0
  23. package/src/repositories/product-projection.ts +29 -55
  24. package/src/repositories/product-type.ts +88 -6
  25. package/src/repositories/product.ts +49 -9
  26. package/src/repositories/shipping-method.ts +31 -0
  27. package/src/repositories/store.ts +43 -3
  28. package/src/repositories/type.ts +19 -0
  29. package/src/services/custom-object.test.ts +2 -2
  30. package/src/services/product-discount.ts +33 -0
  31. package/src/services/product-projection.test.ts +171 -116
  32. package/src/services/product.test.ts +12 -0
  33. package/src/storage.ts +116 -58
  34. package/src/types.ts +9 -2
  35. package/dist/commercetools-mock.cjs.development.js +0 -4380
  36. package/dist/commercetools-mock.cjs.development.js.map +0 -1
  37. package/dist/commercetools-mock.cjs.production.min.js +0 -2
  38. package/dist/commercetools-mock.cjs.production.min.js.map +0 -1
  39. package/dist/commercetools-mock.esm.js +0 -4372
  40. package/dist/commercetools-mock.esm.js.map +0 -1
  41. package/dist/constants.d.ts +0 -2
  42. package/dist/ctMock.d.ts +0 -32
  43. package/dist/exceptions.d.ts +0 -12
  44. package/dist/helpers.d.ts +0 -6
  45. package/dist/lib/expandParser.d.ts +0 -15
  46. package/dist/lib/filterParser.d.ts +0 -1
  47. package/dist/lib/haversine.d.ts +0 -8
  48. package/dist/lib/masking.d.ts +0 -1
  49. package/dist/lib/predicateParser.d.ts +0 -11
  50. package/dist/lib/proxy.d.ts +0 -1
  51. package/dist/oauth/errors.d.ts +0 -8
  52. package/dist/oauth/helpers.d.ts +0 -2
  53. package/dist/oauth/server.d.ts +0 -12
  54. package/dist/oauth/store.d.ts +0 -14
  55. package/dist/projectAPI.d.ts +0 -12
  56. package/dist/repositories/abstract.d.ts +0 -33
  57. package/dist/repositories/cart-discount.d.ts +0 -9
  58. package/dist/repositories/cart.d.ts +0 -21
  59. package/dist/repositories/category.d.ts +0 -18
  60. package/dist/repositories/channel.d.ts +0 -6
  61. package/dist/repositories/custom-object.d.ts +0 -8
  62. package/dist/repositories/customer-group.d.ts +0 -11
  63. package/dist/repositories/customer.d.ts +0 -11
  64. package/dist/repositories/discount-code.d.ts +0 -8
  65. package/dist/repositories/errors.d.ts +0 -2
  66. package/dist/repositories/extension.d.ts +0 -8
  67. package/dist/repositories/helpers.d.ts +0 -10
  68. package/dist/repositories/inventory-entry.d.ts +0 -14
  69. package/dist/repositories/my-order.d.ts +0 -6
  70. package/dist/repositories/order.d.ts +0 -26
  71. package/dist/repositories/payment.d.ts +0 -23
  72. package/dist/repositories/product-projection.d.ts +0 -10
  73. package/dist/repositories/product-type.d.ts +0 -10
  74. package/dist/repositories/product.d.ts +0 -11
  75. package/dist/repositories/project.d.ts +0 -8
  76. package/dist/repositories/shipping-method.d.ts +0 -10
  77. package/dist/repositories/shopping-list.d.ts +0 -6
  78. package/dist/repositories/state.d.ts +0 -8
  79. package/dist/repositories/store.d.ts +0 -10
  80. package/dist/repositories/subscription.d.ts +0 -6
  81. package/dist/repositories/tax-category.d.ts +0 -10
  82. package/dist/repositories/type.d.ts +0 -8
  83. package/dist/repositories/zone.d.ts +0 -8
  84. package/dist/server.d.ts +0 -1
  85. package/dist/services/abstract.d.ts +0 -20
  86. package/dist/services/cart-discount.d.ts +0 -9
  87. package/dist/services/cart.d.ts +0 -12
  88. package/dist/services/category.d.ts +0 -9
  89. package/dist/services/channel.d.ts +0 -9
  90. package/dist/services/custom-object.d.ts +0 -13
  91. package/dist/services/customer-group.d.ts +0 -9
  92. package/dist/services/customer.d.ts +0 -10
  93. package/dist/services/discount-code.d.ts +0 -9
  94. package/dist/services/extension.d.ts +0 -9
  95. package/dist/services/inventory-entry.d.ts +0 -9
  96. package/dist/services/my-cart.d.ts +0 -11
  97. package/dist/services/my-customer.d.ts +0 -13
  98. package/dist/services/my-order.d.ts +0 -10
  99. package/dist/services/my-payment.d.ts +0 -9
  100. package/dist/services/order.d.ts +0 -12
  101. package/dist/services/payment.d.ts +0 -9
  102. package/dist/services/product-projection.d.ts +0 -11
  103. package/dist/services/product-type.d.ts +0 -11
  104. package/dist/services/product.d.ts +0 -9
  105. package/dist/services/project.d.ts +0 -11
  106. package/dist/services/shipping-method.d.ts +0 -10
  107. package/dist/services/shopping-list.d.ts +0 -9
  108. package/dist/services/state.d.ts +0 -9
  109. package/dist/services/store.d.ts +0 -11
  110. package/dist/services/subscription.d.ts +0 -9
  111. package/dist/services/tax-category.d.ts +0 -11
  112. package/dist/services/type.d.ts +0 -9
  113. package/dist/services/zone.d.ts +0 -9
  114. package/dist/storage.d.ts +0 -56
  115. package/dist/types.d.ts +0 -89
  116. package/dist/validate.d.ts +0 -7482
  117. package/src/lib/filterParser.test.ts +0 -15
  118. 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,77 +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 filter = (query['filter.query'] ?? query.filter) as any
54
- const wherePredicate = filter ? parseFilterExpression(filter) : undefined
55
-
56
- const results = this._storage.query(context.projectKey, this.getTypeId(), {
57
- where: wherePredicate,
39
+ const results = this._searchService.search(context.projectKey, {
40
+ filter: QueryParamsAsArray(query.filter),
41
+ 'filter.query': QueryParamsAsArray(query['filter.query']),
58
42
  offset: query.offset ? Number(query.offset) : undefined,
59
43
  limit: query.limit ? Number(query.limit) : undefined,
60
- }) //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
+ })
61
46
 
62
47
  return results
63
48
  }
64
49
 
65
50
  actions = {}
66
51
  }
67
-
68
- const variantFromDraft = (
69
- variantId: number,
70
- variant: ProductVariantDraft
71
- ): ProductVariant => {
72
- return {
73
- id: variantId,
74
- sku: variant?.sku,
75
- attributes: variant?.attributes,
76
- }
77
- }
@@ -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
  }
@@ -8,11 +8,16 @@ import {
8
8
  StoreSetDistributionChannelsAction,
9
9
  ChannelResourceIdentifier,
10
10
  StoreSetLanguagesAction,
11
+ StoreSetCustomFieldAction,
12
+ StoreSetCustomTypeAction,
11
13
  } from '@commercetools/platform-sdk'
12
14
  import { Writable } from 'types'
13
15
  import { getBaseResourceProperties } from '../helpers'
14
16
  import { AbstractResourceRepository, RepositoryContext } from './abstract'
15
- import { getReferenceFromResourceIdentifier } from './helpers'
17
+ import {
18
+ getReferenceFromResourceIdentifier,
19
+ createCustomFields,
20
+ } from './helpers'
16
21
 
17
22
  export class StoreRepository extends AbstractResourceRepository {
18
23
  getTypeId(): ReferenceTypeId {
@@ -24,12 +29,18 @@ export class StoreRepository extends AbstractResourceRepository {
24
29
  ...getBaseResourceProperties(),
25
30
  key: draft.key,
26
31
  name: draft.name,
27
- languages: draft.languages,
32
+ languages: draft.languages ?? [],
28
33
  distributionChannels: this.transformChannels(
29
34
  context,
30
35
  draft.distributionChannels
31
36
  ),
32
37
  supplyChannels: this.transformChannels(context, draft.supplyChannels),
38
+ productSelections: [],
39
+ custom: createCustomFields(
40
+ draft.custom,
41
+ context.projectKey,
42
+ this._storage
43
+ ),
33
44
  }
34
45
  this.save(context, resource)
35
46
  return resource
@@ -97,7 +108,36 @@ export class StoreRepository extends AbstractResourceRepository {
97
108
  resource: Writable<Store>,
98
109
  { languages }: StoreSetLanguagesAction
99
110
  ) => {
100
- resource.languages = languages
111
+ resource.languages = languages ?? []
112
+ },
113
+ setCustomType: (
114
+ context: RepositoryContext,
115
+ resource: Writable<Store>,
116
+ { type, fields }: StoreSetCustomTypeAction
117
+ ) => {
118
+ if (type) {
119
+ resource.custom = createCustomFields(
120
+ { type, fields },
121
+ context.projectKey,
122
+ this._storage
123
+ )
124
+ } else {
125
+ resource.custom = undefined
126
+ }
127
+ },
128
+ setCustomField: (
129
+ context: RepositoryContext,
130
+ resource: Writable<Store>,
131
+ { name, value }: StoreSetCustomFieldAction
132
+ ) => {
133
+ if (!resource.custom) {
134
+ return
135
+ }
136
+ if (value === null) {
137
+ delete resource.custom.fields[name]
138
+ } else {
139
+ resource.custom.fields[name] = value
140
+ }
101
141
  },
102
142
  }
103
143
  }