@sixtyninecommerce/admin 0.10.0 → 0.12.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 (302) hide show
  1. package/README.md +5772 -118
  2. package/dist/auth/index.d.ts +7 -1
  3. package/dist/auth/index.js +8 -1
  4. package/dist/catalog/assets.d.ts +120 -8
  5. package/dist/catalog/assets.js +98 -12
  6. package/dist/catalog/collections.d.ts +279 -14
  7. package/dist/catalog/collections.js +246 -15
  8. package/dist/catalog/documents.d.ts +142 -0
  9. package/dist/catalog/documents.js +114 -0
  10. package/dist/catalog/index.d.ts +54 -6
  11. package/dist/catalog/index.js +10 -1
  12. package/dist/catalog/metadata.d.ts +244 -0
  13. package/dist/catalog/metadata.js +220 -0
  14. package/dist/catalog/products.d.ts +159 -19
  15. package/dist/catalog/products.js +88 -13
  16. package/dist/catalog/properties.d.ts +140 -14
  17. package/dist/catalog/properties.js +65 -1
  18. package/dist/catalog/recommendations.d.ts +288 -0
  19. package/dist/catalog/recommendations.js +237 -0
  20. package/dist/catalog/reviews.d.ts +381 -0
  21. package/dist/catalog/reviews.js +325 -0
  22. package/dist/catalog/types.d.ts +17 -1
  23. package/dist/catalog/types.js +10 -0
  24. package/dist/catalog/variant-find.d.ts +136 -0
  25. package/dist/catalog/variant-find.js +239 -0
  26. package/dist/catalog/variants.d.ts +293 -26
  27. package/dist/catalog/variants.js +164 -7
  28. package/dist/catalog/visibility.d.ts +38 -7
  29. package/dist/catalog/visibility.js +19 -1
  30. package/dist/client.d.ts +121 -9
  31. package/dist/client.js +53 -14
  32. package/dist/content/assets.d.ts +285 -0
  33. package/dist/content/assets.js +181 -0
  34. package/dist/content/forms.d.ts +332 -1
  35. package/dist/content/forms.js +140 -4
  36. package/dist/content/items.d.ts +292 -0
  37. package/dist/content/items.js +170 -0
  38. package/dist/content/menus.d.ts +254 -0
  39. package/dist/content/menus.js +70 -0
  40. package/dist/content/strings.d.ts +137 -0
  41. package/dist/content/strings.js +82 -0
  42. package/dist/content/types.d.ts +282 -0
  43. package/dist/content/types.js +100 -0
  44. package/dist/customers/age-verification.d.ts +66 -0
  45. package/dist/customers/age-verification.js +79 -0
  46. package/dist/customers/credit.d.ts +263 -0
  47. package/dist/customers/credit.js +244 -0
  48. package/dist/customers/delivery-preferences.d.ts +120 -0
  49. package/dist/customers/delivery-preferences.js +97 -0
  50. package/dist/customers/delivery-terms.d.ts +44 -0
  51. package/dist/customers/delivery-terms.js +32 -0
  52. package/dist/customers/groups.d.ts +207 -0
  53. package/dist/customers/groups.js +438 -0
  54. package/dist/customers/index.d.ts +462 -37
  55. package/dist/customers/index.js +317 -40
  56. package/dist/customers/invitation-status.d.ts +57 -0
  57. package/dist/customers/invitation-status.js +21 -0
  58. package/dist/customers/notes.d.ts +67 -0
  59. package/dist/customers/notes.js +51 -0
  60. package/dist/customers/notification-recipients.d.ts +97 -0
  61. package/dist/customers/notification-recipients.js +84 -0
  62. package/dist/customers/saved-lists.d.ts +42 -0
  63. package/dist/customers/saved-lists.js +61 -0
  64. package/dist/customers/vat.d.ts +83 -0
  65. package/dist/customers/vat.js +46 -0
  66. package/dist/customers/wire.d.ts +20 -0
  67. package/dist/customers/wire.js +35 -0
  68. package/dist/documents/ar.d.ts +307 -0
  69. package/dist/documents/ar.js +254 -0
  70. package/dist/documents/emails.d.ts +150 -0
  71. package/dist/documents/emails.js +220 -0
  72. package/dist/documents/index.d.ts +744 -21
  73. package/dist/documents/index.js +438 -24
  74. package/dist/documents/pdf.d.ts +2 -0
  75. package/dist/documents/pdf.js +11 -0
  76. package/dist/fulfillments/create.d.ts +167 -0
  77. package/dist/fulfillments/create.js +216 -0
  78. package/dist/fulfillments/index.d.ts +163 -11
  79. package/dist/fulfillments/index.js +135 -6
  80. package/dist/fulfillments/payment-policy.d.ts +64 -0
  81. package/dist/fulfillments/payment-policy.js +140 -0
  82. package/dist/fulfillments/warehouse.d.ts +724 -0
  83. package/dist/fulfillments/warehouse.js +914 -0
  84. package/dist/geo/index.d.ts +119 -0
  85. package/dist/geo/index.js +107 -0
  86. package/dist/index.d.ts +147 -39
  87. package/dist/index.js +51 -12
  88. package/dist/integrations/afas-actions.d.ts +234 -0
  89. package/dist/integrations/afas-actions.js +310 -0
  90. package/dist/integrations/afas-types.d.ts +483 -0
  91. package/dist/integrations/afas-types.js +5 -0
  92. package/dist/integrations/afas.d.ts +234 -0
  93. package/dist/integrations/afas.js +290 -0
  94. package/dist/integrations/connections.d.ts +103 -0
  95. package/dist/integrations/connections.js +55 -0
  96. package/dist/integrations/esp.d.ts +313 -0
  97. package/dist/integrations/esp.js +169 -0
  98. package/dist/integrations/exact-online-types.d.ts +965 -0
  99. package/dist/integrations/exact-online-types.js +6 -0
  100. package/dist/integrations/exact-online.d.ts +784 -0
  101. package/dist/integrations/exact-online.js +1089 -0
  102. package/dist/integrations/index.d.ts +44 -3
  103. package/dist/integrations/index.js +23 -3
  104. package/dist/integrations/pipeline-discoveries.d.ts +65 -0
  105. package/dist/integrations/pipeline-discoveries.js +65 -0
  106. package/dist/integrations/pipeline-keys.d.ts +13 -0
  107. package/dist/integrations/pipeline-keys.js +22 -0
  108. package/dist/integrations/pipeline-runs.d.ts +119 -0
  109. package/dist/integrations/pipeline-runs.js +87 -0
  110. package/dist/integrations/pipelines.d.ts +87 -15
  111. package/dist/integrations/pipelines.js +41 -22
  112. package/dist/integrations/price-import.d.ts +223 -0
  113. package/dist/integrations/price-import.js +124 -0
  114. package/dist/integrations/types.d.ts +367 -3
  115. package/dist/integrations/types.js +4 -3
  116. package/dist/locations/index.d.ts +66 -0
  117. package/dist/locations/index.js +31 -0
  118. package/dist/meta/index.d.ts +172 -0
  119. package/dist/metafields/index.d.ts +8 -1
  120. package/dist/metafields/index.js +10 -0
  121. package/dist/orders/cancel-with-money.d.ts +237 -0
  122. package/dist/orders/cancel-with-money.js +155 -0
  123. package/dist/orders/commit-edit.d.ts +23 -1
  124. package/dist/orders/commit-edit.js +19 -2
  125. package/dist/orders/deposit-policy.d.ts +3 -1
  126. package/dist/orders/drafts.d.ts +800 -0
  127. package/dist/orders/drafts.js +771 -0
  128. package/dist/orders/fields.d.ts +245 -0
  129. package/dist/orders/fields.js +188 -0
  130. package/dist/orders/get.d.ts +29 -19
  131. package/dist/orders/get.js +17 -8
  132. package/dist/orders/index.d.ts +66 -15
  133. package/dist/orders/index.js +25 -2
  134. package/dist/orders/lifecycle.d.ts +128 -0
  135. package/dist/orders/lifecycle.js +158 -0
  136. package/dist/orders/line-price-preview.d.ts +7 -2
  137. package/dist/orders/list.d.ts +243 -0
  138. package/dist/orders/list.js +487 -0
  139. package/dist/orders/manual-discounts.d.ts +13 -5
  140. package/dist/orders/manual-pricing.d.ts +5 -0
  141. package/dist/orders/money-view.d.ts +149 -0
  142. package/dist/orders/money-view.js +99 -0
  143. package/dist/orders/order-entry.d.ts +20 -7
  144. package/dist/orders/plan-edit.d.ts +34 -2
  145. package/dist/orders/plan-edit.js +112 -11
  146. package/dist/orders/settings.d.ts +201 -0
  147. package/dist/orders/settings.js +325 -0
  148. package/dist/orders/status.d.ts +159 -13
  149. package/dist/orders/status.js +21 -0
  150. package/dist/orders/surcharges.d.ts +20 -1
  151. package/dist/orders/surcharges.js +37 -11
  152. package/dist/payments/account-credit.d.ts +46 -0
  153. package/dist/payments/account-credit.js +42 -0
  154. package/dist/payments/ar.d.ts +292 -0
  155. package/dist/payments/ar.js +223 -0
  156. package/dist/payments/connected-account.d.ts +47 -0
  157. package/dist/payments/connected-account.js +61 -0
  158. package/dist/payments/credit-noted-fields.d.ts +19 -0
  159. package/dist/payments/credit-noted-fields.js +69 -0
  160. package/dist/payments/customer-consent.d.ts +30 -0
  161. package/dist/payments/customer-consent.js +49 -0
  162. package/dist/payments/index.d.ts +340 -19
  163. package/dist/payments/index.js +151 -1
  164. package/dist/payments/methods.d.ts +303 -8
  165. package/dist/payments/methods.js +337 -7
  166. package/dist/payments/mollie-methods.d.ts +159 -0
  167. package/dist/payments/mollie-methods.js +141 -0
  168. package/dist/payments/payment-links.d.ts +180 -0
  169. package/dist/payments/payment-links.js +97 -0
  170. package/dist/payments/provider-keys.d.ts +150 -0
  171. package/dist/payments/provider-keys.js +118 -0
  172. package/dist/payments/providers.d.ts +86 -11
  173. package/dist/payments/providers.js +29 -0
  174. package/dist/payments/requests.d.ts +147 -0
  175. package/dist/payments/requests.js +93 -0
  176. package/dist/payments/store-credit-fields.d.ts +15 -0
  177. package/dist/payments/store-credit-fields.js +51 -0
  178. package/dist/pickups/index.d.ts +106 -0
  179. package/dist/pickups/index.js +108 -0
  180. package/dist/platform/channels.d.ts +132 -0
  181. package/dist/platform/channels.js +128 -0
  182. package/dist/platform/email-gateways.d.ts +165 -0
  183. package/dist/platform/email-gateways.js +78 -0
  184. package/dist/platform/geo.d.ts +123 -0
  185. package/dist/platform/geo.js +144 -0
  186. package/dist/platform/tax.d.ts +162 -0
  187. package/dist/platform/tax.js +169 -0
  188. package/dist/pos/anomalies.d.ts +158 -0
  189. package/dist/pos/anomalies.js +64 -0
  190. package/dist/pos/assisted-selling.d.ts +79 -0
  191. package/dist/pos/assisted-selling.js +38 -0
  192. package/dist/pos/exchanges.d.ts +108 -0
  193. package/dist/pos/exchanges.js +22 -0
  194. package/dist/pos/gift-cards.d.ts +135 -0
  195. package/dist/pos/gift-cards.js +47 -0
  196. package/dist/pos/index.d.ts +2370 -58
  197. package/dist/pos/index.js +854 -7
  198. package/dist/pos/no-receipt.d.ts +94 -0
  199. package/dist/pos/no-receipt.js +25 -0
  200. package/dist/pos/offline-sales.d.ts +228 -0
  201. package/dist/pos/offline-sales.js +170 -0
  202. package/dist/pos/pay-by-link.d.ts +143 -0
  203. package/dist/pos/pay-by-link.js +57 -0
  204. package/dist/pos/quick-keys.d.ts +103 -0
  205. package/dist/pos/quick-keys.js +45 -0
  206. package/dist/pos/reports.d.ts +360 -0
  207. package/dist/pos/reports.js +62 -0
  208. package/dist/pos/returns.d.ts +244 -0
  209. package/dist/pos/returns.js +83 -0
  210. package/dist/pricing/bulk-coupons.d.ts +139 -0
  211. package/dist/pricing/bulk-coupons.js +112 -0
  212. package/dist/pricing/index.d.ts +174 -4
  213. package/dist/pricing/index.js +174 -1
  214. package/dist/pricing/price-lists.d.ts +606 -0
  215. package/dist/pricing/price-lists.js +600 -0
  216. package/dist/purchasing/alerts.d.ts +104 -0
  217. package/dist/purchasing/alerts.js +88 -0
  218. package/dist/purchasing/backorders.d.ts +61 -0
  219. package/dist/purchasing/backorders.js +92 -0
  220. package/dist/purchasing/cost.d.ts +110 -0
  221. package/dist/purchasing/cost.js +86 -0
  222. package/dist/purchasing/index.d.ts +54 -0
  223. package/dist/purchasing/index.js +24 -0
  224. package/dist/purchasing/links.d.ts +263 -0
  225. package/dist/purchasing/links.js +192 -0
  226. package/dist/purchasing/purchase-orders.d.ts +551 -0
  227. package/dist/purchasing/purchase-orders.js +491 -0
  228. package/dist/purchasing/receipts.d.ts +396 -0
  229. package/dist/purchasing/receipts.js +287 -0
  230. package/dist/purchasing/replenishment.d.ts +281 -0
  231. package/dist/purchasing/replenishment.js +240 -0
  232. package/dist/purchasing/returns.d.ts +273 -0
  233. package/dist/purchasing/returns.js +229 -0
  234. package/dist/purchasing/settings.d.ts +152 -0
  235. package/dist/purchasing/settings.js +181 -0
  236. package/dist/purchasing/suppliers.d.ts +476 -0
  237. package/dist/purchasing/suppliers.js +438 -0
  238. package/dist/quotes/index.d.ts +518 -0
  239. package/dist/quotes/index.js +439 -0
  240. package/dist/reports/index.d.ts +71 -8
  241. package/dist/reports/index.js +74 -11
  242. package/dist/returns/index.d.ts +675 -21
  243. package/dist/returns/index.js +756 -11
  244. package/dist/search/index.d.ts +76 -1
  245. package/dist/search/index.js +63 -0
  246. package/dist/seo/config.d.ts +128 -0
  247. package/dist/seo/config.js +95 -0
  248. package/dist/seo/redirects.d.ts +125 -0
  249. package/dist/seo/redirects.js +60 -1
  250. package/dist/seo/settings.d.ts +147 -0
  251. package/dist/seo/settings.js +209 -0
  252. package/dist/shipping/definitions.d.ts +29 -0
  253. package/dist/shipping/definitions.js +47 -0
  254. package/dist/shipping/fulfillment-profiles.d.ts +174 -0
  255. package/dist/shipping/fulfillment-profiles.js +104 -0
  256. package/dist/shipping/hendriks.d.ts +97 -0
  257. package/dist/shipping/hendriks.js +50 -0
  258. package/dist/shipping/index.d.ts +54 -0
  259. package/dist/shipping/index.js +27 -0
  260. package/dist/shipping/methods.d.ts +205 -0
  261. package/dist/shipping/methods.js +240 -0
  262. package/dist/shipping/myparcel.d.ts +668 -0
  263. package/dist/shipping/myparcel.js +466 -0
  264. package/dist/shipping/parcel-count-suggestion.d.ts +2 -0
  265. package/dist/shipping/parcel-rule.d.ts +6 -5
  266. package/dist/shipping/parcel-rule.js +21 -23
  267. package/dist/shipping/rate-tables.d.ts +324 -0
  268. package/dist/shipping/rate-tables.js +390 -0
  269. package/dist/shipping/ship-to-countries.d.ts +75 -0
  270. package/dist/shipping/ship-to-countries.js +47 -0
  271. package/dist/stock/by-location.d.ts +86 -0
  272. package/dist/stock/by-location.js +94 -0
  273. package/dist/stock/index.d.ts +18 -4
  274. package/dist/stock/index.js +7 -0
  275. package/dist/stock/locations.d.ts +144 -0
  276. package/dist/stock/locations.js +168 -0
  277. package/dist/stock/settings.d.ts +106 -0
  278. package/dist/stock/settings.js +103 -0
  279. package/dist/stock/transfers.d.ts +386 -52
  280. package/dist/stock/transfers.js +222 -17
  281. package/dist/stored-value/index.d.ts +312 -11
  282. package/dist/stored-value/index.js +223 -4
  283. package/dist/subscriptions/index.d.ts +682 -0
  284. package/dist/subscriptions/index.js +815 -0
  285. package/dist/tax/display-policy.d.ts +105 -0
  286. package/dist/tax/display-policy.js +84 -0
  287. package/dist/tax/index.d.ts +79 -1
  288. package/dist/tax/index.js +52 -0
  289. package/dist/tenant/email-style.d.ts +102 -0
  290. package/dist/tenant/email-style.js +72 -0
  291. package/dist/tenant/email-templates.d.ts +287 -0
  292. package/dist/tenant/email-templates.js +271 -0
  293. package/dist/tenant/notifications.d.ts +23 -17
  294. package/dist/tenant/settings-sources.d.ts +1 -1
  295. package/dist/tenant/time-zone.d.ts +17 -0
  296. package/dist/tenant/time-zone.js +11 -0
  297. package/dist/types.d.ts +50 -3
  298. package/dist/users/index.d.ts +3 -0
  299. package/dist/users/index.js +2 -0
  300. package/dist/users/warehouses.d.ts +50 -0
  301. package/dist/users/warehouses.js +51 -0
  302. package/package.json +2 -2
@@ -1,9 +1,16 @@
1
1
  import { NotFoundError, UpstreamError, ValidationError, } from '@sixtyninecommerce/core';
2
- import { ASSET_REF_FIELDS, assertDeleted, availabilityCustomFields, DELETION_FIELDS, FACET_VALUE_REF_FIELDS, fieldOf, vendureListPage, } from './types.js';
2
+ import { ASSET_REF_FIELDS, assertDeleted, availabilityCustomFields, DELETION_FIELDS, FACET_VALUE_REF_FIELDS, fieldOf, MAX_PAGE_SIZE, toAssetRef, vendureListPage, } from './types.js';
3
+ import { findVariants } from './variant-find.js';
3
4
  const PARCEL_PACKING_MODES = ['shared', 'separate', 'none'];
4
5
  /** The engine's bounds for `parcelCapacity` (shipping-calculator's `MAX_PARCEL_CAPACITY`). */
5
6
  const PARCEL_CAPACITY_MIN = 1;
6
7
  const PARCEL_CAPACITY_MAX = 10_000;
8
+ /** The sources {@link VariantsModule.setAvailableFromSource} sends. */
9
+ export const AVAILABLE_FROM_SOURCES = ['manual', 'incoming'];
10
+ /** The variants {@link VariantsModule.optionSets} reads at most by default. */
11
+ export const DEFAULT_OPTION_SET_LIMIT = MAX_PAGE_SIZE;
12
+ /** The most variants one {@link VariantsModule.optionSets} call reads. */
13
+ export const MAX_OPTION_SET_LIMIT = 100_000;
7
14
  /** The engine's bound on one `revertPrice` call (`MAX_REVERT_VARIANTS`). */
8
15
  export const MAX_REVERT_PRICE_VARIANTS = 500;
9
16
  export const VARIANT_FIELDS = /* GraphQL */ `
@@ -15,9 +22,16 @@ export const VARIANT_FIELDS = /* GraphQL */ `
15
22
  name
16
23
  sku
17
24
  enabled
18
- price
19
- priceWithTax
20
- currencyCode
25
+ storePrice {
26
+ price
27
+ priceWithTax
28
+ currencyCode
29
+ }
30
+ prices {
31
+ currencyCode
32
+ price
33
+ }
34
+ stockOnHand
21
35
  taxCategory {
22
36
  id
23
37
  name
@@ -51,6 +65,18 @@ export const VARIANT_FIELDS = /* GraphQL */ `
51
65
  preorderLimit
52
66
  parcelCapacity
53
67
  parcelPacking
68
+ minOrderQuantity
69
+ salesUnit
70
+ position
71
+ cost
72
+ packageWeightGrams
73
+ packageLengthCm
74
+ packageWidthCm
75
+ packageHeightCm
76
+ backorderPolicy
77
+ backorderLimit
78
+ gtin
79
+ mpn
54
80
  }
55
81
  `;
56
82
  export const VARIANTS_QUERY = /* GraphQL */ `
@@ -61,6 +87,20 @@ export const VARIANTS_QUERY = /* GraphQL */ `
61
87
  }
62
88
  }
63
89
  `;
90
+ /** Two fields a row, for {@link VariantsModule.optionSets}: the id and its options' ids. */
91
+ export const VARIANT_OPTION_SETS_QUERY = /* GraphQL */ `
92
+ query CatalogVariantOptionSets($productId: ID!, $options: ProductVariantListOptions) {
93
+ productVariants(productId: $productId, options: $options) {
94
+ items {
95
+ id
96
+ options {
97
+ id
98
+ }
99
+ }
100
+ totalItems
101
+ }
102
+ }
103
+ `;
64
104
  export const VARIANT_QUERY = /* GraphQL */ `
65
105
  query CatalogVariant($id: ID!) {
66
106
  productVariant(id: $id) { ${VARIANT_FIELDS} }
@@ -104,6 +144,31 @@ export const REVERT_TO_ORGANIZATION_PRICE_MUTATION = /* GraphQL */ `
104
144
  revertToOrganizationPrice(variantIds: $variantIds, currencyCodes: $currencyCodes) { ${VARIANT_FIELDS} }
105
145
  }
106
146
  `;
147
+ const VARIANT_AVAILABLE_FROM_SOURCE_FIELDS = /* GraphQL */ `
148
+ productVariantId
149
+ source
150
+ availableFrom
151
+ confirmedIncomingOn
152
+ sharedAcrossLegalEntities
153
+ `;
154
+ /** Its own document: see {@link VariantsModule.availableFromSource}. */
155
+ export const VARIANT_AVAILABLE_FROM_SOURCE_QUERY = /* GraphQL */ `
156
+ query CatalogVariantAvailableFromSource($productVariantId: ID!) {
157
+ variantAvailableFromSource(productVariantId: $productVariantId) {
158
+ ${VARIANT_AVAILABLE_FROM_SOURCE_FIELDS}
159
+ }
160
+ }
161
+ `;
162
+ export const SET_VARIANT_AVAILABLE_FROM_SOURCE_MUTATION = /* GraphQL */ `
163
+ mutation CatalogSetVariantAvailableFromSource(
164
+ $input: SetVariantAvailableFromSourceInput!
165
+ $idempotencyKey: String
166
+ ) {
167
+ setVariantAvailableFromSource(input: $input, idempotencyKey: $idempotencyKey) {
168
+ ${VARIANT_AVAILABLE_FROM_SOURCE_FIELDS}
169
+ }
170
+ }
171
+ `;
107
172
  /** The price basis the store stores, read on the SAME tenant as the write. */
108
173
  export const PRICE_BASIS_QUERY = /* GraphQL */ `
109
174
  query CatalogPriceBasis {
@@ -112,13 +177,33 @@ export const PRICE_BASIS_QUERY = /* GraphQL */ `
112
177
  }
113
178
  }
114
179
  `;
180
+ /** The variant fields read out of `customFields` as they are, null for an unset one. */
181
+ export const LIFTED_CUSTOM_FIELDS = [
182
+ 'minOrderQuantity',
183
+ 'salesUnit',
184
+ 'position',
185
+ 'cost',
186
+ 'packageWeightGrams',
187
+ 'packageLengthCm',
188
+ 'packageWidthCm',
189
+ 'packageHeightCm',
190
+ 'backorderPolicy',
191
+ 'backorderLimit',
192
+ 'gtin',
193
+ 'mpn',
194
+ ];
115
195
  function isParcelPacking(value) {
116
196
  return PARCEL_PACKING_MODES.includes(value);
117
197
  }
198
+ /** Lift the custom fields to first-class fields. */
118
199
  export function toVariant(wire) {
119
- const { customFields, ...rest } = wire;
200
+ const { customFields, featuredAsset, assets, ...rest } = wire;
201
+ const lifted = Object.fromEntries(LIFTED_CUSTOM_FIELDS.map((key) => [key, customFields?.[key] ?? null]));
120
202
  return {
121
203
  ...rest,
204
+ ...lifted,
205
+ featuredAsset: featuredAsset ? toAssetRef(featuredAsset) : null,
206
+ assets: assets.map(toAssetRef),
122
207
  taxClassKey: customFields?.taxClassKey ?? null,
123
208
  availabilityState: customFields?.availabilityState ?? 'inherit',
124
209
  availableFrom: customFields?.availableFrom ?? null,
@@ -180,6 +265,40 @@ function toWireInput(input) {
180
265
  function refuse(code, message) {
181
266
  return new ValidationError({ code, message, status: 400, service: 'vendure' });
182
267
  }
268
+ const VARIANT_SORT_FIELDS = [
269
+ 'position',
270
+ 'name',
271
+ 'sku',
272
+ 'createdAt',
273
+ 'updatedAt',
274
+ ];
275
+ /**
276
+ * The engine's `ProductVariantListOptions` for {@link VariantListOptions}, without the page
277
+ * window. ONE sort key, never a tie-breaker beside it: graphql-js coerces an input object in the
278
+ * order its TYPE declares the fields, and `ProductVariantSortParameter` declares `id` before every
279
+ * field named here, so `{ position, id }` reaches the engine as `{ id, position }` and sorts by id
280
+ * alone (W10-113 finding). The engine completes the order itself: `productVariants(productId:)`
281
+ * (core's `getVariantsByProductId`) appends `id ASC` after the caller's key, which makes it total,
282
+ * so offset pages neither repeat nor skip a row even where `position` is null.
283
+ */
284
+ export function variantListOptions(options) {
285
+ const sort = options?.sort ?? { field: 'position', direction: 'ASC' };
286
+ if (!VARIANT_SORT_FIELDS.includes(sort.field) ||
287
+ (sort.direction !== 'ASC' && sort.direction !== 'DESC')) {
288
+ throw refuse('INVALID_VARIANT_SORT', `sort must name one of ${VARIANT_SORT_FIELDS.join(', ')} and the direction ASC or DESC; got ${JSON.stringify(sort)}. Nothing was sent.`);
289
+ }
290
+ const term = options?.term?.trim() ?? '';
291
+ return {
292
+ sort: { [sort.field]: sort.direction },
293
+ // `filterOperator` joins the top-level fields, which are exactly these two.
294
+ ...(term === ''
295
+ ? {}
296
+ : {
297
+ filter: { sku: { contains: term }, name: { contains: term } },
298
+ filterOperator: 'OR',
299
+ }),
300
+ };
301
+ }
183
302
  /**
184
303
  * Every priced input (`price`, or any `prices` entry) must be whole minor units and state its
185
304
  * basis, and the basis must be the store's. Read per call, with the call's own options, so a
@@ -239,13 +358,39 @@ export function createVariantsModule(transport) {
239
358
  return mapAll(rows, 'updateProductVariants');
240
359
  };
241
360
  return {
242
- list(productId, options) {
243
- return vendureListPage(transport, VARIANTS_QUERY, 'productVariants', (skip, take) => ({ productId, options: { skip, take } }), options, toVariant);
361
+ async list(productId, options) {
362
+ const listOptions = variantListOptions(options);
363
+ return vendureListPage(transport, VARIANTS_QUERY, 'productVariants', (skip, take) => ({ productId, options: { skip, take, ...listOptions } }), options, toVariant);
364
+ },
365
+ async optionSets(productId, options) {
366
+ const { limit = DEFAULT_OPTION_SET_LIMIT, ...call } = options ?? {};
367
+ if (!Number.isInteger(limit) || limit < 1 || limit > MAX_OPTION_SET_LIMIT) {
368
+ throw refuse('INVALID_OPTION_SET_LIMIT', `limit must be a whole number from 1 to ${String(MAX_OPTION_SET_LIMIT)}; got ${String(limit)}. Nothing was sent.`);
369
+ }
370
+ const combinations = [];
371
+ let totalItems = 0;
372
+ while (combinations.length < limit) {
373
+ const take = Math.min(MAX_PAGE_SIZE, limit - combinations.length);
374
+ const page = await fieldOf(transport, VARIANT_OPTION_SETS_QUERY, 'productVariants',
375
+ // By id alone (unique, so no page repeats a row of another): one key, as above.
376
+ { productId, options: { skip: combinations.length, take, sort: { id: 'ASC' } } }, call);
377
+ totalItems = page.totalItems;
378
+ for (const item of page.items) {
379
+ combinations.push(item.options.map((option) => option.id).sort());
380
+ }
381
+ // A short page is the end, whatever `totalItems` claims: never ask past it.
382
+ if (page.items.length < take || combinations.length >= totalItems)
383
+ break;
384
+ }
385
+ return { combinations, totalItems, truncated: totalItems > combinations.length };
244
386
  },
245
387
  async get(id, options) {
246
388
  const variant = await fieldOf(transport, VARIANT_QUERY, 'productVariant', { id }, options);
247
389
  return variant ? toVariant(variant) : null;
248
390
  },
391
+ find(input, options) {
392
+ return findVariants(transport, input, options);
393
+ },
249
394
  async create(inputs, options) {
250
395
  inputs.forEach(assertParcelRule);
251
396
  await assertPriceBasis(inputs, options);
@@ -284,5 +429,17 @@ export function createVariantsModule(transport) {
284
429
  const rows = await fieldOf(transport, REVERT_TO_ORGANIZATION_PRICE_MUTATION, 'revertToOrganizationPrice', { variantIds, currencyCodes: currencyCodes === undefined ? null : [...currencyCodes] }, call);
285
430
  return mapAll(rows, 'revertToOrganizationPrice');
286
431
  },
432
+ async availableFromSource(variantId, options) {
433
+ return fieldOf(transport, VARIANT_AVAILABLE_FROM_SOURCE_QUERY, 'variantAvailableFromSource', { productVariantId: variantId }, options);
434
+ },
435
+ async setAvailableFromSource(variantId, source, options) {
436
+ if (!AVAILABLE_FROM_SOURCES.includes(source)) {
437
+ throw refuse('AVAILABLE_FROM_SOURCE_INVALID', 'The pre-order date source must be manual or incoming. Nothing was sent.');
438
+ }
439
+ return fieldOf(transport, SET_VARIANT_AVAILABLE_FROM_SOURCE_MUTATION, 'setVariantAvailableFromSource', {
440
+ input: { productVariantId: variantId, source },
441
+ idempotencyKey: options?.idempotencyKey,
442
+ }, options);
443
+ },
287
444
  };
288
445
  }
@@ -1,5 +1,6 @@
1
- import { type Transport } from '@sixtyninecommerce/core';
1
+ import { type Page, type Transport } from '@sixtyninecommerce/core';
2
2
  import type { Call } from '../types.js';
3
+ import { type Product, type ProductListOptions } from './products.js';
3
4
  export type ProductVisibilityMode = 'public' | 'private';
4
5
  /**
5
6
  * Who a product is shown to on the storefront. A product with no row is
@@ -29,16 +30,35 @@ export interface SetProductVisibilityInput {
29
30
  * `USER_INPUT_ERROR` (`ValidationError`): "Product {id} not found in this
30
31
  * channel". A write from here is always `source: manual`, which a later
31
32
  * pipeline import leaves alone.
32
- *
33
- * The Admin API's `productsByVisibility` list is deliberately NOT exposed: it
34
- * counts and pages visibility rows across every store before narrowing to this
35
- * one, so its totals and pages are wrong (recorded as a finding).
36
33
  */
37
34
  export interface VisibilityModule {
38
- /** Null when the product has no override (it is public). `NotFoundError` for an unknown product. */
35
+ /**
36
+ * This store's products in one mode, with `products.list`'s filter, sort and
37
+ * paging (filtered before paging; `totalItems` counts this store only).
38
+ * `public` lists products with an explicit public row, not every product
39
+ * without one. With no sort, newest product first.
40
+ *
41
+ * Needs an engine whose `productsByVisibility` honours its options: an older
42
+ * one ignored all but the page and counted other stores' products, so it is
43
+ * refused before running (`ValidationError`, `GRAPHQL_VALIDATION_FAILED` or
44
+ * `BAD_REQUEST`) rather than answered with an unfiltered page.
45
+ *
46
+ * @effect read
47
+ */
48
+ list(mode: ProductVisibilityMode, options?: ProductListOptions): Promise<Page<Product>>;
49
+ /**
50
+ * Null when the product has no override (it is public). `NotFoundError` for an unknown product.
51
+ *
52
+ * @effect read
53
+ */
39
54
  get(productId: string, options?: Call): Promise<ProductVisibility | null>;
55
+ /** @effect write */
40
56
  set(input: SetProductVisibilityInput, options?: Call): Promise<ProductVisibility>;
41
- /** Apply one setting to many products; answers how many rows changed. */
57
+ /**
58
+ * Apply one setting to many products; answers how many rows changed.
59
+ *
60
+ * @effect write
61
+ */
42
62
  bulkSet(input: {
43
63
  productIds: string[];
44
64
  mode: ProductVisibilityMode;
@@ -47,10 +67,21 @@ export interface VisibilityModule {
47
67
  /**
48
68
  * Remove the override (the product becomes public). Resolves the same way
49
69
  * whether or not there was one: the engine does not say.
70
+ *
71
+ * Tagged `destructive`: it deletes the product's visibility record, and a private product
72
+ * becomes every shopper's at once.
73
+ *
74
+ * @effect destructive
50
75
  */
51
76
  clear(productId: string, options?: Call): Promise<void>;
52
77
  }
53
78
  export declare const PRODUCT_VISIBILITY_QUERY = "\n query CatalogProductVisibility($id: ID!) {\n product(id: $id) {\n id\n visibility { \n productId\n mode\n source\n allowedCustomerGroupIds\n createdAt\n updatedAt\n }\n }\n }\n";
79
+ /**
80
+ * The marker field is selected only so that an engine from before the list
81
+ * honoured its options refuses the document as an unknown field; nothing reads
82
+ * its answer. It must stay the SECOND root field.
83
+ */
84
+ export declare const PRODUCTS_BY_VISIBILITY_QUERY = "\n query CatalogProductsByVisibility($mode: ProductVisibilityMode!, $options: ProductListOptions) {\n productsByVisibility(mode: $mode, options: $options) {\n items { \n id\n \n catalogueOwnership {\n state\n organizationName\n editableHere\n }\n\n createdAt\n updatedAt\n languageCode\n name\n slug\n description\n enabled\n featuredAsset { \n id\n name\n preview\n source\n type\n mimeType\n customFields {\n altText\n }\n }\n assets { \n id\n name\n preview\n source\n type\n mimeType\n customFields {\n altText\n }\n }\n facetValues { \n id\n code\n name\n facet {\n id\n code\n name\n }\n }\n optionGroups {\n id\n code\n name\n customFields {\n isShared\n }\n options {\n id\n code\n name\n }\n translations {\n id\n languageCode\n name\n }\n }\n translations {\n id\n languageCode\n name\n slug\n description\n }\n excludedFromStore\n variantList(options: { take: 1 }) {\n totalItems\n }\n customFields {\n availabilityState\n availableFrom\n preorderLimit\n brand\n condition\n }\n }\n totalItems\n }\n productsByVisibilityHonoursListOptions\n }\n";
54
85
  export declare const SET_VISIBILITY_MUTATION = "\n mutation CatalogSetVisibility($input: SetProductVisibilityInput!) {\n setProductVisibility(input: $input) { \n productId\n mode\n source\n allowedCustomerGroupIds\n createdAt\n updatedAt\n }\n }\n";
55
86
  export declare const BULK_SET_VISIBILITY_MUTATION = "\n mutation CatalogBulkSetVisibility($input: BulkSetProductVisibilityInput!) {\n bulkSetProductVisibility(input: $input) {\n updated\n }\n }\n";
56
87
  export declare const CLEAR_VISIBILITY_MUTATION = "\n mutation CatalogClearVisibility($productId: ID!) {\n clearProductVisibility(productId: $productId)\n }\n";
@@ -1,5 +1,6 @@
1
1
  import { NotFoundError } from '@sixtyninecommerce/core';
2
- import { fieldOf } from './types.js';
2
+ import { PRODUCT_FIELDS, productListOptions, toProduct, } from './products.js';
3
+ import { fieldOf, vendureListPage } from './types.js';
3
4
  const VISIBILITY_FIELDS = /* GraphQL */ `
4
5
  productId
5
6
  mode
@@ -16,6 +17,20 @@ export const PRODUCT_VISIBILITY_QUERY = /* GraphQL */ `
16
17
  }
17
18
  }
18
19
  `;
20
+ /**
21
+ * The marker field is selected only so that an engine from before the list
22
+ * honoured its options refuses the document as an unknown field; nothing reads
23
+ * its answer. It must stay the SECOND root field.
24
+ */
25
+ export const PRODUCTS_BY_VISIBILITY_QUERY = /* GraphQL */ `
26
+ query CatalogProductsByVisibility($mode: ProductVisibilityMode!, $options: ProductListOptions) {
27
+ productsByVisibility(mode: $mode, options: $options) {
28
+ items { ${PRODUCT_FIELDS} }
29
+ totalItems
30
+ }
31
+ productsByVisibilityHonoursListOptions
32
+ }
33
+ `;
19
34
  export const SET_VISIBILITY_MUTATION = /* GraphQL */ `
20
35
  mutation CatalogSetVisibility($input: SetProductVisibilityInput!) {
21
36
  setProductVisibility(input: $input) { ${VISIBILITY_FIELDS} }
@@ -35,6 +50,9 @@ export const CLEAR_VISIBILITY_MUTATION = /* GraphQL */ `
35
50
  `;
36
51
  export function createVisibilityModule(transport) {
37
52
  return {
53
+ list(mode, options) {
54
+ return vendureListPage(transport, PRODUCTS_BY_VISIBILITY_QUERY, 'productsByVisibility', (skip, take) => ({ mode, options: productListOptions(options, skip, take) }), options, toProduct);
55
+ },
38
56
  async get(productId, options) {
39
57
  const product = await fieldOf(transport, PRODUCT_VISIBILITY_QUERY, 'product', { id: productId }, options);
40
58
  if (!product) {
package/dist/client.d.ts CHANGED
@@ -10,13 +10,19 @@ import { type AuthModule } from './auth/index.js';
10
10
  import { type BulkModule } from './bulk/index.js';
11
11
  import { type CatalogModule } from './catalog/index.js';
12
12
  import { type ComplianceModule } from './compliance/index.js';
13
+ import { type ContentAssetsModule } from './content/assets.js';
13
14
  import { type FormsModule } from './content/forms.js';
15
+ import { type ContentItemsModule } from './content/items.js';
16
+ import { type ContentMenusModule } from './content/menus.js';
17
+ import { type ContentStringsModule } from './content/strings.js';
18
+ import { type ContentFieldsModule, type ContentPageValuesModule, type ContentTypesModule } from './content/types.js';
14
19
  import { type CustomObjectsModule } from './custom-objects/index.js';
15
20
  import { type CustomersModule } from './customers/index.js';
16
21
  import { type DocumentsModule } from './documents/index.js';
17
22
  import { type EventsModule } from './events/index.js';
18
23
  import { type FeedsModule } from './feeds/index.js';
19
24
  import { type FulfillmentsModule } from './fulfillments/index.js';
25
+ import { type GeoModule } from './geo/index.js';
20
26
  import { type HeadsModule } from './heads/index.js';
21
27
  import { type HooksModule } from './hooks/index.js';
22
28
  import { type IntegrationsModule } from './integrations/index.js';
@@ -26,34 +32,46 @@ import { type MetaModule } from './meta/index.js';
26
32
  import { type MetafieldsModule } from './metafields/index.js';
27
33
  import { type OrdersModule } from './orders/index.js';
28
34
  import { type PaymentsModule } from './payments/index.js';
35
+ import { type PickupsModule } from './pickups/index.js';
29
36
  import { type PlatformAppsModule } from './platform/apps.js';
30
37
  import { type PlatformCatalogModule } from './platform/catalog.js';
38
+ import { type PlatformChannelsModule } from './platform/channels.js';
39
+ import { type PlatformEmailGatewaysModule } from './platform/email-gateways.js';
31
40
  import { type PlatformEntitlementsModule } from './platform/entitlements.js';
41
+ import { type PlatformGeoModule } from './platform/geo.js';
32
42
  import { type PlatformLegalEntitiesModule } from './platform/legal-entities.js';
33
43
  import { type PlatformOrganizationsModule } from './platform/organizations.js';
34
44
  import { type PlatformModule } from './platform/provision-store.js';
35
45
  import { type PlatformReportsModule } from './platform/reports.js';
36
46
  import { type PlatformServerMetricsModule } from './platform/server-metrics.js';
47
+ import { type PlatformTaxModule } from './platform/tax.js';
37
48
  import { type PosModule } from './pos/index.js';
38
49
  import { type PricingModule } from './pricing/index.js';
39
50
  import { type ProvenanceModule } from './provenance/index.js';
51
+ import { type PurchasingModule } from './purchasing/index.js';
52
+ import { type QuotesModule } from './quotes/index.js';
40
53
  import { type ReportsModule } from './reports/index.js';
41
54
  import { type ReturnsModule } from './returns/index.js';
42
55
  import { type SearchModule } from './search/index.js';
56
+ import { type SeoConfigModule } from './seo/config.js';
43
57
  import { type RedirectsModule } from './seo/redirects.js';
44
- import { type ParcelCountSuggestionMethod } from './shipping/parcel-count-suggestion.js';
45
- import { type ShippingModule } from './shipping/parcel-rule.js';
58
+ import { type SeoSettingsModule } from './seo/settings.js';
59
+ import { type ShippingModule } from './shipping/index.js';
46
60
  import { type StockModule } from './stock/index.js';
47
61
  import { type StoredValueModule } from './stored-value/index.js';
62
+ import { type SubscriptionsModule } from './subscriptions/index.js';
48
63
  import { type TaxModule } from './tax/index.js';
49
64
  import { type CapabilitiesModule } from './tenant/capabilities.js';
50
65
  import { type ChannelsModule } from './tenant/channels.js';
66
+ import { type EmailStyleModule } from './tenant/email-style.js';
67
+ import { type EmailTemplatesModule } from './tenant/email-templates.js';
51
68
  import { type TenantEntitlementsReader } from './tenant/entitlements.js';
52
69
  import { type FieldGroupOwnersReader, type FieldGroupSyncSourcesReader } from './tenant/field-groups.js';
53
70
  import { type LegalEntityModule } from './tenant/legal-entity.js';
54
71
  import { type NotificationsModule } from './tenant/notifications.js';
55
72
  import { type RetentionModule } from './tenant/retention.js';
56
73
  import { type SettingsSourcesModule } from './tenant/settings-sources.js';
74
+ import { type TenantTimeZoneReader } from './tenant/time-zone.js';
57
75
  import { type UploadsModule } from './uploads/index.js';
58
76
  import { type UsersModule } from './users/index.js';
59
77
  export interface AdminClientConfig {
@@ -120,13 +138,26 @@ export interface AdminClient {
120
138
  };
121
139
  audit: AuditModule;
122
140
  /**
123
- * Products, variants, options, facets, collections, assets, visibility and
124
- * properties (spec §9.2 `catalog`). Needs the catalog permissions.
141
+ * Products, variants, options, facets, collections, assets, visibility,
142
+ * properties and recommendations (spec §9.2 `catalog`). Needs the catalog
143
+ * permissions.
125
144
  */
126
145
  catalog: CatalogModule;
127
146
  channels: ChannelsModule;
147
+ /**
148
+ * The CMS's content: forms, content types (collections) with their fields, each type's
149
+ * index-page values, the types' items, the media library, navigation menus and content
150
+ * strings (spec §9.2 `content`).
151
+ */
128
152
  content: {
129
153
  forms: FormsModule;
154
+ types: ContentTypesModule;
155
+ fields: ContentFieldsModule;
156
+ pageValues: ContentPageValuesModule;
157
+ items: ContentItemsModule;
158
+ assets: ContentAssetsModule;
159
+ menus: ContentMenusModule;
160
+ strings: ContentStringsModule;
130
161
  };
131
162
  /**
132
163
  * Compliance requests to installed apps: data requests, customer and
@@ -175,6 +206,11 @@ export interface AdminClient {
175
206
  * AI helpers. Channel-scoped throughout — no method takes a channel.
176
207
  */
177
208
  feeds: FeedsModule;
209
+ /**
210
+ * Countries and zones (spec §9.2, ruling G128): platform-wide reads, the same for every store.
211
+ * `mostSpecificZone` (exported beside it) answers the zone provisioning picks for a country.
212
+ */
213
+ geo: GeoModule;
178
214
  /** The store's head registry: every client surface it serves (spec §6.7). */
179
215
  heads: HeadsModule;
180
216
  /** Every long-running operation the platform runs, under one resource (spec §6.11). */
@@ -206,6 +242,12 @@ export interface AdminClient {
206
242
  * recorded against an order with what it stands at (spec §8.2).
207
243
  */
208
244
  payments: PaymentsModule;
245
+ /**
246
+ * Store pickup (click & collect, POS C1/33): the store's pickups, an order's pickup, and
247
+ * "ready". A location's pickup settings are `locations.pickup/setPickup`; the hand-over is the
248
+ * till's.
249
+ */
250
+ pickups: PickupsModule;
209
251
  /**
210
252
  * Point of sale on a machine principal (spec §8.8): register sessions, cash,
211
253
  * tenders, the sale, refunds, X and Z — with no paired tablet. Needs a `pos`
@@ -224,8 +266,33 @@ export interface AdminClient {
224
266
  * writer only; the history is the platform event log.
225
267
  */
226
268
  provenance: ProvenanceModule;
269
+ /**
270
+ * Buying stock from suppliers, per legal entity (purchase-orders spec §10.1): `settings` with
271
+ * its document `numbering`, `suppliers` with their `contacts`, `purchaseOrders` with their
272
+ * `lines`, `replenishment` (reorder rules and suggestions), `cost` (a variant's cost ledger),
273
+ * `receipts` (goods receipts and what can be received), and `returns` (goods sent back to
274
+ * suppliers). Needs the Purchasing plugin on the store.
275
+ */
276
+ purchasing: PurchasingModule;
277
+ /**
278
+ * B2B quotes: list, read, build and price a quote, move it through its statuses, and convert an
279
+ * approved one into an order (keyed); its PDF, its email, the store's quote design and settings
280
+ * (headless W10-35a). `Quote.editable` / `convertible` are the engine's answer to "what can be
281
+ * done now".
282
+ */
283
+ quotes: QuotesModule;
227
284
  /** Tenant reporting in minor units and ISO-8601 UTC (spec §9.2 `reports`, §9.3). */
228
285
  reports: ReportsModule;
286
+ /**
287
+ * Subscription plans (list, read, create, update, products, delete, price breakdown) and the
288
+ * subscriptions sold on them (list, read, a customer's subscriptions and mandates, the store's
289
+ * billing readiness) (headless W10-36), and their lifecycle and billing commands: purchase,
290
+ * pause/resume/skip/reschedule, cancel, payment method replacement, recovery, reconciliation,
291
+ * renewal and settlement retries, attention clearing and price changes, each money command under
292
+ * one idempotency key per attempt (headless W10-114). Statuses are the meta catalog's lower-case
293
+ * words.
294
+ */
295
+ subscriptions: SubscriptionsModule;
229
296
  /**
230
297
  * Order returns (RMA): one return, an order's returns, what of an order can
231
298
  * still be returned, and the plan for settling a return (headless W9-47). The
@@ -238,16 +305,23 @@ export interface AdminClient {
238
305
  * the credential may not read is skipped and named, never refused.
239
306
  */
240
307
  search: SearchModule;
308
+ /**
309
+ * SEO of the ACTIVE store (spec §9.2 `seo`): its URL redirects (`redirects`), its SEO channel
310
+ * settings and defaults (`settings`, on the engine) and its SEO automation (`config`, on the
311
+ * plugins service).
312
+ */
241
313
  seo: {
242
314
  redirects: RedirectsModule;
315
+ settings: SeoSettingsModule;
316
+ config: SeoConfigModule;
243
317
  };
244
318
  /**
245
319
  * Shipping of the ACTIVE channel (spec §9.2 `shipping`): the channel's
246
- * `parcelRule`, and `parcelCountSuggestion` for a set of variant items.
320
+ * `parcelRule`, `parcelCountSuggestion` for a set of variant items, the
321
+ * C.J. Hendriks 3PL settings (`hendriks.config`) and the MyParcel set-up,
322
+ * carriers and parcel senders (`myparcel`).
247
323
  */
248
- shipping: ShippingModule & {
249
- parcelCountSuggestion: ParcelCountSuggestionMethod;
250
- };
324
+ shipping: ShippingModule;
251
325
  /**
252
326
  * Stock per location by state, the ledger with reasons, reason-carrying
253
327
  * adjustments, transfers and allocation release (spec §9.2 `stock`, §8.7).
@@ -259,7 +333,10 @@ export interface AdminClient {
259
333
  * payment on an order.
260
334
  */
261
335
  storedValue: StoredValueModule;
262
- /** The store's own tax classes and their per-country mappings (spec §8.6). */
336
+ /**
337
+ * The store's own tax classes and their per-country mappings (spec §8.6), and the platform-wide
338
+ * tax categories and rates they map onto.
339
+ */
263
340
  tax: TaxModule;
264
341
  /**
265
342
  * Signed direct-to-storage uploads (spec §6.11): reserve a place, PUT the
@@ -290,6 +367,10 @@ export interface AdminClient {
290
367
  retention: RetentionModule;
291
368
  /** Per notification event: on or off, who sends it (spec §8.15), and to whom. */
292
369
  notifications: NotificationsModule;
370
+ /** The look of the store's emails: colours, type, logo and layout (`settings.email`). */
371
+ emailStyle: EmailStyleModule;
372
+ /** The store's email templates, by type: previews rendered as the store would send them. */
373
+ emailTemplates: EmailTemplatesModule;
293
374
  /**
294
375
  * Where each settings group comes from — the store or its organization — and the store's
295
376
  * choice to keep its own values (multi-region spec §5.3).
@@ -300,6 +381,11 @@ export interface AdminClient {
300
381
  * Changing it needs `UpdateSeller` on every store of the entity.
301
382
  */
302
383
  legalEntity: LegalEntityModule;
384
+ /**
385
+ * The active store's IANA time zone as the engine resolves it (`Europe/Amsterdam` when unset
386
+ * or invalid): the zone the API counts calendar days in. Never the browser's.
387
+ */
388
+ timeZone: TenantTimeZoneReader;
303
389
  };
304
390
  /**
305
391
  * Human SuperAdmin surface. Every method refuses an API token or an app
@@ -310,11 +396,27 @@ export interface AdminClient {
310
396
  apps: PlatformAppsModule;
311
397
  /** Catalogue maintenance on a named store (the translation-language repair). */
312
398
  catalog: PlatformCatalogModule;
399
+ /**
400
+ * The codes renames hold against reuse, and their release: a release that must clear files
401
+ * first is finished by the engine itself — see {@link PlatformChannelsModule}.
402
+ */
403
+ channels: PlatformChannelsModule;
313
404
  /**
314
405
  * Which external plugins each store may use: read one store's grants or every store's, and
315
406
  * connect or disconnect a plugin for a store — see {@link PlatformEntitlementsModule}.
316
407
  */
317
408
  entitlements: PlatformEntitlementsModule;
409
+ /**
410
+ * The stores' email gateways (SMTP or sixtynine.email): list, create, change, delete and test
411
+ * the connection — see {@link PlatformEmailGatewaysModule}.
412
+ */
413
+ emailGateways: PlatformEmailGatewaysModule;
414
+ /**
415
+ * The platform's zones and countries every store shares: create, rename, delete and change
416
+ * the members of a zone; switch a country on or off — see {@link PlatformGeoModule}. Reads
417
+ * are `geo`.
418
+ */
419
+ geo: PlatformGeoModule;
318
420
  /**
319
421
  * The platform's legal entities (multi-region spec §7.1): SuperAdmin list and create; read and
320
422
  * update through every store of an entity — see {@link PlatformLegalEntitiesModule}.
@@ -329,6 +431,11 @@ export interface AdminClient {
329
431
  reports: PlatformReportsModule;
330
432
  /** Basic health of the platform's own servers (CPU, memory, disk, network). */
331
433
  serverMetrics: PlatformServerMetricsModule;
434
+ /**
435
+ * The platform's tax categories and tax rates every store shares: create, change and delete
436
+ * them — see {@link PlatformTaxModule}. Reads are `tax.categories` / `tax.rates`.
437
+ */
438
+ tax: PlatformTaxModule;
332
439
  };
333
440
  /** A derived client on another tenant, sharing this one's principal. */
334
441
  withTenant(tenant: Partial<TenantContext> & {
@@ -359,6 +466,11 @@ export interface SessionConfig {
359
466
  * A bearer is not proof of a session: Vendure mints an ANONYMOUS session for
360
467
  * an unauthenticated read. Treat "signed in" as "`auth.me()` resolved", never
361
468
  * as "a token is stored".
469
+ *
470
+ * A rotation is stored (and reported here) only while `token` still holds
471
+ * the bearer its call was sent with: a call answered after a `logout()` or a
472
+ * new sign-in replaced it never overwrites the newer bearer. `login()`'s own
473
+ * bearer always applies.
362
474
  */
363
475
  onToken?: (token: string) => void;
364
476
  }