@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,97 @@
1
+ import type { Transport } from '@sixtyninecommerce/core';
2
+ import type { Call } from '../types.js';
3
+ /** How the order reference sent to C.J. Hendriks is prefixed. */
4
+ export type HendriksWirePrefixMode = 'year' | 'custom';
5
+ /** A store's C.J. Hendriks 3PL settings: one record per store. */
6
+ export interface HendriksConfig {
7
+ id: string;
8
+ channelId: string;
9
+ /** Gates every Hendriks export of the store. */
10
+ enabled: boolean;
11
+ /** The plugins-service export pipeline that sends the orders; `null` is not linked. */
12
+ pipelineId: string | null;
13
+ /** `year` prefixes the current UTC year; `custom` prefixes {@link wirePrefixDigits}. */
14
+ wirePrefixMode: HendriksWirePrefixMode;
15
+ /** 1 to 4 digits without a leading zero. Only read in `custom` mode; `null` in `year` mode. */
16
+ wirePrefixDigits: string | null;
17
+ /**
18
+ * Refuse to export an order the source platform already sent to its own fulfillment
19
+ * provider. On by default: while a migrated shop is still live both systems feed the same
20
+ * warehouse, and neither can spot the other's reference, so the goods would ship twice.
21
+ */
22
+ blockSourceFulfilledOrders: boolean;
23
+ /** ISO-8601, UTC. */
24
+ createdAt: string;
25
+ /** ISO-8601, UTC. */
26
+ updatedAt: string;
27
+ }
28
+ /**
29
+ * A PATCH: a key left out keeps the stored value. The custom-prefix rule is judged on the
30
+ * RESULTING settings, so switching to `custom` needs `wirePrefixDigits` in the same call unless
31
+ * valid digits are already stored.
32
+ */
33
+ export interface UpdateHendriksConfigInput {
34
+ enabled?: boolean;
35
+ /** `null` unlinks the pipeline. */
36
+ pipelineId?: string | null;
37
+ wirePrefixMode?: HendriksWirePrefixMode;
38
+ /** Cleared by the engine whenever the resulting mode is `year`. */
39
+ wirePrefixDigits?: string | null;
40
+ blockSourceFulfilledOrders?: boolean;
41
+ }
42
+ /**
43
+ * The C.J. Hendriks 3PL settings of the store the client is scoped to
44
+ * (`admin.shipping.hendriks.config`). There is no channel argument: a SuperAdmin head configures
45
+ * ANOTHER store with `admin.withTenant({ scope: { kind: 'channel', code } })`, or a per-call
46
+ * `tenant`.
47
+ */
48
+ export interface HendriksConfigModule {
49
+ /**
50
+ * The store's settings, or `null` when it never saved any. Needs `ReadSettings`, and is
51
+ * answered for a store without the Hendriks plugin too (a head reads it to decide whether to
52
+ * show the integration).
53
+ *
54
+ * @effect read
55
+ * @permission ReadSettings
56
+ */
57
+ get(options?: Call): Promise<HendriksConfig | null>;
58
+ /**
59
+ * Save the settings; the first call creates the record (`enabled` off, `year` prefix,
60
+ * `blockSourceFulfilledOrders` on, unless given). Needs `UpdateSettings`.
61
+ *
62
+ * Refused, with nothing saved:
63
+ * - `HENDRIKS_CONFIG_INVALID` (`ValidationError`, 400): `custom` mode without 1 to 4 digits not
64
+ * starting with 0. `details[]` names each field (`wirePrefixDigits`, `wirePrefixMode`), so a
65
+ * form can put the reason on it;
66
+ * - `PLUGIN_ACCESS_DENIED` (`PermissionDeniedError`, 403): the store does not hold the
67
+ * Hendriks plugin. An ordinary caller only: the engine never refuses a SuperAdmin on this
68
+ * ground, so a SuperAdmin head that must know reads `tenant.entitlements()` on that store;
69
+ * - `ORGANIZATION_WORKSPACE_NOT_A_STORE` (`BusinessRuleError`, 422): switching the export on,
70
+ * or linking a pipeline, in an organization's workspace.
71
+ *
72
+ * `pipelineId` is not checked against the store's pipelines; an export through a pipeline
73
+ * that does not exist fails when it runs.
74
+ *
75
+ * @effect write
76
+ * @permission UpdateSettings
77
+ */
78
+ update(input: UpdateHendriksConfigInput, options?: Call): Promise<HendriksConfig>;
79
+ /**
80
+ * Delete the store's settings record. Every Hendriks export of the store is refused until
81
+ * settings are saved again, and the prefix and pipeline link are gone with it. `true` when a
82
+ * record was deleted, `false` when the store had none. Needs `UpdateSettings`; allowed for a
83
+ * store that no longer holds the plugin, so it can always remove its connection.
84
+ *
85
+ * @effect destructive
86
+ * @permission UpdateSettings
87
+ */
88
+ delete(options?: Call): Promise<boolean>;
89
+ }
90
+ /** `admin.shipping.hendriks`: the C.J. Hendriks 3PL integration of the store. */
91
+ export interface HendriksModule {
92
+ config: HendriksConfigModule;
93
+ }
94
+ export declare const HENDRIKS_CONFIG_QUERY = "\n query HendriksConfig {\n hendriksConfig { \n id\n channelId\n enabled\n pipelineId\n wirePrefixMode\n wirePrefixDigits\n blockSourceFulfilledOrders\n createdAt\n updatedAt\n }\n }\n";
95
+ export declare const UPDATE_HENDRIKS_CONFIG_MUTATION = "\n mutation UpdateHendriksConfig($input: UpdateHendriksConfigInput!) {\n updateHendriksConfig(input: $input) { \n id\n channelId\n enabled\n pipelineId\n wirePrefixMode\n wirePrefixDigits\n blockSourceFulfilledOrders\n createdAt\n updatedAt\n }\n }\n";
96
+ export declare const DELETE_HENDRIKS_CONFIG_MUTATION = "\n mutation DeleteHendriksConfig {\n deleteHendriksConfig\n }\n";
97
+ export declare function createHendriksModule(transport: Transport): HendriksModule;
@@ -0,0 +1,50 @@
1
+ const CONFIG_FIELDS = /* GraphQL */ `
2
+ id
3
+ channelId
4
+ enabled
5
+ pipelineId
6
+ wirePrefixMode
7
+ wirePrefixDigits
8
+ blockSourceFulfilledOrders
9
+ createdAt
10
+ updatedAt
11
+ `;
12
+ export const HENDRIKS_CONFIG_QUERY = /* GraphQL */ `
13
+ query HendriksConfig {
14
+ hendriksConfig { ${CONFIG_FIELDS} }
15
+ }
16
+ `;
17
+ export const UPDATE_HENDRIKS_CONFIG_MUTATION = /* GraphQL */ `
18
+ mutation UpdateHendriksConfig($input: UpdateHendriksConfigInput!) {
19
+ updateHendriksConfig(input: $input) { ${CONFIG_FIELDS} }
20
+ }
21
+ `;
22
+ export const DELETE_HENDRIKS_CONFIG_MUTATION = /* GraphQL */ `
23
+ mutation DeleteHendriksConfig {
24
+ deleteHendriksConfig
25
+ }
26
+ `;
27
+ export function createHendriksModule(transport) {
28
+ return {
29
+ config: {
30
+ async get(options) {
31
+ const data = await transport.graphql({ api: 'admin', query: HENDRIKS_CONFIG_QUERY }, options);
32
+ return data.hendriksConfig ?? null;
33
+ },
34
+ async update(input, options) {
35
+ const data = await transport.graphql({
36
+ api: 'admin',
37
+ query: UPDATE_HENDRIKS_CONFIG_MUTATION,
38
+ // Sent as given: a key left out stays off the wire (the engine reads an absent
39
+ // key as "keep"), and the engine names anything it refuses.
40
+ variables: { input },
41
+ }, options);
42
+ return data.updateHendriksConfig;
43
+ },
44
+ async delete(options) {
45
+ const data = await transport.graphql({ api: 'admin', query: DELETE_HENDRIKS_CONFIG_MUTATION }, options);
46
+ return data.deleteHendriksConfig === true;
47
+ },
48
+ },
49
+ };
50
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Shipping (headless spec §9.2 `shipping`): everything about getting a store's orders to its
3
+ * customers. Each member lives in a file of its own and is only assembled here, so a branch
4
+ * that adds one (shipping methods, rate tables, a carrier) adds a file and one line.
5
+ */
6
+ import type { Transport } from '@sixtyninecommerce/core';
7
+ import { type ShippingDefinitionsModule } from './definitions.js';
8
+ import { type FulfillmentProfilesModule } from './fulfillment-profiles.js';
9
+ import { type HendriksModule } from './hendriks.js';
10
+ import { type ShippingMethodsModule } from './methods.js';
11
+ import { type MyparcelModule } from './myparcel.js';
12
+ import { type ParcelCountSuggestionMethod } from './parcel-count-suggestion.js';
13
+ import { type ParcelRuleModule } from './parcel-rule.js';
14
+ import { type RateTablesModule } from './rate-tables.js';
15
+ /** `admin.shipping` (spec §9.2 `shipping`). Always the store the client is scoped to. */
16
+ export interface ShippingModule {
17
+ /** The store's shipping methods: what checkout offers and what each charges. */
18
+ methods: ShippingMethodsModule;
19
+ /** What a shipping method's calculator, checker and fulfillment handler may be. */
20
+ definitions: ShippingDefinitionsModule;
21
+ /**
22
+ * The weight-zone rate tables a `weight-zone-calculator` method prices with: per table its
23
+ * zones (postal-code ranges or countries) and per zone its weight tiers' prices.
24
+ */
25
+ rateTables: RateTablesModule;
26
+ /** How the store counts parcels for extra-parcel shipping charges. */
27
+ parcelRule: ParcelRuleModule;
28
+ /**
29
+ * How many parcels the store's rule gives a set of variant + quantity items.
30
+ *
31
+ * @effect read
32
+ */
33
+ parcelCountSuggestion: ParcelCountSuggestionMethod;
34
+ /** The C.J. Hendriks 3PL integration: its settings (`config`). */
35
+ hendriks: HendriksModule;
36
+ /**
37
+ * The MyParcel integration: its set-up (`config`: the API key, label format, on/off and webhook
38
+ * secret, both secrets read back masked), the carriers MyParcel offers, and the store's stock
39
+ * locations as parcel senders (`senders`).
40
+ */
41
+ myparcel: MyparcelModule;
42
+ /**
43
+ * The store's fulfillment profiles (warehouse + handler + shipping method + minimum), its
44
+ * default profile, and who is emailed per handler when a fulfilment is created.
45
+ */
46
+ fulfillmentProfiles: FulfillmentProfilesModule;
47
+ }
48
+ export declare function createShippingModule(transport: Transport): ShippingModule;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Shipping (headless spec §9.2 `shipping`): everything about getting a store's orders to its
3
+ * customers. Each member lives in a file of its own and is only assembled here, so a branch
4
+ * that adds one (shipping methods, rate tables, a carrier) adds a file and one line.
5
+ */
6
+ import { createShippingDefinitionsModule } from './definitions.js';
7
+ import { createFulfillmentProfilesModule, } from './fulfillment-profiles.js';
8
+ import { createHendriksModule } from './hendriks.js';
9
+ import { createShippingMethodsModule } from './methods.js';
10
+ import { createMyparcelModule } from './myparcel.js';
11
+ import { createParcelCountSuggestion, } from './parcel-count-suggestion.js';
12
+ import { createParcelRuleModule } from './parcel-rule.js';
13
+ import { createRateTablesModule } from './rate-tables.js';
14
+ export function createShippingModule(transport) {
15
+ return {
16
+ methods: createShippingMethodsModule(transport),
17
+ definitions: createShippingDefinitionsModule(transport),
18
+ rateTables: createRateTablesModule(transport),
19
+ parcelRule: createParcelRuleModule(transport),
20
+ parcelCountSuggestion: createParcelCountSuggestion(transport),
21
+ hendriks: createHendriksModule(transport),
22
+ myparcel: createMyparcelModule(transport),
23
+ fulfillmentProfiles: createFulfillmentProfilesModule(transport),
24
+ };
25
+ }
@@ -0,0 +1,198 @@
1
+ import { type Page, type Transport } from '@sixtyninecommerce/core';
2
+ import { type ConfigurableOperation, type ConfigurableOperationInput, type LanguageCode } from '../catalog/types.js';
3
+ import type { Call, ListOptions } from '../types.js';
4
+ /** A shipping method's name and description in one language. */
5
+ export interface ShippingMethodTranslation {
6
+ id: string;
7
+ /** As the engine spells it: `en`, `nl`, `pt_BR`. */
8
+ languageCode: string;
9
+ name: string;
10
+ description: string;
11
+ }
12
+ /** One shipping method of the store, as its list reads it. */
13
+ export interface ShippingMethodSummary {
14
+ id: string;
15
+ /** What checkout and a fulfillment profile name the method by. */
16
+ code: string;
17
+ /** In the language the client is set to (`tenant.language`), else the store's default. */
18
+ name: string;
19
+ /**
20
+ * The fulfillment handler of an order fulfilled WITHOUT a fulfillment profile (the profiles
21
+ * route every other one). `manual-fulfillment` unless a carrier's was picked.
22
+ */
23
+ fulfillmentHandlerCode: string;
24
+ /** What the method charges, with its stored arguments (every value a string). */
25
+ calculator: ConfigurableOperation;
26
+ /**
27
+ * The master switch: a disabled method is offered nowhere (webshop, staff, till) and a cart on
28
+ * it re-quotes. On unless it was switched off (a method stored before the switch existed).
29
+ */
30
+ enabled: boolean;
31
+ /**
32
+ * Offered at webshop checkout; staff orders and the till do not read it. On unless it was
33
+ * switched off. Only meaningful while {@link enabled}.
34
+ */
35
+ enabledInStorefront: boolean;
36
+ /** ISO-8601, UTC. */
37
+ createdAt: string;
38
+ /** ISO-8601, UTC. */
39
+ updatedAt: string;
40
+ }
41
+ /** One shipping method of the store, as its settings read it. */
42
+ export interface ShippingMethod extends ShippingMethodSummary {
43
+ /** In the same language as {@link name}; empty when the method has none. */
44
+ description: string;
45
+ /** Which orders the method is offered for, with its stored arguments. Every method has one. */
46
+ checker: ConfigurableOperation;
47
+ /** Every language the method is named in. */
48
+ translations: ShippingMethodTranslation[];
49
+ /**
50
+ * The Exact Online integration created the method from one of its own shipping definitions:
51
+ * Exact's sync owns its code and calculator (the name is the store's). Written by that sync
52
+ * only; neither write here takes it.
53
+ */
54
+ exactManaged: boolean;
55
+ /**
56
+ * Added once per parcel after the first, in minor units and the calculator's own tax basis;
57
+ * null charges nothing, 0 is a price. Only the two flat-rate calculators
58
+ * (`default-shipping-calculator`, `flat-threshold-calculator`) charge it, and the store's
59
+ * parcel rule decides how many parcels an order is; on any other calculator a stored value is
60
+ * kept but charges nothing.
61
+ */
62
+ extraParcelPrice: number | null;
63
+ }
64
+ /**
65
+ * A method's name and description in one language, as a create or an update writes them. The
66
+ * engine keeps one row per language: writing a language the method has replaces that row's
67
+ * name and description, and any other language is added beside the ones it has.
68
+ */
69
+ export interface ShippingMethodTranslationInput {
70
+ /** As the engine spells it: `en`, `nl`, `pt_BR`. */
71
+ languageCode: LanguageCode;
72
+ name: string;
73
+ /** Empty when left out. */
74
+ description?: string;
75
+ }
76
+ /** A new shipping method, as {@link ShippingMethodsModule.create} takes it. */
77
+ export interface CreateShippingMethodInput {
78
+ code: string;
79
+ /**
80
+ * One of `shipping.definitions.get()`'s `fulfillmentHandlers`. The engine requires one; a
81
+ * store that routes by fulfillment profiles names `manual-fulfillment`.
82
+ */
83
+ fulfillmentHandler: string;
84
+ /**
85
+ * One of `eligibilityCheckers`, with every argument it needs (a value is always a string; lists
86
+ * and booleans JSON-encoded). The engine requires one; "everyone" is
87
+ * `default-shipping-eligibility-checker` with `orderMinimum: '0'`.
88
+ */
89
+ checker: ConfigurableOperationInput;
90
+ /** One of `calculators`, with its arguments. */
91
+ calculator: ConfigurableOperationInput;
92
+ /** At least the store's default language: it is the name shoppers and staff are shown. */
93
+ translations: ShippingMethodTranslationInput[];
94
+ /** On when left out. See {@link ShippingMethodSummary.enabled}. */
95
+ enabled?: boolean;
96
+ /** On when left out. */
97
+ enabledInStorefront?: boolean;
98
+ /** Minor units, or null for no charge (left out: none). See {@link ShippingMethod.extraParcelPrice}. */
99
+ extraParcelPrice?: number | null;
100
+ }
101
+ /**
102
+ * A change to a shipping method, as {@link ShippingMethodsModule.update} takes it. A field left
103
+ * out keeps what the method has. The checker can be replaced, never taken away: every method has
104
+ * one.
105
+ */
106
+ export interface UpdateShippingMethodInput {
107
+ code?: string;
108
+ fulfillmentHandler?: string;
109
+ checker?: ConfigurableOperationInput;
110
+ calculator?: ConfigurableOperationInput;
111
+ translations?: ShippingMethodTranslationInput[];
112
+ enabled?: boolean;
113
+ enabledInStorefront?: boolean;
114
+ /** `null` clears it (no charge); left out, the stored price stays. */
115
+ extraParcelPrice?: number | null;
116
+ }
117
+ /**
118
+ * The store's shipping methods (`admin.shipping.methods`): what checkout offers, what a
119
+ * fulfillment profile and the till's delivery setting name, and what the store's shipping
120
+ * settings show.
121
+ *
122
+ * Every read needs `ReadSettings` or `ReadShippingMethod` (either one, so no `@permission` tag:
123
+ * the tag can only say "all of these"). Scoped to the channel the client is on: another store's
124
+ * methods are not listed, and not answered by id.
125
+ */
126
+ export interface ShippingMethodsModule {
127
+ /**
128
+ * Every method of the store, enabled or not, in id order. Paged (`options.limit`, default 100,
129
+ * at most 1,000 or `INVALID_PAGE_SIZE`; and `options.after` from a previous page);
130
+ * `for await (const method of page)` walks them all.
131
+ *
132
+ * @effect read
133
+ */
134
+ list(options?: ListOptions): Promise<Page<ShippingMethodSummary>>;
135
+ /**
136
+ * One method by id, or `null` when the store the client is on has no such method: an id that
137
+ * does not exist, a deleted method and the id of a method only ANOTHER store holds read the
138
+ * same.
139
+ *
140
+ * @effect read
141
+ */
142
+ get(id: string, options?: Call): Promise<ShippingMethod | null>;
143
+ /**
144
+ * Add a shipping method to the store the client is on, and answer it as {@link get} reads it.
145
+ * Needs `CreateSettings` or `CreateShippingMethod` (either one). Nothing is saved when it is
146
+ * refused:
147
+ *
148
+ * - `INVALID_SHIPPING_METHOD_INPUT` (`ValidationError`, 400): the input's shape, checked here
149
+ * before anything is sent.
150
+ * - `ORGANIZATION_WORKSPACE_NOT_A_STORE` (`BusinessRuleError`, 422): an organization's
151
+ * workspace ships nothing; create the method in one of its stores.
152
+ * - `PLUGIN_ACCESS_DENIED` (`PermissionDeniedError`, 403): the fulfillment handler, checker or
153
+ * calculator belongs to a plugin the store does not hold (a carrier, Exact Online).
154
+ * - The engine's own input refusal (`ValidationError`, 400): a handler, checker or calculator
155
+ * code it has not registered, a missing argument, or an `extraParcelPrice` outside
156
+ * 0–10,000,000.
157
+ *
158
+ * @effect write
159
+ */
160
+ create(input: CreateShippingMethodInput, options?: Call): Promise<ShippingMethod>;
161
+ /**
162
+ * Change a shipping method of the store the client is on, and answer it as {@link get} reads
163
+ * it. A field left out keeps what the method has. Needs `UpdateSettings` or
164
+ * `UpdateShippingMethod` (either one).
165
+ *
166
+ * One method may be held by several stores, and a change reaches every one of them. Refused,
167
+ * with nothing saved, as {@link create} is (`PLUGIN_ACCESS_DENIED` only for a handler, checker
168
+ * or calculator the patch CHANGES: one the method already has is no new pick), and:
169
+ *
170
+ * - `ENTITY_NOT_FOUND` (`NotFoundError`, 404): the store has no such method (another store's
171
+ * reads the same).
172
+ * - `SHARED_SHIPPING_METHOD_NOT_ALLOWED` (`PermissionDeniedError`, 403): the method is shared
173
+ * with another store where the caller lacks `UpdateSettings` or `UpdateShippingMethod`.
174
+ *
175
+ * @effect write
176
+ */
177
+ update(id: string, patch: UpdateShippingMethodInput, options?: Call): Promise<ShippingMethod>;
178
+ /**
179
+ * Delete a shipping method. The method is withdrawn from checkout in EVERY store that holds
180
+ * it, not only the one the client is on; orders already shipped with it keep their shipping
181
+ * line. Needs `DeleteSettings` or `DeleteShippingMethod` (either one), and the same in every
182
+ * other store holding the method, else `SHARED_SHIPPING_METHOD_NOT_ALLOWED`
183
+ * (`PermissionDeniedError`, 403) and nothing is deleted.
184
+ *
185
+ * `ENTITY_NOT_FOUND` (`NotFoundError`, 404): the store has no such method, or it is already
186
+ * deleted. A refusal the engine answers as a result rather than an error is
187
+ * `SHIPPING_METHOD_NOT_DELETED` (`ConflictError`, 409) with the engine's reason.
188
+ *
189
+ * @effect destructive
190
+ */
191
+ delete(id: string, options?: Call): Promise<void>;
192
+ }
193
+ export declare const SHIPPING_METHODS_QUERY = "\n query StoreShippingMethods($options: ShippingMethodListOptions) {\n shippingMethods(options: $options) {\n items { \n id\n createdAt\n updatedAt\n code\n name\n fulfillmentHandlerCode\n calculator { \n code\n args {\n name\n value\n }\n }\n customFields {\n enabled\n enabledInStorefront\n }\n }\n totalItems\n }\n }\n";
194
+ export declare const SHIPPING_METHOD_QUERY = "\n query StoreShippingMethod($id: ID!) {\n shippingMethod(id: $id) { \n id\n createdAt\n updatedAt\n code\n name\n description\n fulfillmentHandlerCode\n calculator { \n code\n args {\n name\n value\n }\n }\n checker { \n code\n args {\n name\n value\n }\n }\n translations {\n id\n languageCode\n name\n description\n }\n customFields {\n enabled\n enabledInStorefront\n exactManaged\n extraParcelPrice\n }\n }\n }\n";
195
+ export declare const CREATE_SHIPPING_METHOD_MUTATION = "\n mutation CreateStoreShippingMethod($input: CreateShippingMethodInput!) {\n createShippingMethod(input: $input) { \n id\n createdAt\n updatedAt\n code\n name\n description\n fulfillmentHandlerCode\n calculator { \n code\n args {\n name\n value\n }\n }\n checker { \n code\n args {\n name\n value\n }\n }\n translations {\n id\n languageCode\n name\n description\n }\n customFields {\n enabled\n enabledInStorefront\n exactManaged\n extraParcelPrice\n }\n }\n }\n";
196
+ export declare const UPDATE_SHIPPING_METHOD_MUTATION = "\n mutation UpdateStoreShippingMethod($input: UpdateShippingMethodInput!) {\n updateShippingMethod(input: $input) { \n id\n createdAt\n updatedAt\n code\n name\n description\n fulfillmentHandlerCode\n calculator { \n code\n args {\n name\n value\n }\n }\n checker { \n code\n args {\n name\n value\n }\n }\n translations {\n id\n languageCode\n name\n description\n }\n customFields {\n enabled\n enabledInStorefront\n exactManaged\n extraParcelPrice\n }\n }\n }\n";
197
+ export declare const DELETE_SHIPPING_METHOD_MUTATION = "\n mutation DeleteStoreShippingMethod($id: ID!) {\n deleteShippingMethod(id: $id) {\n result\n message\n }\n }\n";
198
+ export declare function createShippingMethodsModule(transport: Transport): ShippingMethodsModule;
@@ -0,0 +1,240 @@
1
+ import { ValidationError } from '@sixtyninecommerce/core';
2
+ import { assertDeleted, fieldOf, vendureListPage, } from '../catalog/types.js';
3
+ /** A store has a handful; one page holds them. */
4
+ const DEFAULT_PAGE_SIZE = 100;
5
+ /**
6
+ * Vendure's list queries add no ORDER BY of their own, and `skip/take` over an unordered query
7
+ * can repeat or skip rows between two requests: id is the one unique key a sort can name.
8
+ */
9
+ const BY_ID = { id: 'ASC' };
10
+ const OPERATION_FIELDS = /* GraphQL */ `
11
+ code
12
+ args {
13
+ name
14
+ value
15
+ }
16
+ `;
17
+ const SUMMARY_FIELDS = /* GraphQL */ `
18
+ id
19
+ createdAt
20
+ updatedAt
21
+ code
22
+ name
23
+ fulfillmentHandlerCode
24
+ calculator { ${OPERATION_FIELDS} }
25
+ customFields {
26
+ enabled
27
+ enabledInStorefront
28
+ }
29
+ `;
30
+ /** One selection for the single read and both writes, so all three answer the same method. */
31
+ const METHOD_FIELDS = /* GraphQL */ `
32
+ id
33
+ createdAt
34
+ updatedAt
35
+ code
36
+ name
37
+ description
38
+ fulfillmentHandlerCode
39
+ calculator { ${OPERATION_FIELDS} }
40
+ checker { ${OPERATION_FIELDS} }
41
+ translations {
42
+ id
43
+ languageCode
44
+ name
45
+ description
46
+ }
47
+ customFields {
48
+ enabled
49
+ enabledInStorefront
50
+ exactManaged
51
+ extraParcelPrice
52
+ }
53
+ `;
54
+ export const SHIPPING_METHODS_QUERY = /* GraphQL */ `
55
+ query StoreShippingMethods($options: ShippingMethodListOptions) {
56
+ shippingMethods(options: $options) {
57
+ items { ${SUMMARY_FIELDS} }
58
+ totalItems
59
+ }
60
+ }
61
+ `;
62
+ export const SHIPPING_METHOD_QUERY = /* GraphQL */ `
63
+ query StoreShippingMethod($id: ID!) {
64
+ shippingMethod(id: $id) { ${METHOD_FIELDS} }
65
+ }
66
+ `;
67
+ export const CREATE_SHIPPING_METHOD_MUTATION = /* GraphQL */ `
68
+ mutation CreateStoreShippingMethod($input: CreateShippingMethodInput!) {
69
+ createShippingMethod(input: $input) { ${METHOD_FIELDS} }
70
+ }
71
+ `;
72
+ export const UPDATE_SHIPPING_METHOD_MUTATION = /* GraphQL */ `
73
+ mutation UpdateStoreShippingMethod($input: UpdateShippingMethodInput!) {
74
+ updateShippingMethod(input: $input) { ${METHOD_FIELDS} }
75
+ }
76
+ `;
77
+ export const DELETE_SHIPPING_METHOD_MUTATION = /* GraphQL */ `
78
+ mutation DeleteStoreShippingMethod($id: ID!) {
79
+ deleteShippingMethod(id: $id) {
80
+ result
81
+ message
82
+ }
83
+ }
84
+ `;
85
+ const invalidInput = (message) => new ValidationError({
86
+ code: 'INVALID_SHIPPING_METHOD_INPUT',
87
+ message,
88
+ status: 400,
89
+ service: 'vendure',
90
+ });
91
+ const isObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
92
+ /** A handler-like operation as the engine takes it, checked here so a wrong shape never leaves. */
93
+ function operationInput(value, what) {
94
+ if (!isObject(value) || typeof value.code !== 'string' || value.code === '') {
95
+ throw invalidInput(`${what} needs a code.`);
96
+ }
97
+ const args = value.arguments;
98
+ if (!Array.isArray(args) ||
99
+ !args.every((arg) => isObject(arg) && typeof arg.name === 'string' && typeof arg.value === 'string')) {
100
+ throw invalidInput(`${what}.arguments must be a list of { name, value } strings (a list or a boolean JSON-encoded).`);
101
+ }
102
+ return {
103
+ code: value.code,
104
+ arguments: args.map((arg) => ({ name: String(arg.name), value: String(arg.value) })),
105
+ };
106
+ }
107
+ function translationsInput(value) {
108
+ if (!Array.isArray(value) ||
109
+ !value.every((row) => isObject(row) &&
110
+ typeof row.languageCode === 'string' &&
111
+ row.languageCode !== '' &&
112
+ typeof row.name === 'string' &&
113
+ (row.description === undefined || typeof row.description === 'string'))) {
114
+ throw invalidInput('translations must be a list of { languageCode, name, description? } with strings.');
115
+ }
116
+ return value.map((row) => ({
117
+ languageCode: String(row.languageCode),
118
+ name: String(row.name),
119
+ description: typeof row.description === 'string' ? row.description : '',
120
+ }));
121
+ }
122
+ /**
123
+ * The fields both writes share, in the engine's shape: the three store switches under
124
+ * `customFields`. The range of `extraParcelPrice` is the engine's to judge.
125
+ */
126
+ function sharedInput(input) {
127
+ const out = {};
128
+ if (input.code !== undefined) {
129
+ if (typeof input.code !== 'string' || input.code === '') {
130
+ throw invalidInput('code must be a non-empty string.');
131
+ }
132
+ out.code = input.code;
133
+ }
134
+ if (input.fulfillmentHandler !== undefined) {
135
+ if (typeof input.fulfillmentHandler !== 'string' || input.fulfillmentHandler === '') {
136
+ throw invalidInput('fulfillmentHandler must be a fulfillment handler code.');
137
+ }
138
+ out.fulfillmentHandler = input.fulfillmentHandler;
139
+ }
140
+ if (input.checker === null) {
141
+ throw invalidInput('Every shipping method has a checker: send default-shipping-eligibility-checker for "everyone".');
142
+ }
143
+ if (input.checker !== undefined)
144
+ out.checker = operationInput(input.checker, 'checker');
145
+ if (input.calculator !== undefined) {
146
+ out.calculator = operationInput(input.calculator, 'calculator');
147
+ }
148
+ if (input.translations !== undefined)
149
+ out.translations = translationsInput(input.translations);
150
+ const customFields = {};
151
+ for (const flag of ['enabled', 'enabledInStorefront']) {
152
+ const value = input[flag];
153
+ if (value === undefined)
154
+ continue;
155
+ if (typeof value !== 'boolean')
156
+ throw invalidInput(`${flag} must be true or false.`);
157
+ customFields[flag] = value;
158
+ }
159
+ const extra = input.extraParcelPrice;
160
+ if (extra !== undefined) {
161
+ if (extra !== null && (typeof extra !== 'number' || !Number.isSafeInteger(extra))) {
162
+ throw invalidInput('extraParcelPrice must be a whole number of minor units, or null.');
163
+ }
164
+ customFields.extraParcelPrice = extra;
165
+ }
166
+ if (Object.keys(customFields).length > 0)
167
+ out.customFields = customFields;
168
+ return out;
169
+ }
170
+ const toSummary = (method) => ({
171
+ id: method.id,
172
+ code: method.code,
173
+ name: method.name,
174
+ fulfillmentHandlerCode: method.fulfillmentHandlerCode,
175
+ calculator: method.calculator,
176
+ // A switch the engine did not answer (a method stored before it existed) reads as ON: the
177
+ // checkout's own rule (`shipping-method-enabled.ts` in the shipping-calculator plugin) is the same fail-open one.
178
+ enabled: method.customFields?.enabled !== false,
179
+ enabledInStorefront: method.customFields?.enabledInStorefront !== false,
180
+ createdAt: method.createdAt,
181
+ updatedAt: method.updatedAt,
182
+ });
183
+ const toMethod = (method) => {
184
+ const extra = method.customFields?.extraParcelPrice;
185
+ return {
186
+ ...toSummary(method),
187
+ description: method.description,
188
+ checker: method.checker,
189
+ translations: method.translations,
190
+ exactManaged: method.customFields?.exactManaged === true,
191
+ extraParcelPrice: typeof extra === 'number' ? extra : null,
192
+ };
193
+ };
194
+ const requireId = (id) => {
195
+ if (typeof id !== 'string' || id === '')
196
+ throw invalidInput('id must be a shipping method id.');
197
+ return id;
198
+ };
199
+ export function createShippingMethodsModule(transport) {
200
+ return {
201
+ list(options) {
202
+ return vendureListPage(transport, SHIPPING_METHODS_QUERY, 'shippingMethods', (skip, take) => ({ options: { skip, take, sort: BY_ID } }), { ...options, limit: options?.limit ?? DEFAULT_PAGE_SIZE }, toSummary);
203
+ },
204
+ async get(id, options) {
205
+ const method = await fieldOf(transport, SHIPPING_METHOD_QUERY, 'shippingMethod', { id: requireId(id) }, options);
206
+ return method ? toMethod(method) : null;
207
+ },
208
+ async create(input, options) {
209
+ if (!isObject(input))
210
+ throw invalidInput('A new shipping method must be an object.');
211
+ if (input.code === undefined)
212
+ throw invalidInput('A shipping method needs a code.');
213
+ if (input.fulfillmentHandler === undefined) {
214
+ throw invalidInput('A shipping method needs a fulfillment handler.');
215
+ }
216
+ if (input.checker === undefined)
217
+ throw invalidInput('A shipping method needs a checker.');
218
+ if (input.calculator === undefined) {
219
+ throw invalidInput('A shipping method needs a calculator.');
220
+ }
221
+ if (input.translations === undefined) {
222
+ throw invalidInput('A shipping method needs its name in at least one language.');
223
+ }
224
+ return toMethod(await fieldOf(transport, CREATE_SHIPPING_METHOD_MUTATION, 'createShippingMethod', { input: sharedInput(input) }, options));
225
+ },
226
+ async update(id, patch, options) {
227
+ const methodId = requireId(id);
228
+ if (!isObject(patch))
229
+ throw invalidInput('The change to a shipping method must be an object.');
230
+ const input = sharedInput(patch);
231
+ // The engine's input REQUIRES a translations list; an empty one changes no name.
232
+ return toMethod(await fieldOf(transport, UPDATE_SHIPPING_METHOD_MUTATION, 'updateShippingMethod', { input: { id: methodId, translations: [], ...input } }, options));
233
+ },
234
+ async delete(id, options) {
235
+ assertDeleted('SHIPPING_METHOD_NOT_DELETED', [
236
+ await fieldOf(transport, DELETE_SHIPPING_METHOD_MUTATION, 'deleteShippingMethod', { id: requireId(id) }, options),
237
+ ]);
238
+ },
239
+ };
240
+ }