@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.
- package/README.md +5772 -118
- package/dist/auth/index.d.ts +7 -1
- package/dist/auth/index.js +8 -1
- package/dist/catalog/assets.d.ts +120 -8
- package/dist/catalog/assets.js +98 -12
- package/dist/catalog/collections.d.ts +279 -14
- package/dist/catalog/collections.js +246 -15
- package/dist/catalog/documents.d.ts +142 -0
- package/dist/catalog/documents.js +114 -0
- package/dist/catalog/index.d.ts +54 -6
- package/dist/catalog/index.js +10 -1
- package/dist/catalog/metadata.d.ts +244 -0
- package/dist/catalog/metadata.js +220 -0
- package/dist/catalog/products.d.ts +159 -19
- package/dist/catalog/products.js +88 -13
- package/dist/catalog/properties.d.ts +140 -14
- package/dist/catalog/properties.js +65 -1
- package/dist/catalog/recommendations.d.ts +288 -0
- package/dist/catalog/recommendations.js +237 -0
- package/dist/catalog/reviews.d.ts +381 -0
- package/dist/catalog/reviews.js +325 -0
- package/dist/catalog/types.d.ts +17 -1
- package/dist/catalog/types.js +10 -0
- package/dist/catalog/variant-find.d.ts +136 -0
- package/dist/catalog/variant-find.js +239 -0
- package/dist/catalog/variants.d.ts +293 -26
- package/dist/catalog/variants.js +164 -7
- package/dist/catalog/visibility.d.ts +38 -7
- package/dist/catalog/visibility.js +19 -1
- package/dist/client.d.ts +121 -9
- package/dist/client.js +53 -14
- package/dist/content/assets.d.ts +285 -0
- package/dist/content/assets.js +181 -0
- package/dist/content/forms.d.ts +332 -1
- package/dist/content/forms.js +140 -4
- package/dist/content/items.d.ts +292 -0
- package/dist/content/items.js +170 -0
- package/dist/content/menus.d.ts +254 -0
- package/dist/content/menus.js +70 -0
- package/dist/content/strings.d.ts +137 -0
- package/dist/content/strings.js +82 -0
- package/dist/content/types.d.ts +282 -0
- package/dist/content/types.js +100 -0
- package/dist/customers/age-verification.d.ts +66 -0
- package/dist/customers/age-verification.js +79 -0
- package/dist/customers/credit.d.ts +263 -0
- package/dist/customers/credit.js +244 -0
- package/dist/customers/delivery-preferences.d.ts +120 -0
- package/dist/customers/delivery-preferences.js +97 -0
- package/dist/customers/delivery-terms.d.ts +44 -0
- package/dist/customers/delivery-terms.js +32 -0
- package/dist/customers/groups.d.ts +207 -0
- package/dist/customers/groups.js +438 -0
- package/dist/customers/index.d.ts +462 -37
- package/dist/customers/index.js +317 -40
- package/dist/customers/invitation-status.d.ts +57 -0
- package/dist/customers/invitation-status.js +21 -0
- package/dist/customers/notes.d.ts +67 -0
- package/dist/customers/notes.js +51 -0
- package/dist/customers/notification-recipients.d.ts +97 -0
- package/dist/customers/notification-recipients.js +84 -0
- package/dist/customers/saved-lists.d.ts +42 -0
- package/dist/customers/saved-lists.js +61 -0
- package/dist/customers/vat.d.ts +83 -0
- package/dist/customers/vat.js +46 -0
- package/dist/customers/wire.d.ts +20 -0
- package/dist/customers/wire.js +35 -0
- package/dist/documents/ar.d.ts +307 -0
- package/dist/documents/ar.js +254 -0
- package/dist/documents/emails.d.ts +150 -0
- package/dist/documents/emails.js +220 -0
- package/dist/documents/index.d.ts +744 -21
- package/dist/documents/index.js +438 -24
- package/dist/documents/pdf.d.ts +2 -0
- package/dist/documents/pdf.js +11 -0
- package/dist/fulfillments/create.d.ts +167 -0
- package/dist/fulfillments/create.js +216 -0
- package/dist/fulfillments/index.d.ts +163 -11
- package/dist/fulfillments/index.js +135 -6
- package/dist/fulfillments/payment-policy.d.ts +64 -0
- package/dist/fulfillments/payment-policy.js +140 -0
- package/dist/fulfillments/warehouse.d.ts +724 -0
- package/dist/fulfillments/warehouse.js +914 -0
- package/dist/geo/index.d.ts +119 -0
- package/dist/geo/index.js +107 -0
- package/dist/index.d.ts +147 -39
- package/dist/index.js +51 -12
- package/dist/integrations/afas-actions.d.ts +234 -0
- package/dist/integrations/afas-actions.js +310 -0
- package/dist/integrations/afas-types.d.ts +483 -0
- package/dist/integrations/afas-types.js +5 -0
- package/dist/integrations/afas.d.ts +234 -0
- package/dist/integrations/afas.js +290 -0
- package/dist/integrations/connections.d.ts +103 -0
- package/dist/integrations/connections.js +55 -0
- package/dist/integrations/esp.d.ts +313 -0
- package/dist/integrations/esp.js +169 -0
- package/dist/integrations/exact-online-types.d.ts +965 -0
- package/dist/integrations/exact-online-types.js +6 -0
- package/dist/integrations/exact-online.d.ts +784 -0
- package/dist/integrations/exact-online.js +1089 -0
- package/dist/integrations/index.d.ts +44 -3
- package/dist/integrations/index.js +23 -3
- package/dist/integrations/pipeline-discoveries.d.ts +65 -0
- package/dist/integrations/pipeline-discoveries.js +65 -0
- package/dist/integrations/pipeline-keys.d.ts +13 -0
- package/dist/integrations/pipeline-keys.js +22 -0
- package/dist/integrations/pipeline-runs.d.ts +119 -0
- package/dist/integrations/pipeline-runs.js +87 -0
- package/dist/integrations/pipelines.d.ts +87 -15
- package/dist/integrations/pipelines.js +41 -22
- package/dist/integrations/price-import.d.ts +223 -0
- package/dist/integrations/price-import.js +124 -0
- package/dist/integrations/types.d.ts +367 -3
- package/dist/integrations/types.js +4 -3
- package/dist/locations/index.d.ts +66 -0
- package/dist/locations/index.js +31 -0
- package/dist/meta/index.d.ts +172 -0
- package/dist/metafields/index.d.ts +8 -1
- package/dist/metafields/index.js +10 -0
- package/dist/orders/cancel-with-money.d.ts +237 -0
- package/dist/orders/cancel-with-money.js +155 -0
- package/dist/orders/commit-edit.d.ts +23 -1
- package/dist/orders/commit-edit.js +19 -2
- package/dist/orders/deposit-policy.d.ts +3 -1
- package/dist/orders/drafts.d.ts +800 -0
- package/dist/orders/drafts.js +771 -0
- package/dist/orders/fields.d.ts +245 -0
- package/dist/orders/fields.js +188 -0
- package/dist/orders/get.d.ts +29 -19
- package/dist/orders/get.js +17 -8
- package/dist/orders/index.d.ts +66 -15
- package/dist/orders/index.js +25 -2
- package/dist/orders/lifecycle.d.ts +128 -0
- package/dist/orders/lifecycle.js +158 -0
- package/dist/orders/line-price-preview.d.ts +7 -2
- package/dist/orders/list.d.ts +243 -0
- package/dist/orders/list.js +487 -0
- package/dist/orders/manual-discounts.d.ts +13 -5
- package/dist/orders/manual-pricing.d.ts +5 -0
- package/dist/orders/money-view.d.ts +149 -0
- package/dist/orders/money-view.js +99 -0
- package/dist/orders/order-entry.d.ts +20 -7
- package/dist/orders/plan-edit.d.ts +34 -2
- package/dist/orders/plan-edit.js +112 -11
- package/dist/orders/settings.d.ts +201 -0
- package/dist/orders/settings.js +325 -0
- package/dist/orders/status.d.ts +159 -13
- package/dist/orders/status.js +21 -0
- package/dist/orders/surcharges.d.ts +20 -1
- package/dist/orders/surcharges.js +37 -11
- package/dist/payments/account-credit.d.ts +46 -0
- package/dist/payments/account-credit.js +42 -0
- package/dist/payments/ar.d.ts +292 -0
- package/dist/payments/ar.js +223 -0
- package/dist/payments/connected-account.d.ts +47 -0
- package/dist/payments/connected-account.js +61 -0
- package/dist/payments/credit-noted-fields.d.ts +19 -0
- package/dist/payments/credit-noted-fields.js +69 -0
- package/dist/payments/customer-consent.d.ts +30 -0
- package/dist/payments/customer-consent.js +49 -0
- package/dist/payments/index.d.ts +340 -19
- package/dist/payments/index.js +151 -1
- package/dist/payments/methods.d.ts +303 -8
- package/dist/payments/methods.js +337 -7
- package/dist/payments/mollie-methods.d.ts +159 -0
- package/dist/payments/mollie-methods.js +141 -0
- package/dist/payments/payment-links.d.ts +180 -0
- package/dist/payments/payment-links.js +97 -0
- package/dist/payments/provider-keys.d.ts +150 -0
- package/dist/payments/provider-keys.js +118 -0
- package/dist/payments/providers.d.ts +86 -11
- package/dist/payments/providers.js +29 -0
- package/dist/payments/requests.d.ts +147 -0
- package/dist/payments/requests.js +93 -0
- package/dist/payments/store-credit-fields.d.ts +15 -0
- package/dist/payments/store-credit-fields.js +51 -0
- package/dist/pickups/index.d.ts +106 -0
- package/dist/pickups/index.js +108 -0
- package/dist/platform/channels.d.ts +132 -0
- package/dist/platform/channels.js +128 -0
- package/dist/platform/email-gateways.d.ts +165 -0
- package/dist/platform/email-gateways.js +78 -0
- package/dist/platform/geo.d.ts +123 -0
- package/dist/platform/geo.js +144 -0
- package/dist/platform/tax.d.ts +162 -0
- package/dist/platform/tax.js +169 -0
- package/dist/pos/anomalies.d.ts +158 -0
- package/dist/pos/anomalies.js +64 -0
- package/dist/pos/assisted-selling.d.ts +79 -0
- package/dist/pos/assisted-selling.js +38 -0
- package/dist/pos/exchanges.d.ts +108 -0
- package/dist/pos/exchanges.js +22 -0
- package/dist/pos/gift-cards.d.ts +135 -0
- package/dist/pos/gift-cards.js +47 -0
- package/dist/pos/index.d.ts +2370 -58
- package/dist/pos/index.js +854 -7
- package/dist/pos/no-receipt.d.ts +94 -0
- package/dist/pos/no-receipt.js +25 -0
- package/dist/pos/offline-sales.d.ts +228 -0
- package/dist/pos/offline-sales.js +170 -0
- package/dist/pos/pay-by-link.d.ts +143 -0
- package/dist/pos/pay-by-link.js +57 -0
- package/dist/pos/quick-keys.d.ts +103 -0
- package/dist/pos/quick-keys.js +45 -0
- package/dist/pos/reports.d.ts +360 -0
- package/dist/pos/reports.js +62 -0
- package/dist/pos/returns.d.ts +244 -0
- package/dist/pos/returns.js +83 -0
- package/dist/pricing/bulk-coupons.d.ts +139 -0
- package/dist/pricing/bulk-coupons.js +112 -0
- package/dist/pricing/index.d.ts +174 -4
- package/dist/pricing/index.js +174 -1
- package/dist/pricing/price-lists.d.ts +606 -0
- package/dist/pricing/price-lists.js +600 -0
- package/dist/purchasing/alerts.d.ts +104 -0
- package/dist/purchasing/alerts.js +88 -0
- package/dist/purchasing/backorders.d.ts +61 -0
- package/dist/purchasing/backorders.js +92 -0
- package/dist/purchasing/cost.d.ts +110 -0
- package/dist/purchasing/cost.js +86 -0
- package/dist/purchasing/index.d.ts +54 -0
- package/dist/purchasing/index.js +24 -0
- package/dist/purchasing/links.d.ts +263 -0
- package/dist/purchasing/links.js +192 -0
- package/dist/purchasing/purchase-orders.d.ts +551 -0
- package/dist/purchasing/purchase-orders.js +491 -0
- package/dist/purchasing/receipts.d.ts +396 -0
- package/dist/purchasing/receipts.js +287 -0
- package/dist/purchasing/replenishment.d.ts +281 -0
- package/dist/purchasing/replenishment.js +240 -0
- package/dist/purchasing/returns.d.ts +273 -0
- package/dist/purchasing/returns.js +229 -0
- package/dist/purchasing/settings.d.ts +152 -0
- package/dist/purchasing/settings.js +181 -0
- package/dist/purchasing/suppliers.d.ts +476 -0
- package/dist/purchasing/suppliers.js +438 -0
- package/dist/quotes/index.d.ts +518 -0
- package/dist/quotes/index.js +439 -0
- package/dist/reports/index.d.ts +71 -8
- package/dist/reports/index.js +74 -11
- package/dist/returns/index.d.ts +675 -21
- package/dist/returns/index.js +756 -11
- package/dist/search/index.d.ts +76 -1
- package/dist/search/index.js +63 -0
- package/dist/seo/config.d.ts +128 -0
- package/dist/seo/config.js +95 -0
- package/dist/seo/redirects.d.ts +125 -0
- package/dist/seo/redirects.js +60 -1
- package/dist/seo/settings.d.ts +147 -0
- package/dist/seo/settings.js +209 -0
- package/dist/shipping/definitions.d.ts +29 -0
- package/dist/shipping/definitions.js +47 -0
- package/dist/shipping/fulfillment-profiles.d.ts +174 -0
- package/dist/shipping/fulfillment-profiles.js +104 -0
- package/dist/shipping/hendriks.d.ts +97 -0
- package/dist/shipping/hendriks.js +50 -0
- package/dist/shipping/index.d.ts +54 -0
- package/dist/shipping/index.js +27 -0
- package/dist/shipping/methods.d.ts +205 -0
- package/dist/shipping/methods.js +240 -0
- package/dist/shipping/myparcel.d.ts +668 -0
- package/dist/shipping/myparcel.js +466 -0
- package/dist/shipping/parcel-count-suggestion.d.ts +2 -0
- package/dist/shipping/parcel-rule.d.ts +6 -5
- package/dist/shipping/parcel-rule.js +21 -23
- package/dist/shipping/rate-tables.d.ts +324 -0
- package/dist/shipping/rate-tables.js +390 -0
- package/dist/shipping/ship-to-countries.d.ts +75 -0
- package/dist/shipping/ship-to-countries.js +47 -0
- package/dist/stock/by-location.d.ts +86 -0
- package/dist/stock/by-location.js +94 -0
- package/dist/stock/index.d.ts +18 -4
- package/dist/stock/index.js +7 -0
- package/dist/stock/locations.d.ts +144 -0
- package/dist/stock/locations.js +168 -0
- package/dist/stock/settings.d.ts +106 -0
- package/dist/stock/settings.js +103 -0
- package/dist/stock/transfers.d.ts +386 -52
- package/dist/stock/transfers.js +222 -17
- package/dist/stored-value/index.d.ts +312 -11
- package/dist/stored-value/index.js +223 -4
- package/dist/subscriptions/index.d.ts +682 -0
- package/dist/subscriptions/index.js +815 -0
- package/dist/tax/display-policy.d.ts +105 -0
- package/dist/tax/display-policy.js +84 -0
- package/dist/tax/index.d.ts +79 -1
- package/dist/tax/index.js +52 -0
- package/dist/tenant/email-style.d.ts +102 -0
- package/dist/tenant/email-style.js +72 -0
- package/dist/tenant/email-templates.d.ts +287 -0
- package/dist/tenant/email-templates.js +271 -0
- package/dist/tenant/notifications.d.ts +23 -17
- package/dist/tenant/settings-sources.d.ts +1 -1
- package/dist/tenant/time-zone.d.ts +17 -0
- package/dist/tenant/time-zone.js +11 -0
- package/dist/types.d.ts +50 -3
- package/dist/users/index.d.ts +3 -0
- package/dist/users/index.js +2 -0
- package/dist/users/warehouses.d.ts +50 -0
- package/dist/users/warehouses.js +51 -0
- 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 {
|
|
45
|
-
import { createShippingModule } from './shipping/
|
|
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:
|
|
347
|
+
token: store.read(),
|
|
331
348
|
onToken: (rotated) => {
|
|
332
|
-
//
|
|
333
|
-
//
|
|
334
|
-
//
|
|
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: {
|
|
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: {
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
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
|
+
}
|