@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
package/dist/client.js CHANGED
@@ -10,13 +10,19 @@ import { createAuthModule } from './auth/index.js';
10
10
  import { createBulkModule } from './bulk/index.js';
11
11
  import { createCatalogModule } from './catalog/index.js';
12
12
  import { createComplianceModule } from './compliance/index.js';
13
+ import { createContentAssetsModule } from './content/assets.js';
13
14
  import { createFormsModule } from './content/forms.js';
15
+ import { createContentItemsModule } from './content/items.js';
16
+ import { createContentMenusModule } from './content/menus.js';
17
+ import { createContentStringsModule } from './content/strings.js';
18
+ import { createContentFieldsModule, createContentPageValuesModule, createContentTypesModule, } from './content/types.js';
14
19
  import { createCustomObjectsModule } from './custom-objects/index.js';
15
20
  import { createCustomersModule } from './customers/index.js';
16
21
  import { createDocumentsModule } from './documents/index.js';
17
22
  import { createEventsModule } from './events/index.js';
18
23
  import { createFeedsModule } from './feeds/index.js';
19
24
  import { createFulfillmentsModule } from './fulfillments/index.js';
25
+ import { createGeoModule } from './geo/index.js';
20
26
  import { createHeadsModule } from './heads/index.js';
21
27
  import { createHooksModule } from './hooks/index.js';
22
28
  import { createIntegrationsModule } from './integrations/index.js';
@@ -26,34 +32,46 @@ import { createMetaModule } from './meta/index.js';
26
32
  import { createMetafieldsModule } from './metafields/index.js';
27
33
  import { createOrdersModule } from './orders/index.js';
28
34
  import { createPaymentsModule } from './payments/index.js';
35
+ import { createPickupsModule } from './pickups/index.js';
29
36
  import { createPlatformAppsModule } from './platform/apps.js';
30
37
  import { createPlatformCatalogModule } from './platform/catalog.js';
38
+ import { createPlatformChannelsModule } from './platform/channels.js';
39
+ import { createPlatformEmailGatewaysModule, } from './platform/email-gateways.js';
31
40
  import { createPlatformEntitlementsModule, } from './platform/entitlements.js';
41
+ import { createPlatformGeoModule } from './platform/geo.js';
32
42
  import { createPlatformLegalEntitiesModule, } from './platform/legal-entities.js';
33
43
  import { createPlatformOrganizationsModule, } from './platform/organizations.js';
34
44
  import { createPlatformModule } from './platform/provision-store.js';
35
45
  import { createPlatformReportsModule } from './platform/reports.js';
36
46
  import { createPlatformServerMetricsModule, } from './platform/server-metrics.js';
47
+ import { createPlatformTaxModule } from './platform/tax.js';
37
48
  import { createPosModule } from './pos/index.js';
38
49
  import { createPricingModule } from './pricing/index.js';
39
50
  import { createProvenanceModule } from './provenance/index.js';
51
+ import { createPurchasingModule } from './purchasing/index.js';
52
+ import { createQuotesModule } from './quotes/index.js';
40
53
  import { createReportsModule } from './reports/index.js';
41
54
  import { createReturnsModule } from './returns/index.js';
42
55
  import { createSearchModule } from './search/index.js';
56
+ import { createSeoConfigModule } from './seo/config.js';
43
57
  import { createRedirectsModule } from './seo/redirects.js';
44
- import { createParcelCountSuggestion, } from './shipping/parcel-count-suggestion.js';
45
- import { createShippingModule } from './shipping/parcel-rule.js';
58
+ import { createSeoSettingsModule } from './seo/settings.js';
59
+ import { createShippingModule } from './shipping/index.js';
46
60
  import { createStockModule } from './stock/index.js';
47
61
  import { createStoredValueModule } from './stored-value/index.js';
62
+ import { createSubscriptionsModule } from './subscriptions/index.js';
48
63
  import { createTaxModule } from './tax/index.js';
49
64
  import { createCapabilitiesModule } from './tenant/capabilities.js';
50
65
  import { createChannelsModule } from './tenant/channels.js';
66
+ import { createEmailStyleModule } from './tenant/email-style.js';
67
+ import { createEmailTemplatesModule } from './tenant/email-templates.js';
51
68
  import { createTenantEntitlementsReader, } from './tenant/entitlements.js';
52
69
  import { createFieldGroupOwnersReader, createFieldGroupSyncSourcesReader, } from './tenant/field-groups.js';
53
70
  import { createLegalEntityModule } from './tenant/legal-entity.js';
54
71
  import { createNotificationsModule } from './tenant/notifications.js';
55
72
  import { createRetentionModule } from './tenant/retention.js';
56
73
  import { createSettingsSourcesModule, } from './tenant/settings-sources.js';
74
+ import { createTenantTimeZoneReader } from './tenant/time-zone.js';
57
75
  import { createUploadsModule } from './uploads/index.js';
58
76
  import { createUsersModule } from './users/index.js';
59
77
  /**
@@ -324,14 +342,15 @@ function buildClient(config, overrides, resolver, shared, credential) {
324
342
  throw credentialMissing();
325
343
  return { kind: 'bearer', token };
326
344
  }
327
- const sent = store.read();
328
345
  return {
329
346
  kind: 'bearer',
330
- token: sent,
347
+ token: store.read(),
331
348
  onToken: (rotated) => {
332
- // Only while the slot still holds what THIS call sent. A `logout()`
333
- // that landed meanwhile cleared it, and a rotation for the session
334
- // that ended must not re-arm the one that replaced it.
349
+ // `core` calls this only while the slot still holds what THIS call
350
+ // sent (it re-reads this principal, i.e. the caller's own store), or
351
+ // for `login`, which starts a session. A `logout()` that landed
352
+ // meanwhile cleared the slot, and a rotation for the session that
353
+ // ended must not re-arm the one that replaced it.
335
354
  //
336
355
  // Keyed on the bearer, never on a per-client counter: the session
337
356
  // store is the CALLER's, and on the documented one-client-per-server
@@ -339,8 +358,6 @@ function buildClient(config, overrides, resolver, shared, credential) {
339
358
  // process, so one administrator's sign-out discarded the bearer
340
359
  // another administrator's concurrent sign-in had just been issued —
341
360
  // reported to them as "the engine returned no vendure-auth-token".
342
- if (store.read() !== sent)
343
- return;
344
361
  store.write(rotated);
345
362
  shared.rotations += 1;
346
363
  },
@@ -395,7 +412,16 @@ function buildClient(config, overrides, resolver, shared, credential) {
395
412
  audit: createAuditModule(transport),
396
413
  catalog: createCatalogModule(transport),
397
414
  channels: createChannelsModule(resolver),
398
- content: { forms: createFormsModule(transport) },
415
+ content: {
416
+ forms: createFormsModule(transport),
417
+ types: createContentTypesModule(transport),
418
+ fields: createContentFieldsModule(transport),
419
+ pageValues: createContentPageValuesModule(transport),
420
+ items: createContentItemsModule(transport),
421
+ assets: createContentAssetsModule(transport),
422
+ menus: createContentMenusModule(transport),
423
+ strings: createContentStringsModule(transport),
424
+ },
399
425
  fulfillments: createFulfillmentsModule(transport),
400
426
  heads: createHeadsModule(transport),
401
427
  jobs: jobsModule,
@@ -405,9 +431,13 @@ function buildClient(config, overrides, resolver, shared, credential) {
405
431
  metafields: createMetafieldsModule(transport),
406
432
  orders: createOrdersModule(transport),
407
433
  payments: createPaymentsModule(transport),
434
+ pickups: createPickupsModule(transport),
408
435
  pos: createPosModule(transport),
409
436
  pricing: createPricingModule(transport),
410
437
  provenance: createProvenanceModule(transport),
438
+ purchasing: createPurchasingModule(transport),
439
+ quotes: createQuotesModule(transport),
440
+ subscriptions: createSubscriptionsModule(transport),
411
441
  reports: createReportsModule(transport, bulkModule, jobsModule, () => tenant.location),
412
442
  returns: createReturnsModule(transport),
413
443
  documents: createDocumentsModule(transport),
@@ -417,12 +447,14 @@ function buildClient(config, overrides, resolver, shared, credential) {
417
447
  customers: createCustomersModule(transport),
418
448
  compliance: createComplianceModule(transport),
419
449
  feeds: createFeedsModule(transport),
450
+ geo: createGeoModule(transport),
420
451
  search: createSearchModule(transport),
421
- seo: { redirects: createRedirectsModule(transport) },
422
- shipping: {
423
- ...createShippingModule(transport),
424
- parcelCountSuggestion: createParcelCountSuggestion(transport),
452
+ seo: {
453
+ redirects: createRedirectsModule(transport),
454
+ settings: createSeoSettingsModule(transport),
455
+ config: createSeoConfigModule(transport),
425
456
  },
457
+ shipping: createShippingModule(transport),
426
458
  stock: createStockModule(transport),
427
459
  storedValue: createStoredValueModule(transport),
428
460
  tax: createTaxModule(transport),
@@ -435,18 +467,25 @@ function buildClient(config, overrides, resolver, shared, credential) {
435
467
  fieldGroupSyncSources: createFieldGroupSyncSourcesReader(transport),
436
468
  retention: createRetentionModule(transport),
437
469
  notifications: createNotificationsModule(transport),
470
+ emailStyle: createEmailStyleModule(transport),
471
+ emailTemplates: createEmailTemplatesModule(transport),
438
472
  settingsSources: createSettingsSourcesModule(transport),
439
473
  legalEntity: createLegalEntityModule(transport),
474
+ timeZone: createTenantTimeZoneReader(transport),
440
475
  },
441
476
  platform: {
442
477
  ...createPlatformModule(transport, config),
443
478
  apps: createPlatformAppsModule(transport, config),
444
479
  catalog: createPlatformCatalogModule(transport, config),
480
+ channels: createPlatformChannelsModule(transport, config),
445
481
  entitlements: createPlatformEntitlementsModule(transport, config),
482
+ emailGateways: createPlatformEmailGatewaysModule(transport, config),
483
+ geo: createPlatformGeoModule(transport, config),
446
484
  legalEntities: createPlatformLegalEntitiesModule(transport, config),
447
485
  organizations: createPlatformOrganizationsModule(transport, config),
448
486
  reports: createPlatformReportsModule(transport, config),
449
487
  serverMetrics: createPlatformServerMetricsModule(transport, config),
488
+ tax: createPlatformTaxModule(transport, config),
450
489
  },
451
490
  withTenant(next) {
452
491
  // `mergeTenant`, not a spread: it merges `actor` FIELD BY FIELD, so a
@@ -0,0 +1,285 @@
1
+ import { type Page, type Transport } from '@sixtyninecommerce/core';
2
+ import type { Call, ListOptions } from '../types.js';
3
+ /** An image's alt text in one language. */
4
+ export interface ContentAssetTranslation {
5
+ languageCode: string;
6
+ altText: string;
7
+ }
8
+ /** One scaled copy of an image: the original format and WebP. */
9
+ export interface ContentAssetPresetUrls {
10
+ url: string;
11
+ webpUrl: string;
12
+ }
13
+ /**
14
+ * A file in the store's media library (the CMS's assets): what a content item's image, file or
15
+ * video field refers to.
16
+ *
17
+ * `storageKey` is where the bytes live, under the store's own prefix (`{store code}/content/…`):
18
+ * a content field stores it, and a storefront resolves it to a URL. The platform chooses it from
19
+ * the store the call is made for; no call here takes one.
20
+ */
21
+ export interface ContentAsset {
22
+ id: string;
23
+ channelId: string;
24
+ /** The folder it sits in; null at the top level. */
25
+ folderId: string | null;
26
+ /** The stored file name, made safe for a URL. */
27
+ filename: string;
28
+ /** The file name as uploaded. */
29
+ originalFilename: string;
30
+ mimeType: string;
31
+ /** Bytes. */
32
+ fileSize: number;
33
+ storageKey: string;
34
+ contentHash: string | null;
35
+ /** Pixels; null for a file that is not an image, or one the CMS could not measure. */
36
+ width: number | null;
37
+ height: number | null;
38
+ /** The alt text in no particular language; see `translations` for the per-language ones. */
39
+ altText: string | null;
40
+ /** Stored verbatim: its keys are never case-converted. */
41
+ metadata: Record<string, unknown> | null;
42
+ /**
43
+ * The scaled copies of a raster image, by preset name (`xxs` … `xl`); null for any other file.
44
+ * They are made in the background after an upload, so a URL can answer 404 for a few seconds.
45
+ */
46
+ presets: Record<string, ContentAssetPresetUrls> | null;
47
+ /** The alt text per language, as `update` last wrote each one. */
48
+ translations: ContentAssetTranslation[];
49
+ createdAt: string;
50
+ updatedAt: string;
51
+ [extra: string]: unknown;
52
+ }
53
+ /** A folder of the media library. */
54
+ export interface ContentAssetFolder {
55
+ id: string;
56
+ channelId: string;
57
+ name: string;
58
+ /** The folder it sits in; null at the top level. */
59
+ parentId: string | null;
60
+ createdAt: string;
61
+ updatedAt: string;
62
+ /** Its direct subfolders: answered by `folders.get` only. */
63
+ children?: ContentAssetFolder[];
64
+ [extra: string]: unknown;
65
+ }
66
+ export interface ContentAssetListOptions extends ListOptions {
67
+ /** Only the files in this folder; `null` for the ones in no folder. */
68
+ folderId?: string | null;
69
+ /** Only the files whose MIME type starts with this (`image/`, `application/pdf`). */
70
+ mimeType?: string;
71
+ /**
72
+ * Full-text search over the file names and the alt text; the results come in relevance order,
73
+ * filtered by `mimeType` and `folderId` as a list is. (A CMS before 2026-10-14 matched a search's
74
+ * `mimeType` exactly, so a prefix found nothing, and ignored `folderId: null`.)
75
+ */
76
+ search?: string;
77
+ }
78
+ /** What `upload` sends: the file and where it goes. */
79
+ export interface UploadContentAssetInput {
80
+ file: Blob;
81
+ /**
82
+ * The name the file is stored under. Required unless `file` is a `File` (which carries its
83
+ * own): a bare Blob would otherwise be stored as "blob".
84
+ */
85
+ fileName?: string;
86
+ /** A folder of the store; the top level when omitted. */
87
+ folderId?: string;
88
+ altText?: string;
89
+ }
90
+ /** What `uploadFromUrl` sends. */
91
+ export interface UploadContentAssetFromUrlInput {
92
+ /** An `http` or `https` URL the CMS fetches the file from. */
93
+ url: string;
94
+ /** A folder of the store; the top level when omitted. */
95
+ folderId?: string;
96
+ altText?: string;
97
+ }
98
+ /** The members `update` acts on; an absent key leaves the stored value alone. */
99
+ export interface UpdateContentAssetInput {
100
+ /**
101
+ * Moves the file into this folder of the store; `null` to the top level. A CMS older than the
102
+ * platform release that fixed it (headless W10-6) answers the update and keeps the file where
103
+ * it was.
104
+ */
105
+ folderId?: string | null;
106
+ /** At most 255 characters; `null` clears it. */
107
+ altText?: string | null;
108
+ /** Replaces the stored metadata, sent verbatim; `null` clears it. */
109
+ metadata?: Record<string, unknown> | null;
110
+ /**
111
+ * The alt text of each named language (at most 500 characters), written as given. A language
112
+ * left out keeps the alt text it had: nothing here removes one.
113
+ */
114
+ translations?: readonly ContentAssetTranslation[];
115
+ }
116
+ export interface CreateContentAssetFolderInput {
117
+ /** At most 255 characters. */
118
+ name: string;
119
+ /** A folder of the store to create it in; the top level when omitted. */
120
+ parentId?: string;
121
+ }
122
+ export interface UpdateContentAssetFolderInput {
123
+ name?: string;
124
+ /**
125
+ * Moves the folder into another of the store's folders; `null` to the top level. A CMS older
126
+ * than the platform release of headless W10-6 moves it but answers `parentId: null`.
127
+ */
128
+ parentId?: string | null;
129
+ }
130
+ export interface ListContentAssetFoldersOptions extends Call {
131
+ /** The folders inside this one; the top-level folders when omitted. */
132
+ parentId?: string;
133
+ }
134
+ /**
135
+ * The folders of the media library. Reads need `ReadCmsAsset`; writes the permission each method
136
+ * names.
137
+ */
138
+ export interface ContentAssetFoldersModule {
139
+ /**
140
+ * Every folder directly inside `parentId` (the top level when omitted), ordered by name. The
141
+ * CMS answers them whole: there is no page.
142
+ *
143
+ * @effect read
144
+ * @permission ReadCmsAsset
145
+ */
146
+ list(options?: ListContentAssetFoldersOptions): Promise<ContentAssetFolder[]>;
147
+ /**
148
+ * One folder with its direct subfolders (`children`). `NotFoundError` for a folder this store
149
+ * does not hold.
150
+ *
151
+ * @effect read
152
+ * @permission ReadCmsAsset
153
+ */
154
+ get(id: string, options?: Call): Promise<ContentAssetFolder>;
155
+ /**
156
+ * Adds a folder. A `parentId` this store does not hold is `NotFoundError`.
157
+ *
158
+ * @effect write
159
+ * @permission CreateCmsAsset
160
+ */
161
+ create(input: CreateContentAssetFolderInput, options?: Call): Promise<ContentAssetFolder>;
162
+ /**
163
+ * Renames or moves a folder. Moving it into itself or into one of its own subfolders is refused
164
+ * (`ValidationError`).
165
+ *
166
+ * @effect write
167
+ * @permission UpdateCmsAsset
168
+ */
169
+ update(id: string, input: UpdateContentAssetFolderInput, options?: Call): Promise<ContentAssetFolder>;
170
+ /**
171
+ * Removes an empty folder. One that still holds a subfolder or a file is refused
172
+ * (`ValidationError`) and nothing is removed.
173
+ *
174
+ * @effect destructive
175
+ * @permission DeleteCmsAsset
176
+ */
177
+ delete(id: string, options?: Call): Promise<void>;
178
+ }
179
+ /**
180
+ * The store's media library (the CMS's assets and folders): the files content items show.
181
+ * Product images are a different library, `catalog.assets`.
182
+ *
183
+ * Everything is scoped to the store the client is for: another store's file or folder answers
184
+ * `NotFoundError` (404, `NOT_FOUND`), as one that never existed does, and is never listed.
185
+ *
186
+ * Refusals are the CMS's problem+json, mapped by status:
187
+ * - `ValidationError` (400): a file type the platform does not accept, a file over the size limit
188
+ * the CMS is configured with, a URL it cannot fetch or that points into a private network, a
189
+ * refused input member (`VALIDATION_FAILED`, with `details[]`).
190
+ * - 413 (`PlatformError`): a multipart body over the 200 MB the upload route reads at most.
191
+ * - `PermissionDeniedError` (403): the credential lacks the method's permission on the store.
192
+ * - `NotFoundError` (404): no such file or folder in this store.
193
+ *
194
+ * `upload` sends the file through the CMS as `multipart/form-data` and is never retried: a retry
195
+ * would store it twice. For a large file, `uploads` (spec §6.11) puts it straight into storage
196
+ * instead. No write here is deduplicated: an `idempotencyKey` is sent and acts on nothing.
197
+ */
198
+ export interface ContentAssetsModule {
199
+ folders: ContentAssetFoldersModule;
200
+ /**
201
+ * The store's files, newest first, a page at a time (relevance order with `search`). Pages are
202
+ * offset-based (`Page.total` counts the matches), so `after: offsetCursor((n - 1) * size)` opens
203
+ * page `n`, and a file uploaded while a walk runs can be seen twice or not at all.
204
+ *
205
+ * @effect read
206
+ * @permission ReadCmsAsset
207
+ */
208
+ list(options?: ContentAssetListOptions): Promise<Page<ContentAsset>>;
209
+ /**
210
+ * One file. `NotFoundError` for a file this store does not hold.
211
+ *
212
+ * @effect read
213
+ * @permission ReadCmsAsset
214
+ */
215
+ get(id: string, options?: Call): Promise<ContentAsset>;
216
+ /**
217
+ * The file stored under `storageKey` (what a content field holds), or null when this store holds
218
+ * none. The same bytes uploaded twice under the same name share a key; then the newest file
219
+ * answers.
220
+ *
221
+ * @effect read
222
+ * @permission ReadCmsAsset
223
+ */
224
+ byStorageKey(storageKey: string, options?: Call): Promise<ContentAsset | null>;
225
+ /**
226
+ * Stores a file in the media library. Raster images get their scaled copies in the background.
227
+ * A file without a name is refused before anything is sent (`ValidationError`,
228
+ * `ASSET_FILE_NAME_REQUIRED`). Never retried.
229
+ *
230
+ * @effect write
231
+ * @permission CreateCmsAsset
232
+ */
233
+ upload(input: UploadContentAssetInput, options?: Call): Promise<ContentAsset>;
234
+ /**
235
+ * Has the CMS fetch a file from a public URL and store it, as `upload` would. The CMS refuses a
236
+ * URL into a private network, one that answers an error, redirects too often or takes over 30
237
+ * seconds (`ValidationError`).
238
+ *
239
+ * @effect write
240
+ * @permission CreateCmsAsset
241
+ */
242
+ uploadFromUrl(input: UploadContentAssetFromUrlInput, options?: Call): Promise<ContentAsset>;
243
+ /**
244
+ * Changes a file's folder, alt text, metadata or per-language alt text, in one transaction.
245
+ *
246
+ * @effect write
247
+ * @permission UpdateCmsAsset
248
+ */
249
+ update(id: string, input: UpdateContentAssetInput, options?: Call): Promise<ContentAsset>;
250
+ /**
251
+ * Removes the file from the library. Its bytes and scaled copies are deleted from storage too
252
+ * unless another file of the store shares them, so a content field still holding its key then
253
+ * shows nothing. Nothing in the SDK brings it back.
254
+ *
255
+ * @effect destructive
256
+ * @permission DeleteCmsAsset
257
+ */
258
+ delete(id: string, options?: Call): Promise<void>;
259
+ /**
260
+ * A URL to download the original file with, valid for one hour.
261
+ *
262
+ * @effect read
263
+ * @permission ReadCmsAsset
264
+ */
265
+ downloadUrl(id: string, options?: Call): Promise<string>;
266
+ /**
267
+ * Has the CMS fetch a file from a public URL and hand it back, storing nothing: how a browser
268
+ * gets a file it may not fetch itself (another origin) to upload somewhere else, such as
269
+ * `catalog.assets.create`. The CMS refuses what `uploadFromUrl` refuses. The `File` is named
270
+ * as the CMS names it, else after the URL's last path segment.
271
+ *
272
+ * @effect read
273
+ * @permission CreateCmsAsset
274
+ */
275
+ proxyFetch(url: string, options?: Call): Promise<File>;
276
+ }
277
+ /**
278
+ * The file name a `Content-Disposition` header carries. The CMS percent-encodes it inside a
279
+ * quoted `filename` (`attachment; filename="logo%20dark.png"`), and RFC 6266's `filename*`
280
+ * (`UTF-8''…`) is read too.
281
+ */
282
+ export declare function fileNameOfDisposition(header: string | null): string | null;
283
+ /** The URL's last path segment when it names a file (has an extension), else a generic name. */
284
+ export declare function fileNameOfUrl(url: string, mimeType: string): string;
285
+ export declare function createContentAssetsModule(transport: Transport): ContentAssetsModule;
@@ -0,0 +1,181 @@
1
+ import { createPage, offsetCursor, PLATFORM_PASSTHROUGH_KEYS, readOffsetCursor, ValidationError, } from '@sixtyninecommerce/core';
2
+ const DEFAULT_PAGE_SIZE = 50;
3
+ /** The cursor-mode opener: `after` present and empty starts the CMS's keyset walk. */
4
+ const FIRST_PAGE = '';
5
+ /** `metadata` is a stored-verbatim bag; nothing else in an asset is merchant-keyed. */
6
+ const ASSET_KEYS = PLATFORM_PASSTHROUGH_KEYS;
7
+ function assetPath(id) {
8
+ return `/assets/${encodeURIComponent(id)}`;
9
+ }
10
+ function folderPath(id) {
11
+ return `/asset-folders/${encodeURIComponent(id)}`;
12
+ }
13
+ /** A `File` without depending on the DOM lib: anything Blob-like carrying a `name`. */
14
+ function nameOf(file) {
15
+ const name = file.name;
16
+ return typeof name === 'string' && name !== '' ? name : undefined;
17
+ }
18
+ /**
19
+ * The file name a `Content-Disposition` header carries. The CMS percent-encodes it inside a
20
+ * quoted `filename` (`attachment; filename="logo%20dark.png"`), and RFC 6266's `filename*`
21
+ * (`UTF-8''…`) is read too.
22
+ */
23
+ export function fileNameOfDisposition(header) {
24
+ if (header === null)
25
+ return null;
26
+ const extended = /filename\*\s*=\s*(?:UTF-8|utf-8)''([^;]+)/.exec(header)?.[1];
27
+ const plain = /filename\s*=\s*"([^"]*)"|filename\s*=\s*([^;\s]+)/.exec(header);
28
+ const raw = extended ?? plain?.[1] ?? plain?.[2];
29
+ if (raw === undefined || raw.trim() === '')
30
+ return null;
31
+ try {
32
+ return decodeURIComponent(raw.trim());
33
+ }
34
+ catch {
35
+ return raw.trim();
36
+ }
37
+ }
38
+ /** The URL's last path segment when it names a file (has an extension), else a generic name. */
39
+ export function fileNameOfUrl(url, mimeType) {
40
+ try {
41
+ const segment = new URL(url).pathname.split('/').pop();
42
+ if (segment?.includes('.'))
43
+ return decodeURIComponent(segment);
44
+ }
45
+ catch {
46
+ // An unparseable URL or segment falls through to the generic name.
47
+ }
48
+ const subtype = mimeType.split(';')[0]?.split('/')[1]?.trim();
49
+ return `fetched-file.${subtype !== undefined && subtype !== '' ? subtype : 'bin'}`;
50
+ }
51
+ export function createContentAssetsModule(transport) {
52
+ async function listPage(offset, limit, options) {
53
+ const body = await transport.rest('cms', {
54
+ method: 'GET',
55
+ path: '/assets',
56
+ query: {
57
+ // `offset` is always sent: it keeps the CMS out of its keyset mode, which cannot search
58
+ // or open page n. Without `limit` an offset read answers the WHOLE library.
59
+ limit,
60
+ offset,
61
+ folder_id: options?.folderId === null ? 'null' : options?.folderId,
62
+ mime_type: options?.mimeType,
63
+ search: options?.search,
64
+ },
65
+ }, { ...options, preserveKeys: ASSET_KEYS });
66
+ const items = body.data ?? [];
67
+ // An offset read echoes neither the offset nor a cursor: the page is built from what THIS
68
+ // call asked for.
69
+ const total = body.pagination?.total ?? items.length;
70
+ const advanced = offset + (items.length > 0 ? items.length : limit);
71
+ const hasNext = advanced < total;
72
+ return createPage(items, { nextCursor: hasNext ? offsetCursor(advanced) : null, hasNext, total }, (cursor) => listPage(readOffsetCursor(cursor), limit, options));
73
+ }
74
+ async function writeAsset(method, path, body, options) {
75
+ const answer = await transport.rest('cms', { method, path, body }, { ...options, preserveKeys: ASSET_KEYS });
76
+ return answer.data;
77
+ }
78
+ async function folderCall(method, path, body, options) {
79
+ const answer = await transport.rest('cms', { method, path, ...(body === undefined ? {} : { body }) }, options);
80
+ return answer.data;
81
+ }
82
+ return {
83
+ folders: {
84
+ async list(options) {
85
+ // No `after`: only then does the CMS keep the folders in name order and answer them all.
86
+ const body = await transport.rest('cms', { method: 'GET', path: '/asset-folders', query: { parent_id: options?.parentId } }, options);
87
+ return body.data ?? [];
88
+ },
89
+ get(id, options) {
90
+ return folderCall('GET', folderPath(id), undefined, options);
91
+ },
92
+ create(input, options) {
93
+ return folderCall('POST', '/asset-folders', {
94
+ name: input.name,
95
+ ...(input.parentId === undefined ? {} : { parentId: input.parentId }),
96
+ }, options);
97
+ },
98
+ update(id, input, options) {
99
+ return folderCall('PATCH', folderPath(id), input, options);
100
+ },
101
+ async delete(id, options) {
102
+ await transport.rest('cms', { method: 'DELETE', path: folderPath(id), expect: 'void' }, options);
103
+ },
104
+ },
105
+ list(options) {
106
+ const limit = options?.limit ?? DEFAULT_PAGE_SIZE;
107
+ const offset = options?.after === undefined ? 0 : readOffsetCursor(options.after);
108
+ return listPage(offset, limit, options);
109
+ },
110
+ async get(id, options) {
111
+ const body = await transport.rest('cms', { method: 'GET', path: assetPath(id) }, { ...options, preserveKeys: ASSET_KEYS });
112
+ return body.data;
113
+ },
114
+ async byStorageKey(storageKey, options) {
115
+ const body = await transport.rest('cms', {
116
+ method: 'GET',
117
+ path: '/assets',
118
+ // Keyset mode on purpose: it pages the ids first and then loads each file whole. An
119
+ // offset read limits the joined translation rows instead, so `limit: 1` there would
120
+ // answer the file with one of its translations.
121
+ query: { storage_key: storageKey, limit: 1, after: FIRST_PAGE },
122
+ }, { ...options, preserveKeys: ASSET_KEYS });
123
+ return body.data?.[0] ?? null;
124
+ },
125
+ async upload(input, options) {
126
+ const fileName = input.fileName ?? nameOf(input.file);
127
+ if (fileName === undefined || fileName.trim() === '') {
128
+ throw new ValidationError({
129
+ code: 'ASSET_FILE_NAME_REQUIRED',
130
+ message: 'A file needs a name: pass fileName, or a File that carries one. A bare Blob would be stored as "blob". Nothing was sent.',
131
+ status: 400,
132
+ service: 'cms',
133
+ });
134
+ }
135
+ const fields = {};
136
+ if (input.folderId !== undefined)
137
+ fields.folder_id = input.folderId;
138
+ if (input.altText !== undefined)
139
+ fields.alt_text = input.altText;
140
+ const answer = await transport.rest('cms', {
141
+ method: 'POST',
142
+ path: '/assets/upload',
143
+ multipart: { fields, files: [{ field: 'file', file: input.file, fileName }] },
144
+ }, { ...options, preserveKeys: ASSET_KEYS });
145
+ return answer.data;
146
+ },
147
+ uploadFromUrl(input, options) {
148
+ return writeAsset('POST', '/assets/upload-from-url', {
149
+ url: input.url,
150
+ ...(input.folderId === undefined ? {} : { folderId: input.folderId }),
151
+ ...(input.altText === undefined ? {} : { altText: input.altText }),
152
+ }, options);
153
+ },
154
+ update(id, input, options) {
155
+ return writeAsset('PATCH', assetPath(id), {
156
+ ...input,
157
+ ...(input.translations === undefined
158
+ ? {}
159
+ : {
160
+ translations: input.translations.map(({ languageCode, altText }) => ({
161
+ languageCode,
162
+ altText,
163
+ })),
164
+ }),
165
+ }, options);
166
+ },
167
+ async delete(id, options) {
168
+ await transport.rest('cms', { method: 'DELETE', path: assetPath(id), expect: 'void' }, options);
169
+ },
170
+ async downloadUrl(id, options) {
171
+ const body = await transport.rest('cms', { method: 'GET', path: `${assetPath(id)}/download-url` }, options);
172
+ return body.data.url;
173
+ },
174
+ async proxyFetch(url, options) {
175
+ const answer = await transport.rest('cms', { method: 'POST', path: '/assets/proxy-fetch', body: { url }, expect: 'blob' }, options);
176
+ const type = answer.blob.type || (answer.contentType ?? '');
177
+ const name = fileNameOfDisposition(answer.contentDisposition) ?? fileNameOfUrl(url, type);
178
+ return new File([answer.blob], name, { type });
179
+ },
180
+ };
181
+ }