@sixtyninecommerce/client 0.29.0 → 0.31.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 +556 -16
- package/dist/admin/http.d.ts.map +1 -1
- package/dist/admin/http.js.map +1 -1
- package/dist/admin/types.d.ts.map +1 -1
- package/dist/build-client.d.ts +9 -0
- package/dist/build-client.d.ts.map +1 -0
- package/dist/build-client.js +58 -0
- package/dist/build-client.js.map +1 -0
- package/dist/cache-tags.d.ts +35 -1
- package/dist/cache-tags.d.ts.map +1 -1
- package/dist/cache-tags.js +39 -1
- package/dist/cache-tags.js.map +1 -1
- package/dist/client.d.ts +25 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +9 -62
- package/dist/client.js.map +1 -1
- package/dist/commerce/age-verification.d.ts +7 -4
- package/dist/commerce/age-verification.d.ts.map +1 -1
- package/dist/commerce/age-verification.js +6 -4
- package/dist/commerce/age-verification.js.map +1 -1
- package/dist/commerce/arguments.d.ts +13 -0
- package/dist/commerce/arguments.d.ts.map +1 -0
- package/dist/commerce/arguments.js +19 -0
- package/dist/commerce/arguments.js.map +1 -0
- package/dist/commerce/branding.d.ts.map +1 -1
- package/dist/commerce/branding.js.map +1 -1
- package/dist/commerce/capabilities.d.ts +40 -0
- package/dist/commerce/capabilities.d.ts.map +1 -0
- package/dist/commerce/capabilities.js +41 -0
- package/dist/commerce/capabilities.js.map +1 -0
- package/dist/commerce/cart.d.ts +9 -12
- package/dist/commerce/cart.d.ts.map +1 -1
- package/dist/commerce/cart.js +6 -1
- package/dist/commerce/cart.js.map +1 -1
- package/dist/commerce/checkout.d.ts +95 -15
- package/dist/commerce/checkout.d.ts.map +1 -1
- package/dist/commerce/checkout.js +230 -10
- package/dist/commerce/checkout.js.map +1 -1
- package/dist/commerce/customer.d.ts +82 -38
- package/dist/commerce/customer.d.ts.map +1 -1
- package/dist/commerce/customer.js +146 -10
- package/dist/commerce/customer.js.map +1 -1
- package/dist/commerce/favorites.d.ts +2 -5
- package/dist/commerce/favorites.d.ts.map +1 -1
- package/dist/commerce/favorites.js.map +1 -1
- package/dist/commerce/index.d.ts +189 -133
- package/dist/commerce/index.d.ts.map +1 -1
- package/dist/commerce/index.js +9 -0
- package/dist/commerce/index.js.map +1 -1
- package/dist/commerce/order-states.d.ts +18 -0
- package/dist/commerce/order-states.d.ts.map +1 -0
- package/dist/commerce/order-states.js +30 -0
- package/dist/commerce/order-states.js.map +1 -0
- package/dist/commerce/parcel-pricing.d.ts +48 -0
- package/dist/commerce/parcel-pricing.d.ts.map +1 -0
- package/dist/commerce/parcel-pricing.js +39 -0
- package/dist/commerce/parcel-pricing.js.map +1 -0
- package/dist/commerce/parked-orders.d.ts +22 -0
- package/dist/commerce/parked-orders.d.ts.map +1 -0
- package/dist/commerce/parked-orders.js +47 -0
- package/dist/commerce/parked-orders.js.map +1 -0
- package/dist/commerce/payments.d.ts +12 -5
- package/dist/commerce/payments.d.ts.map +1 -1
- package/dist/commerce/payments.js +10 -1
- package/dist/commerce/payments.js.map +1 -1
- package/dist/commerce/placement-error.d.ts +17 -0
- package/dist/commerce/placement-error.d.ts.map +1 -1
- package/dist/commerce/placement-error.js.map +1 -1
- package/dist/commerce/products.d.ts +92 -38
- package/dist/commerce/products.d.ts.map +1 -1
- package/dist/commerce/products.js +162 -123
- package/dist/commerce/products.js.map +1 -1
- package/dist/commerce/queries.d.ts +204 -49
- package/dist/commerce/queries.d.ts.map +1 -1
- package/dist/commerce/queries.js +1296 -737
- package/dist/commerce/queries.js.map +1 -1
- package/dist/commerce/quotes.d.ts +5 -4
- package/dist/commerce/quotes.d.ts.map +1 -1
- package/dist/commerce/quotes.js +1 -36
- package/dist/commerce/quotes.js.map +1 -1
- package/dist/commerce/recommendations.d.ts +3 -3
- package/dist/commerce/recommendations.d.ts.map +1 -1
- package/dist/commerce/recommendations.js +3 -1
- package/dist/commerce/recommendations.js.map +1 -1
- package/dist/commerce/returns.d.ts +7 -6
- package/dist/commerce/returns.d.ts.map +1 -1
- package/dist/commerce/returns.js.map +1 -1
- package/dist/commerce/reviews.d.ts +24 -15
- package/dist/commerce/reviews.d.ts.map +1 -1
- package/dist/commerce/reviews.js +67 -50
- package/dist/commerce/reviews.js.map +1 -1
- package/dist/commerce/saved-lists.d.ts +15 -15
- package/dist/commerce/saved-lists.d.ts.map +1 -1
- package/dist/commerce/saved-lists.js +67 -55
- package/dist/commerce/saved-lists.js.map +1 -1
- package/dist/commerce/search.d.ts +3 -2
- package/dist/commerce/search.d.ts.map +1 -1
- package/dist/commerce/search.js +10 -2
- package/dist/commerce/search.js.map +1 -1
- package/dist/commerce/shipping.d.ts +11 -4
- package/dist/commerce/shipping.d.ts.map +1 -1
- package/dist/commerce/shipping.js +17 -2
- package/dist/commerce/shipping.js.map +1 -1
- package/dist/commerce/stock-notifications.d.ts +2 -0
- package/dist/commerce/stock-notifications.d.ts.map +1 -1
- package/dist/commerce/stock-notifications.js +2 -2
- package/dist/commerce/stock-notifications.js.map +1 -1
- package/dist/commerce/subscriptions.d.ts +35 -37
- package/dist/commerce/subscriptions.d.ts.map +1 -1
- package/dist/commerce/subscriptions.js +159 -120
- package/dist/commerce/subscriptions.js.map +1 -1
- package/dist/commerce/vat-validation.d.ts +6 -3
- package/dist/commerce/vat-validation.d.ts.map +1 -1
- package/dist/commerce/vat-validation.js +24 -19
- package/dist/commerce/vat-validation.js.map +1 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js.map +1 -1
- package/dist/content/assets.d.ts +5 -4
- package/dist/content/assets.d.ts.map +1 -1
- package/dist/content/assets.js.map +1 -1
- package/dist/content/collection-pages.d.ts +3 -2
- package/dist/content/collection-pages.d.ts.map +1 -1
- package/dist/content/collection-pages.js.map +1 -1
- package/dist/content/collections.d.ts +5 -4
- package/dist/content/collections.d.ts.map +1 -1
- package/dist/content/collections.js.map +1 -1
- package/dist/content/filtered-products.d.ts.map +1 -1
- package/dist/content/filtered-products.js.map +1 -1
- package/dist/content/form-field-types.d.ts +3 -3
- package/dist/content/form-field-types.d.ts.map +1 -1
- package/dist/content/form-field-types.js.map +1 -1
- package/dist/content/forms.d.ts +4 -3
- package/dist/content/forms.d.ts.map +1 -1
- package/dist/content/forms.js +3 -0
- package/dist/content/forms.js.map +1 -1
- package/dist/content/index.d.ts +18 -17
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/items.d.ts +5 -4
- package/dist/content/items.d.ts.map +1 -1
- package/dist/content/items.js +2 -0
- package/dist/content/items.js.map +1 -1
- package/dist/content/menus.d.ts +3 -2
- package/dist/content/menus.d.ts.map +1 -1
- package/dist/content/menus.js +7 -1
- package/dist/content/menus.js.map +1 -1
- package/dist/content/resolve.d.ts +3 -2
- package/dist/content/resolve.d.ts.map +1 -1
- package/dist/content/resolve.js +1 -1
- package/dist/content/resolve.js.map +1 -1
- package/dist/content/sitemap.d.ts +3 -2
- package/dist/content/sitemap.d.ts.map +1 -1
- package/dist/content/sitemap.js.map +1 -1
- package/dist/content/strings.d.ts +16 -2
- package/dist/content/strings.d.ts.map +1 -1
- package/dist/content/strings.js +32 -4
- package/dist/content/strings.js.map +1 -1
- package/dist/core/context.d.ts +127 -1
- package/dist/core/context.d.ts.map +1 -1
- package/dist/core/context.js +436 -45
- package/dist/core/context.js.map +1 -1
- package/dist/core/currency.d.ts +14 -0
- package/dist/core/currency.d.ts.map +1 -0
- package/dist/core/currency.js +52 -0
- package/dist/core/currency.js.map +1 -0
- package/dist/core/deprecation.d.ts +23 -0
- package/dist/core/deprecation.d.ts.map +1 -0
- package/dist/core/deprecation.js +81 -0
- package/dist/core/deprecation.js.map +1 -0
- package/dist/core/http.d.ts +15 -1
- package/dist/core/http.d.ts.map +1 -1
- package/dist/core/http.js +55 -3
- package/dist/core/http.js.map +1 -1
- package/dist/core/public-artifact.d.ts +72 -0
- package/dist/core/public-artifact.d.ts.map +1 -0
- package/dist/core/public-artifact.js +122 -0
- package/dist/core/public-artifact.js.map +1 -0
- package/dist/core/unknown-field-rejection.d.ts +18 -0
- package/dist/core/unknown-field-rejection.d.ts.map +1 -0
- package/dist/core/unknown-field-rejection.js +37 -0
- package/dist/core/unknown-field-rejection.js.map +1 -0
- package/dist/credit/credit-status.d.ts +2 -0
- package/dist/credit/credit-status.d.ts.map +1 -1
- package/dist/credit/credit-status.js +71 -19
- package/dist/credit/credit-status.js.map +1 -1
- package/dist/credit/index.d.ts +1 -1
- package/dist/credit/payment-terms.d.ts +3 -3
- package/dist/credit/payment-terms.d.ts.map +1 -1
- package/dist/credit/payment-terms.js +28 -24
- package/dist/credit/payment-terms.js.map +1 -1
- package/dist/currency/exchange.d.ts +7 -7
- package/dist/currency/exchange.d.ts.map +1 -1
- package/dist/currency/exchange.js +5 -1
- package/dist/currency/exchange.js.map +1 -1
- package/dist/errors.d.ts +17 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +13 -0
- package/dist/errors.js.map +1 -1
- package/dist/events/index.d.ts +20 -7
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +17 -5
- package/dist/events/index.js.map +1 -1
- package/dist/events/payloads.d.ts +7 -4
- package/dist/events/payloads.d.ts.map +1 -1
- package/dist/events/payloads.js +6 -3
- package/dist/events/payloads.js.map +1 -1
- package/dist/feeds/index.d.ts +5 -0
- package/dist/feeds/index.d.ts.map +1 -0
- package/dist/feeds/index.js +12 -0
- package/dist/feeds/index.js.map +1 -0
- package/dist/feeds/types.d.ts +18 -0
- package/dist/feeds/types.d.ts.map +1 -0
- package/dist/feeds/types.js +8 -0
- package/dist/feeds/types.js.map +1 -0
- package/dist/generated/cms.d.ts +2136 -0
- package/dist/generated/cms.d.ts.map +1 -0
- package/dist/generated/cms.js +4 -0
- package/dist/generated/cms.js.map +1 -0
- package/dist/generated/plugins.d.ts +550 -0
- package/dist/generated/plugins.d.ts.map +1 -0
- package/dist/generated/plugins.js +4 -0
- package/dist/generated/plugins.js.map +1 -0
- package/dist/generated/shop.d.ts +5539 -0
- package/dist/generated/shop.d.ts.map +1 -0
- package/dist/generated/shop.js +5 -0
- package/dist/generated/shop.js.map +1 -0
- package/dist/graphql-document.d.ts +29 -0
- package/dist/graphql-document.d.ts.map +1 -0
- package/dist/graphql-document.js +21 -0
- package/dist/graphql-document.js.map +1 -0
- package/dist/index.d.ts +9 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/media/urls.d.ts.map +1 -1
- package/dist/media/urls.js +12 -1
- package/dist/media/urls.js.map +1 -1
- package/dist/media/video.d.ts.map +1 -1
- package/dist/media/video.js.map +1 -1
- package/dist/multi-store.d.ts +200 -0
- package/dist/multi-store.d.ts.map +1 -0
- package/dist/multi-store.js +558 -0
- package/dist/multi-store.js.map +1 -0
- package/dist/navigation/routes.d.ts +4 -3
- package/dist/navigation/routes.d.ts.map +1 -1
- package/dist/navigation/routes.js.map +1 -1
- package/dist/next/artifact-handler.d.ts +21 -13
- package/dist/next/artifact-handler.d.ts.map +1 -1
- package/dist/next/artifact-handler.js +28 -66
- package/dist/next/artifact-handler.js.map +1 -1
- package/dist/next/event-revalidate-handler.d.ts +26 -6
- package/dist/next/event-revalidate-handler.d.ts.map +1 -1
- package/dist/next/event-revalidate-handler.js +126 -19
- package/dist/next/event-revalidate-handler.js.map +1 -1
- package/dist/next/feed-handler.d.ts +50 -0
- package/dist/next/feed-handler.d.ts.map +1 -0
- package/dist/next/feed-handler.js +61 -0
- package/dist/next/feed-handler.js.map +1 -0
- package/dist/next/index.d.ts +3 -1
- package/dist/next/index.d.ts.map +1 -1
- package/dist/next/index.js +1 -0
- package/dist/next/index.js.map +1 -1
- package/dist/next/metadata.d.ts.map +1 -1
- package/dist/next/metadata.js.map +1 -1
- package/dist/next/redirect-middleware.d.ts +5 -31
- package/dist/next/redirect-middleware.d.ts.map +1 -1
- package/dist/next/redirect-middleware.js +4 -46
- package/dist/next/redirect-middleware.js.map +1 -1
- package/dist/next/revalidate-handler.d.ts.map +1 -1
- package/dist/next/revalidate-handler.js.map +1 -1
- package/dist/pricing/index.d.ts +1 -1
- package/dist/pricing/index.d.ts.map +1 -1
- package/dist/pricing/index.js +5 -2
- package/dist/pricing/index.js.map +1 -1
- package/dist/pricing/tax-display.js +1 -1
- package/dist/pricing/tax-display.js.map +1 -1
- package/dist/pricing/tiers.d.ts +3 -2
- package/dist/pricing/tiers.d.ts.map +1 -1
- package/dist/pricing/tiers.js.map +1 -1
- package/dist/pricing/validation.d.ts +152 -13
- package/dist/pricing/validation.d.ts.map +1 -1
- package/dist/pricing/validation.js +167 -13
- package/dist/pricing/validation.js.map +1 -1
- package/dist/redirects/index.d.ts.map +1 -1
- package/dist/redirects/index.js +2 -1
- package/dist/redirects/index.js.map +1 -1
- package/dist/redirects/store.d.ts.map +1 -1
- package/dist/redirects/store.js +6 -2
- package/dist/redirects/store.js.map +1 -1
- package/dist/redirects/types.d.ts +5 -2
- package/dist/redirects/types.d.ts.map +1 -1
- package/dist/revalidation/event-plan.d.ts +55 -4
- package/dist/revalidation/event-plan.d.ts.map +1 -1
- package/dist/revalidation/event-plan.js +115 -8
- package/dist/revalidation/event-plan.js.map +1 -1
- package/dist/revalidation/event-verify.d.ts +8 -37
- package/dist/revalidation/event-verify.d.ts.map +1 -1
- package/dist/revalidation/event-verify.js +7 -97
- package/dist/revalidation/event-verify.js.map +1 -1
- package/dist/revalidation/types.d.ts.map +1 -1
- package/dist/revalidation/url-context.d.ts +17 -0
- package/dist/revalidation/url-context.d.ts.map +1 -1
- package/dist/revalidation/url-context.js +35 -2
- package/dist/revalidation/url-context.js.map +1 -1
- package/dist/seo/ai.d.ts.map +1 -1
- package/dist/seo/ai.js.map +1 -1
- package/dist/seo/artifacts.d.ts +86 -4
- package/dist/seo/artifacts.d.ts.map +1 -1
- package/dist/seo/artifacts.js +115 -16
- package/dist/seo/artifacts.js.map +1 -1
- package/dist/seo/availability.d.ts +95 -0
- package/dist/seo/availability.d.ts.map +1 -0
- package/dist/seo/availability.js +89 -0
- package/dist/seo/availability.js.map +1 -0
- package/dist/seo/index.d.ts +4 -0
- package/dist/seo/index.d.ts.map +1 -1
- package/dist/seo/index.js +6 -1
- package/dist/seo/index.js.map +1 -1
- package/dist/seo/json-ld.d.ts.map +1 -1
- package/dist/seo/json-ld.js +34 -1
- package/dist/seo/json-ld.js.map +1 -1
- package/dist/seo/meta-tags.d.ts +40 -1
- package/dist/seo/meta-tags.d.ts.map +1 -1
- package/dist/seo/meta-tags.js +8 -1
- package/dist/seo/meta-tags.js.map +1 -1
- package/dist/seo/metadata-parser.d.ts.map +1 -1
- package/dist/seo/metadata-parser.js.map +1 -1
- package/dist/seo/metadata-types.d.ts.map +1 -1
- package/dist/seo/robots.d.ts.map +1 -1
- package/dist/seo/robots.js.map +1 -1
- package/dist/seo/types.d.ts +20 -2
- package/dist/seo/types.d.ts.map +1 -1
- package/dist/seo/url-builder.d.ts +5 -3
- package/dist/seo/url-builder.d.ts.map +1 -1
- package/dist/seo/url-builder.js +3 -1
- package/dist/seo/url-builder.js.map +1 -1
- package/dist/types.d.ts +1306 -2429
- package/dist/types.d.ts.map +1 -1
- package/dist/web/artifact-responder.d.ts +69 -0
- package/dist/web/artifact-responder.d.ts.map +1 -0
- package/dist/web/artifact-responder.js +90 -0
- package/dist/web/artifact-responder.js.map +1 -0
- package/dist/web/feed-responder.d.ts +72 -0
- package/dist/web/feed-responder.d.ts.map +1 -0
- package/dist/web/feed-responder.js +81 -0
- package/dist/web/feed-responder.js.map +1 -0
- package/dist/web/index.d.ts +23 -0
- package/dist/web/index.d.ts.map +1 -0
- package/dist/web/index.js +19 -0
- package/dist/web/index.js.map +1 -0
- package/dist/web/redirect-middleware.d.ts +76 -0
- package/dist/web/redirect-middleware.d.ts.map +1 -0
- package/dist/web/redirect-middleware.js +94 -0
- package/dist/web/redirect-middleware.js.map +1 -0
- package/dist/web/respond.d.ts +20 -0
- package/dist/web/respond.d.ts.map +1 -0
- package/dist/web/respond.js +52 -0
- package/dist/web/respond.js.map +1 -0
- package/package.json +19 -3
package/dist/core/context.js
CHANGED
|
@@ -1,10 +1,241 @@
|
|
|
1
|
-
import { createChannelResolver, PlatformError, } from '@sixtyninecommerce/core';
|
|
1
|
+
import { assertConditionalReadsOption, createChannelResolver, isBrowserRuntime, PlatformError, STOREFRONT_TOKEN_PREFIX, } from '@sixtyninecommerce/core';
|
|
2
2
|
import { DEFAULT_CMS_URL, DEFAULT_PLUGINS_URL, DEFAULT_VENDURE_URL, INIT_TIMEOUT_MS, } from '../constants.js';
|
|
3
3
|
import { StorefrontError, toStorefrontError } from '../errors.js';
|
|
4
|
+
import { CURRENCY_CODE_PATTERN } from './currency.js';
|
|
5
|
+
import { assertDeprecationHook, endpointDeprecationHook, methodDeprecationReporter, } from './deprecation.js';
|
|
4
6
|
export async function createStoreContext(config) {
|
|
7
|
+
// FIRST, before anything reaches the network: a private token in a page is a
|
|
8
|
+
// token every visitor holds, and the refusal must not depend on the CMS being
|
|
9
|
+
// up (spec §15.21).
|
|
10
|
+
assertPrivateTokenConfig(config);
|
|
5
11
|
if (!config.storeCode) {
|
|
6
12
|
throw new StorefrontError('storeCode is required', 'cms');
|
|
7
13
|
}
|
|
14
|
+
const endpoints = readClientEndpoints(config);
|
|
15
|
+
assertCustomerToken(config.customerToken);
|
|
16
|
+
assertCurrencyCode(config.currencyCode);
|
|
17
|
+
assertHeadKey(config.head, 'head');
|
|
18
|
+
assertDeprecationHook(config.onDeprecation);
|
|
19
|
+
// One resolver for the life of the client, shared with the transport: it
|
|
20
|
+
// caches the channel, collapses concurrent resolutions into one request, and
|
|
21
|
+
// — the reason it is not just this one startup call — can go BACK to the CMS
|
|
22
|
+
// when a request is refused with CHANNEL_NOT_FOUND, so a channel whose token
|
|
23
|
+
// rotated under a running storefront heals itself instead of failing until
|
|
24
|
+
// the process restarts (spec §6.2, §15.1).
|
|
25
|
+
const resolver = createClientChannelResolver(endpoints);
|
|
26
|
+
// Single startup roundtrip — the CMS /channels/by-code/:code endpoint now
|
|
27
|
+
// also returns custom_fields (proxied from Vendure with a server-side cache).
|
|
28
|
+
const startup = await resolveCoreChannel(resolver, config.storeCode, endpoints.cmsUrl);
|
|
29
|
+
// The store's code can move under a running client (a rename keeps the old one answering for
|
|
30
|
+
// a while). The follower is what the context's `channel` reads, and what the transport
|
|
31
|
+
// resolves through, so the first answer under the new code switches everything over.
|
|
32
|
+
const follower = createRenameFollower(resolver, config.storeCode, startup, renameReporter(config.onStoreRenamed));
|
|
33
|
+
const channels = follower.channels;
|
|
34
|
+
const onEndpointDeprecation = endpointDeprecationHook(config.onDeprecation);
|
|
35
|
+
const ctx = assembleStoreContext(endpoints, follower.current(), channels, {
|
|
36
|
+
languageCode: config.defaultLanguageCode,
|
|
37
|
+
currencyCode: config.currencyCode,
|
|
38
|
+
authToken: config.customerToken,
|
|
39
|
+
privateToken: config.privateToken,
|
|
40
|
+
buyerIp: config.buyerIp,
|
|
41
|
+
orderScope: config.orderScope,
|
|
42
|
+
head: config.head,
|
|
43
|
+
onAuthToken: config.onAuthToken,
|
|
44
|
+
onAuthExpired: config.onAuthExpired,
|
|
45
|
+
onAuthCleared: config.onAuthCleared,
|
|
46
|
+
}, {
|
|
47
|
+
...(onEndpointDeprecation ? { onDeprecation: onEndpointDeprecation } : {}),
|
|
48
|
+
reportDeprecatedMethod: methodDeprecationReporter(config.onDeprecation),
|
|
49
|
+
});
|
|
50
|
+
// A getter over the follower: every reader — the transport's tenant, the feed and sitemap
|
|
51
|
+
// URLs, the asset-path prefix, the cache tags — sees the store's CURRENT code. No setter
|
|
52
|
+
// (`StoreContext.channel` is readonly); configurable, so a test double can still redefine it.
|
|
53
|
+
Object.defineProperty(ctx, 'channel', {
|
|
54
|
+
get: () => follower.current(),
|
|
55
|
+
enumerable: true,
|
|
56
|
+
configurable: true,
|
|
57
|
+
});
|
|
58
|
+
return ctx;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Who hears that a store was renamed. A configured `onStoreRenamed` is called once per client
|
|
62
|
+
* for each rename and may not throw into a request; without one the client warns ONCE PER
|
|
63
|
+
* PROCESS for each rename (several clients of one store in one process say it once).
|
|
64
|
+
* `audience` picks the warning: a single-store client follows the new code, a store router
|
|
65
|
+
* keeps the code `resolveStore` names.
|
|
66
|
+
*
|
|
67
|
+
* `instance` tells occurrences of the same pair of codes apart. A single-store client reports
|
|
68
|
+
* only when it actually switches, so it passes the alias's `renamedAt` (stamped afresh on every
|
|
69
|
+
* alias row the CMS writes): a rename undone, submitted again and undone again is heard each
|
|
70
|
+
* time. A router reports on every request that reaches an old code and never switches, so it
|
|
71
|
+
* passes the window's end, which a rewritten row keeps. A switch-back ("no longer answers") is
|
|
72
|
+
* never swallowed by another client's warning: a client says it whenever IT goes back, since
|
|
73
|
+
* its last word must not name a dead code.
|
|
74
|
+
*/
|
|
75
|
+
export function renameReporter(onStoreRenamed, audience = 'client') {
|
|
76
|
+
const told = new Set();
|
|
77
|
+
return (rename, instance) => {
|
|
78
|
+
const key = [
|
|
79
|
+
rename.previousCode,
|
|
80
|
+
rename.code,
|
|
81
|
+
rename.previousCodeGone ? 'gone' : 'renamed',
|
|
82
|
+
instance,
|
|
83
|
+
].join('\u0000');
|
|
84
|
+
if (onStoreRenamed) {
|
|
85
|
+
if (told.has(key))
|
|
86
|
+
return;
|
|
87
|
+
told.add(key);
|
|
88
|
+
const failed = (error) => {
|
|
89
|
+
console.warn(`[@sixtyninecommerce/client] the onStoreRenamed handler threw for "${rename.previousCode}" -> "${rename.code}"`, error);
|
|
90
|
+
};
|
|
91
|
+
try {
|
|
92
|
+
// An async handler's rejection is caught too: left alone it is an unhandled rejection,
|
|
93
|
+
// which ends a Node process.
|
|
94
|
+
void Promise.resolve(onStoreRenamed(rename)).catch(failed);
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
failed(error);
|
|
98
|
+
}
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const warned = `${audience}\u0000${key}`;
|
|
102
|
+
if (WARNED_RENAMES.has(warned) && !rename.previousCodeGone)
|
|
103
|
+
return;
|
|
104
|
+
WARNED_RENAMES.add(warned);
|
|
105
|
+
console.warn(renameWarning(rename, audience));
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/** Process-wide: the default warning is said once per rename, however many clients see it. */
|
|
109
|
+
const WARNED_RENAMES = new Set();
|
|
110
|
+
/**
|
|
111
|
+
* What the default reporter says. The end is the exact instant, in UTC: the old code stops at
|
|
112
|
+
* the rename's time of day, and a bare date reads as "through that day" in every zone.
|
|
113
|
+
*/
|
|
114
|
+
export function renameWarning(rename, audience = 'client') {
|
|
115
|
+
const { previousCode: from, code: to } = rename;
|
|
116
|
+
if (rename.previousCodeGone) {
|
|
117
|
+
return `[@sixtyninecommerce/client] Store code "${from}" no longer answers; this client found the store under "${to}" by itself. Configure storeCode: "${to}".`;
|
|
118
|
+
}
|
|
119
|
+
const until = rename.previousCodeUntil
|
|
120
|
+
? `until ${rename.previousCodeUntil} (UTC) only`
|
|
121
|
+
: 'for a limited time only';
|
|
122
|
+
const head = `[@sixtyninecommerce/client] Store "${from}" was renamed to "${to}".`;
|
|
123
|
+
if (audience === 'router') {
|
|
124
|
+
return `${head} This router serves "${from}" as that store while "${from}" still answers, ${until}; after that "${from}" finds no store, or another store that takes the code, in this process too. Update resolveStore (and any stores / privateToken entries) to "${to}".`;
|
|
125
|
+
}
|
|
126
|
+
return `${head} This client switched to "${to}" by itself; "${from}" keeps answering ${until}. Configure storeCode: "${to}".`;
|
|
127
|
+
}
|
|
128
|
+
/** Which rename an old-code answer belongs to (see {@link renameReporter}). */
|
|
129
|
+
export function renameInstance(info) {
|
|
130
|
+
return info.renamedAt ?? info.previousCodeUntil ?? '';
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* The store's current channel, following renames.
|
|
134
|
+
*
|
|
135
|
+
* `code` is the code the client now uses; it starts as whatever the startup answer carried (the
|
|
136
|
+
* new code already, when the client was configured with an old one). The wrapped resolver
|
|
137
|
+
* watches every answer for THAT code: one that names a different code is the platform
|
|
138
|
+
* answering an old code for its renamed store, and from then on the client asks under the new
|
|
139
|
+
* code — so it keeps working after the old one stops answering. Answers for any other code
|
|
140
|
+
* (a call already in flight under the old one) change nothing.
|
|
141
|
+
*
|
|
142
|
+
* The record moves ONLY on such a switch, never on a TTL re-read of the same code: a re-read can
|
|
143
|
+
* be the CMS's degraded answer (empty custom fields while its Vendure call fails), and the
|
|
144
|
+
* startup snapshot is what `ctx.channel` always was. The transport does not read the token from
|
|
145
|
+
* here; it resolves `ctx.channel.code` through `channels`, so a rotated token still heals.
|
|
146
|
+
*
|
|
147
|
+
* A switch is undone only when the new code stops answering while the code it came from
|
|
148
|
+
* answers as the SAME channel (see `fallBack`).
|
|
149
|
+
*/
|
|
150
|
+
function createRenameFollower(inner, configuredCode, startup, report) {
|
|
151
|
+
let code = configuredCode;
|
|
152
|
+
let record = toChannelInfo(startup);
|
|
153
|
+
/** The codes this client switched away from, the latest last. */
|
|
154
|
+
const left = [];
|
|
155
|
+
const observe = (asked, info) => {
|
|
156
|
+
if (asked !== code || info.code === asked)
|
|
157
|
+
return;
|
|
158
|
+
left.push(asked);
|
|
159
|
+
code = info.code;
|
|
160
|
+
// An alias answer is the CMS's proven one: it follows an alias only after Vendure confirmed
|
|
161
|
+
// a storefront, so its custom fields are real.
|
|
162
|
+
record = toChannelInfo(info);
|
|
163
|
+
report({
|
|
164
|
+
previousCode: asked,
|
|
165
|
+
code: info.code,
|
|
166
|
+
...(info.previousCodeUntil ? { previousCodeUntil: info.previousCodeUntil } : {}),
|
|
167
|
+
}, renameInstance(info));
|
|
168
|
+
};
|
|
169
|
+
observe(configuredCode, startup);
|
|
170
|
+
// The code this client switched to is gone. A rename that failed after its CMS step answered
|
|
171
|
+
// the old code under the new one for seconds, then put the old code back: without this the
|
|
172
|
+
// client would ask for the dead code until restarted. Ask the code it switched from once more,
|
|
173
|
+
// and take the answer ONLY when it is the same channel — by now that code may name another
|
|
174
|
+
// store. Otherwise the original refusal stands.
|
|
175
|
+
const fallBack = async (dead, refusal) => {
|
|
176
|
+
const from = left.at(-1);
|
|
177
|
+
if (from === undefined)
|
|
178
|
+
throw refusal;
|
|
179
|
+
inner.invalidate(from);
|
|
180
|
+
const info = await inner.resolve(from).catch(() => {
|
|
181
|
+
throw refusal;
|
|
182
|
+
});
|
|
183
|
+
if (info.id !== record.id)
|
|
184
|
+
throw refusal;
|
|
185
|
+
// Two requests refused at once both get here: the first moved the client, the second only
|
|
186
|
+
// needs the answer to retry with.
|
|
187
|
+
if (code !== dead)
|
|
188
|
+
return info;
|
|
189
|
+
if (info.code === from)
|
|
190
|
+
left.pop();
|
|
191
|
+
// Per client, the undo of the switch the record came from.
|
|
192
|
+
const undone = renameInstance(record);
|
|
193
|
+
code = info.code;
|
|
194
|
+
// Only the identity moves. An exact-code answer carries no proof the CMS reached Vendure
|
|
195
|
+
// (its degraded answer has empty custom fields), and the store's settings did not change
|
|
196
|
+
// with its code.
|
|
197
|
+
const { previousCode: _code, renamedAt: _at, previousCodeUntil: _until, ...settings } = record;
|
|
198
|
+
record = {
|
|
199
|
+
...settings,
|
|
200
|
+
code: info.code,
|
|
201
|
+
token: info.token,
|
|
202
|
+
...(info.previousCode !== undefined ? { previousCode: info.previousCode } : {}),
|
|
203
|
+
...(info.renamedAt !== undefined ? { renamedAt: info.renamedAt } : {}),
|
|
204
|
+
...(info.previousCodeUntil !== undefined
|
|
205
|
+
? { previousCodeUntil: info.previousCodeUntil }
|
|
206
|
+
: {}),
|
|
207
|
+
};
|
|
208
|
+
report({ previousCode: dead, code: info.code, previousCodeGone: true }, undone);
|
|
209
|
+
return info;
|
|
210
|
+
};
|
|
211
|
+
return {
|
|
212
|
+
channels: {
|
|
213
|
+
async resolve(asked) {
|
|
214
|
+
let info;
|
|
215
|
+
try {
|
|
216
|
+
info = await inner.resolve(asked);
|
|
217
|
+
}
|
|
218
|
+
catch (error) {
|
|
219
|
+
const gone = error instanceof PlatformError && error.code === 'CHANNEL_NOT_FOUND';
|
|
220
|
+
if (!gone || asked !== code)
|
|
221
|
+
throw error;
|
|
222
|
+
return fallBack(asked, error);
|
|
223
|
+
}
|
|
224
|
+
observe(asked, info);
|
|
225
|
+
return info;
|
|
226
|
+
},
|
|
227
|
+
invalidate(asked) {
|
|
228
|
+
inner.invalidate(asked);
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
current: () => record,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Validate and normalise the parts of a config every store shares. Throws the
|
|
236
|
+
* same refusals, in the same order, a single-store client always has.
|
|
237
|
+
*/
|
|
238
|
+
export function readClientEndpoints(config) {
|
|
8
239
|
if (!config.cdnUrl) {
|
|
9
240
|
throw new StorefrontError('cdnUrl is required', 'cms');
|
|
10
241
|
}
|
|
@@ -13,53 +244,172 @@ export async function createStoreContext(config) {
|
|
|
13
244
|
typeof config.cacheTags !== 'function') {
|
|
14
245
|
throw new StorefrontError('cacheTags must be true, false or a resolver function', 'cms');
|
|
15
246
|
}
|
|
247
|
+
try {
|
|
248
|
+
assertConditionalReadsOption(config.conditionalReads);
|
|
249
|
+
}
|
|
250
|
+
catch (error) {
|
|
251
|
+
throw toStorefrontError(error, 'cms');
|
|
252
|
+
}
|
|
16
253
|
const fetchFn = config.fetch ?? globalThis.fetch;
|
|
17
|
-
|
|
18
|
-
const vendureUrl = (config.vendureUrl ?? DEFAULT_VENDURE_URL).replace(/\/+$/, '');
|
|
19
|
-
const cmsUrl = (config.cmsUrl ?? DEFAULT_CMS_URL).replace(/\/+$/, '');
|
|
20
|
-
const pluginsUrl = (config.pluginsUrl ?? DEFAULT_PLUGINS_URL).replace(/\/+$/, '');
|
|
21
|
-
// One resolver for the life of the client, shared with the transport: it
|
|
22
|
-
// caches the channel, collapses concurrent resolutions into one request, and
|
|
23
|
-
// — the reason it is not just this one startup call — can go BACK to the CMS
|
|
24
|
-
// when a request is refused with CHANNEL_NOT_FOUND, so a channel whose token
|
|
25
|
-
// rotated under a running storefront heals itself instead of failing until
|
|
26
|
-
// the process restarts (spec §6.2, §15.1).
|
|
27
|
-
const channels = staleIfError(createChannelResolver({
|
|
28
|
-
cmsUrl,
|
|
254
|
+
return {
|
|
29
255
|
fetch: fetchFn,
|
|
256
|
+
cdnUrl: config.cdnUrl.replace(/\/+$/, ''),
|
|
257
|
+
vendureUrl: (config.vendureUrl ?? DEFAULT_VENDURE_URL).replace(/\/+$/, ''),
|
|
258
|
+
cmsUrl: (config.cmsUrl ?? DEFAULT_CMS_URL).replace(/\/+$/, ''),
|
|
259
|
+
pluginsUrl: (config.pluginsUrl ?? DEFAULT_PLUGINS_URL).replace(/\/+$/, ''),
|
|
260
|
+
retry: {
|
|
261
|
+
attempts: config.retry?.attempts ?? 2,
|
|
262
|
+
baseDelayMs: config.retry?.baseDelayMs ?? 200,
|
|
263
|
+
},
|
|
264
|
+
cacheTags: config.cacheTags ?? true,
|
|
265
|
+
conditionalReads: config.conditionalReads ?? !isNextPatchedFetch(fetchFn),
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
/** The CMS channel resolver a client's transports re-resolve through. */
|
|
269
|
+
export function createClientChannelResolver(endpoints) {
|
|
270
|
+
return staleIfError(createChannelResolver({
|
|
271
|
+
cmsUrl: endpoints.cmsUrl,
|
|
272
|
+
fetch: endpoints.fetch,
|
|
30
273
|
timeoutMs: INIT_TIMEOUT_MS,
|
|
31
274
|
}));
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
275
|
+
}
|
|
276
|
+
/** The store's own CDN when its channel names one, else the configured CDN. */
|
|
277
|
+
export function cdnForChannel(channel, fallbackCdnUrl) {
|
|
35
278
|
const rawCdnDomain = channel.customFields.cdnDomain;
|
|
36
279
|
const channelCdnDomain = typeof rawCdnDomain === 'string' && rawCdnDomain.trim() !== '' ? rawCdnDomain.trim() : null;
|
|
280
|
+
return {
|
|
281
|
+
cdnUrl: channelCdnDomain ? `https://${channelCdnDomain}` : fallbackCdnUrl,
|
|
282
|
+
channelCdnDomain,
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* One request's context: the store's shared parts plus a NEW shopper half.
|
|
287
|
+
* Every field the modules write (`authToken`, `languageCode`, the session
|
|
288
|
+
* currency, `taxDisplay`, `orderScope`) lives on the object returned here and
|
|
289
|
+
* nowhere else, which is what keeps two requests from seeing each other's.
|
|
290
|
+
*/
|
|
291
|
+
export function assembleStoreContext(endpoints, channel, channels, shopper, options) {
|
|
292
|
+
const { cdnUrl, channelCdnDomain } = cdnForChannel(channel, endpoints.cdnUrl);
|
|
37
293
|
return {
|
|
38
294
|
channel,
|
|
39
295
|
channels,
|
|
40
|
-
cdnUrl
|
|
296
|
+
cdnUrl,
|
|
41
297
|
channelCdnDomain,
|
|
42
|
-
vendureUrl,
|
|
43
|
-
cmsUrl,
|
|
44
|
-
pluginsUrl,
|
|
45
|
-
languageCode:
|
|
46
|
-
currencyCode: channel.defaultCurrencyCode,
|
|
298
|
+
vendureUrl: endpoints.vendureUrl,
|
|
299
|
+
cmsUrl: endpoints.cmsUrl,
|
|
300
|
+
pluginsUrl: endpoints.pluginsUrl,
|
|
301
|
+
languageCode: shopper.languageCode ?? channel.defaultLanguageCode,
|
|
302
|
+
currencyCode: shopper.currencyCode ?? channel.defaultCurrencyCode,
|
|
303
|
+
sessionCurrencyCode: shopper.currencyCode ?? null,
|
|
47
304
|
pricesIncludeTax: channel.pricesIncludeTax,
|
|
48
|
-
authToken: null,
|
|
305
|
+
authToken: shopper.authToken ?? null,
|
|
306
|
+
privateToken: shopper.privateToken ?? null,
|
|
307
|
+
buyerIp: shopper.buyerIp ?? null,
|
|
49
308
|
// `null`, not a default of CONSUMER: a client that never opted into scopes
|
|
50
309
|
// must send no header at all, so the engine keeps its legacy behaviour.
|
|
51
|
-
orderScope:
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
310
|
+
orderScope: shopper.orderScope ?? null,
|
|
311
|
+
head: shopper.head ?? null,
|
|
312
|
+
fetch: endpoints.fetch,
|
|
313
|
+
onAuthToken: shopper.onAuthToken,
|
|
314
|
+
onAuthExpired: shopper.onAuthExpired,
|
|
315
|
+
onAuthCleared: shopper.onAuthCleared,
|
|
316
|
+
retry: { attempts: endpoints.retry.attempts, baseDelayMs: endpoints.retry.baseDelayMs },
|
|
317
|
+
cacheTags: endpoints.cacheTags,
|
|
318
|
+
conditionalReads: endpoints.conditionalReads,
|
|
319
|
+
...(options?.storeScopedCacheTags ? { storeScopedCacheTags: true } : {}),
|
|
320
|
+
...(options?.onDeprecation ? { onDeprecation: options.onDeprecation } : {}),
|
|
321
|
+
...(options?.reportDeprecatedMethod
|
|
322
|
+
? { reportDeprecatedMethod: options.reportDeprecatedMethod }
|
|
323
|
+
: {}),
|
|
61
324
|
};
|
|
62
325
|
}
|
|
326
|
+
/**
|
|
327
|
+
* A customer token, refused blank. Blank would silently build an ANONYMOUS
|
|
328
|
+
* client — the opposite of what the caller asked for, discovered only when the
|
|
329
|
+
* first cart call lands elsewhere.
|
|
330
|
+
*/
|
|
331
|
+
export function assertCustomerToken(token) {
|
|
332
|
+
if (token !== undefined && token.trim() === '') {
|
|
333
|
+
throw new StorefrontError('customerToken must not be blank', 'vendure');
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
/** A session currency: three upper-case letters (the engine's `CurrencyCode`). */
|
|
337
|
+
export function assertCurrencyCode(currencyCode) {
|
|
338
|
+
if (currencyCode !== undefined && !CURRENCY_CODE_PATTERN.test(String(currencyCode))) {
|
|
339
|
+
throw new StorefrontError(`currencyCode "${String(currencyCode)}" is not an ISO 4217 code (three upper-case letters, e.g. "EUR")`, 'vendure', 400, 'INVALID_ARGUMENT');
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* A head key (`x-head`): the server's own key rule, kebab-case and at most 64
|
|
344
|
+
* characters (`services/vendure/src/heads/head-validation.ts`). Refused here
|
|
345
|
+
* rather than sent, because the server IGNORES a key it cannot use — a typo
|
|
346
|
+
* would silently mail every login link to the store's default head instead.
|
|
347
|
+
*/
|
|
348
|
+
const HEAD_KEY_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
349
|
+
const MAX_HEAD_KEY_LENGTH = 64;
|
|
350
|
+
export function assertHeadKey(head, label) {
|
|
351
|
+
if (head === undefined)
|
|
352
|
+
return;
|
|
353
|
+
if (typeof head !== 'string' ||
|
|
354
|
+
head.length > MAX_HEAD_KEY_LENGTH ||
|
|
355
|
+
!HEAD_KEY_PATTERN.test(head)) {
|
|
356
|
+
throw new StorefrontError(`${label} must be a head key — lowercase letters, digits and single hyphens, at most ${String(MAX_HEAD_KEY_LENGTH)} characters (e.g. "web", "trade" or "native"); got ${JSON.stringify(head)}`, 'vendure', 400, 'INVALID_ARGUMENT');
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Refuse a private token in a browser: a token a page holds is a token every
|
|
361
|
+
* visitor holds. Runs before anything reaches the network.
|
|
362
|
+
*/
|
|
363
|
+
export function assertPrivateTokenRuntime() {
|
|
364
|
+
if (isBrowserRuntime()) {
|
|
365
|
+
throw new StorefrontError('A private storefront token must never be constructed in a browser — it would ship the credential to every visitor. Build this client on the server, or drop privateToken for a browser client.', 'vendure', 400, 'CREDENTIAL_IN_BROWSER');
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
/** A private token's SHAPE; whether it is live is the platform's answer. */
|
|
369
|
+
export function assertPrivateTokenShape(token) {
|
|
370
|
+
if (!token.startsWith(STOREFRONT_TOKEN_PREFIX)) {
|
|
371
|
+
throw new StorefrontError(`privateToken must be a private storefront token (${STOREFRONT_TOKEN_PREFIX}…), issued per head with admin.heads.privateTokens.issue.`, 'vendure', 400, 'INVALID_PRIVATE_TOKEN');
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
/** A buyer address is honoured only beside a private token, and never blank. */
|
|
375
|
+
export function assertBuyerIp(buyerIp, hasPrivateToken) {
|
|
376
|
+
if (buyerIp === undefined)
|
|
377
|
+
return;
|
|
378
|
+
if (!hasPrivateToken) {
|
|
379
|
+
throw new StorefrontError('buyerIp is honoured only beside a privateToken; without one the platform ignores it.', 'vendure', 400, 'BUYER_IP_WITHOUT_PRIVATE_TOKEN');
|
|
380
|
+
}
|
|
381
|
+
if (buyerIp.trim() === '') {
|
|
382
|
+
throw new StorefrontError('buyerIp must not be blank', 'vendure', 400, 'INVALID_BUYER_IP');
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Is this Next.js's patched `fetch`? Next sets `__nextPatched` on it for exactly
|
|
387
|
+
* this question (`next/dist/server/lib/patch-fetch.js`: "for external consumers
|
|
388
|
+
* to determine if the fetch function has been patched").
|
|
389
|
+
*
|
|
390
|
+
* Conditional reads default OFF there: Next keys its data cache on the request
|
|
391
|
+
* headers and stores only 200s, so an added `If-None-Match` would turn each of
|
|
392
|
+
* Next's zero-request cache hits into a 304 round trip. A wrapper around Next's
|
|
393
|
+
* fetch does not carry the marker — the TSDoc tells that caller to pass `false`.
|
|
394
|
+
*/
|
|
395
|
+
function isNextPatchedFetch(fetchFn) {
|
|
396
|
+
return (typeof fetchFn === 'function' && fetchFn.__nextPatched === true);
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* The private storefront token's configuration, refused at construction.
|
|
400
|
+
*
|
|
401
|
+
* Only the token's SHAPE is checked here — whether it is live is the platform's
|
|
402
|
+
* answer, and a revoked or foreign token simply earns no storefront budget.
|
|
403
|
+
* The buyer address is left to the platform too (`INVALID_BUYER_IP`): parsing
|
|
404
|
+
* IPv6 here would need a dependency this package does not take.
|
|
405
|
+
*/
|
|
406
|
+
function assertPrivateTokenConfig(config) {
|
|
407
|
+
if (config.privateToken !== undefined) {
|
|
408
|
+
assertPrivateTokenRuntime();
|
|
409
|
+
assertPrivateTokenShape(config.privateToken);
|
|
410
|
+
}
|
|
411
|
+
assertBuyerIp(config.buyerIp, config.privateToken !== undefined);
|
|
412
|
+
}
|
|
63
413
|
/**
|
|
64
414
|
* Keep serving the channel we last resolved when the CMS cannot be reached.
|
|
65
415
|
*
|
|
@@ -95,19 +445,46 @@ function cmsUnreachable(error) {
|
|
|
95
445
|
// upgrading — serving a stale channel past either would hide it.
|
|
96
446
|
return UNREACHABLE_CODES.has(error.code) || error.status >= 500;
|
|
97
447
|
}
|
|
448
|
+
/**
|
|
449
|
+
* How many codes the fallback remembers. A single-store client uses one; a
|
|
450
|
+
* multi-store client one per store it has served — the cap only bounds a
|
|
451
|
+
* process that keeps resolving codes it never sees again.
|
|
452
|
+
*/
|
|
453
|
+
const MAX_LAST_GOOD_CODES = 1024;
|
|
454
|
+
/**
|
|
455
|
+
* An answer for a renamed store's OLD code whose window has ended (or whose end is unreadable):
|
|
456
|
+
* the code may name another store now, so an outage must not keep serving it as this one.
|
|
457
|
+
*/
|
|
458
|
+
function oldCodeLapsed(info) {
|
|
459
|
+
if (info.previousCode === undefined)
|
|
460
|
+
return false;
|
|
461
|
+
const until = info.previousCodeUntil ? Date.parse(info.previousCodeUntil) : Number.NaN;
|
|
462
|
+
return Number.isNaN(until) || until <= Date.now();
|
|
463
|
+
}
|
|
98
464
|
function staleIfError(inner) {
|
|
99
|
-
|
|
465
|
+
// Keyed by CODE, never one slot: a multi-store client shares this resolver
|
|
466
|
+
// between its stores, and a single "last good" would answer store B's
|
|
467
|
+
// lookup with store A's channel — its token, its id — during a CMS outage.
|
|
468
|
+
const lastGood = new Map();
|
|
100
469
|
return {
|
|
101
470
|
async resolve(code) {
|
|
102
471
|
try {
|
|
103
472
|
const info = await inner.resolve(code);
|
|
104
|
-
lastGood
|
|
473
|
+
lastGood.delete(code);
|
|
474
|
+
lastGood.set(code, info);
|
|
475
|
+
if (lastGood.size > MAX_LAST_GOOD_CODES) {
|
|
476
|
+
const oldest = lastGood.keys().next().value;
|
|
477
|
+
if (oldest !== undefined)
|
|
478
|
+
lastGood.delete(oldest);
|
|
479
|
+
}
|
|
105
480
|
return info;
|
|
106
481
|
}
|
|
107
482
|
catch (error) {
|
|
108
|
-
|
|
483
|
+
const fallback = lastGood.get(code);
|
|
484
|
+
if (fallback === undefined || !cmsUnreachable(error) || oldCodeLapsed(fallback)) {
|
|
109
485
|
throw error;
|
|
110
|
-
|
|
486
|
+
}
|
|
487
|
+
return fallback;
|
|
111
488
|
}
|
|
112
489
|
},
|
|
113
490
|
invalidate(code) {
|
|
@@ -123,18 +500,21 @@ function staleIfError(inner) {
|
|
|
123
500
|
* makes by hand, usually while wiring the SDK up for the first time, so the
|
|
124
501
|
* three failures they are actually going to hit name the thing to check.
|
|
125
502
|
*/
|
|
126
|
-
async function resolveChannel(channels, storeCode, cmsUrl) {
|
|
503
|
+
export async function resolveChannel(channels, storeCode, cmsUrl) {
|
|
504
|
+
return toChannelInfo(await resolveCoreChannel(channels, storeCode, cmsUrl));
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* {@link resolveChannel} without the reshaping: the resolver's own object, so
|
|
508
|
+
* a caller can tell by identity whether the answer changed since it last asked.
|
|
509
|
+
*/
|
|
510
|
+
export async function resolveCoreChannel(channels, storeCode, cmsUrl) {
|
|
127
511
|
try {
|
|
128
|
-
|
|
129
|
-
// `core` types the bag as `Record<string, unknown>`; this package's
|
|
130
|
-
// `ChannelCustomFields` names the keys it reads out of the same JSON.
|
|
131
|
-
return { ...resolved, customFields: resolved.customFields };
|
|
512
|
+
return await channels.resolve(storeCode);
|
|
132
513
|
}
|
|
133
514
|
catch (error) {
|
|
134
515
|
if (error instanceof PlatformError) {
|
|
135
|
-
if (error.code === 'CHANNEL_NOT_FOUND')
|
|
136
|
-
throw
|
|
137
|
-
}
|
|
516
|
+
if (error.code === 'CHANNEL_NOT_FOUND')
|
|
517
|
+
throw channelNotFound(storeCode);
|
|
138
518
|
if (error.code === 'CHANNEL_RESOLUTION_TIMEOUT') {
|
|
139
519
|
throw new StorefrontError(`Timed out connecting to CMS at ${cmsUrl}. Is the service running?`, 'cms', undefined, error.code);
|
|
140
520
|
}
|
|
@@ -142,4 +522,15 @@ async function resolveChannel(channels, storeCode, cmsUrl) {
|
|
|
142
522
|
throw toStorefrontError(error, 'cms');
|
|
143
523
|
}
|
|
144
524
|
}
|
|
525
|
+
/**
|
|
526
|
+
* `core` types the bag as `Record<string, unknown>` (it only checks it is an
|
|
527
|
+
* object); the generated `PublicChannelDto` names the keys the CMS sends.
|
|
528
|
+
*/
|
|
529
|
+
export function toChannelInfo(resolved) {
|
|
530
|
+
return { ...resolved, customFields: resolved.customFields };
|
|
531
|
+
}
|
|
532
|
+
/** The refusal for a code that names no store this client may serve. */
|
|
533
|
+
export function channelNotFound(storeCode) {
|
|
534
|
+
return new StorefrontError(`Store code "${storeCode}" not found. Check storeCode matches a channel code in the dashboard — if the store was renamed, its old code stops answering a while after the rename: configure the new one.`, 'cms', 404, 'CHANNEL_NOT_FOUND');
|
|
535
|
+
}
|
|
145
536
|
//# sourceMappingURL=context.js.map
|
package/dist/core/context.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/core/context.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/core/context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { StorefrontError } from '../errors.js';
|
|
2
|
+
/** ISO 4217 as the engine's `CurrencyCode` enum spells it: three upper-case letters. */
|
|
3
|
+
export declare const CURRENCY_CODE_PATTERN: RegExp;
|
|
4
|
+
/** The code a currency the store does not offer is refused with. */
|
|
5
|
+
export declare const CURRENCY_NOT_AVAILABLE = "CURRENCY_NOT_AVAILABLE";
|
|
6
|
+
/**
|
|
7
|
+
* The request carried a session currency the channel does not offer (a stale
|
|
8
|
+
* restored code, or a currency the merchant removed mid-session). `undefined`
|
|
9
|
+
* when `error` is something else.
|
|
10
|
+
*/
|
|
11
|
+
export declare function sessionCurrencyRefusal(error: StorefrontError, sessionCurrencyCode: string): StorefrontError | undefined;
|
|
12
|
+
/** `setOrderCurrency(currencyCode)` was refused because the store does not offer it. */
|
|
13
|
+
export declare function orderCurrencyRefusal(error: StorefrontError, currencyCode: string): StorefrontError | undefined;
|
|
14
|
+
//# sourceMappingURL=currency.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"currency.d.ts","sourceRoot":"","sources":["../../src/core/currency.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,wFAAwF;AACxF,eAAO,MAAM,qBAAqB,QAAe,CAAC;AAElD,oEAAoE;AACpE,eAAO,MAAM,sBAAsB,2BAA2B,CAAC;AAqC/D;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,eAAe,EACtB,mBAAmB,EAAE,MAAM,GAC1B,eAAe,GAAG,SAAS,CAU7B;AAED,wFAAwF;AACxF,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,eAAe,EACtB,YAAY,EAAE,MAAM,GACnB,eAAe,GAAG,SAAS,CAO7B"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { StorefrontError } from '../errors.js';
|
|
2
|
+
/** ISO 4217 as the engine's `CurrencyCode` enum spells it: three upper-case letters. */
|
|
3
|
+
export const CURRENCY_CODE_PATTERN = /^[A-Z]{3}$/;
|
|
4
|
+
/** The code a currency the store does not offer is refused with. */
|
|
5
|
+
export const CURRENCY_NOT_AVAILABLE = 'CURRENCY_NOT_AVAILABLE';
|
|
6
|
+
/**
|
|
7
|
+
* The engine's two "not offered" refusals, as they reach the client. Both are
|
|
8
|
+
* `USER_INPUT_ERROR`s whose message is an i18n key or its translation, so the
|
|
9
|
+
* test is on the key, and on the quoted code every translation interpolates:
|
|
10
|
+
*
|
|
11
|
+
* - `error.currency-not-available-in-channel` — `?currencyCode=` names a
|
|
12
|
+
* currency the channel does not offer (`RequestContextService`); refuses the
|
|
13
|
+
* whole request, whatever it asked for. Translated (`The currency "JPY" is
|
|
14
|
+
* not available in the current Channel`).
|
|
15
|
+
* - `error.currency-not-available` — `setCurrencyCodeForOrder` to such a
|
|
16
|
+
* currency (`OrderService.updateOrderCurrency`). No translation exists, so
|
|
17
|
+
* the raw key is the message.
|
|
18
|
+
*/
|
|
19
|
+
function refusesCurrency(error, currencyCode, key) {
|
|
20
|
+
if (error.errorCode !== 'USER_INPUT_ERROR')
|
|
21
|
+
return false;
|
|
22
|
+
return error.message.includes(key) || error.message.includes(`"${currencyCode}"`);
|
|
23
|
+
}
|
|
24
|
+
/** `error` re-labelled `CURRENCY_NOT_AVAILABLE` with `message`, keeping everything else. */
|
|
25
|
+
function asCurrencyNotAvailable(error, message) {
|
|
26
|
+
return new StorefrontError(message, 'vendure', 400, CURRENCY_NOT_AVAILABLE, error.details, undefined, {
|
|
27
|
+
traceId: error.traceId,
|
|
28
|
+
problem: error.problem,
|
|
29
|
+
cause: error,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The request carried a session currency the channel does not offer (a stale
|
|
34
|
+
* restored code, or a currency the merchant removed mid-session). `undefined`
|
|
35
|
+
* when `error` is something else.
|
|
36
|
+
*/
|
|
37
|
+
export function sessionCurrencyRefusal(error, sessionCurrencyCode) {
|
|
38
|
+
if (!refusesCurrency(error, sessionCurrencyCode, 'currency-not-available-in-channel')) {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
return asCurrencyNotAvailable(error, `This store does not offer ${sessionCurrencyCode}, the currency this client was pricing in. ` +
|
|
42
|
+
"The client has gone back to the store's default currency: drop the stored currency and " +
|
|
43
|
+
'retry the request.');
|
|
44
|
+
}
|
|
45
|
+
/** `setOrderCurrency(currencyCode)` was refused because the store does not offer it. */
|
|
46
|
+
export function orderCurrencyRefusal(error, currencyCode) {
|
|
47
|
+
if (!refusesCurrency(error, currencyCode, 'error.currency-not-available'))
|
|
48
|
+
return undefined;
|
|
49
|
+
return asCurrencyNotAvailable(error, `This store does not offer ${currencyCode}. Choose one of the currencies the store lists ` +
|
|
50
|
+
'(getActiveChannel().availableCurrencyCodes).');
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=currency.js.map
|