@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,254 @@
1
+ import { type PlatformError, type Transport, type VendureErrorResult } from '@sixtyninecommerce/core';
2
+ import type { Call } from '../types.js';
3
+ /**
4
+ * The store-wide default label format: `A4` or `A6` paper, or `BOTH`, which has MyParcel make
5
+ * both for every new fulfillment.
6
+ */
7
+ export type MyparcelLabelFormat = 'A4' | 'A6' | 'BOTH';
8
+ /**
9
+ * A store's MyParcel set-up, as every reader gets it: both secrets masked. The API key is never
10
+ * readable again once saved, and the webhook secret is only ever needed by the platform itself
11
+ * (it registers the callback URL at MyParcel), so neither is answered in clear here.
12
+ */
13
+ export interface MyparcelConfig {
14
+ id: string;
15
+ channelId: string;
16
+ /** A key is stored. */
17
+ hasApiKey: boolean;
18
+ /**
19
+ * The key's preview, for display only: mask glyphs (`•`) and its last 4 characters. It is never
20
+ * the key: `update` refuses it (`SECRET_ARG_MASK_INVALID`).
21
+ */
22
+ maskedApiKey: string;
23
+ /** The webhook secret's preview, for display only: 8 mask glyphs and its last 4 characters. */
24
+ maskedWebhookSecret: string;
25
+ defaultLabelFormat: MyparcelLabelFormat;
26
+ /** MyParcel is on for the store. Independent of the key: switching off keeps it. */
27
+ enabled: boolean;
28
+ }
29
+ /** What `config.update` takes: the key alone. */
30
+ export interface UpdateMyparcelConfigInput {
31
+ /** The MyParcel API key, from the store's MyParcel account. Trimmed; never empty. */
32
+ apiKey: string;
33
+ }
34
+ /** A carrier MyParcel offers. The list is the same for every store (`GET /carriers`). */
35
+ export interface MyparcelCarrier {
36
+ /** MyParcel's carrier id, as a shipment names it. */
37
+ id: number;
38
+ /** The carrier's slug (`postnl`, `dhlforyou`, …). */
39
+ name: string;
40
+ /** Its name for people (`PostNL`). */
41
+ human: string;
42
+ /** MyParcel's logo links; `''` where MyParcel has none. */
43
+ meta: {
44
+ logoSvg: string;
45
+ logoPng: string;
46
+ };
47
+ }
48
+ /** A stock location's parcel sender address. */
49
+ export interface MyparcelSenderAddress {
50
+ streetLine1: string;
51
+ streetLine2: string | null;
52
+ city: string;
53
+ postalCode: string;
54
+ province: string | null;
55
+ /** ISO 3166-1 alpha-2, upper case. */
56
+ countryCode: string;
57
+ phoneNumber: string | null;
58
+ contactName: string | null;
59
+ company: string | null;
60
+ }
61
+ /** One stock location of the store as a parcel sender. */
62
+ export interface MyparcelSenderLocation {
63
+ /** The stock location's id. */
64
+ id: string;
65
+ name: string;
66
+ /** Its sender address, or `null` when none is stored or the stored one does not parse. */
67
+ address: MyparcelSenderAddress | null;
68
+ /** The store's default sender: a shipment that names no location ships from it. */
69
+ isDefaultSender: boolean;
70
+ /** The address has every field a shipment needs (street, city, postal code, country). */
71
+ isResolvable: boolean;
72
+ }
73
+ /** What `senders.set` writes. */
74
+ export interface SetMyparcelSenderInput {
75
+ stockLocationId: string;
76
+ /** The whole address. `null` or a blank optional field is stored as absent. */
77
+ address: {
78
+ streetLine1: string;
79
+ streetLine2?: string | null;
80
+ city: string;
81
+ postalCode: string;
82
+ province?: string | null;
83
+ countryCode: string;
84
+ phoneNumber?: string | null;
85
+ contactName?: string | null;
86
+ company?: string | null;
87
+ };
88
+ /**
89
+ * Make this location the store's default sender (`true`) or not. Send the location's CURRENT
90
+ * flag to change the address alone: only a change of the flag is judged and written.
91
+ */
92
+ isDefault: boolean;
93
+ }
94
+ /**
95
+ * The MyParcel set-up of the store the client is scoped to (`admin.shipping.myparcel.config`).
96
+ * There is no channel argument: a SuperAdmin head configures ANOTHER store with
97
+ * `admin.withTenant({ scope: { kind: 'channel', code } })`, or a per-call `tenant`.
98
+ *
99
+ * Every method needs `UpdateSettings`. An app installation is refused all of them
100
+ * (`APP_CREDENTIAL_NOT_ALLOWED`), the read included: the engine still answers the webhook secret
101
+ * in clear on an older field of the same object. A store without the MyParcel plugin is refused
102
+ * `PLUGIN_ACCESS_DENIED` (`PermissionDeniedError`, 403) on every write, `remove` included, for an
103
+ * ordinary caller; the engine never refuses a SuperAdmin on that ground.
104
+ */
105
+ export interface MyparcelConfigModule {
106
+ /**
107
+ * The store's set-up, or `null` when no key was ever saved (or it was removed). A stored key the
108
+ * engine can no longer decrypt (its encryption key was rotated) fails this read with the
109
+ * engine's internal error (code `INTERNAL_SERVER_ERROR`: a non-retryable 500, raised as
110
+ * `UpstreamError`), not a coded refusal: the read is not a union. Saving the key again with `update` repairs it; the writes answer the
111
+ * same condition as `MYPARCEL_DECRYPTION_FAILED_ERROR` (`BusinessRuleError`, 422).
112
+ *
113
+ * @effect read
114
+ * @permission UpdateSettings
115
+ */
116
+ get(options?: Call): Promise<MyparcelConfig | null>;
117
+ /**
118
+ * Save the store's API key; the first save also switches MyParcel on, with `A6` labels and a new
119
+ * webhook secret. A later save replaces the key alone (the on/off switch, the label format and
120
+ * the webhook secret stay). The key is trimmed and stored as given: the engine does not test it
121
+ * against MyParcel, so a wrong key fails at the first shipment or label.
122
+ *
123
+ * An empty key is refused here (`TypeError`), never sent: an empty key REMOVES the whole set-up
124
+ * on the wire, and that is `remove()`'s job. The message never quotes the argument.
125
+ *
126
+ * Refused, with nothing stored:
127
+ * - `SECRET_ARG_MASK_INVALID` (`ValidationError`, 400, `details[0].field: 'apiKey'`): a key
128
+ * carrying the mask glyph (`•`), {@link MyparcelConfig.maskedApiKey} sent back included. The
129
+ * preview is never the key; leave the key alone to keep it;
130
+ * - `ORGANIZATION_WORKSPACE_NOT_A_STORE` (`BusinessRuleError`, 422): an organization's workspace
131
+ * ships nothing.
132
+ *
133
+ * @effect write
134
+ * @permission UpdateSettings
135
+ */
136
+ update(input: UpdateMyparcelConfigInput, options?: Call): Promise<MyparcelConfig>;
137
+ /**
138
+ * Remove the store's MyParcel set-up: the API key, the label format, the on/off switch AND the
139
+ * webhook secret. MyParcel's status and label callbacks for the store are refused from then on,
140
+ * and every MyParcel shipment or label of the store is refused (`MYPARCEL_NOT_CONFIGURED_ERROR`)
141
+ * until a key is saved again, which mints a new webhook secret. Resolves when the store has no
142
+ * set-up any more, also when it had none. Allowed in an organization's workspace.
143
+ *
144
+ * @effect destructive
145
+ * @permission UpdateSettings
146
+ */
147
+ remove(options?: Call): Promise<void>;
148
+ /**
149
+ * Set the store-wide default label format. A fulfillment's own format, when it has one, wins.
150
+ *
151
+ * Refused: `MYPARCEL_NOT_CONFIGURED_ERROR` (`BusinessRuleError`, 422) before a key is saved;
152
+ * `MYPARCEL_INVALID_LABEL_FORMAT_ERROR` (422) for any other value.
153
+ *
154
+ * @effect write
155
+ * @permission UpdateSettings
156
+ */
157
+ setLabelFormat(format: MyparcelLabelFormat, options?: Call): Promise<MyparcelConfig>;
158
+ /**
159
+ * Switch MyParcel on or off for the store without touching the key or the webhook secret. Off,
160
+ * every new MyParcel shipment and label of the store is refused; what MyParcel already holds is
161
+ * left as it is.
162
+ *
163
+ * Refused: `MYPARCEL_NOT_CONFIGURED_ERROR` (`BusinessRuleError`, 422) before a key is saved;
164
+ * switching ON in an organization's workspace, `ORGANIZATION_WORKSPACE_NOT_A_STORE` (422).
165
+ *
166
+ * @effect write
167
+ * @permission UpdateSettings
168
+ */
169
+ setEnabled(enabled: boolean, options?: Call): Promise<MyparcelConfig>;
170
+ /**
171
+ * Replace the store's webhook secret, answering the set-up with the NEW secret's preview (the
172
+ * secret itself is never answered). The old secret stops authenticating at once, and MyParcel
173
+ * keeps calling the old callback URL, refused, until the engine's worker registers the webhooks
174
+ * again, which it does when it starts. Status and label updates sent meanwhile are lost.
175
+ *
176
+ * The secret is answered in clear by the engine's older `webhookSecret` field and stored in
177
+ * clear; hashing it at rest is an open follow-up, after which only a preview can be read.
178
+ *
179
+ * Refused: `MYPARCEL_NOT_CONFIGURED_ERROR` (`BusinessRuleError`, 422) before a key is saved.
180
+ *
181
+ * @effect destructive
182
+ * @permission UpdateSettings
183
+ */
184
+ regenerateWebhookSecret(options?: Call): Promise<MyparcelConfig>;
185
+ }
186
+ /**
187
+ * The stock locations of the store as MyParcel parcel senders (`admin.shipping.myparcel.senders`).
188
+ * A location's sender address and default flag are columns of its ONE row, so a location several
189
+ * stores hold has one sender for all of them.
190
+ */
191
+ export interface MyparcelSendersModule {
192
+ /**
193
+ * Every stock location of the store with its sender address, default flag and whether a
194
+ * shipment can ship from it. Needs `ReadStockLocation`; answered whether or not MyParcel is set
195
+ * up.
196
+ *
197
+ * @effect read
198
+ * @permission ReadStockLocation
199
+ */
200
+ list(options?: Call): Promise<MyparcelSenderLocation[]>;
201
+ /**
202
+ * Set a stock location's sender address, and whether it is the store's default sender. Making it
203
+ * the default clears the flag on the store's other locations in the same transaction, so the
204
+ * store keeps exactly one. This is the one door that writes either column: core's stock-location
205
+ * create and update refuse a change to them (`STOCK_LOCATION_SENDER_READ_ONLY`).
206
+ *
207
+ * Refused, with nothing written:
208
+ * - `MYPARCEL_INVALID_SENDER_ERROR` (`BusinessRuleError`, 422): a mandatory field missing or a
209
+ * country code that is not 2 letters; `details[]` names each field (`streetLine1`, `city`,
210
+ * `postalCode`, `countryCode`);
211
+ * - `MYPARCEL_STOCK_LOCATION_NOT_FOUND_ERROR` (`NotFoundError`, 404): no such location in the
212
+ * store (another store's, a missing and a malformed id alike);
213
+ * - `SHARED_STOCK_LOCATION_NOT_ALLOWED` (403): the location, or a default it would clear, is
214
+ * also another store's, and the caller may not update stock locations there;
215
+ * - `LOCATION_NOT_ALLOWED` (403): a credential restricted to some locations names, or would
216
+ * clear the default of, one it does not hold;
217
+ * - `ORGANIZATION_WORKSPACE_NOT_A_STORE` / `DEFAULT_SENDER_NOT_A_STORE` (422): changing the
218
+ * default flag in an organization's workspace or on the platform root. Sending the current
219
+ * flag there saves the address alone.
220
+ *
221
+ * @effect write
222
+ * @permission UpdateStockLocation
223
+ */
224
+ set(input: SetMyparcelSenderInput, options?: Call): Promise<MyparcelSenderLocation>;
225
+ }
226
+ /** `admin.shipping.myparcel`: the MyParcel integration of the store. */
227
+ export interface MyparcelModule {
228
+ config: MyparcelConfigModule;
229
+ /**
230
+ * The carriers MyParcel offers, the same list for every store (cached by the engine for an
231
+ * hour). What a carrier can do for one address is not in it. Needs `ReadSettings`; a store
232
+ * without the MyParcel plugin is refused `PLUGIN_ACCESS_DENIED` (403).
233
+ *
234
+ * @effect read
235
+ * @permission ReadSettings
236
+ */
237
+ carriers(options?: Call): Promise<MyparcelCarrier[]>;
238
+ senders: MyparcelSendersModule;
239
+ }
240
+ export declare const MYPARCEL_CONFIG_QUERY = "\n query MyparcelConfig {\n myparcelConfig { \n id\n channelId\n hasApiKey\n maskedApiKey\n maskedWebhookSecret\n defaultLabelFormat\n enabled\n }\n }\n";
241
+ export declare const UPDATE_MYPARCEL_CONFIG_MUTATION = "\n mutation UpdateMyparcelConfig($input: MyparcelConfigInput!) {\n updateMyparcelConfig(input: $input) {\n \n __typename\n ... on MyparcelConfig { \n id\n channelId\n hasApiKey\n maskedApiKey\n maskedWebhookSecret\n defaultLabelFormat\n enabled\n }\n ... on ErrorResult { errorCode message }\n\n ... on MyparcelValidationError { errors }\n }\n }\n";
242
+ export declare const UPDATE_MYPARCEL_LABEL_FORMAT_MUTATION = "\n mutation UpdateMyparcelLabelFormat($input: MyparcelLabelFormatInput!) {\n updateMyparcelLabelFormat(input: $input) { \n __typename\n ... on MyparcelConfig { \n id\n channelId\n hasApiKey\n maskedApiKey\n maskedWebhookSecret\n defaultLabelFormat\n enabled\n }\n ... on ErrorResult { errorCode message }\n }\n }\n";
243
+ export declare const SET_MYPARCEL_ENABLED_MUTATION = "\n mutation SetMyparcelEnabled($enabled: Boolean!) {\n setMyparcelEnabled(enabled: $enabled) {\n \n __typename\n ... on MyparcelConfig { \n id\n channelId\n hasApiKey\n maskedApiKey\n maskedWebhookSecret\n defaultLabelFormat\n enabled\n }\n ... on ErrorResult { errorCode message }\n\n ... on MyparcelValidationError { errors }\n }\n }\n";
244
+ export declare const REGENERATE_MYPARCEL_WEBHOOK_SECRET_MUTATION = "\n mutation RegenerateMyparcelWebhookSecret {\n regenerateMyparcelWebhookSecret { \n __typename\n ... on MyparcelConfig { \n id\n channelId\n hasApiKey\n maskedApiKey\n maskedWebhookSecret\n defaultLabelFormat\n enabled\n }\n ... on ErrorResult { errorCode message }\n }\n }\n";
245
+ export declare const MYPARCEL_CARRIERS_QUERY = "\n query MyparcelCarriers {\n myparcelCarriers {\n id\n name\n human\n meta { logoSvg logoPng }\n }\n }\n";
246
+ export declare const MYPARCEL_SENDERS_QUERY = "\n query MyparcelSenderStockLocations {\n myparcelSenderStockLocations { \n id\n name\n address {\n streetLine1\n streetLine2\n city\n postalCode\n province\n countryCode\n phoneNumber\n contactName\n company\n }\n isDefaultSender\n isResolvable\n }\n }\n";
247
+ export declare const SET_MYPARCEL_SENDER_MUTATION = "\n mutation SetStockLocationSender($input: MyparcelSetStockLocationSenderInput!) {\n setStockLocationSender(input: $input) {\n __typename\n ... on MyparcelSenderStockLocationSummary { \n id\n name\n address {\n streetLine1\n streetLine2\n city\n postalCode\n province\n countryCode\n phoneNumber\n contactName\n company\n }\n isDefaultSender\n isResolvable\n }\n ... on ErrorResult { errorCode message }\n ... on MyparcelInvalidSenderError { fields }\n }\n }\n";
248
+ /**
249
+ * A refusal member as its error class, by core's `errorFromErrorResult`. The field names a member
250
+ * carries (`MyparcelInvalidSenderError.fields`, `MyparcelValidationError.errors`) ride
251
+ * `details[]`, one per field, so a form can mark each without matching the sentence.
252
+ */
253
+ export declare function myparcelRefusal(result: VendureErrorResult): PlatformError;
254
+ export declare function createMyparcelModule(transport: Transport): MyparcelModule;
@@ -0,0 +1,178 @@
1
+ import { errorForStatus, errorFromErrorResult, isErrorResult, } from '@sixtyninecommerce/core';
2
+ const CONFIG_FIELDS = /* GraphQL */ `
3
+ id
4
+ channelId
5
+ hasApiKey
6
+ maskedApiKey
7
+ maskedWebhookSecret
8
+ defaultLabelFormat
9
+ enabled
10
+ `;
11
+ /** The union answer of every config write: the set-up, or a refusal. */
12
+ const CONFIG_RESULT = /* GraphQL */ `
13
+ __typename
14
+ ... on MyparcelConfig { ${CONFIG_FIELDS} }
15
+ ... on ErrorResult { errorCode message }
16
+ `;
17
+ export const MYPARCEL_CONFIG_QUERY = /* GraphQL */ `
18
+ query MyparcelConfig {
19
+ myparcelConfig { ${CONFIG_FIELDS} }
20
+ }
21
+ `;
22
+ export const UPDATE_MYPARCEL_CONFIG_MUTATION = /* GraphQL */ `
23
+ mutation UpdateMyparcelConfig($input: MyparcelConfigInput!) {
24
+ updateMyparcelConfig(input: $input) {
25
+ ${CONFIG_RESULT}
26
+ ... on MyparcelValidationError { errors }
27
+ }
28
+ }
29
+ `;
30
+ export const UPDATE_MYPARCEL_LABEL_FORMAT_MUTATION = /* GraphQL */ `
31
+ mutation UpdateMyparcelLabelFormat($input: MyparcelLabelFormatInput!) {
32
+ updateMyparcelLabelFormat(input: $input) { ${CONFIG_RESULT} }
33
+ }
34
+ `;
35
+ export const SET_MYPARCEL_ENABLED_MUTATION = /* GraphQL */ `
36
+ mutation SetMyparcelEnabled($enabled: Boolean!) {
37
+ setMyparcelEnabled(enabled: $enabled) {
38
+ ${CONFIG_RESULT}
39
+ ... on MyparcelValidationError { errors }
40
+ }
41
+ }
42
+ `;
43
+ export const REGENERATE_MYPARCEL_WEBHOOK_SECRET_MUTATION = /* GraphQL */ `
44
+ mutation RegenerateMyparcelWebhookSecret {
45
+ regenerateMyparcelWebhookSecret { ${CONFIG_RESULT} }
46
+ }
47
+ `;
48
+ export const MYPARCEL_CARRIERS_QUERY = /* GraphQL */ `
49
+ query MyparcelCarriers {
50
+ myparcelCarriers {
51
+ id
52
+ name
53
+ human
54
+ meta { logoSvg logoPng }
55
+ }
56
+ }
57
+ `;
58
+ const SENDER_FIELDS = /* GraphQL */ `
59
+ id
60
+ name
61
+ address {
62
+ streetLine1
63
+ streetLine2
64
+ city
65
+ postalCode
66
+ province
67
+ countryCode
68
+ phoneNumber
69
+ contactName
70
+ company
71
+ }
72
+ isDefaultSender
73
+ isResolvable
74
+ `;
75
+ export const MYPARCEL_SENDERS_QUERY = /* GraphQL */ `
76
+ query MyparcelSenderStockLocations {
77
+ myparcelSenderStockLocations { ${SENDER_FIELDS} }
78
+ }
79
+ `;
80
+ export const SET_MYPARCEL_SENDER_MUTATION = /* GraphQL */ `
81
+ mutation SetStockLocationSender($input: MyparcelSetStockLocationSenderInput!) {
82
+ setStockLocationSender(input: $input) {
83
+ __typename
84
+ ... on MyparcelSenderStockLocationSummary { ${SENDER_FIELDS} }
85
+ ... on ErrorResult { errorCode message }
86
+ ... on MyparcelInvalidSenderError { fields }
87
+ }
88
+ }
89
+ `;
90
+ /** `updateMyparcelConfig` with an empty key answers this member: the set-up is gone. */
91
+ const NOT_CONFIGURED = 'MYPARCEL_NOT_CONFIGURED_ERROR';
92
+ /**
93
+ * A refusal member as its error class, by core's `errorFromErrorResult`. The field names a member
94
+ * carries (`MyparcelInvalidSenderError.fields`, `MyparcelValidationError.errors`) ride
95
+ * `details[]`, one per field, so a form can mark each without matching the sentence.
96
+ */
97
+ export function myparcelRefusal(result) {
98
+ const base = errorFromErrorResult(result);
99
+ const named = Array.isArray(result.fields)
100
+ ? result.fields
101
+ : Array.isArray(result.errors)
102
+ ? result.errors
103
+ : [];
104
+ const details = named
105
+ .filter((field) => typeof field === 'string' && field.trim() !== '')
106
+ .map((field) => ({ field, code: base.code, message: base.message }));
107
+ if (details.length === 0)
108
+ return base;
109
+ return errorForStatus(base.status, {
110
+ code: base.code,
111
+ message: base.message,
112
+ service: 'vendure',
113
+ details,
114
+ });
115
+ }
116
+ function settled(answer) {
117
+ if (isErrorResult(answer))
118
+ throw myparcelRefusal(answer);
119
+ const { __typename: _typename, ...rest } = answer;
120
+ return rest;
121
+ }
122
+ export function createMyparcelModule(transport) {
123
+ const gql = (query, variables, options) => transport.graphql({ api: 'admin', query, variables }, options);
124
+ return {
125
+ config: {
126
+ async get(options) {
127
+ const data = await gql(MYPARCEL_CONFIG_QUERY, {}, options);
128
+ return data.myparcelConfig ?? null;
129
+ },
130
+ async update(input, options) {
131
+ const apiKey = typeof input?.apiKey === 'string' ? input.apiKey.trim() : '';
132
+ if (apiKey === '') {
133
+ // Never quotes the argument: a key padded with whitespace must not reach a log.
134
+ throw new TypeError('config.update needs a MyParcel API key; remove the stored one with config.remove().');
135
+ }
136
+ const data = await gql(UPDATE_MYPARCEL_CONFIG_MUTATION, { input: { apiKey } }, options);
137
+ return settled(data.updateMyparcelConfig);
138
+ },
139
+ async remove(options) {
140
+ // The wire's removal is an empty key, answered by the not-configured member.
141
+ const data = await gql(UPDATE_MYPARCEL_CONFIG_MUTATION, { input: { apiKey: '' } }, options);
142
+ const answer = data.updateMyparcelConfig;
143
+ if (isErrorResult(answer) && answer.errorCode === NOT_CONFIGURED)
144
+ return;
145
+ if (isErrorResult(answer))
146
+ throw myparcelRefusal(answer);
147
+ // An engine that answered a set-up kept it: never report that as removed.
148
+ throw new Error('MyParcel answered the set-up instead of removing it; nothing was removed.');
149
+ },
150
+ async setLabelFormat(format, options) {
151
+ const data = await gql(UPDATE_MYPARCEL_LABEL_FORMAT_MUTATION, { input: { format } }, options);
152
+ return settled(data.updateMyparcelLabelFormat);
153
+ },
154
+ async setEnabled(enabled, options) {
155
+ const data = await gql(SET_MYPARCEL_ENABLED_MUTATION, { enabled }, options);
156
+ return settled(data.setMyparcelEnabled);
157
+ },
158
+ async regenerateWebhookSecret(options) {
159
+ const data = await gql(REGENERATE_MYPARCEL_WEBHOOK_SECRET_MUTATION, {}, options);
160
+ return settled(data.regenerateMyparcelWebhookSecret);
161
+ },
162
+ },
163
+ async carriers(options) {
164
+ const data = await gql(MYPARCEL_CARRIERS_QUERY, {}, options);
165
+ return data.myparcelCarriers;
166
+ },
167
+ senders: {
168
+ async list(options) {
169
+ const data = await gql(MYPARCEL_SENDERS_QUERY, {}, options);
170
+ return data.myparcelSenderStockLocations;
171
+ },
172
+ async set(input, options) {
173
+ const data = await gql(SET_MYPARCEL_SENDER_MUTATION, { input }, options);
174
+ return settled(data.setStockLocationSender);
175
+ },
176
+ },
177
+ };
178
+ }
@@ -46,6 +46,8 @@ export interface ParcelCountSuggestion {
46
46
  * or `ReadFulfillment`. A malformed input is refused before any request with
47
47
  * `PARCEL_COUNT_INPUT_INVALID` ({@link ValidationError}); an unknown variant,
48
48
  * or another store's, is `PARCEL_COUNT_VARIANT_NOT_FOUND` (`NotFoundError`).
49
+ *
50
+ * @effect read
49
51
  */
50
52
  export type ParcelCountSuggestionMethod = (input: ParcelCountSuggestionInput, options?: Call) => Promise<ParcelCountSuggestion>;
51
53
  export declare const PARCEL_COUNT_SUGGESTION_QUERY = "\n query ParcelCountSuggestion($input: ParcelCountSuggestionInput!) {\n parcelCountSuggestion(input: $input) {\n count\n raw\n resolvable\n exact\n capped\n capacity\n maxWeightGrams\n unratedLines\n unweighedLines\n reason\n warnings\n destinationRequiresCustoms\n }\n }\n";
@@ -36,13 +36,14 @@ export interface SetParcelRuleInput {
36
36
  * change reaches another process after that cache refreshes.
37
37
  */
38
38
  export interface ParcelRuleModule {
39
+ /** @effect read */
39
40
  get(options?: Call): Promise<ParcelRule>;
41
+ /**
42
+ * @effect write
43
+ * @permission UpdateChannel
44
+ */
40
45
  set(input: SetParcelRuleInput, options?: Call): Promise<ParcelRule>;
41
46
  }
42
- /** `admin.shipping` (spec §9.2 `shipping`). */
43
- export interface ShippingModule {
44
- parcelRule: ParcelRuleModule;
45
- }
46
47
  export declare const PARCEL_RULE_QUERY = "\n query ParcelRule {\n activeChannel { \n id\n customFields {\n defaultParcelCapacity\n maxParcelWeightGrams\n }\n }\n }\n";
47
48
  export declare const SET_PARCEL_RULE_MUTATION = "\n mutation SetParcelRule($input: UpdateChannelInput!) {\n updateChannel(input: $input) {\n ... on Channel { \n id\n customFields {\n defaultParcelCapacity\n maxParcelWeightGrams\n }\n }\n ... on ErrorResult { errorCode message }\n }\n }\n";
48
- export declare function createShippingModule(transport: Transport): ShippingModule;
49
+ export declare function createParcelRuleModule(transport: Transport): ParcelRuleModule;
@@ -58,34 +58,32 @@ function customFieldsOf(input) {
58
58
  }
59
59
  return fields;
60
60
  }
61
- export function createShippingModule(transport) {
61
+ export function createParcelRuleModule(transport) {
62
62
  const get = async (options) => {
63
63
  const data = await transport.graphql({ api: 'admin', query: PARCEL_RULE_QUERY }, options);
64
64
  return toRule(data.activeChannel);
65
65
  };
66
66
  return {
67
- parcelRule: {
68
- get,
69
- async set(input, options) {
70
- assertBound('defaultParcelCapacity', input?.defaultParcelCapacity, PARCEL_CAPACITY_MAX, 'items');
71
- assertBound('maxParcelWeightGrams', input?.maxParcelWeightGrams, PARCEL_WEIGHT_GRAMS_MAX, 'grams');
72
- const customFields = customFieldsOf(input ?? {});
73
- if (Object.keys(customFields).length === 0) {
74
- throw invalid('input', 'Pass defaultParcelCapacity and/or maxParcelWeightGrams; an empty input changes nothing.');
75
- }
76
- // `updateChannel` needs the id, and the active channel is the one the
77
- // client is scoped to — read it with the SAME call options, so a
78
- // per-call tenant writes its own channel rather than the client's.
79
- const { channelId } = await get(options);
80
- const data = await transport.graphql({
81
- api: 'admin',
82
- query: SET_PARCEL_RULE_MUTATION,
83
- variables: { input: { id: channelId, customFields } },
84
- }, options);
85
- if (isErrorResult(data.updateChannel))
86
- throw errorFromErrorResult(data.updateChannel);
87
- return toRule(data.updateChannel);
88
- },
67
+ get,
68
+ async set(input, options) {
69
+ assertBound('defaultParcelCapacity', input?.defaultParcelCapacity, PARCEL_CAPACITY_MAX, 'items');
70
+ assertBound('maxParcelWeightGrams', input?.maxParcelWeightGrams, PARCEL_WEIGHT_GRAMS_MAX, 'grams');
71
+ const customFields = customFieldsOf(input ?? {});
72
+ if (Object.keys(customFields).length === 0) {
73
+ throw invalid('input', 'Pass defaultParcelCapacity and/or maxParcelWeightGrams; an empty input changes nothing.');
74
+ }
75
+ // `updateChannel` needs the id, and the active channel is the one the
76
+ // client is scoped to — read it with the SAME call options, so a
77
+ // per-call tenant writes its own channel rather than the client's.
78
+ const { channelId } = await get(options);
79
+ const data = await transport.graphql({
80
+ api: 'admin',
81
+ query: SET_PARCEL_RULE_MUTATION,
82
+ variables: { input: { id: channelId, customFields } },
83
+ }, options);
84
+ if (isErrorResult(data.updateChannel))
85
+ throw errorFromErrorResult(data.updateChannel);
86
+ return toRule(data.updateChannel);
89
87
  },
90
88
  };
91
89
  }