@sixtyninecommerce/admin 0.9.0 → 0.11.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 (258) hide show
  1. package/README.md +4598 -128
  2. package/dist/catalog/assets.d.ts +120 -8
  3. package/dist/catalog/assets.js +98 -12
  4. package/dist/catalog/collections.d.ts +279 -14
  5. package/dist/catalog/collections.js +246 -15
  6. package/dist/catalog/index.d.ts +9 -2
  7. package/dist/catalog/index.js +4 -0
  8. package/dist/catalog/products.d.ts +318 -17
  9. package/dist/catalog/products.js +182 -14
  10. package/dist/catalog/properties.d.ts +102 -14
  11. package/dist/catalog/properties.js +13 -0
  12. package/dist/catalog/recommendations.d.ts +261 -0
  13. package/dist/catalog/recommendations.js +145 -0
  14. package/dist/catalog/reviews.d.ts +368 -0
  15. package/dist/catalog/reviews.js +318 -0
  16. package/dist/catalog/types.d.ts +17 -1
  17. package/dist/catalog/types.js +10 -0
  18. package/dist/catalog/variant-find.d.ts +136 -0
  19. package/dist/catalog/variant-find.js +239 -0
  20. package/dist/catalog/variants.d.ts +282 -25
  21. package/dist/catalog/variants.js +173 -25
  22. package/dist/catalog/visibility.d.ts +20 -5
  23. package/dist/catalog/visibility.js +19 -1
  24. package/dist/client.d.ts +116 -9
  25. package/dist/client.js +41 -7
  26. package/dist/content/assets.d.ts +286 -0
  27. package/dist/content/assets.js +181 -0
  28. package/dist/content/items.d.ts +269 -0
  29. package/dist/content/items.js +170 -0
  30. package/dist/content/types.d.ts +282 -0
  31. package/dist/content/types.js +100 -0
  32. package/dist/customers/age-verification.d.ts +66 -0
  33. package/dist/customers/age-verification.js +79 -0
  34. package/dist/customers/credit.d.ts +263 -0
  35. package/dist/customers/credit.js +244 -0
  36. package/dist/customers/delivery-preferences.d.ts +120 -0
  37. package/dist/customers/delivery-preferences.js +97 -0
  38. package/dist/customers/groups.d.ts +207 -0
  39. package/dist/customers/groups.js +438 -0
  40. package/dist/customers/index.d.ts +447 -37
  41. package/dist/customers/index.js +313 -40
  42. package/dist/customers/invitation-status.d.ts +57 -0
  43. package/dist/customers/invitation-status.js +21 -0
  44. package/dist/customers/notes.d.ts +67 -0
  45. package/dist/customers/notes.js +51 -0
  46. package/dist/customers/notification-recipients.d.ts +97 -0
  47. package/dist/customers/notification-recipients.js +84 -0
  48. package/dist/customers/saved-lists.d.ts +42 -0
  49. package/dist/customers/saved-lists.js +61 -0
  50. package/dist/customers/vat.d.ts +83 -0
  51. package/dist/customers/vat.js +46 -0
  52. package/dist/customers/wire.d.ts +20 -0
  53. package/dist/customers/wire.js +35 -0
  54. package/dist/documents/ar.d.ts +307 -0
  55. package/dist/documents/ar.js +254 -0
  56. package/dist/documents/index.d.ts +731 -21
  57. package/dist/documents/index.js +436 -24
  58. package/dist/documents/pdf.d.ts +2 -0
  59. package/dist/documents/pdf.js +11 -0
  60. package/dist/fulfillments/create.d.ts +167 -0
  61. package/dist/fulfillments/create.js +216 -0
  62. package/dist/fulfillments/index.d.ts +121 -10
  63. package/dist/fulfillments/index.js +120 -2
  64. package/dist/fulfillments/payment-policy.d.ts +64 -0
  65. package/dist/fulfillments/payment-policy.js +140 -0
  66. package/dist/fulfillments/warehouse.d.ts +724 -0
  67. package/dist/fulfillments/warehouse.js +914 -0
  68. package/dist/geo/index.d.ts +119 -0
  69. package/dist/geo/index.js +107 -0
  70. package/dist/index.d.ts +129 -30
  71. package/dist/index.js +47 -9
  72. package/dist/integrations/afas-actions.d.ts +234 -0
  73. package/dist/integrations/afas-actions.js +310 -0
  74. package/dist/integrations/afas-types.d.ts +483 -0
  75. package/dist/integrations/afas-types.js +5 -0
  76. package/dist/integrations/afas.d.ts +234 -0
  77. package/dist/integrations/afas.js +290 -0
  78. package/dist/integrations/connections.d.ts +103 -0
  79. package/dist/integrations/connections.js +55 -0
  80. package/dist/integrations/esp.d.ts +313 -0
  81. package/dist/integrations/esp.js +169 -0
  82. package/dist/integrations/exact-online-types.d.ts +423 -0
  83. package/dist/integrations/exact-online-types.js +6 -0
  84. package/dist/integrations/exact-online.d.ts +248 -0
  85. package/dist/integrations/exact-online.js +376 -0
  86. package/dist/integrations/index.d.ts +40 -0
  87. package/dist/integrations/index.js +24 -0
  88. package/dist/integrations/pipeline-keys.d.ts +13 -0
  89. package/dist/integrations/pipeline-keys.js +22 -0
  90. package/dist/integrations/pipelines.d.ts +114 -0
  91. package/dist/integrations/pipelines.js +46 -0
  92. package/dist/integrations/types.d.ts +322 -0
  93. package/dist/integrations/types.js +8 -0
  94. package/dist/jobs/bulk-action-run.d.ts +11 -2
  95. package/dist/jobs/bulk-action-run.js +4 -5
  96. package/dist/locations/index.d.ts +66 -0
  97. package/dist/locations/index.js +31 -0
  98. package/dist/meta/index.d.ts +162 -0
  99. package/dist/orders/bulk.d.ts +75 -0
  100. package/dist/orders/bulk.js +150 -0
  101. package/dist/orders/cancel-with-money.d.ts +227 -0
  102. package/dist/orders/cancel-with-money.js +153 -0
  103. package/dist/orders/commit-edit.d.ts +7 -1
  104. package/dist/orders/commit-edit.js +5 -1
  105. package/dist/orders/deposit-policy.d.ts +103 -0
  106. package/dist/orders/deposit-policy.js +202 -0
  107. package/dist/orders/drafts.d.ts +800 -0
  108. package/dist/orders/drafts.js +771 -0
  109. package/dist/orders/fields.d.ts +245 -0
  110. package/dist/orders/fields.js +188 -0
  111. package/dist/orders/get.d.ts +29 -19
  112. package/dist/orders/get.js +17 -8
  113. package/dist/orders/index.d.ts +125 -5
  114. package/dist/orders/index.js +35 -2
  115. package/dist/orders/lifecycle.d.ts +128 -0
  116. package/dist/orders/lifecycle.js +158 -0
  117. package/dist/orders/line-price-preview.d.ts +7 -2
  118. package/dist/orders/list.d.ts +222 -0
  119. package/dist/orders/list.js +377 -0
  120. package/dist/orders/manual-discounts.d.ts +11 -2
  121. package/dist/orders/manual-discounts.js +2 -0
  122. package/dist/orders/manual-pricing.d.ts +5 -0
  123. package/dist/orders/order-entry.d.ts +20 -7
  124. package/dist/orders/plan-edit.d.ts +1 -1
  125. package/dist/orders/plan-edit.js +4 -1
  126. package/dist/orders/settings.d.ts +201 -0
  127. package/dist/orders/settings.js +325 -0
  128. package/dist/orders/status.d.ts +159 -13
  129. package/dist/orders/status.js +21 -0
  130. package/dist/orders/surcharges.d.ts +8 -1
  131. package/dist/orders/surcharges.js +3 -2
  132. package/dist/payments/account-credit.d.ts +30 -0
  133. package/dist/payments/account-credit.js +19 -0
  134. package/dist/payments/ar.d.ts +292 -0
  135. package/dist/payments/ar.js +223 -0
  136. package/dist/payments/connected-account.d.ts +47 -0
  137. package/dist/payments/connected-account.js +61 -0
  138. package/dist/payments/credit-noted-fields.d.ts +12 -0
  139. package/dist/payments/credit-noted-fields.js +37 -0
  140. package/dist/payments/index.d.ts +263 -10
  141. package/dist/payments/index.js +133 -1
  142. package/dist/payments/methods.d.ts +332 -0
  143. package/dist/payments/methods.js +363 -0
  144. package/dist/payments/mollie-methods.d.ts +159 -0
  145. package/dist/payments/mollie-methods.js +141 -0
  146. package/dist/payments/payment-links.d.ts +180 -0
  147. package/dist/payments/payment-links.js +97 -0
  148. package/dist/payments/provider-keys.d.ts +150 -0
  149. package/dist/payments/provider-keys.js +118 -0
  150. package/dist/payments/providers.d.ts +86 -11
  151. package/dist/payments/providers.js +29 -0
  152. package/dist/payments/requests.d.ts +144 -0
  153. package/dist/payments/requests.js +92 -0
  154. package/dist/payments/store-credit-fields.d.ts +15 -0
  155. package/dist/payments/store-credit-fields.js +51 -0
  156. package/dist/pickups/index.d.ts +104 -0
  157. package/dist/pickups/index.js +105 -0
  158. package/dist/platform/channels.d.ts +132 -0
  159. package/dist/platform/channels.js +128 -0
  160. package/dist/platform/geo.d.ts +123 -0
  161. package/dist/platform/geo.js +144 -0
  162. package/dist/platform/tax.d.ts +154 -0
  163. package/dist/platform/tax.js +139 -0
  164. package/dist/pos/anomalies.d.ts +158 -0
  165. package/dist/pos/anomalies.js +64 -0
  166. package/dist/pos/assisted-selling.d.ts +79 -0
  167. package/dist/pos/assisted-selling.js +38 -0
  168. package/dist/pos/exchanges.d.ts +103 -0
  169. package/dist/pos/exchanges.js +22 -0
  170. package/dist/pos/gift-cards.d.ts +135 -0
  171. package/dist/pos/gift-cards.js +47 -0
  172. package/dist/pos/index.d.ts +2125 -32
  173. package/dist/pos/index.js +742 -4
  174. package/dist/pos/no-receipt.d.ts +94 -0
  175. package/dist/pos/no-receipt.js +25 -0
  176. package/dist/pos/offline-sales.d.ts +187 -0
  177. package/dist/pos/offline-sales.js +116 -0
  178. package/dist/pos/pay-by-link.d.ts +143 -0
  179. package/dist/pos/pay-by-link.js +57 -0
  180. package/dist/pos/quick-keys.d.ts +103 -0
  181. package/dist/pos/quick-keys.js +45 -0
  182. package/dist/pos/reports.d.ts +360 -0
  183. package/dist/pos/reports.js +62 -0
  184. package/dist/pos/returns.d.ts +217 -0
  185. package/dist/pos/returns.js +53 -0
  186. package/dist/pricing/bulk-coupons.d.ts +139 -0
  187. package/dist/pricing/bulk-coupons.js +112 -0
  188. package/dist/pricing/index.d.ts +177 -4
  189. package/dist/pricing/index.js +176 -1
  190. package/dist/pricing/price-lists.d.ts +604 -0
  191. package/dist/pricing/price-lists.js +600 -0
  192. package/dist/pricing/vouchers.d.ts +103 -0
  193. package/dist/pricing/vouchers.js +69 -0
  194. package/dist/purchasing/alerts.d.ts +89 -0
  195. package/dist/purchasing/alerts.js +62 -0
  196. package/dist/purchasing/cost.d.ts +110 -0
  197. package/dist/purchasing/cost.js +86 -0
  198. package/dist/purchasing/index.d.ts +36 -0
  199. package/dist/purchasing/index.js +16 -0
  200. package/dist/purchasing/purchase-orders.d.ts +548 -0
  201. package/dist/purchasing/purchase-orders.js +491 -0
  202. package/dist/purchasing/replenishment.d.ts +281 -0
  203. package/dist/purchasing/replenishment.js +240 -0
  204. package/dist/purchasing/settings.d.ts +152 -0
  205. package/dist/purchasing/settings.js +181 -0
  206. package/dist/purchasing/suppliers.d.ts +476 -0
  207. package/dist/purchasing/suppliers.js +438 -0
  208. package/dist/quotes/index.d.ts +501 -0
  209. package/dist/quotes/index.js +439 -0
  210. package/dist/reports/index.d.ts +71 -8
  211. package/dist/reports/index.js +74 -11
  212. package/dist/returns/index.d.ts +818 -0
  213. package/dist/returns/index.js +844 -0
  214. package/dist/search/index.d.ts +174 -0
  215. package/dist/search/index.js +125 -0
  216. package/dist/shipping/definitions.d.ts +29 -0
  217. package/dist/shipping/definitions.js +47 -0
  218. package/dist/shipping/fulfillment-profiles.d.ts +174 -0
  219. package/dist/shipping/fulfillment-profiles.js +104 -0
  220. package/dist/shipping/hendriks.d.ts +97 -0
  221. package/dist/shipping/hendriks.js +50 -0
  222. package/dist/shipping/index.d.ts +48 -0
  223. package/dist/shipping/index.js +25 -0
  224. package/dist/shipping/methods.d.ts +198 -0
  225. package/dist/shipping/methods.js +240 -0
  226. package/dist/shipping/myparcel.d.ts +254 -0
  227. package/dist/shipping/myparcel.js +178 -0
  228. package/dist/shipping/parcel-count-suggestion.d.ts +2 -0
  229. package/dist/shipping/parcel-rule.d.ts +6 -5
  230. package/dist/shipping/parcel-rule.js +21 -23
  231. package/dist/shipping/rate-tables.d.ts +179 -0
  232. package/dist/shipping/rate-tables.js +184 -0
  233. package/dist/stock/index.d.ts +10 -3
  234. package/dist/stock/index.js +3 -0
  235. package/dist/stock/locations.d.ts +144 -0
  236. package/dist/stock/locations.js +168 -0
  237. package/dist/stock/transfers.d.ts +216 -43
  238. package/dist/stock/transfers.js +140 -13
  239. package/dist/stored-value/index.d.ts +214 -4
  240. package/dist/stored-value/index.js +152 -0
  241. package/dist/subscriptions/index.d.ts +682 -0
  242. package/dist/subscriptions/index.js +815 -0
  243. package/dist/tax/index.d.ts +76 -1
  244. package/dist/tax/index.js +50 -0
  245. package/dist/tenant/email-style.d.ts +102 -0
  246. package/dist/tenant/email-style.js +72 -0
  247. package/dist/tenant/email-templates.d.ts +66 -0
  248. package/dist/tenant/email-templates.js +54 -0
  249. package/dist/tenant/notifications.d.ts +23 -17
  250. package/dist/tenant/settings-sources.d.ts +1 -1
  251. package/dist/tenant/time-zone.d.ts +17 -0
  252. package/dist/tenant/time-zone.js +11 -0
  253. package/dist/types.d.ts +51 -4
  254. package/dist/users/index.d.ts +3 -0
  255. package/dist/users/index.js +2 -0
  256. package/dist/users/warehouses.d.ts +50 -0
  257. package/dist/users/warehouses.js +51 -0
  258. package/package.json +2 -2
@@ -1,4 +1,30 @@
1
- import { ASSET_REF_FIELDS, assertDeleted, CATALOGUE_OWNERSHIP_FIELDS, DELETION_FIELDS, fieldOf, vendureListPage, } from './types.js';
1
+ import { pageFromVendureList, ValidationError, } from '@sixtyninecommerce/core';
2
+ import { createSearchModule } from '../search/index.js';
3
+ import { ASSET_REF_FIELDS, assertDeleted, CATALOGUE_OWNERSHIP_FIELDS, DEFAULT_PAGE_SIZE, DELETION_FIELDS, fieldOf, toAssetRef, vendureListPage, } from './types.js';
4
+ /** The most collections one {@link CollectionsModule.search} answers. */
5
+ export const MAX_COLLECTION_SEARCH_TAKE = 100;
6
+ const SEO_FIELDS = /* GraphQL */ `
7
+ customFields {
8
+ isRoutable
9
+ isCanonical
10
+ noindex
11
+ nofollow
12
+ metaRobotsMaxImagePreview
13
+ socialImageId
14
+ socialOgType
15
+ twitterCardType
16
+ }
17
+ `;
18
+ const TRANSLATION_SEO_FIELDS = /* GraphQL */ `
19
+ customFields {
20
+ seoTitle
21
+ seoDescription
22
+ canonicalUrl
23
+ socialTitle
24
+ socialDescription
25
+ socialImageAlt
26
+ }
27
+ `;
2
28
  export const COLLECTION_FIELDS = /* GraphQL */ `
3
29
  id
4
30
  ${CATALOGUE_OWNERSHIP_FIELDS}
@@ -26,12 +52,14 @@ export const COLLECTION_FIELDS = /* GraphQL */ `
26
52
  slug
27
53
  }
28
54
  productVariantCount
55
+ ${SEO_FIELDS}
29
56
  translations {
30
57
  id
31
58
  languageCode
32
59
  name
33
60
  slug
34
61
  description
62
+ ${TRANSLATION_SEO_FIELDS}
35
63
  }
36
64
  `;
37
65
  export const COLLECTIONS_QUERY = /* GraphQL */ `
@@ -44,7 +72,19 @@ export const COLLECTIONS_QUERY = /* GraphQL */ `
44
72
  `;
45
73
  export const COLLECTION_QUERY = /* GraphQL */ `
46
74
  query CatalogCollection($id: ID!) {
47
- collection(id: $id) { ${COLLECTION_FIELDS} }
75
+ collection(id: $id) {
76
+ ${COLLECTION_FIELDS}
77
+ parent {
78
+ id
79
+ name
80
+ }
81
+ children {
82
+ id
83
+ name
84
+ slug
85
+ position
86
+ }
87
+ }
48
88
  }
49
89
  `;
50
90
  export const CREATE_COLLECTION_MUTATION = /* GraphQL */ `
@@ -67,25 +107,216 @@ export const MOVE_COLLECTION_MUTATION = /* GraphQL */ `
67
107
  moveCollection(input: $input) { ${COLLECTION_FIELDS} }
68
108
  }
69
109
  `;
110
+ export const COLLECTION_FILTER_DEFINITIONS_QUERY = /* GraphQL */ `
111
+ query CatalogCollectionFilterDefinitions {
112
+ collectionFilters {
113
+ code
114
+ description
115
+ args {
116
+ name
117
+ type
118
+ list
119
+ required
120
+ defaultValue
121
+ label
122
+ description
123
+ ui
124
+ }
125
+ }
126
+ }
127
+ `;
128
+ /**
129
+ * The preview's price is `storePrice` (null for a variant the store has no price for), never
130
+ * core's `price` / `priceWithTax` / `currencyCode`, which raise "No price information was
131
+ * found…" for such a variant and, being non-null, empty the whole preview (#1504).
132
+ */
133
+ export const PREVIEW_COLLECTION_VARIANTS_QUERY = /* GraphQL */ `
134
+ query CatalogPreviewCollectionVariants(
135
+ $input: PreviewCollectionVariantsInput!
136
+ $options: ProductVariantListOptions
137
+ ) {
138
+ previewCollectionVariants(input: $input, options: $options) {
139
+ items {
140
+ id
141
+ name
142
+ sku
143
+ storePrice {
144
+ price
145
+ priceWithTax
146
+ currencyCode
147
+ }
148
+ product {
149
+ id
150
+ name
151
+ featuredAsset { ${ASSET_REF_FIELDS} }
152
+ }
153
+ }
154
+ totalItems
155
+ }
156
+ }
157
+ `;
158
+ const COLLECTION_SORT_FIELDS = [
159
+ 'position',
160
+ 'name',
161
+ 'createdAt',
162
+ 'updatedAt',
163
+ 'id',
164
+ ];
165
+ function toPreviewVariant(wire) {
166
+ const { featuredAsset, ...product } = wire.product;
167
+ return {
168
+ ...wire,
169
+ product: { ...product, featuredAsset: featuredAsset ? toAssetRef(featuredAsset) : null },
170
+ };
171
+ }
172
+ function toSeo(wire) {
173
+ return {
174
+ isRoutable: wire?.isRoutable ?? null,
175
+ isCanonical: wire?.isCanonical ?? null,
176
+ noindex: wire?.noindex ?? null,
177
+ nofollow: wire?.nofollow ?? null,
178
+ metaRobotsMaxImagePreview: wire?.metaRobotsMaxImagePreview ?? null,
179
+ socialImageId: wire?.socialImageId ?? null,
180
+ socialOgType: wire?.socialOgType ?? null,
181
+ twitterCardType: wire?.twitterCardType ?? null,
182
+ };
183
+ }
184
+ function toTranslationSeo(wire) {
185
+ return {
186
+ seoTitle: wire?.seoTitle ?? null,
187
+ seoDescription: wire?.seoDescription ?? null,
188
+ canonicalUrl: wire?.canonicalUrl ?? null,
189
+ socialTitle: wire?.socialTitle ?? null,
190
+ socialDescription: wire?.socialDescription ?? null,
191
+ socialImageAlt: wire?.socialImageAlt ?? null,
192
+ };
193
+ }
194
+ function toCollection(wire) {
195
+ const { customFields, translations, featuredAsset, assets, ...rest } = wire;
196
+ return {
197
+ ...rest,
198
+ featuredAsset: featuredAsset ? toAssetRef(featuredAsset) : null,
199
+ assets: (assets ?? []).map(toAssetRef),
200
+ seo: toSeo(customFields),
201
+ translations: (translations ?? []).map(({ customFields: seo, ...translation }) => ({
202
+ ...translation,
203
+ seo: toTranslationSeo(seo),
204
+ })),
205
+ };
206
+ }
207
+ /** `seo` goes on the wire as the engine's `customFields`, only the keys the caller named. */
208
+ function toWireTranslation(translation) {
209
+ const { seo, ...rest } = translation;
210
+ return seo === undefined ? rest : { ...rest, customFields: { ...seo } };
211
+ }
212
+ function toWireInput(input) {
213
+ const { seo, translations, ...rest } = input;
214
+ return {
215
+ ...rest,
216
+ ...(translations === undefined ? {} : { translations: translations.map(toWireTranslation) }),
217
+ ...(seo === undefined ? {} : { customFields: { ...seo } }),
218
+ };
219
+ }
220
+ function invalidSort(sort) {
221
+ return new ValidationError({
222
+ code: 'INVALID_COLLECTION_SORT',
223
+ message: `sort must name one of ${COLLECTION_SORT_FIELDS.join(', ')} and the direction ASC or DESC; got ${JSON.stringify(sort)}. Nothing was sent.`,
224
+ status: 400,
225
+ service: 'vendure',
226
+ });
227
+ }
228
+ function listOptionsOf(options) {
229
+ const filter = {};
230
+ if (options?.parentId !== undefined)
231
+ filter.parentId = { eq: options.parentId };
232
+ if (options?.name !== undefined)
233
+ filter.name = { contains: options.name };
234
+ if (options?.ids !== undefined)
235
+ filter.id = { in: [...options.ids] };
236
+ const sort = options?.sort;
237
+ if (sort !== undefined &&
238
+ (!COLLECTION_SORT_FIELDS.includes(sort.field) ||
239
+ (sort.direction !== 'ASC' && sort.direction !== 'DESC'))) {
240
+ throw invalidSort(sort);
241
+ }
242
+ return {
243
+ ...(options?.topLevelOnly === true ? { topLevelOnly: true } : {}),
244
+ ...(Object.keys(filter).length > 0 ? { filter } : {}),
245
+ ...(sort === undefined ? {} : { sort: { [sort.field]: sort.direction } }),
246
+ };
247
+ }
248
+ function invalidSearch(message) {
249
+ return new ValidationError({
250
+ code: 'SEARCH_INPUT_INVALID',
251
+ message: `${message} Nothing was sent.`,
252
+ status: 400,
253
+ service: 'vendure',
254
+ });
255
+ }
70
256
  export function createCollectionsModule(transport) {
257
+ const write = async (document, field, variables, options) => toCollection(await fieldOf(transport, document, field, variables, options));
258
+ const list = async (options) => {
259
+ const listOptions = listOptionsOf(options);
260
+ if (options?.ids !== undefined && options.ids.length === 0) {
261
+ return pageFromVendureList({ items: [], totalItems: 0 }, 0, options.limit ?? DEFAULT_PAGE_SIZE, () => Promise.reject(new Error('an empty page has no next page')));
262
+ }
263
+ return vendureListPage(transport, COLLECTIONS_QUERY, 'collections', (skip, take) => ({ options: { skip, take, ...listOptions } }), options, toCollection);
264
+ };
71
265
  return {
72
- list: (options) => {
73
- const filter = {};
74
- if (options?.parentId !== undefined)
75
- filter.parentId = { eq: options.parentId };
76
- if (options?.name !== undefined)
77
- filter.name = { contains: options.name };
78
- return vendureListPage(transport, COLLECTIONS_QUERY, 'collections', (skip, take) => ({
79
- options: { skip, take, ...(Object.keys(filter).length > 0 ? { filter } : {}) },
80
- }), options);
266
+ list,
267
+ async get(id, options) {
268
+ const collection = await fieldOf(transport, COLLECTION_QUERY, 'collection', { id }, options);
269
+ return collection ? toCollection(collection) : null;
81
270
  },
82
- get: (id, options) => fieldOf(transport, COLLECTION_QUERY, 'collection', { id }, options),
83
- create: (input, options) => fieldOf(transport, CREATE_COLLECTION_MUTATION, 'createCollection', { input }, options),
84
- update: (input, options) => fieldOf(transport, UPDATE_COLLECTION_MUTATION, 'updateCollection', { input }, options),
271
+ async search(term, options = {}) {
272
+ const { take = DEFAULT_PAGE_SIZE, skip = 0, ...call } = options;
273
+ if (!Number.isInteger(take) || take < 1 || take > MAX_COLLECTION_SEARCH_TAKE) {
274
+ throw invalidSearch(`take must be a whole number from 1 to ${String(MAX_COLLECTION_SEARCH_TAKE)}; got ${String(take)}.`);
275
+ }
276
+ if (!Number.isInteger(skip) || skip < 0) {
277
+ throw invalidSearch(`skip must be a whole number from 0; got ${String(skip)}.`);
278
+ }
279
+ const hits = await createSearchModule(transport).index('collections', { term, take, skip }, call);
280
+ const ids = [...new Set(hits.items.map((hit) => hit.id))];
281
+ if (ids.length === 0)
282
+ return { items: [], total: hits.total };
283
+ // The index says which and in what order; the rows are the engine's, read in the store the
284
+ // call acts on, so a collection the store no longer holds is not answered.
285
+ const page = await list({ ...call, ids, limit: ids.length });
286
+ const byId = new Map(page.items.map((collection) => [collection.id, collection]));
287
+ return {
288
+ items: ids.flatMap((id) => {
289
+ const collection = byId.get(id);
290
+ return collection ? [collection] : [];
291
+ }),
292
+ total: hits.total,
293
+ };
294
+ },
295
+ create: (input, options) => write(CREATE_COLLECTION_MUTATION, 'createCollection', { input: toWireInput(input) }, options),
296
+ update: (input, options) => write(UPDATE_COLLECTION_MUTATION, 'updateCollection', { input: toWireInput(input) }, options),
85
297
  async delete(id, options) {
86
298
  const response = await fieldOf(transport, DELETE_COLLECTION_MUTATION, 'deleteCollection', { id }, options);
87
299
  assertDeleted('COLLECTION_NOT_DELETED', [response]);
88
300
  },
89
- move: (collectionId, parentId, index, options) => fieldOf(transport, MOVE_COLLECTION_MUTATION, 'moveCollection', { input: { collectionId, parentId, index } }, options),
301
+ move: (collectionId, parentId, index, options) => write(MOVE_COLLECTION_MUTATION, 'moveCollection', { input: { collectionId, parentId, index } }, options),
302
+ filterDefinitions: (options) => fieldOf(transport, COLLECTION_FILTER_DEFINITIONS_QUERY, 'collectionFilters', {}, options),
303
+ previewVariants(input, options = {}) {
304
+ const { term: rawTerm, ...listOptions } = options;
305
+ const term = rawTerm?.trim() ?? '';
306
+ const filter = term === ''
307
+ ? {}
308
+ : {
309
+ filter: { name: { contains: term }, sku: { contains: term } },
310
+ filterOperator: 'OR',
311
+ };
312
+ return vendureListPage(transport, PREVIEW_COLLECTION_VARIANTS_QUERY, 'previewCollectionVariants', (skip, take) => ({
313
+ input: {
314
+ filters: input.filters,
315
+ inheritFilters: input.inheritFilters,
316
+ ...(input.parentId === undefined ? {} : { parentId: input.parentId }),
317
+ },
318
+ options: { skip, take, ...filter },
319
+ }), listOptions, toPreviewVariant);
320
+ },
90
321
  };
91
322
  }
@@ -6,12 +6,15 @@ import { type FacetsModule } from './facets.js';
6
6
  import { type OptionsModule } from './options.js';
7
7
  import { type ProductsModule } from './products.js';
8
8
  import { type ContentFacetSyncResult, type PropertiesModule } from './properties.js';
9
+ import { type RecommendationsModule } from './recommendations.js';
10
+ import { type ReviewsModule } from './reviews.js';
9
11
  import { type VariantsModule } from './variants.js';
10
12
  import { type VisibilityModule } from './visibility.js';
11
13
  /**
12
14
  * The catalogue (spec §9.2 `catalog`): products, variants, options, facets,
13
- * collections, assets, storefront visibility and product properties — one
14
- * resource per namespace, over the Admin API the dashboard itself uses.
15
+ * collections, assets, storefront visibility, product properties, product
16
+ * recommendations and product reviews — one resource per namespace, over the Admin API the
17
+ * dashboard itself uses.
15
18
  *
16
19
  * **Per-resource, not per-intent.** Saving a product form is several calls
17
20
  * here (the product, its variants, its properties, its collections), and they
@@ -70,6 +73,10 @@ export interface CatalogModule {
70
73
  assets: AssetsModule;
71
74
  visibility: VisibilityModule;
72
75
  properties: PropertiesModule;
76
+ /** Recommendation groups, their rules and the products picked per product (W10-13). */
77
+ recommendations: RecommendationsModule;
78
+ /** Product reviews: moderation, the store's replies, statistics, review attributes (W10-117). */
79
+ reviews: ReviewsModule;
73
80
  /**
74
81
  * "Sync filter values" for one filterable `content_item` or `product` property, done by the
75
82
  * engine (headless spec §7 `catalog.syncContentFacets`, by property, the unit the merchant syncs).
@@ -4,6 +4,8 @@ import { createFacetsModule } from './facets.js';
4
4
  import { createOptionsModule } from './options.js';
5
5
  import { createProductsModule } from './products.js';
6
6
  import { createPropertiesModule, syncContentFacets, } from './properties.js';
7
+ import { createRecommendationsModule } from './recommendations.js';
8
+ import { createReviewsModule } from './reviews.js';
7
9
  import { createVariantsModule } from './variants.js';
8
10
  import { createVisibilityModule } from './visibility.js';
9
11
  export function createCatalogModule(transport) {
@@ -16,6 +18,8 @@ export function createCatalogModule(transport) {
16
18
  assets: createAssetsModule(transport),
17
19
  visibility: createVisibilityModule(transport),
18
20
  properties: createPropertiesModule(transport),
21
+ recommendations: createRecommendationsModule(transport),
22
+ reviews: createReviewsModule(transport),
19
23
  syncContentFacets: (propertyId, options) => syncContentFacets(transport, propertyId, options),
20
24
  };
21
25
  }