@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
@@ -0,0 +1,390 @@
1
+ import { ValidationError } from '@sixtyninecommerce/core';
2
+ import { assertDeleted, fieldOf } from '../catalog/types.js';
3
+ const SUMMARY_FIELDS = /* GraphQL */ `
4
+ id
5
+ name
6
+ volumetricDivisor
7
+ defaultWeightGrams
8
+ enabled
9
+ createdAt
10
+ updatedAt
11
+ `;
12
+ const MEMBER_FIELDS = /* GraphQL */ `
13
+ id
14
+ countryCode
15
+ postalCodeFrom
16
+ postalCodeTo
17
+ `;
18
+ const RATE_FIELDS = /* GraphQL */ `
19
+ id
20
+ minWeightGrams
21
+ maxWeightGrams
22
+ price
23
+ currencyCode
24
+ `;
25
+ /** One selection for a zone wherever it is read or answered, so every door answers the same zone. */
26
+ const ZONE_FIELDS = /* GraphQL */ `
27
+ id
28
+ name
29
+ type
30
+ position
31
+ members { ${MEMBER_FIELDS} }
32
+ rates { ${RATE_FIELDS} }
33
+ createdAt
34
+ updatedAt
35
+ `;
36
+ /** One selection for the single read and both writes, so all three answer the same table. */
37
+ const TABLE_FIELDS = /* GraphQL */ `
38
+ ${SUMMARY_FIELDS}
39
+ zones { ${ZONE_FIELDS} }
40
+ `;
41
+ export const RATE_TABLES_QUERY = /* GraphQL */ `
42
+ query StoreRateTables {
43
+ shippingZoneConfigs { ${SUMMARY_FIELDS} }
44
+ }
45
+ `;
46
+ export const RATE_TABLE_QUERY = /* GraphQL */ `
47
+ query StoreRateTable($id: ID!) {
48
+ shippingZoneConfig(id: $id) { ${TABLE_FIELDS} }
49
+ }
50
+ `;
51
+ export const CREATE_RATE_TABLE_MUTATION = /* GraphQL */ `
52
+ mutation CreateStoreRateTable($input: CreateShippingZoneConfigInput!) {
53
+ createShippingZoneConfig(input: $input) { ${TABLE_FIELDS} }
54
+ }
55
+ `;
56
+ export const UPDATE_RATE_TABLE_MUTATION = /* GraphQL */ `
57
+ mutation UpdateStoreRateTable($id: ID!, $input: UpdateShippingZoneConfigInput!) {
58
+ updateShippingZoneConfig(id: $id, input: $input) { ${TABLE_FIELDS} }
59
+ }
60
+ `;
61
+ export const DELETE_RATE_TABLE_MUTATION = /* GraphQL */ `
62
+ mutation DeleteStoreRateTable($id: ID!) {
63
+ deleteShippingZoneConfig(id: $id) {
64
+ result
65
+ message
66
+ }
67
+ }
68
+ `;
69
+ export const CREATE_RATE_TABLE_ZONE_MUTATION = /* GraphQL */ `
70
+ mutation CreateStoreRateTableZone($configId: ID!, $input: CreateShippingZoneInput!) {
71
+ createShippingZone(configId: $configId, input: $input) { ${ZONE_FIELDS} }
72
+ }
73
+ `;
74
+ export const UPDATE_RATE_TABLE_ZONE_MUTATION = /* GraphQL */ `
75
+ mutation UpdateStoreRateTableZone($id: ID!, $input: UpdateShippingZoneInput!) {
76
+ updateShippingZone(id: $id, input: $input) { ${ZONE_FIELDS} }
77
+ }
78
+ `;
79
+ export const DELETE_RATE_TABLE_ZONE_MUTATION = /* GraphQL */ `
80
+ mutation DeleteStoreRateTableZone($id: ID!) {
81
+ deleteShippingZone(id: $id) {
82
+ result
83
+ message
84
+ }
85
+ }
86
+ `;
87
+ export const REORDER_RATE_TABLE_ZONES_MUTATION = /* GraphQL */ `
88
+ mutation ReorderStoreRateTableZones($configId: ID!, $zoneIds: [ID!]!) {
89
+ reorderShippingZones(configId: $configId, zoneIds: $zoneIds) { ${ZONE_FIELDS} }
90
+ }
91
+ `;
92
+ export const SET_RATE_TABLE_ZONE_MEMBERS_MUTATION = /* GraphQL */ `
93
+ mutation SetStoreRateTableZoneMembers($zoneId: ID!, $members: [ShippingZoneMemberInput!]!) {
94
+ setShippingZoneMembers(zoneId: $zoneId, members: $members) { ${MEMBER_FIELDS} }
95
+ }
96
+ `;
97
+ export const SET_RATE_TABLE_ZONE_RATES_MUTATION = /* GraphQL */ `
98
+ mutation SetStoreRateTableZoneRates($zoneId: ID!, $rates: [ShippingRateInput!]!) {
99
+ setShippingRates(zoneId: $zoneId, rates: $rates) { ${RATE_FIELDS} }
100
+ }
101
+ `;
102
+ /** GraphQL's `Int`: a 32-bit signed integer. A wider number cannot be sent at all. */
103
+ const INT_MIN = -2_147_483_648;
104
+ const INT_MAX = 2_147_483_647;
105
+ /**
106
+ * Collects every problem of one call, and refuses them in ONE error with the engine's code and
107
+ * JSON Pointers, so a caller marks each field the same way whichever side refused.
108
+ */
109
+ class Problems {
110
+ details = [];
111
+ add(field, code, message) {
112
+ this.details.push({ field, code, message });
113
+ }
114
+ throwIfAny() {
115
+ const [first, ...rest] = this.details;
116
+ if (!first)
117
+ return;
118
+ const more = rest.length;
119
+ throw new ValidationError({
120
+ code: 'SHIPPING_ZONE_INPUT_INVALID',
121
+ message: more === 0
122
+ ? first.message
123
+ : `${first.message} ${String(more)} more ${more === 1 ? 'problem' : 'problems'} with this save.`,
124
+ status: 400,
125
+ service: 'vendure',
126
+ details: this.details,
127
+ });
128
+ }
129
+ }
130
+ const isObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
131
+ /**
132
+ * A whole number GraphQL's `Int` carries. Whether it is a sensible value (not negative) is the
133
+ * engine's to judge, so this refuses only what could not be sent.
134
+ */
135
+ function intInput(problems, field, label, value) {
136
+ if (typeof value !== 'number' || !Number.isSafeInteger(value)) {
137
+ problems.add(field, 'type', `${label} must be a whole number.`);
138
+ }
139
+ else if (value > INT_MAX) {
140
+ problems.add(field, 'maximum', `${label} must be at most ${String(INT_MAX)}.`);
141
+ }
142
+ else if (value < INT_MIN) {
143
+ problems.add(field, 'minimum', `${label} cannot be negative.`);
144
+ }
145
+ }
146
+ /**
147
+ * The input as the engine takes it, with only the fields the caller named. An explicit `null`
148
+ * goes through as sent: the engine says which field cannot be cleared.
149
+ */
150
+ function tableInput(input, mode) {
151
+ const problems = new Problems();
152
+ if (!isObject(input)) {
153
+ problems.add('/input', 'type', mode === 'create'
154
+ ? 'A new rate table must be an object.'
155
+ : 'The change to a rate table must be an object.');
156
+ problems.throwIfAny();
157
+ }
158
+ const fields = input;
159
+ const out = {};
160
+ // A create's name is `String!`: null cannot be sent at all (only an update may send null, which
161
+ // the engine refuses as "cannot be cleared").
162
+ if (fields.name == null && mode === 'create') {
163
+ problems.add('/input/name', 'required', 'Give the rate table a name.');
164
+ }
165
+ else if (fields.name !== undefined) {
166
+ if (fields.name !== null && typeof fields.name !== 'string') {
167
+ problems.add('/input/name', 'type', 'The rate table name must be text.');
168
+ }
169
+ out.name = fields.name;
170
+ }
171
+ const numbers = [
172
+ ['volumetricDivisor', 'The volumetric divisor'],
173
+ ['defaultWeightGrams', 'The default weight'],
174
+ ];
175
+ for (const [key, label] of numbers) {
176
+ const value = fields[key];
177
+ if (value === undefined)
178
+ continue;
179
+ if (value !== null)
180
+ intInput(problems, `/input/${key}`, label, value);
181
+ out[key] = value;
182
+ }
183
+ if (mode === 'update' && fields.enabled !== undefined) {
184
+ if (fields.enabled !== null && typeof fields.enabled !== 'boolean') {
185
+ problems.add('/input/enabled', 'type', 'Enabled must be true or false.');
186
+ }
187
+ out.enabled = fields.enabled;
188
+ }
189
+ problems.throwIfAny();
190
+ return out;
191
+ }
192
+ /** `field` is the operation's own argument (`/id`, `/configId`, `/zoneId`). */
193
+ const requireId = (id, field = '/id', what = 'a rate table id') => {
194
+ if (typeof id !== 'string' || id === '') {
195
+ const problems = new Problems();
196
+ problems.add(field, 'type', `${field.slice(1)} must be ${what}.`);
197
+ problems.throwIfAny();
198
+ }
199
+ return id;
200
+ };
201
+ /**
202
+ * A zone's input as the engine takes it, with only the fields the caller named. A create's name
203
+ * and type are `String!`, so a missing one cannot be sent; every other `null` goes through as
204
+ * sent (a create reads a null position as "after the last zone", an update refuses it).
205
+ */
206
+ function zoneInput(input, mode) {
207
+ const problems = new Problems();
208
+ if (!isObject(input)) {
209
+ problems.add('/input', 'type', mode === 'create'
210
+ ? 'A new zone must be an object.'
211
+ : 'The change to a zone must be an object.');
212
+ problems.throwIfAny();
213
+ }
214
+ const fields = input;
215
+ const out = {};
216
+ const texts = [
217
+ ['name', 'Give the zone a name.', 'The zone name must be text.'],
218
+ [
219
+ 'type',
220
+ 'Give the zone a type: "domestic" (it matches postal-code ranges) or "international" (it matches countries).',
221
+ 'The zone type must be text.',
222
+ ],
223
+ ];
224
+ for (const [key, missing, notText] of texts) {
225
+ const value = fields[key];
226
+ if (value == null && mode === 'create') {
227
+ problems.add(`/input/${key}`, 'required', missing);
228
+ }
229
+ else if (value !== undefined) {
230
+ if (value !== null && typeof value !== 'string') {
231
+ problems.add(`/input/${key}`, 'type', notText);
232
+ }
233
+ out[key] = value;
234
+ }
235
+ }
236
+ if (fields.position !== undefined) {
237
+ if (fields.position !== null) {
238
+ intInput(problems, '/input/position', 'The position', fields.position);
239
+ }
240
+ out.position = fields.position;
241
+ }
242
+ problems.throwIfAny();
243
+ return out;
244
+ }
245
+ const MEMBER_TEXTS = [
246
+ ['countryCode', 'country'],
247
+ ['postalCodeFrom', 'postal-code start'],
248
+ ['postalCodeTo', 'postal-code end'],
249
+ ];
250
+ /** Only the three member fields, each text or null; whether the zone matches it is the engine's. */
251
+ function membersInput(members) {
252
+ const problems = new Problems();
253
+ if (!Array.isArray(members)) {
254
+ problems.add('/members', 'type', 'The members must be a list.');
255
+ problems.throwIfAny();
256
+ }
257
+ const out = members.map((member, index) => {
258
+ const at = `/members/${String(index)}`;
259
+ const row = {};
260
+ if (!isObject(member)) {
261
+ problems.add(at, 'type', `Member ${String(index + 1)} must be an object.`);
262
+ return row;
263
+ }
264
+ for (const [key, label] of MEMBER_TEXTS) {
265
+ const value = member[key];
266
+ if (value === undefined)
267
+ continue;
268
+ if (value !== null && typeof value !== 'string') {
269
+ problems.add(`${at}/${key}`, 'type', `Member ${String(index + 1)}'s ${label} must be text.`);
270
+ }
271
+ row[key] = value;
272
+ }
273
+ return row;
274
+ });
275
+ problems.throwIfAny();
276
+ return out;
277
+ }
278
+ const RATE_NUMBERS = [
279
+ ['minWeightGrams', 'a start weight'],
280
+ ['maxWeightGrams', 'an end weight'],
281
+ ['price', 'a price'],
282
+ ];
283
+ /**
284
+ * Only the four tier fields. Each is non-null on the wire (`Int!`, `String!`), so a missing one
285
+ * cannot be sent; the tier's values (negative, ending before it starts, overlapping another, an
286
+ * unknown currency) are the engine's to judge.
287
+ */
288
+ function ratesInput(rates) {
289
+ const problems = new Problems();
290
+ if (!Array.isArray(rates)) {
291
+ problems.add('/rates', 'type', 'The rates must be a list of weight tiers.');
292
+ problems.throwIfAny();
293
+ }
294
+ const out = rates.map((rate, index) => {
295
+ const at = `/rates/${String(index)}`;
296
+ const tier = `Tier ${String(index + 1)}`;
297
+ if (!isObject(rate)) {
298
+ problems.add(at, 'type', `${tier} must be an object.`);
299
+ return {};
300
+ }
301
+ for (const [key, label] of RATE_NUMBERS) {
302
+ const value = rate[key];
303
+ if (value == null)
304
+ problems.add(`${at}/${key}`, 'required', `${tier} needs ${label}.`);
305
+ else
306
+ intInput(problems, `${at}/${key}`, `${tier}'s ${label.replace(/^an? /, '')}`, value);
307
+ }
308
+ if (rate.currencyCode == null) {
309
+ problems.add(`${at}/currencyCode`, 'required', `${tier} needs a currency.`);
310
+ }
311
+ else if (typeof rate.currencyCode !== 'string') {
312
+ problems.add(`${at}/currencyCode`, 'type', `${tier}'s currency must be text (ISO 4217, e.g. EUR).`);
313
+ }
314
+ return {
315
+ minWeightGrams: rate.minWeightGrams,
316
+ maxWeightGrams: rate.maxWeightGrams,
317
+ price: rate.price,
318
+ currencyCode: rate.currencyCode,
319
+ };
320
+ });
321
+ problems.throwIfAny();
322
+ return out;
323
+ }
324
+ /** A list of zone ids; whether it names every zone of the table once is the engine's. */
325
+ function zoneIdsInput(zoneIds) {
326
+ const problems = new Problems();
327
+ if (!Array.isArray(zoneIds)) {
328
+ problems.add('/zoneIds', 'type', 'The zone order must be a list of zone ids.');
329
+ problems.throwIfAny();
330
+ }
331
+ zoneIds.forEach((id, index) => {
332
+ if (typeof id !== 'string' || id === '') {
333
+ problems.add(`/zoneIds/${String(index)}`, 'type', `Place ${String(index + 1)} must be a zone id.`);
334
+ }
335
+ });
336
+ problems.throwIfAny();
337
+ return zoneIds;
338
+ }
339
+ function createZonesModule(transport) {
340
+ return {
341
+ async create(tableId, input, options) {
342
+ const configId = requireId(tableId, '/configId');
343
+ return fieldOf(transport, CREATE_RATE_TABLE_ZONE_MUTATION, 'createShippingZone', { configId, input: zoneInput(input, 'create') }, options);
344
+ },
345
+ async update(zoneId, patch, options) {
346
+ const id = requireId(zoneId, '/id', 'a zone id');
347
+ return fieldOf(transport, UPDATE_RATE_TABLE_ZONE_MUTATION, 'updateShippingZone', { id, input: zoneInput(patch, 'update') }, options);
348
+ },
349
+ async delete(zoneId, options) {
350
+ assertDeleted('SHIPPING_ZONE_NOT_DELETED', [
351
+ await fieldOf(transport, DELETE_RATE_TABLE_ZONE_MUTATION, 'deleteShippingZone', { id: requireId(zoneId, '/id', 'a zone id') }, options),
352
+ ]);
353
+ },
354
+ async reorder(tableId, zoneIds, options) {
355
+ const configId = requireId(tableId, '/configId');
356
+ return fieldOf(transport, REORDER_RATE_TABLE_ZONES_MUTATION, 'reorderShippingZones', { configId, zoneIds: zoneIdsInput(zoneIds) }, options);
357
+ },
358
+ async setMembers(zoneId, members, options) {
359
+ const id = requireId(zoneId, '/zoneId', 'a zone id');
360
+ return fieldOf(transport, SET_RATE_TABLE_ZONE_MEMBERS_MUTATION, 'setShippingZoneMembers', { zoneId: id, members: membersInput(members) }, options);
361
+ },
362
+ async setRates(zoneId, rates, options) {
363
+ const id = requireId(zoneId, '/zoneId', 'a zone id');
364
+ return fieldOf(transport, SET_RATE_TABLE_ZONE_RATES_MUTATION, 'setShippingRates', { zoneId: id, rates: ratesInput(rates) }, options);
365
+ },
366
+ };
367
+ }
368
+ export function createRateTablesModule(transport) {
369
+ return {
370
+ async list(options) {
371
+ return fieldOf(transport, RATE_TABLES_QUERY, 'shippingZoneConfigs', {}, options);
372
+ },
373
+ async get(id, options) {
374
+ return fieldOf(transport, RATE_TABLE_QUERY, 'shippingZoneConfig', { id: requireId(id) }, options);
375
+ },
376
+ async create(input, options) {
377
+ return fieldOf(transport, CREATE_RATE_TABLE_MUTATION, 'createShippingZoneConfig', { input: tableInput(input, 'create') }, options);
378
+ },
379
+ async update(id, patch, options) {
380
+ const tableId = requireId(id);
381
+ return fieldOf(transport, UPDATE_RATE_TABLE_MUTATION, 'updateShippingZoneConfig', { id: tableId, input: tableInput(patch, 'update') }, options);
382
+ },
383
+ async delete(id, options) {
384
+ assertDeleted('SHIPPING_ZONE_CONFIG_NOT_DELETED', [
385
+ await fieldOf(transport, DELETE_RATE_TABLE_MUTATION, 'deleteShippingZoneConfig', { id: requireId(id) }, options),
386
+ ]);
387
+ },
388
+ zones: createZonesModule(transport),
389
+ };
390
+ }
@@ -0,0 +1,75 @@
1
+ import type { Transport } from '@sixtyninecommerce/core';
2
+ import type { Call } from '../types.js';
3
+ /**
4
+ * How a store's ship-to list reads: `ALL` (no list: every enabled country is offered), `SUBSET`
5
+ * (only the listed countries are offered, and an order to any other cannot be placed), or
6
+ * `MALFORMED` (the stored value cannot be read; checkout offers every enabled country and logs
7
+ * it, and saving a list replaces it).
8
+ */
9
+ export type ShipToCountriesGate = 'ALL' | 'SUBSET' | 'MALFORMED';
10
+ /** One row of a ship-to picker. */
11
+ export interface ShipToCountryOption {
12
+ /** ISO-3166 alpha-2 code, upper-case. */
13
+ code: string;
14
+ /** The country's name; a selected code that is not an enabled country shows as its code. */
15
+ name: string;
16
+ /** False for a selected code that is not an enabled country: no shopper can choose it. */
17
+ enabled: boolean;
18
+ }
19
+ /** The countries a store ships to, as checkout applies them. */
20
+ export interface ShipToCountries {
21
+ gate: ShipToCountriesGate;
22
+ /** Why the stored value cannot be read (`MALFORMED` only); else null. */
23
+ reason: string | null;
24
+ /** The selected codes, trimmed, upper-cased and de-duplicated (`SUBSET` only); else empty. */
25
+ selected: string[];
26
+ /** The codes the storefront offers at checkout (Shop `availableCountries`), in its order. */
27
+ served: string[];
28
+ /**
29
+ * Selected codes that are not enabled countries: selected, but no shopper can choose them.
30
+ * Only a platform administrator enables a country (`platform.countries`).
31
+ */
32
+ unservable: string[];
33
+ /** The enabled countries, then every selected code that is not one, so it can be removed. */
34
+ options: ShipToCountryOption[];
35
+ }
36
+ /**
37
+ * The ACTIVE store's ship-to countries (`admin.shipping.shipToCountries`): which countries its
38
+ * storefront offers at checkout, and to which an order may be addressed. Reading needs any
39
+ * administrator permission on the store; `set` needs `UpdateChannel`.
40
+ *
41
+ * The engine owns every rule (how codes are read, which are offered, which are unservable): ask
42
+ * {@link preview} for a list that is not saved.
43
+ */
44
+ export interface ShipToCountriesModule {
45
+ /**
46
+ * The list as checkout applies it.
47
+ *
48
+ * @effect read
49
+ */
50
+ get(options?: Call): Promise<ShipToCountries>;
51
+ /**
52
+ * How a list WOULD read once stored, without saving anything. Refused as {@link set} refuses.
53
+ *
54
+ * @effect read
55
+ */
56
+ preview(countryCodes: readonly string[], options?: Call): Promise<ShipToCountries>;
57
+ /**
58
+ * Replace the list, and answer it as checkout now applies it. Codes are trimmed, upper-cased
59
+ * and de-duplicated. An empty list means every enabled country, never "ships nowhere".
60
+ *
61
+ * Refused `SHIP_TO_COUNTRIES_INVALID` (`ValidationError`, one `details[]` entry per offending
62
+ * entry, `field` = `countryCodes.<index>`) for an entry that is not a two-letter ISO-3166 code,
63
+ * or more than 300 entries; `FORBIDDEN` / `CHANNEL_ACCESS_DENIED` without `UpdateChannel`.
64
+ * A two-letter code that is not an enabled country is stored and reported in `unservable`.
65
+ *
66
+ * Narrowing the list changes which countries shoppers may order to.
67
+ *
68
+ * @effect write
69
+ */
70
+ set(countryCodes: readonly string[], options?: Call): Promise<ShipToCountries>;
71
+ }
72
+ export declare const SHIP_TO_COUNTRIES_QUERY = "\n query ShipToCountries {\n shipToCountries { \n gate\n reason\n selected\n served\n unservable\n options { code name enabled }\n }\n }\n";
73
+ export declare const PREVIEW_SHIP_TO_COUNTRIES_QUERY = "\n query PreviewShipToCountries($countryCodes: [String!]!) {\n previewShipToCountries(countryCodes: $countryCodes) { \n gate\n reason\n selected\n served\n unservable\n options { code name enabled }\n }\n }\n";
74
+ export declare const SET_SHIP_TO_COUNTRIES_MUTATION = "\n mutation SetShipToCountries($countryCodes: [String!]!) {\n setShipToCountries(countryCodes: $countryCodes) { \n gate\n reason\n selected\n served\n unservable\n options { code name enabled }\n }\n }\n";
75
+ export declare function createShipToCountriesModule(transport: Transport): ShipToCountriesModule;
@@ -0,0 +1,47 @@
1
+ const VIEW_FIELDS = /* GraphQL */ `
2
+ gate
3
+ reason
4
+ selected
5
+ served
6
+ unservable
7
+ options { code name enabled }
8
+ `;
9
+ export const SHIP_TO_COUNTRIES_QUERY = /* GraphQL */ `
10
+ query ShipToCountries {
11
+ shipToCountries { ${VIEW_FIELDS} }
12
+ }
13
+ `;
14
+ export const PREVIEW_SHIP_TO_COUNTRIES_QUERY = /* GraphQL */ `
15
+ query PreviewShipToCountries($countryCodes: [String!]!) {
16
+ previewShipToCountries(countryCodes: $countryCodes) { ${VIEW_FIELDS} }
17
+ }
18
+ `;
19
+ export const SET_SHIP_TO_COUNTRIES_MUTATION = /* GraphQL */ `
20
+ mutation SetShipToCountries($countryCodes: [String!]!) {
21
+ setShipToCountries(countryCodes: $countryCodes) { ${VIEW_FIELDS} }
22
+ }
23
+ `;
24
+ export function createShipToCountriesModule(transport) {
25
+ return {
26
+ async get(options) {
27
+ const data = await transport.graphql({ api: 'admin', query: SHIP_TO_COUNTRIES_QUERY }, options);
28
+ return data.shipToCountries;
29
+ },
30
+ async preview(countryCodes, options) {
31
+ const data = await transport.graphql({
32
+ api: 'admin',
33
+ query: PREVIEW_SHIP_TO_COUNTRIES_QUERY,
34
+ variables: { countryCodes: [...countryCodes] },
35
+ }, options);
36
+ return data.previewShipToCountries;
37
+ },
38
+ async set(countryCodes, options) {
39
+ const data = await transport.graphql({
40
+ api: 'admin',
41
+ query: SET_SHIP_TO_COUNTRIES_MUTATION,
42
+ variables: { countryCodes: [...countryCodes] },
43
+ }, options);
44
+ return data.setShipToCountries;
45
+ },
46
+ };
47
+ }
@@ -0,0 +1,86 @@
1
+ import { type Page, type Transport } from '@sixtyninecommerce/core';
2
+ import type { ListOptions } from '../types.js';
3
+ import type { StockMovementType } from './index.js';
4
+ /** One variant's stock level at one location. */
5
+ export interface LocationStockLevel {
6
+ /** The stock level's own id. */
7
+ id: string;
8
+ variantId: string;
9
+ sku: string;
10
+ variantName: string;
11
+ /** The variant's product, for its name and picture. */
12
+ product: {
13
+ id: string;
14
+ name: string;
15
+ featuredAsset: {
16
+ id: string;
17
+ preview: string;
18
+ } | null;
19
+ };
20
+ /** Units the location holds. */
21
+ onHand: number;
22
+ /** Of those, the units reserved for orders. */
23
+ allocated: number;
24
+ /** When the level last changed. */
25
+ updatedAt: string;
26
+ }
27
+ export interface LocationStockLevelFilter extends ListOptions {
28
+ /** Matches the SKU or the variant's name, ignoring case. Blank searches nothing. */
29
+ search?: string;
30
+ /** By units on hand: `DESC` (most first, the default) or `ASC`. */
31
+ sort?: 'ASC' | 'DESC';
32
+ }
33
+ /** One line of a location's stock ledger. */
34
+ export interface LocationStockMovement {
35
+ id: string;
36
+ createdAt: string;
37
+ type: StockMovementType;
38
+ /**
39
+ * The movement's own signed quantity as the engine stores it. A `SALE` is negative; a
40
+ * `RELEASE` is stored positive although it lowers `allocated`.
41
+ */
42
+ quantity: number;
43
+ variantId: string;
44
+ sku: string;
45
+ variantName: string;
46
+ /** The order the movement was made for (an allocation, a sale, a release, …), else null. */
47
+ order: {
48
+ id: string;
49
+ code: string;
50
+ } | null;
51
+ }
52
+ /**
53
+ * What one stock location holds and what moved there, a page at a time. The location must be
54
+ * the store's own: another store's, or an id that does not exist, is refused
55
+ * `LOCATION_NOT_IN_CHANNEL` (→ `ValidationError`), never read; a credential restricted with
56
+ * `locationIds` is refused `LOCATION_NOT_ALLOWED` (→ `PermissionDeniedError`) at a location it
57
+ * does not hold. A location several stores share lists only this store's variants.
58
+ */
59
+ export interface StockByLocationReads {
60
+ /**
61
+ * The variants stocked at `locationId`, by units on hand (most first unless `sort` says
62
+ * `ASC`); `limit` defaults to 25 and the engine answers at most 200 per page. A variant whose
63
+ * level row was never written there is not listed.
64
+ *
65
+ * @effect read
66
+ * @permission ReadStockLocation
67
+ */
68
+ levelsAt(locationId: string, filter?: LocationStockLevelFilter): Promise<Page<LocationStockLevel>>;
69
+ /**
70
+ * The stock ledger at `locationId`, newest first; `limit` defaults to 25. It lists the
71
+ * movements the engine records (allocations, sales, releases, cancellations, returns and
72
+ * adjustments); a bulk stock import writes the levels directly and is not on it.
73
+ *
74
+ * Known limit: at a location several stores share, a variant that more than one of them sells
75
+ * also carries the other stores' order movements, whose order this store cannot read. The
76
+ * engine then fails the whole page (`GRAPHQL_ERROR`, "Cannot return null for non-nullable
77
+ * field") instead of leaving the row out; the levels read is not affected.
78
+ *
79
+ * @effect read
80
+ * @permission ReadStockLocation
81
+ */
82
+ movementsAt(locationId: string, filter?: ListOptions): Promise<Page<LocationStockMovement>>;
83
+ }
84
+ export declare const STOCK_LEVELS_AT_LOCATION_QUERY = "\n query StockLevelsAtLocation($locationId: ID!, $options: StockLevelListOptions) {\n stockLevelsByLocation(locationId: $locationId, options: $options) {\n items {\n id\n stockOnHand\n stockAllocated\n updatedAt\n productVariant {\n id\n name\n sku\n product { id name featuredAsset { id preview } }\n }\n }\n totalItems\n }\n }\n";
85
+ export declare const STOCK_MOVEMENTS_AT_LOCATION_QUERY = "\n query StockMovementsAtLocation($locationId: ID!, $options: StockMovementListOptions) {\n stockMovementsByLocation(locationId: $locationId, options: $options) {\n items {\n id\n createdAt\n type\n quantity\n productVariant { id name sku }\n orderLine { order { id code } }\n }\n totalItems\n }\n }\n";
86
+ export declare function createStockByLocationReads(transport: Transport): StockByLocationReads;