@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
@@ -0,0 +1,261 @@
1
+ /**
2
+ * Product recommendations (headless spec §9.2 `catalog`: "recommendations"; W10-13): the store's
3
+ * recommendation groups ("Customers also bought", "Complete the look"), what each one draws its
4
+ * products from, and the products hand-picked per product for a manual group.
5
+ *
6
+ * - **A `DYNAMIC` group's entries are its rules**, read in `position` order: one named product
7
+ * (`PRODUCT`), the products of a collection (`COLLECTION`) or with a facet value
8
+ * (`FACET_VALUE`), or the viewed product's own collections (`SAME_COLLECTION`) or properties
9
+ * (`SAME_PROPERTIES`). The storefront fills the group up to `maxItems` from the first entry on,
10
+ * never with the viewed product, a disabled product or one the store hides from the shopper.
11
+ * - **A `MANUAL` group has no entries**: its products are picked per viewed product
12
+ * (`manual.set`), and the storefront shows them in the order picked. A group's mode is chosen
13
+ * when it is created and never changes.
14
+ * - **A disabled group** (`enabled: false`) is kept but never shown on the storefront.
15
+ * - **Positions** are integers; a group or entry created without one goes after the last.
16
+ * `reorder` rewrites them as `0, 1, 2…` in the order given.
17
+ *
18
+ * Permissions: reads need `ReadCatalog`, writes `UpdateCatalog`. Every row is the store's own: a
19
+ * group or entry of another store is never answered and never changed (a read answers `null` or
20
+ * leaves it out; a write refuses it as unknown), and a rule only ever draws from the store's own
21
+ * products, collections and facet values.
22
+ *
23
+ * Refusals, GraphQL errors mapped by `core`. An unknown id and another store's get the same answer,
24
+ * so none tells whether another store holds the row:
25
+ * - `ENTITY_NOT_FOUND` → `NotFoundError` (404): a group or entry the store does not have, and the
26
+ * viewed product of `manual.set` when the store does not hold it.
27
+ * - `RECOMMENDATION_SOURCE_NOT_FOUND` → `NotFoundError` (404): a rule's `sourceId` that is not a
28
+ * product, collection or facet value of the store (`entries.create`, `entries.update`).
29
+ * - `RECOMMENDATION_TARGET_NOT_FOUND` → `NotFoundError` (404): `manual.set` picks the store does
30
+ * not hold, each named in the message and in `details` (`field` `/targetProductIds/<index>`).
31
+ * - `RECOMMENDATION_GROUP_SLUG_TAKEN` → `ConflictError` (409): another of the store's groups holds
32
+ * the slug, also when two writes race for one free slug.
33
+ * - `USER_INPUT_ERROR` → `ValidationError` (400), in the engine's words: a rule that does not fit
34
+ * its group or its type (a `MANUAL` group, a `sourceId` missing or sent where none goes), picks
35
+ * in a `DYNAMIC` group.
36
+ * - `FORBIDDEN` → `PermissionDeniedError` (403) without the permission.
37
+ *
38
+ * An id that is not a uuid (any id argument, a `sourceId` and each pick included) is refused
39
+ * before all of these with core's `ENTITY_NOT_FOUND` (`NotFoundError`, 404, no `details`), so
40
+ * branch on the class for not-found and on the code only to tell which row is missing.
41
+ *
42
+ * A platform release older than these codes answers each not-found and a taken slug as
43
+ * `USER_INPUT_ERROR` (400) in its own words ("Recommendation group not found"), a slug lost in a
44
+ * race as `DUPLICATE_RECORD`, and takes another store's collection or facet value as a rule's
45
+ * source.
46
+ *
47
+ * No release gate: every operation here is served by every platform release this SDK supports.
48
+ * No method deduplicates on `idempotencyKey`: repeating a `create` makes a second row.
49
+ */
50
+ import type { Transport } from '@sixtyninecommerce/core';
51
+ import type { Call } from '../types.js';
52
+ /** What a `DYNAMIC` group's entry draws its products from. */
53
+ export type RecommendationSourceType = 'PRODUCT' | 'COLLECTION' | 'FACET_VALUE' | 'SAME_COLLECTION' | 'SAME_PROPERTIES';
54
+ /** `DYNAMIC`: rules (entries). `MANUAL`: products picked per viewed product (`manual.set`). */
55
+ export type RecommendationGroupMode = 'DYNAMIC' | 'MANUAL';
56
+ /** The source types whose entry names a row (`sourceId`); the others must name none. */
57
+ export declare const RECOMMENDATION_SOURCE_TYPES_WITH_ID: readonly RecommendationSourceType[];
58
+ /** One rule of a `DYNAMIC` group. */
59
+ export interface RecommendationEntry {
60
+ id: string;
61
+ groupId: string;
62
+ sourceType: RecommendationSourceType;
63
+ /**
64
+ * The product, collection or facet value for `PRODUCT`, `COLLECTION` and `FACET_VALUE`; `null`
65
+ * for `SAME_COLLECTION` and `SAME_PROPERTIES`. Always a row of this store when it was written:
66
+ * `entries.create` and `entries.update` refuse any other (`RECOMMENDATION_SOURCE_NOT_FOUND`). A
67
+ * row deleted or taken out of the store since adds nothing, and the storefront never draws from
68
+ * another store's collection or facet value, a rule stored before the refusal included. A deleted
69
+ * product's `PRODUCT` entries are removed with it.
70
+ */
71
+ sourceId: string | null;
72
+ position: number;
73
+ /** ISO-8601 UTC. */
74
+ createdAt: string;
75
+ /** ISO-8601 UTC. */
76
+ updatedAt: string;
77
+ }
78
+ /** A group without its entries, as `manual.get` and `manual.set` answer it. */
79
+ export interface RecommendationGroupSummary {
80
+ id: string;
81
+ name: string;
82
+ /** Unique within the store; the storefront asks for one group by it. */
83
+ slug: string;
84
+ description: string | null;
85
+ /** The most products the storefront shows for this group. */
86
+ maxItems: number;
87
+ position: number;
88
+ enabled: boolean;
89
+ mode: RecommendationGroupMode;
90
+ /** ISO-8601 UTC. */
91
+ createdAt: string;
92
+ /** ISO-8601 UTC. */
93
+ updatedAt: string;
94
+ }
95
+ export interface RecommendationGroup extends RecommendationGroupSummary {
96
+ /** In `position` order (ties: the older first). Always empty on a `MANUAL` group. */
97
+ entries: RecommendationEntry[];
98
+ }
99
+ /** One `MANUAL` group and the products picked in it for one viewed product. */
100
+ export interface ProductManualRecommendations {
101
+ group: RecommendationGroupSummary;
102
+ /** In the order picked; empty when none are. */
103
+ productIds: string[];
104
+ }
105
+ export interface CreateRecommendationGroupInput {
106
+ name: string;
107
+ /** Defaults to the name, lower-cased, every run of other characters than `a-z0-9` a `-`. */
108
+ slug?: string;
109
+ description?: string;
110
+ /** Defaults to 10. The engine sets no bounds. */
111
+ maxItems?: number;
112
+ /** Defaults to after the store's last group. */
113
+ position?: number;
114
+ /** Defaults to true. */
115
+ enabled?: boolean;
116
+ /** Defaults to `DYNAMIC`; never changes afterwards. */
117
+ mode?: RecommendationGroupMode;
118
+ }
119
+ /** Only the fields named change; `description: null` clears it. */
120
+ export interface UpdateRecommendationGroupInput {
121
+ name?: string;
122
+ slug?: string;
123
+ description?: string | null;
124
+ maxItems?: number;
125
+ position?: number;
126
+ enabled?: boolean;
127
+ }
128
+ export interface CreateRecommendationEntryInput {
129
+ groupId: string;
130
+ sourceType: RecommendationSourceType;
131
+ /** Required for `PRODUCT`, `COLLECTION` and `FACET_VALUE`; refused for the other two. */
132
+ sourceId?: string;
133
+ /** Defaults to after the group's last entry. */
134
+ position?: number;
135
+ }
136
+ /** Only the fields named change; `sourceId: null` clears it (for a `SAME_*` source type). */
137
+ export interface UpdateRecommendationEntryInput {
138
+ sourceType?: RecommendationSourceType;
139
+ sourceId?: string | null;
140
+ position?: number;
141
+ }
142
+ export interface RecommendationsModule {
143
+ groups: {
144
+ /**
145
+ * Every group of the store, in `position` order (ties: the older first), each with its
146
+ * entries. The engine answers them all at once; there are no pages.
147
+ *
148
+ * @effect read
149
+ */
150
+ list(options?: Call): Promise<RecommendationGroup[]>;
151
+ /**
152
+ * One group with its entries; `null` when the store has no group with that id.
153
+ *
154
+ * @effect read
155
+ */
156
+ get(id: string, options?: Call): Promise<RecommendationGroup | null>;
157
+ /**
158
+ * Refused (`RECOMMENDATION_GROUP_SLUG_TAKEN`) when the store already has a group with that
159
+ * slug, the defaulted one included.
160
+ *
161
+ * @effect write
162
+ */
163
+ create(input: CreateRecommendationGroupInput, options?: Call): Promise<RecommendationGroup>;
164
+ /**
165
+ * Refused: a group the store does not have (`ENTITY_NOT_FOUND`), a slug another of its groups
166
+ * holds (`RECOMMENDATION_GROUP_SLUG_TAKEN`).
167
+ *
168
+ * @effect write
169
+ */
170
+ update(id: string, input: UpdateRecommendationGroupInput, options?: Call): Promise<RecommendationGroup>;
171
+ /**
172
+ * Deletes the group, its entries and every product's picks in it. Refused
173
+ * (`ENTITY_NOT_FOUND`) for a group the store does not have.
174
+ *
175
+ * @effect destructive
176
+ */
177
+ delete(id: string, options?: Call): Promise<void>;
178
+ /**
179
+ * Gives the named groups the positions `0, 1, 2…` in the order given, and answers every group
180
+ * as `list` does. An id the store does not hold is skipped without a word; a group left out
181
+ * keeps its position, which may then equal a named one's: name them all.
182
+ *
183
+ * @effect write
184
+ */
185
+ reorder(ids: string[], options?: Call): Promise<RecommendationGroup[]>;
186
+ };
187
+ /** The rules of `DYNAMIC` groups. */
188
+ entries: {
189
+ /**
190
+ * Refused: a group the store does not have (`ENTITY_NOT_FOUND`); a `sourceId` that is not a
191
+ * product, collection or facet value of the store (`RECOMMENDATION_SOURCE_NOT_FOUND`: another
192
+ * store's is refused like an unknown id); a `MANUAL` group, or a `sourceId` missing for
193
+ * `PRODUCT` / `COLLECTION` / `FACET_VALUE` or sent for `SAME_COLLECTION` / `SAME_PROPERTIES`
194
+ * (`USER_INPUT_ERROR`).
195
+ *
196
+ * @effect write
197
+ */
198
+ create(input: CreateRecommendationEntryInput, options?: Call): Promise<RecommendationEntry>;
199
+ /**
200
+ * Refused: an entry the store does not have (`ENTITY_NOT_FOUND`); a source type and
201
+ * `sourceId` that do not go together once the change is applied (`USER_INPUT_ERROR`); a
202
+ * change of either that leaves the rule naming no row of the store
203
+ * (`RECOMMENDATION_SOURCE_NOT_FOUND`). A change of `position` alone is not judged.
204
+ *
205
+ * @effect write
206
+ */
207
+ update(id: string, input: UpdateRecommendationEntryInput, options?: Call): Promise<RecommendationEntry>;
208
+ /**
209
+ * Refused (`ENTITY_NOT_FOUND`) for an entry the store does not have.
210
+ *
211
+ * @effect destructive
212
+ */
213
+ delete(id: string, options?: Call): Promise<void>;
214
+ /**
215
+ * Gives the group's named entries the positions `0, 1, 2…` in the order given, and answers
216
+ * the group's entries in `position` order. An id that is not one of THIS group's entries is
217
+ * skipped without a word (another group's entry never moves); an entry left out keeps its
218
+ * position. Refused (`ENTITY_NOT_FOUND`) for a group the store does not have.
219
+ *
220
+ * @effect write
221
+ */
222
+ reorder(groupId: string, ids: string[], options?: Call): Promise<RecommendationEntry[]>;
223
+ };
224
+ /** The products picked per viewed product in `MANUAL` groups (the product page's card). */
225
+ manual: {
226
+ /**
227
+ * Every `MANUAL` group of the store, in `position` order, each with the products picked for
228
+ * `productId`. A product with no picks (or none of this store) answers every group with an
229
+ * empty `productIds`; a store with no manual group answers `[]`.
230
+ *
231
+ * @effect read
232
+ */
233
+ get(productId: string, options?: Call): Promise<ProductManualRecommendations[]>;
234
+ /**
235
+ * Replaces the products picked for `productId` in one `MANUAL` group, in the order given:
236
+ * `[]` clears them. The product itself and repeats are dropped (the first one kept). One
237
+ * write: refused, nothing changes.
238
+ *
239
+ * Refused: a group the store does not have, or `productId` not a product of this store
240
+ * (`ENTITY_NOT_FOUND`); a picked product that is not (`RECOMMENDATION_TARGET_NOT_FOUND`,
241
+ * naming each, `details` pointing at where it was sent); a `DYNAMIC` group
242
+ * (`USER_INPUT_ERROR`).
243
+ *
244
+ * @effect write
245
+ */
246
+ set(productId: string, groupId: string, productIds: string[], options?: Call): Promise<RecommendationGroupSummary>;
247
+ };
248
+ }
249
+ export declare const RECOMMENDATION_GROUPS_QUERY = "\n query CatalogRecommendationGroups {\n recommendationGroups { \n \n id\n name\n slug\n description\n maxItems\n position\n enabled\n mode\n createdAt\n updatedAt\n\n entries { \n id\n groupId\n sourceType\n sourceId\n position\n createdAt\n updatedAt\n }\n }\n }\n";
250
+ export declare const RECOMMENDATION_GROUP_QUERY = "\n query CatalogRecommendationGroup($id: ID!) {\n recommendationGroup(id: $id) { \n \n id\n name\n slug\n description\n maxItems\n position\n enabled\n mode\n createdAt\n updatedAt\n\n entries { \n id\n groupId\n sourceType\n sourceId\n position\n createdAt\n updatedAt\n }\n }\n }\n";
251
+ export declare const CREATE_RECOMMENDATION_GROUP_MUTATION = "\n mutation CatalogCreateRecommendationGroup($input: CreateRecommendationGroupInput!) {\n createRecommendationGroup(input: $input) { \n \n id\n name\n slug\n description\n maxItems\n position\n enabled\n mode\n createdAt\n updatedAt\n\n entries { \n id\n groupId\n sourceType\n sourceId\n position\n createdAt\n updatedAt\n }\n }\n }\n";
252
+ export declare const UPDATE_RECOMMENDATION_GROUP_MUTATION = "\n mutation CatalogUpdateRecommendationGroup($id: ID!, $input: UpdateRecommendationGroupInput!) {\n updateRecommendationGroup(id: $id, input: $input) { \n \n id\n name\n slug\n description\n maxItems\n position\n enabled\n mode\n createdAt\n updatedAt\n\n entries { \n id\n groupId\n sourceType\n sourceId\n position\n createdAt\n updatedAt\n }\n }\n }\n";
253
+ export declare const DELETE_RECOMMENDATION_GROUP_MUTATION = "\n mutation CatalogDeleteRecommendationGroup($id: ID!) {\n deleteRecommendationGroup(id: $id) { \n result\n message\n }\n }\n";
254
+ export declare const REORDER_RECOMMENDATION_GROUPS_MUTATION = "\n mutation CatalogReorderRecommendationGroups($ids: [ID!]!) {\n reorderRecommendationGroups(ids: $ids) { \n \n id\n name\n slug\n description\n maxItems\n position\n enabled\n mode\n createdAt\n updatedAt\n\n entries { \n id\n groupId\n sourceType\n sourceId\n position\n createdAt\n updatedAt\n }\n }\n }\n";
255
+ export declare const CREATE_RECOMMENDATION_ENTRY_MUTATION = "\n mutation CatalogCreateRecommendationEntry($input: CreateRecommendationEntryInput!) {\n createRecommendationEntry(input: $input) { \n id\n groupId\n sourceType\n sourceId\n position\n createdAt\n updatedAt\n }\n }\n";
256
+ export declare const UPDATE_RECOMMENDATION_ENTRY_MUTATION = "\n mutation CatalogUpdateRecommendationEntry($id: ID!, $input: UpdateRecommendationEntryInput!) {\n updateRecommendationEntry(id: $id, input: $input) { \n id\n groupId\n sourceType\n sourceId\n position\n createdAt\n updatedAt\n }\n }\n";
257
+ export declare const DELETE_RECOMMENDATION_ENTRY_MUTATION = "\n mutation CatalogDeleteRecommendationEntry($id: ID!) {\n deleteRecommendationEntry(id: $id) { \n result\n message\n }\n }\n";
258
+ export declare const REORDER_RECOMMENDATION_ENTRIES_MUTATION = "\n mutation CatalogReorderRecommendationEntries($groupId: ID!, $ids: [ID!]!) {\n reorderRecommendationEntries(groupId: $groupId, ids: $ids) { \n id\n groupId\n sourceType\n sourceId\n position\n createdAt\n updatedAt\n }\n }\n";
259
+ export declare const PRODUCT_MANUAL_RECOMMENDATIONS_QUERY = "\n query CatalogProductManualRecommendations($productId: ID!) {\n productManualRecommendations(productId: $productId) {\n group { \n id\n name\n slug\n description\n maxItems\n position\n enabled\n mode\n createdAt\n updatedAt\n }\n productIds\n }\n }\n";
260
+ export declare const SET_PRODUCT_MANUAL_RECOMMENDATIONS_MUTATION = "\n mutation CatalogSetProductManualRecommendations(\n $productId: ID!\n $groupId: ID!\n $targetProductIds: [ID!]!\n ) {\n setProductManualRecommendations(\n productId: $productId\n groupId: $groupId\n targetProductIds: $targetProductIds\n ) { \n id\n name\n slug\n description\n maxItems\n position\n enabled\n mode\n createdAt\n updatedAt\n }\n }\n";
261
+ export declare function createRecommendationsModule(transport: Transport): RecommendationsModule;
@@ -0,0 +1,145 @@
1
+ import { assertDeleted, DELETION_FIELDS, fieldOf } from './types.js';
2
+ /** The source types whose entry names a row (`sourceId`); the others must name none. */
3
+ export const RECOMMENDATION_SOURCE_TYPES_WITH_ID = [
4
+ 'PRODUCT',
5
+ 'COLLECTION',
6
+ 'FACET_VALUE',
7
+ ];
8
+ const ENTRY_FIELDS = /* GraphQL */ `
9
+ id
10
+ groupId
11
+ sourceType
12
+ sourceId
13
+ position
14
+ createdAt
15
+ updatedAt
16
+ `;
17
+ const GROUP_SUMMARY_FIELDS = /* GraphQL */ `
18
+ id
19
+ name
20
+ slug
21
+ description
22
+ maxItems
23
+ position
24
+ enabled
25
+ mode
26
+ createdAt
27
+ updatedAt
28
+ `;
29
+ const GROUP_FIELDS = /* GraphQL */ `
30
+ ${GROUP_SUMMARY_FIELDS}
31
+ entries { ${ENTRY_FIELDS} }
32
+ `;
33
+ export const RECOMMENDATION_GROUPS_QUERY = /* GraphQL */ `
34
+ query CatalogRecommendationGroups {
35
+ recommendationGroups { ${GROUP_FIELDS} }
36
+ }
37
+ `;
38
+ export const RECOMMENDATION_GROUP_QUERY = /* GraphQL */ `
39
+ query CatalogRecommendationGroup($id: ID!) {
40
+ recommendationGroup(id: $id) { ${GROUP_FIELDS} }
41
+ }
42
+ `;
43
+ export const CREATE_RECOMMENDATION_GROUP_MUTATION = /* GraphQL */ `
44
+ mutation CatalogCreateRecommendationGroup($input: CreateRecommendationGroupInput!) {
45
+ createRecommendationGroup(input: $input) { ${GROUP_FIELDS} }
46
+ }
47
+ `;
48
+ export const UPDATE_RECOMMENDATION_GROUP_MUTATION = /* GraphQL */ `
49
+ mutation CatalogUpdateRecommendationGroup($id: ID!, $input: UpdateRecommendationGroupInput!) {
50
+ updateRecommendationGroup(id: $id, input: $input) { ${GROUP_FIELDS} }
51
+ }
52
+ `;
53
+ export const DELETE_RECOMMENDATION_GROUP_MUTATION = /* GraphQL */ `
54
+ mutation CatalogDeleteRecommendationGroup($id: ID!) {
55
+ deleteRecommendationGroup(id: $id) { ${DELETION_FIELDS} }
56
+ }
57
+ `;
58
+ export const REORDER_RECOMMENDATION_GROUPS_MUTATION = /* GraphQL */ `
59
+ mutation CatalogReorderRecommendationGroups($ids: [ID!]!) {
60
+ reorderRecommendationGroups(ids: $ids) { ${GROUP_FIELDS} }
61
+ }
62
+ `;
63
+ export const CREATE_RECOMMENDATION_ENTRY_MUTATION = /* GraphQL */ `
64
+ mutation CatalogCreateRecommendationEntry($input: CreateRecommendationEntryInput!) {
65
+ createRecommendationEntry(input: $input) { ${ENTRY_FIELDS} }
66
+ }
67
+ `;
68
+ export const UPDATE_RECOMMENDATION_ENTRY_MUTATION = /* GraphQL */ `
69
+ mutation CatalogUpdateRecommendationEntry($id: ID!, $input: UpdateRecommendationEntryInput!) {
70
+ updateRecommendationEntry(id: $id, input: $input) { ${ENTRY_FIELDS} }
71
+ }
72
+ `;
73
+ export const DELETE_RECOMMENDATION_ENTRY_MUTATION = /* GraphQL */ `
74
+ mutation CatalogDeleteRecommendationEntry($id: ID!) {
75
+ deleteRecommendationEntry(id: $id) { ${DELETION_FIELDS} }
76
+ }
77
+ `;
78
+ export const REORDER_RECOMMENDATION_ENTRIES_MUTATION = /* GraphQL */ `
79
+ mutation CatalogReorderRecommendationEntries($groupId: ID!, $ids: [ID!]!) {
80
+ reorderRecommendationEntries(groupId: $groupId, ids: $ids) { ${ENTRY_FIELDS} }
81
+ }
82
+ `;
83
+ // The engine does not load `entries` for these groups (a MANUAL group has none), and selecting a
84
+ // non-null field it did not load fails the whole read: never add `entries` here.
85
+ export const PRODUCT_MANUAL_RECOMMENDATIONS_QUERY = /* GraphQL */ `
86
+ query CatalogProductManualRecommendations($productId: ID!) {
87
+ productManualRecommendations(productId: $productId) {
88
+ group { ${GROUP_SUMMARY_FIELDS} }
89
+ productIds
90
+ }
91
+ }
92
+ `;
93
+ export const SET_PRODUCT_MANUAL_RECOMMENDATIONS_MUTATION = /* GraphQL */ `
94
+ mutation CatalogSetProductManualRecommendations(
95
+ $productId: ID!
96
+ $groupId: ID!
97
+ $targetProductIds: [ID!]!
98
+ ) {
99
+ setProductManualRecommendations(
100
+ productId: $productId
101
+ groupId: $groupId
102
+ targetProductIds: $targetProductIds
103
+ ) { ${GROUP_SUMMARY_FIELDS} }
104
+ }
105
+ `;
106
+ /** Entries in `position` order, the older first on a tie, as the engine's own entry reads sort. */
107
+ function byPosition(entries) {
108
+ return [...entries].sort((a, b) => a.position - b.position || a.createdAt.localeCompare(b.createdAt));
109
+ }
110
+ // The engine's group list loads `entries` without an order; only its one-group read sorts them.
111
+ function withSortedEntries(group) {
112
+ return { ...group, entries: byPosition(group.entries) };
113
+ }
114
+ export function createRecommendationsModule(transport) {
115
+ const call = (document, field, variables, options) => fieldOf(transport, document, field, variables, options);
116
+ return {
117
+ groups: {
118
+ list: async (options) => (await call(RECOMMENDATION_GROUPS_QUERY, 'recommendationGroups', {}, options)).map(withSortedEntries),
119
+ async get(id, options) {
120
+ const group = await call(RECOMMENDATION_GROUP_QUERY, 'recommendationGroup', { id }, options);
121
+ return group === null ? null : withSortedEntries(group);
122
+ },
123
+ create: async (input, options) => withSortedEntries(await call(CREATE_RECOMMENDATION_GROUP_MUTATION, 'createRecommendationGroup', { input }, options)),
124
+ update: async (id, input, options) => withSortedEntries(await call(UPDATE_RECOMMENDATION_GROUP_MUTATION, 'updateRecommendationGroup', { id, input }, options)),
125
+ async delete(id, options) {
126
+ const response = await call(DELETE_RECOMMENDATION_GROUP_MUTATION, 'deleteRecommendationGroup', { id }, options);
127
+ assertDeleted('RECOMMENDATION_GROUP_NOT_DELETED', [response]);
128
+ },
129
+ reorder: async (ids, options) => (await call(REORDER_RECOMMENDATION_GROUPS_MUTATION, 'reorderRecommendationGroups', { ids }, options)).map(withSortedEntries),
130
+ },
131
+ entries: {
132
+ create: (input, options) => call(CREATE_RECOMMENDATION_ENTRY_MUTATION, 'createRecommendationEntry', { input }, options),
133
+ update: (id, input, options) => call(UPDATE_RECOMMENDATION_ENTRY_MUTATION, 'updateRecommendationEntry', { id, input }, options),
134
+ async delete(id, options) {
135
+ const response = await call(DELETE_RECOMMENDATION_ENTRY_MUTATION, 'deleteRecommendationEntry', { id }, options);
136
+ assertDeleted('RECOMMENDATION_ENTRY_NOT_DELETED', [response]);
137
+ },
138
+ reorder: (groupId, ids, options) => call(REORDER_RECOMMENDATION_ENTRIES_MUTATION, 'reorderRecommendationEntries', { groupId, ids }, options),
139
+ },
140
+ manual: {
141
+ get: (productId, options) => call(PRODUCT_MANUAL_RECOMMENDATIONS_QUERY, 'productManualRecommendations', { productId }, options),
142
+ set: (productId, groupId, productIds, options) => call(SET_PRODUCT_MANUAL_RECOMMENDATIONS_MUTATION, 'setProductManualRecommendations', { productId, groupId, targetProductIds: productIds }, options),
143
+ },
144
+ };
145
+ }