@sixtyninecommerce/client 0.24.0 → 0.26.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 +21 -0
- package/dist/admin/forms.js +19 -0
- package/dist/admin/forms.js.map +1 -1
- package/dist/admin/http.d.ts +9 -0
- package/dist/admin/http.d.ts.map +1 -1
- package/dist/admin/http.js +3 -0
- package/dist/admin/http.js.map +1 -1
- package/dist/admin/index.d.ts +63 -0
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +67 -0
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/redirects.d.ts +6 -0
- package/dist/admin/redirects.d.ts.map +1 -1
- package/dist/admin/redirects.js +12 -0
- package/dist/admin/redirects.js.map +1 -1
- package/dist/admin/types.d.ts +63 -0
- package/dist/admin/types.d.ts.map +1 -1
- package/dist/cache-tags.d.ts +19 -0
- package/dist/cache-tags.d.ts.map +1 -1
- package/dist/cache-tags.js +19 -0
- package/dist/cache-tags.js.map +1 -1
- package/dist/client.d.ts +17 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +17 -0
- package/dist/client.js.map +1 -1
- package/dist/commerce/age-verification.js +3 -3
- package/dist/commerce/age-verification.js.map +1 -1
- package/dist/commerce/branding.js +7 -0
- package/dist/commerce/branding.js.map +1 -1
- package/dist/commerce/cart.js +25 -0
- package/dist/commerce/cart.js.map +1 -1
- package/dist/commerce/checkout.d.ts +68 -0
- package/dist/commerce/checkout.d.ts.map +1 -1
- package/dist/commerce/checkout.js +83 -0
- package/dist/commerce/checkout.js.map +1 -1
- package/dist/commerce/customer.d.ts +58 -0
- package/dist/commerce/customer.d.ts.map +1 -1
- package/dist/commerce/customer.js +65 -0
- package/dist/commerce/customer.js.map +1 -1
- package/dist/commerce/pickup-location-parser.d.ts +18 -0
- package/dist/commerce/pickup-location-parser.d.ts.map +1 -1
- package/dist/commerce/pickup-location-parser.js +28 -0
- package/dist/commerce/pickup-location-parser.js.map +1 -1
- package/dist/commerce/placement-error.d.ts +52 -0
- package/dist/commerce/placement-error.d.ts.map +1 -1
- package/dist/commerce/placement-error.js +87 -0
- package/dist/commerce/placement-error.js.map +1 -1
- package/dist/commerce/products.d.ts +48 -0
- package/dist/commerce/products.d.ts.map +1 -1
- package/dist/commerce/products.js +92 -0
- package/dist/commerce/products.js.map +1 -1
- package/dist/commerce/queries.d.ts +113 -27
- package/dist/commerce/queries.d.ts.map +1 -1
- package/dist/commerce/queries.js +188 -2
- package/dist/commerce/queries.js.map +1 -1
- package/dist/commerce/quotes.js +33 -0
- package/dist/commerce/quotes.js.map +1 -1
- package/dist/commerce/saved-lists.d.ts +7 -7
- package/dist/commerce/saved-lists.d.ts.map +1 -1
- package/dist/commerce/saved-lists.js +1 -1
- package/dist/commerce/search.js +3 -0
- package/dist/commerce/search.js.map +1 -1
- package/dist/commerce/shipping.js +3 -3
- package/dist/commerce/shipping.js.map +1 -1
- package/dist/commerce/stock-notifications.d.ts +11 -0
- package/dist/commerce/stock-notifications.d.ts.map +1 -1
- package/dist/commerce/stock-notifications.js +11 -0
- package/dist/commerce/stock-notifications.js.map +1 -1
- package/dist/commerce/vat-validation.js +4 -4
- package/dist/commerce/vat-validation.js.map +1 -1
- package/dist/constants.d.ts +31 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +32 -0
- package/dist/constants.js.map +1 -1
- package/dist/content/asset-urls.d.ts +50 -0
- package/dist/content/asset-urls.d.ts.map +1 -1
- package/dist/content/asset-urls.js +92 -0
- package/dist/content/asset-urls.js.map +1 -1
- package/dist/content/assets.d.ts +15 -0
- package/dist/content/assets.d.ts.map +1 -1
- package/dist/content/assets.js +15 -0
- package/dist/content/assets.js.map +1 -1
- package/dist/content/collection-pages.d.ts +5 -0
- package/dist/content/collection-pages.d.ts.map +1 -1
- package/dist/content/collection-pages.js +8 -0
- package/dist/content/collection-pages.js.map +1 -1
- package/dist/content/collections.d.ts +14 -0
- package/dist/content/collections.d.ts.map +1 -1
- package/dist/content/collections.js +16 -0
- package/dist/content/collections.js.map +1 -1
- package/dist/content/filtered-products.d.ts +18 -0
- package/dist/content/filtered-products.d.ts.map +1 -1
- package/dist/content/filtered-products.js +16 -0
- package/dist/content/filtered-products.js.map +1 -1
- package/dist/content/form-field-types.d.ts +6 -0
- package/dist/content/form-field-types.d.ts.map +1 -1
- package/dist/content/form-field-types.js +12 -0
- package/dist/content/form-field-types.js.map +1 -1
- package/dist/content/forms.d.ts +16 -0
- package/dist/content/forms.d.ts.map +1 -1
- package/dist/content/forms.js +23 -0
- package/dist/content/forms.js.map +1 -1
- package/dist/content/items.d.ts +26 -0
- package/dist/content/items.d.ts.map +1 -1
- package/dist/content/items.js +33 -0
- package/dist/content/items.js.map +1 -1
- package/dist/content/resolve.js +6 -0
- package/dist/content/resolve.js.map +1 -1
- package/dist/content/sitemap.d.ts +5 -0
- package/dist/content/sitemap.d.ts.map +1 -1
- package/dist/content/sitemap.js +5 -0
- package/dist/content/sitemap.js.map +1 -1
- package/dist/core/context.js +6 -0
- package/dist/core/context.js.map +1 -1
- package/dist/core/headers.js +2 -0
- package/dist/core/headers.js.map +1 -1
- package/dist/core/http.d.ts +8 -0
- package/dist/core/http.d.ts.map +1 -1
- package/dist/core/http.js +89 -1
- package/dist/core/http.js.map +1 -1
- package/dist/credit/credit-status.js +2 -2
- package/dist/credit/credit-status.js.map +1 -1
- package/dist/credit/payment-terms.js +2 -2
- package/dist/credit/payment-terms.js.map +1 -1
- package/dist/currency/exchange.d.ts +11 -0
- package/dist/currency/exchange.d.ts.map +1 -1
- package/dist/currency/exchange.js +11 -0
- package/dist/currency/exchange.js.map +1 -1
- package/dist/errors.d.ts +50 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +48 -2
- package/dist/errors.js.map +1 -1
- package/dist/events/envelope.d.ts +60 -0
- package/dist/events/envelope.d.ts.map +1 -1
- package/dist/events/envelope.js +12 -0
- package/dist/events/envelope.js.map +1 -1
- package/dist/events/index.d.ts +14 -1
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +13 -0
- package/dist/events/index.js.map +1 -1
- package/dist/events/payloads.d.ts +19 -0
- package/dist/events/payloads.d.ts.map +1 -1
- package/dist/events/payloads.js +12 -0
- package/dist/events/payloads.js.map +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/media/index.js +2 -0
- package/dist/media/index.js.map +1 -1
- package/dist/media/urls.d.ts +52 -0
- package/dist/media/urls.d.ts.map +1 -1
- package/dist/media/urls.js +38 -0
- package/dist/media/urls.js.map +1 -1
- package/dist/media/video.d.ts +16 -0
- package/dist/media/video.d.ts.map +1 -1
- package/dist/media/video.js +16 -0
- package/dist/media/video.js.map +1 -1
- package/dist/next/artifact-handler.d.ts +22 -0
- package/dist/next/artifact-handler.d.ts.map +1 -1
- package/dist/next/artifact-handler.js +22 -0
- package/dist/next/artifact-handler.js.map +1 -1
- package/dist/next/event-revalidate-handler.d.ts +67 -0
- package/dist/next/event-revalidate-handler.d.ts.map +1 -1
- package/dist/next/event-revalidate-handler.js +48 -0
- package/dist/next/event-revalidate-handler.js.map +1 -1
- package/dist/next/index.d.ts +6 -0
- package/dist/next/index.d.ts.map +1 -1
- package/dist/next/index.js +6 -0
- package/dist/next/index.js.map +1 -1
- package/dist/next/json-ld.d.ts +9 -0
- package/dist/next/json-ld.d.ts.map +1 -1
- package/dist/next/json-ld.js +9 -0
- package/dist/next/json-ld.js.map +1 -1
- package/dist/next/metadata.d.ts +18 -0
- package/dist/next/metadata.d.ts.map +1 -1
- package/dist/next/metadata.js +21 -0
- package/dist/next/metadata.js.map +1 -1
- package/dist/next/redirect-middleware.d.ts +39 -0
- package/dist/next/redirect-middleware.d.ts.map +1 -1
- package/dist/next/redirect-middleware.js +32 -0
- package/dist/next/redirect-middleware.js.map +1 -1
- package/dist/next/revalidate-handler.d.ts +30 -0
- package/dist/next/revalidate-handler.d.ts.map +1 -1
- package/dist/next/revalidate-handler.js +22 -0
- package/dist/next/revalidate-handler.js.map +1 -1
- package/dist/order-scope.d.ts +27 -0
- package/dist/order-scope.d.ts.map +1 -1
- package/dist/order-scope.js +29 -0
- package/dist/order-scope.js.map +1 -1
- package/dist/pricing/format.d.ts +17 -0
- package/dist/pricing/format.d.ts.map +1 -1
- package/dist/pricing/format.js +19 -0
- package/dist/pricing/format.js.map +1 -1
- package/dist/pricing/index.d.ts +8 -1
- package/dist/pricing/index.d.ts.map +1 -1
- package/dist/pricing/index.js +18 -2
- package/dist/pricing/index.js.map +1 -1
- package/dist/pricing/tax-display.d.ts +77 -0
- package/dist/pricing/tax-display.d.ts.map +1 -1
- package/dist/pricing/tax-display.js +85 -0
- package/dist/pricing/tax-display.js.map +1 -1
- package/dist/pricing/tiers.d.ts +9 -0
- package/dist/pricing/tiers.d.ts.map +1 -1
- package/dist/pricing/tiers.js +9 -0
- package/dist/pricing/tiers.js.map +1 -1
- package/dist/pricing/validation.d.ts +56 -1
- package/dist/pricing/validation.d.ts.map +1 -1
- package/dist/pricing/validation.js +61 -0
- package/dist/pricing/validation.js.map +1 -1
- package/dist/redirects/index.d.ts +1 -0
- package/dist/redirects/index.d.ts.map +1 -1
- package/dist/redirects/index.js +1 -0
- package/dist/redirects/index.js.map +1 -1
- package/dist/redirects/store.d.ts +20 -0
- package/dist/redirects/store.d.ts.map +1 -1
- package/dist/redirects/store.js +57 -0
- package/dist/redirects/store.js.map +1 -1
- package/dist/redirects/types.d.ts +24 -0
- package/dist/redirects/types.d.ts.map +1 -1
- package/dist/redirects/types.js +1 -0
- package/dist/redirects/types.js.map +1 -1
- package/dist/revalidation/event-plan.d.ts +48 -0
- package/dist/revalidation/event-plan.d.ts.map +1 -1
- package/dist/revalidation/event-plan.js +61 -0
- package/dist/revalidation/event-plan.js.map +1 -1
- package/dist/revalidation/event-verify.d.ts +25 -0
- package/dist/revalidation/event-verify.d.ts.map +1 -1
- package/dist/revalidation/event-verify.js +27 -0
- package/dist/revalidation/event-verify.js.map +1 -1
- package/dist/revalidation/types.d.ts +20 -0
- package/dist/revalidation/types.d.ts.map +1 -1
- package/dist/revalidation/types.js +10 -0
- package/dist/revalidation/types.js.map +1 -1
- package/dist/revalidation/url-context.d.ts +25 -0
- package/dist/revalidation/url-context.d.ts.map +1 -1
- package/dist/revalidation/url-context.js +17 -0
- package/dist/revalidation/url-context.js.map +1 -1
- package/dist/revalidation/verify.d.ts +8 -0
- package/dist/revalidation/verify.d.ts.map +1 -1
- package/dist/revalidation/verify.js +8 -0
- package/dist/revalidation/verify.js.map +1 -1
- package/dist/seo/ai.d.ts +17 -0
- package/dist/seo/ai.d.ts.map +1 -1
- package/dist/seo/ai.js +12 -0
- package/dist/seo/ai.js.map +1 -1
- package/dist/seo/alternates.js +13 -0
- package/dist/seo/alternates.js.map +1 -1
- package/dist/seo/artifacts.d.ts +13 -0
- package/dist/seo/artifacts.d.ts.map +1 -1
- package/dist/seo/artifacts.js +19 -0
- package/dist/seo/artifacts.js.map +1 -1
- package/dist/seo/canonical.d.ts +15 -0
- package/dist/seo/canonical.d.ts.map +1 -1
- package/dist/seo/canonical.js +24 -0
- package/dist/seo/canonical.js.map +1 -1
- package/dist/seo/index.js +6 -0
- package/dist/seo/index.js.map +1 -1
- package/dist/seo/json-ld.d.ts +13 -0
- package/dist/seo/json-ld.d.ts.map +1 -1
- package/dist/seo/json-ld.js +32 -0
- package/dist/seo/json-ld.js.map +1 -1
- package/dist/seo/locale-tag.d.ts +31 -0
- package/dist/seo/locale-tag.d.ts.map +1 -1
- package/dist/seo/locale-tag.js +31 -0
- package/dist/seo/locale-tag.js.map +1 -1
- package/dist/seo/meta-tags.d.ts +29 -0
- package/dist/seo/meta-tags.d.ts.map +1 -1
- package/dist/seo/meta-tags.js +28 -0
- package/dist/seo/meta-tags.js.map +1 -1
- package/dist/seo/metadata-parser.d.ts +24 -0
- package/dist/seo/metadata-parser.d.ts.map +1 -1
- package/dist/seo/metadata-parser.js +38 -0
- package/dist/seo/metadata-parser.js.map +1 -1
- package/dist/seo/metadata-types.d.ts +16 -0
- package/dist/seo/metadata-types.d.ts.map +1 -1
- package/dist/seo/product-path.d.ts +96 -0
- package/dist/seo/product-path.d.ts.map +1 -1
- package/dist/seo/product-path.js +96 -0
- package/dist/seo/product-path.js.map +1 -1
- package/dist/seo/robots.d.ts +17 -0
- package/dist/seo/robots.d.ts.map +1 -1
- package/dist/seo/robots.js +12 -0
- package/dist/seo/robots.js.map +1 -1
- package/dist/seo/types.d.ts +39 -0
- package/dist/seo/types.d.ts.map +1 -1
- package/dist/seo/url-builder.d.ts +31 -0
- package/dist/seo/url-builder.d.ts.map +1 -1
- package/dist/seo/url-builder.js +36 -0
- package/dist/seo/url-builder.js.map +1 -1
- package/dist/types.d.ts +1163 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/media/video.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Video embed helpers for storefront rendering.
|
|
3
|
+
* Types and parsing utilities inlined from commerce-shared to keep the client zero-dep.
|
|
4
|
+
*/
|
|
1
5
|
const DIRECT_VIDEO_EXTENSIONS = ['.mp4', '.webm', '.ogv', '.ogg', '.mov', '.m4v'];
|
|
2
6
|
const YOUTUBE_PATTERNS = [
|
|
3
7
|
/(?:youtube\.com\/watch\?.*v=)([a-zA-Z0-9_-]{11})/,
|
|
@@ -10,6 +14,7 @@ const VIMEO_PATTERNS = [
|
|
|
10
14
|
/player\.vimeo\.com\/video\/(\d+)/,
|
|
11
15
|
/vimeo\.com\/(?:channels\/[\w-]+\/|groups\/[\w-]+\/videos\/)?(\d+)/,
|
|
12
16
|
];
|
|
17
|
+
/** Parse a video URL and extract the provider and video ID. */
|
|
13
18
|
export function parseVideoUrl(url) {
|
|
14
19
|
if (!url || typeof url !== 'string')
|
|
15
20
|
return null;
|
|
@@ -26,6 +31,7 @@ export function parseVideoUrl(url) {
|
|
|
26
31
|
}
|
|
27
32
|
return null;
|
|
28
33
|
}
|
|
34
|
+
/** Get a privacy-friendly embed URL for a video provider and ID. */
|
|
29
35
|
export function getEmbedUrl(provider, videoId) {
|
|
30
36
|
switch (provider) {
|
|
31
37
|
case 'youtube':
|
|
@@ -34,6 +40,11 @@ export function getEmbedUrl(provider, videoId) {
|
|
|
34
40
|
return `https://player.vimeo.com/video/${videoId}`;
|
|
35
41
|
}
|
|
36
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Validate that a URL points to a directly-playable video file (HTTPS + known
|
|
45
|
+
* extension). Used for the "external" source — videos hosted outside our
|
|
46
|
+
* asset library on a stable CDN.
|
|
47
|
+
*/
|
|
37
48
|
export function parseDirectVideoUrl(url) {
|
|
38
49
|
if (!url || typeof url !== 'string')
|
|
39
50
|
return null;
|
|
@@ -52,6 +63,7 @@ export function parseDirectVideoUrl(url) {
|
|
|
52
63
|
return null;
|
|
53
64
|
return { url: trimmed };
|
|
54
65
|
}
|
|
66
|
+
/** Get a thumbnail URL for a video. Vimeo requires an oEmbed API call so returns null. */
|
|
55
67
|
export function getThumbnailUrl(provider, videoId) {
|
|
56
68
|
switch (provider) {
|
|
57
69
|
case 'youtube':
|
|
@@ -60,6 +72,10 @@ export function getThumbnailUrl(provider, videoId) {
|
|
|
60
72
|
return null;
|
|
61
73
|
}
|
|
62
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Generate ready-to-use HTML for embedding a video.
|
|
77
|
+
* Returns an iframe for YouTube/Vimeo or a video element for uploads.
|
|
78
|
+
*/
|
|
63
79
|
export function getVideoEmbedHtml(value, options) {
|
|
64
80
|
const { autoplay = false, loop = false, muted = false } = options ?? {};
|
|
65
81
|
if ((value.source === 'youtube' || value.source === 'vimeo') && value.video_id) {
|
package/dist/media/video.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"video.js","sourceRoot":"","sources":["../../src/media/video.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"video.js","sourceRoot":"","sources":["../../src/media/video.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route-handler factory that proxies a platform SEO artifact onto the
|
|
3
|
+
* storefront's own origin (fetch-and-serve — hosting-adapter-independent,
|
|
4
|
+
* unlike next.config rewrites).
|
|
5
|
+
*
|
|
6
|
+
* Two deliberate header behaviors:
|
|
7
|
+
* - The inbound client User-Agent is NOT forwarded — the platform host blocks
|
|
8
|
+
* known crawler UAs, and it must see the storefront server, not Googlebot.
|
|
9
|
+
* - X-Robots-Tag from the platform host is dropped; Cache-Control is replaced
|
|
10
|
+
* with the storefront's own policy.
|
|
11
|
+
*/
|
|
1
12
|
import type { StorefrontClient } from '../types.js';
|
|
2
13
|
export type SeoArtifact = 'sitemap' | 'sitemap-child' | 'robots' | 'llms-txt' | 'indexnow-key';
|
|
3
14
|
export interface SeoArtifactHandlerOptions {
|
|
15
|
+
/** Cache-Control served to crawlers/CDN. */
|
|
4
16
|
cacheControl?: string;
|
|
17
|
+
/** Upstream fetch timeout. Default 15s. */
|
|
5
18
|
timeoutMs?: number;
|
|
6
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Usage (App Router):
|
|
22
|
+
* ```ts
|
|
23
|
+
* // src/app/sitemap.xml/route.ts
|
|
24
|
+
* export const GET = createSeoArtifactHandler(getClient(), 'sitemap');
|
|
25
|
+
* // src/app/sitemaps/[name]/route.ts
|
|
26
|
+
* export const GET = createSeoArtifactHandler(getClient(), 'sitemap-child');
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
7
29
|
export declare function createSeoArtifactHandler(client: StorefrontClient | Promise<StorefrontClient>, artifact: SeoArtifact, options?: SeoArtifactHandlerOptions): (request: Request, context?: {
|
|
8
30
|
params?: Promise<{
|
|
9
31
|
name?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifact-handler.d.ts","sourceRoot":"","sources":["../../src/next/artifact-handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"artifact-handler.d.ts","sourceRoot":"","sources":["../../src/next/artifact-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,eAAe,GAAG,QAAQ,GAAG,UAAU,GAAG,cAAc,CAAC;AAE/F,MAAM,WAAW,yBAAyB;IACxC,4CAA4C;IAC5C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAsBD;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,EACpD,QAAQ,EAAE,WAAW,EACrB,OAAO,CAAC,EAAE,yBAAyB,GAClC,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,KAAK,OAAO,CAAC,QAAQ,CAAC,CAoD5F"}
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route-handler factory that proxies a platform SEO artifact onto the
|
|
3
|
+
* storefront's own origin (fetch-and-serve — hosting-adapter-independent,
|
|
4
|
+
* unlike next.config rewrites).
|
|
5
|
+
*
|
|
6
|
+
* Two deliberate header behaviors:
|
|
7
|
+
* - The inbound client User-Agent is NOT forwarded — the platform host blocks
|
|
8
|
+
* known crawler UAs, and it must see the storefront server, not Googlebot.
|
|
9
|
+
* - X-Robots-Tag from the platform host is dropped; Cache-Control is replaced
|
|
10
|
+
* with the storefront's own policy.
|
|
11
|
+
*/
|
|
1
12
|
import { SEO_ARTIFACT_TAG } from '../cache-tags.js';
|
|
2
13
|
const DEFAULT_CACHE_CONTROL = 'public, max-age=300, s-maxage=3600, stale-while-revalidate=86400';
|
|
3
14
|
const DEFAULT_TIMEOUT_MS = 15_000;
|
|
@@ -18,6 +29,15 @@ function upstreamUrl(client, artifact, childName) {
|
|
|
18
29
|
return client.seo.indexnowKeyUrl();
|
|
19
30
|
}
|
|
20
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Usage (App Router):
|
|
34
|
+
* ```ts
|
|
35
|
+
* // src/app/sitemap.xml/route.ts
|
|
36
|
+
* export const GET = createSeoArtifactHandler(getClient(), 'sitemap');
|
|
37
|
+
* // src/app/sitemaps/[name]/route.ts
|
|
38
|
+
* export const GET = createSeoArtifactHandler(getClient(), 'sitemap-child');
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
21
41
|
export function createSeoArtifactHandler(client, artifact, options) {
|
|
22
42
|
const cacheControl = options?.cacheControl ?? DEFAULT_CACHE_CONTROL;
|
|
23
43
|
const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
@@ -30,6 +50,8 @@ export function createSeoArtifactHandler(client, artifact, options) {
|
|
|
30
50
|
const ifNoneMatch = request.headers.get('if-none-match');
|
|
31
51
|
if (ifNoneMatch)
|
|
32
52
|
headers['If-None-Match'] = ifNoneMatch;
|
|
53
|
+
// Tagged so the `seo-artifact` purge both revalidation handlers issue
|
|
54
|
+
// reaches a cached upstream fetch; before this tag, nothing carried it.
|
|
33
55
|
const init = {
|
|
34
56
|
headers,
|
|
35
57
|
signal: AbortSignal.timeout(timeoutMs),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifact-handler.js","sourceRoot":"","sources":["../../src/next/artifact-handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"artifact-handler.js","sourceRoot":"","sources":["../../src/next/artifact-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,14 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route-handler factory for the storefront's `/api/revalidate/events`
|
|
3
|
+
* endpoint: the receiver for a platform EVENT subscription
|
|
4
|
+
* (Dashboard → Settings → Event Subscriptions). Framework functions are
|
|
5
|
+
* INJECTED, so this package never imports `next`.
|
|
6
|
+
*
|
|
7
|
+
* What each answer makes the platform's dispatcher do:
|
|
8
|
+
* - 200 — delivered (also for an event this SDK does not act on: skipping
|
|
9
|
+
* is an acceptance, and the subscription's cursor moves on);
|
|
10
|
+
* - 401 — bad signature or stale/missing `delivered_at`; counts toward the
|
|
11
|
+
* subscription being auto-disabled after 20 in a row;
|
|
12
|
+
* - 400 — a signed body that is not a valid envelope/payload; dead-lettered;
|
|
13
|
+
* - 500 — `revalidatePath`/`revalidateTag` threw; retried with backoff.
|
|
14
|
+
*
|
|
15
|
+
* A path event whose URLs cannot be composed (the URL context cannot be read
|
|
16
|
+
* or is unusable, or `toRoutePath` throws or returns a non-path) is NOT a 5xx:
|
|
17
|
+
* it revalidates the whole site instead and answers 200 with `degraded`.
|
|
18
|
+
*
|
|
19
|
+
* Stateless by design: revalidating twice is harmless, and a replay is bounded
|
|
20
|
+
* by the `delivered_at` window, so there is no dedupe store to run.
|
|
21
|
+
*/
|
|
1
22
|
import type { PlatformEventEnvelope } from '../events/envelope.js';
|
|
2
23
|
import { type RevalidationPlan, type RevalidationPlanOptions } from '../revalidation/event-plan.js';
|
|
3
24
|
import { type UrlContext, type UrlContextSource } from '../revalidation/url-context.js';
|
|
4
25
|
export interface EventRevalidateHandlerOptions extends RevalidationPlanOptions {
|
|
26
|
+
/** The subscription's signing secret, shown once when it was created. Server-only env. */
|
|
5
27
|
secret: string;
|
|
28
|
+
/** Pass `revalidatePath` from 'next/cache'. */
|
|
6
29
|
revalidatePath(path: string, type?: 'page' | 'layout'): void;
|
|
30
|
+
/**
|
|
31
|
+
* Pass `revalidateTag` from 'next/cache'. Required: product and collection
|
|
32
|
+
* events revalidate by tag alone. It is called with the tag only — if your
|
|
33
|
+
* Next version's `revalidateTag` takes a cache-profile argument, pass a
|
|
34
|
+
* wrapper that supplies one.
|
|
35
|
+
*/
|
|
7
36
|
revalidateTag(tag: string): void;
|
|
37
|
+
/**
|
|
38
|
+
* The channel's URL rule set and languages, used to compose each event path
|
|
39
|
+
* per locale — typically `urlContextFromClient(client)`.
|
|
40
|
+
*/
|
|
8
41
|
urls: UrlContext | UrlContextSource;
|
|
42
|
+
/** Reject deliveries whose `delivered_at` is further than this from now. Default 300s. */
|
|
9
43
|
toleranceSeconds?: number;
|
|
44
|
+
/**
|
|
45
|
+
* Observe every delivery answered 200 — skipped (`plan.skipped`) and degraded
|
|
46
|
+
* (`plan.degraded`) ones included. Not called for a delivery answered 401,
|
|
47
|
+
* 400 or 500. If it throws, the error goes to `onError` and the answer stays
|
|
48
|
+
* 200.
|
|
49
|
+
*/
|
|
10
50
|
onEvent?(envelope: PlatformEventEnvelope, plan: RevalidationPlan): void | Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Called with the error for:
|
|
53
|
+
* - a delivery answered 400 because its payload is off-contract;
|
|
54
|
+
* - a delivery answered 500 because `revalidatePath`/`revalidateTag` threw;
|
|
55
|
+
* - the first URL-mapping failure of a streak — that delivery is answered
|
|
56
|
+
* 200 with `degraded: 'url_mapping_failed'`, and the streak ends when a path
|
|
57
|
+
* event maps again;
|
|
58
|
+
* - an `onEvent` that threw.
|
|
59
|
+
*
|
|
60
|
+
* Not called for signature, replay-window or envelope refusals (401/400).
|
|
61
|
+
* Default: `console.error`.
|
|
62
|
+
*/
|
|
11
63
|
onError?(error: unknown, envelope: PlatformEventEnvelope): void;
|
|
12
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Usage (App Router):
|
|
67
|
+
* ```ts
|
|
68
|
+
* // src/app/api/revalidate/events/route.ts
|
|
69
|
+
* import { revalidatePath, revalidateTag } from 'next/cache';
|
|
70
|
+
* import { createEventRevalidateHandler, urlContextFromClient } from '@sixtyninecommerce/client/next';
|
|
71
|
+
*
|
|
72
|
+
* export const POST = createEventRevalidateHandler({
|
|
73
|
+
* secret: process.env.REVALIDATE_EVENTS_SECRET!,
|
|
74
|
+
* revalidatePath,
|
|
75
|
+
* revalidateTag,
|
|
76
|
+
* urls: urlContextFromClient(getClient()), // a client or a client promise
|
|
77
|
+
* });
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
13
80
|
export declare function createEventRevalidateHandler(options: EventRevalidateHandlerOptions): (request: Request) => Promise<Response>;
|
|
14
81
|
//# sourceMappingURL=event-revalidate-handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-revalidate-handler.d.ts","sourceRoot":"","sources":["../../src/next/event-revalidate-handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"event-revalidate-handler.d.ts","sourceRoot":"","sources":["../../src/next/event-revalidate-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAKL,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,EAE7B,MAAM,+BAA+B,CAAC;AAKvC,OAAO,EACL,KAAK,UAAU,EACf,KAAK,gBAAgB,EAEtB,MAAM,gCAAgC,CAAC;AAExC,MAAM,WAAW,6BAA8B,SAAQ,uBAAuB;IAC5E,0FAA0F;IAC1F,MAAM,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;IAC7D;;;;;OAKG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC;;;OAGG;IACH,IAAI,EAAE,UAAU,GAAG,gBAAgB,CAAC;IACpC,0FAA0F;IAC1F,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;OAKG;IACH,OAAO,CAAC,CAAC,QAAQ,EAAE,qBAAqB,EAAE,IAAI,EAAE,gBAAgB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxF;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,qBAAqB,GAAG,IAAI,CAAC;CACjE;AAgBD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,6BAA6B,GACrC,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAwGzC"}
|
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route-handler factory for the storefront's `/api/revalidate/events`
|
|
3
|
+
* endpoint: the receiver for a platform EVENT subscription
|
|
4
|
+
* (Dashboard → Settings → Event Subscriptions). Framework functions are
|
|
5
|
+
* INJECTED, so this package never imports `next`.
|
|
6
|
+
*
|
|
7
|
+
* What each answer makes the platform's dispatcher do:
|
|
8
|
+
* - 200 — delivered (also for an event this SDK does not act on: skipping
|
|
9
|
+
* is an acceptance, and the subscription's cursor moves on);
|
|
10
|
+
* - 401 — bad signature or stale/missing `delivered_at`; counts toward the
|
|
11
|
+
* subscription being auto-disabled after 20 in a row;
|
|
12
|
+
* - 400 — a signed body that is not a valid envelope/payload; dead-lettered;
|
|
13
|
+
* - 500 — `revalidatePath`/`revalidateTag` threw; retried with backoff.
|
|
14
|
+
*
|
|
15
|
+
* A path event whose URLs cannot be composed (the URL context cannot be read
|
|
16
|
+
* or is unusable, or `toRoutePath` throws or returns a non-path) is NOT a 5xx:
|
|
17
|
+
* it revalidates the whole site instead and answers 200 with `degraded`.
|
|
18
|
+
*
|
|
19
|
+
* Stateless by design: revalidating twice is harmless, and a replay is bounded
|
|
20
|
+
* by the `delivered_at` window, so there is no dedupe store to run.
|
|
21
|
+
*/
|
|
1
22
|
import { classifyEvent, EventPayloadError, planFromIntent, resolveMaxPaths, } from '../revalidation/event-plan.js';
|
|
2
23
|
import { DEFAULT_EVENT_TOLERANCE_SECONDS, verifyEventDelivery, } from '../revalidation/event-verify.js';
|
|
3
24
|
import { urlContextFromChannelSettings, } from '../revalidation/url-context.js';
|
|
@@ -10,6 +31,21 @@ function json(status, body) {
|
|
|
10
31
|
function defaultOnError(error, envelope) {
|
|
11
32
|
console.error(`[@sixtyninecommerce/client] event revalidation failed for ${envelope.type} ${envelope.id}:`, error);
|
|
12
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Usage (App Router):
|
|
36
|
+
* ```ts
|
|
37
|
+
* // src/app/api/revalidate/events/route.ts
|
|
38
|
+
* import { revalidatePath, revalidateTag } from 'next/cache';
|
|
39
|
+
* import { createEventRevalidateHandler, urlContextFromClient } from '@sixtyninecommerce/client/next';
|
|
40
|
+
*
|
|
41
|
+
* export const POST = createEventRevalidateHandler({
|
|
42
|
+
* secret: process.env.REVALIDATE_EVENTS_SECRET!,
|
|
43
|
+
* revalidatePath,
|
|
44
|
+
* revalidateTag,
|
|
45
|
+
* urls: urlContextFromClient(getClient()), // a client or a client promise
|
|
46
|
+
* });
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
13
49
|
export function createEventRevalidateHandler(options) {
|
|
14
50
|
const toleranceSeconds = options.toleranceSeconds ?? DEFAULT_EVENT_TOLERANCE_SECONDS;
|
|
15
51
|
if (!Number.isFinite(toleranceSeconds) || toleranceSeconds <= 0) {
|
|
@@ -21,9 +57,15 @@ export function createEventRevalidateHandler(options) {
|
|
|
21
57
|
throw new TypeError('urls is required — pass urlContextFromClient(client) or a UrlContext');
|
|
22
58
|
}
|
|
23
59
|
const report = options.onError ?? defaultOnError;
|
|
60
|
+
// The rule set the last `channel.url_settings_changed` delivery carried. It
|
|
61
|
+
// is newer than anything `urls` can return: the client's channel snapshot is
|
|
62
|
+
// taken at startup, and a static UrlContext never changes.
|
|
24
63
|
let adopted = null;
|
|
25
64
|
const resolveUrls = async () => adopted ?? (typeof source === 'function' ? await source() : source);
|
|
26
65
|
const planOptions = { maxPaths, toRoutePath: options.toRoutePath };
|
|
66
|
+
// Path events whose URLs could not be composed since the last one that could.
|
|
67
|
+
// Only the first of such a streak is reported, so a broken URL source does not
|
|
68
|
+
// flood the log; every one of them is still visible through `onEvent`.
|
|
27
69
|
let mappingFailures = 0;
|
|
28
70
|
const planPaths = async (intent, envelope) => {
|
|
29
71
|
try {
|
|
@@ -32,6 +74,9 @@ export function createEventRevalidateHandler(options) {
|
|
|
32
74
|
return plan;
|
|
33
75
|
}
|
|
34
76
|
catch (error) {
|
|
77
|
+
// Never a 5xx: delivery is ordered, so a failure that cannot clear would
|
|
78
|
+
// stall the subscription on this event for good without ever tripping the
|
|
79
|
+
// auto-disable. The whole site needs no URL at all.
|
|
35
80
|
if (mappingFailures === 0)
|
|
36
81
|
report(error, envelope);
|
|
37
82
|
mappingFailures += 1;
|
|
@@ -40,6 +85,8 @@ export function createEventRevalidateHandler(options) {
|
|
|
40
85
|
};
|
|
41
86
|
return async (request) => {
|
|
42
87
|
if (!options.secret) {
|
|
88
|
+
// 500, not 401: the storefront is misconfigured, and a 401 streak would
|
|
89
|
+
// get the subscription auto-disabled rather than retried once fixed.
|
|
43
90
|
return json(500, { error: 'revalidation secret is not configured' });
|
|
44
91
|
}
|
|
45
92
|
let rawBody;
|
|
@@ -85,6 +132,7 @@ export function createEventRevalidateHandler(options) {
|
|
|
85
132
|
await options.onEvent(envelope, plan);
|
|
86
133
|
}
|
|
87
134
|
catch (error) {
|
|
135
|
+
// The revalidation happened; an observer must not turn it into a retry.
|
|
88
136
|
report(error, envelope);
|
|
89
137
|
}
|
|
90
138
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-revalidate-handler.js","sourceRoot":"","sources":["../../src/next/event-revalidate-handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"event-revalidate-handler.js","sourceRoot":"","sources":["../../src/next/event-revalidate-handler.ts"],"names":[],"mappings":"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"}
|
package/dist/next/index.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@sixtyninecommerce/client/next` — Next.js App Router adapters. Zero `next`
|
|
3
|
+
* imports by design: `toNextMetadata` returns a structurally-compatible
|
|
4
|
+
* object, and both revalidation handlers take `revalidatePath`/`revalidateTag`
|
|
5
|
+
* as injected functions.
|
|
6
|
+
*/
|
|
1
7
|
export type { RevalidationDegradedReason, RevalidationPlan, RevalidationPlanOptions, RevalidationSkipReason, } from '../revalidation/event-plan.js';
|
|
2
8
|
export type { RevalidateWebhookPayload } from '../revalidation/types.js';
|
|
3
9
|
export type { UrlContext, UrlContextSource } from '../revalidation/url-context.js';
|
package/dist/next/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,YAAY,EACV,0BAA0B,EAC1B,gBAAgB,EAChB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,+BAA+B,CAAC;AACvC,YAAY,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACzE,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACnF,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,YAAY,EAAE,WAAW,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AACpF,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,YAAY,EAAE,6BAA6B,EAAE,MAAM,+BAA+B,CAAC;AACnF,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAClE,YAAY,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACnE,YAAY,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAC9F,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,YAAY,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC"}
|
package/dist/next/index.js
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@sixtyninecommerce/client/next` — Next.js App Router adapters. Zero `next`
|
|
3
|
+
* imports by design: `toNextMetadata` returns a structurally-compatible
|
|
4
|
+
* object, and both revalidation handlers take `revalidatePath`/`revalidateTag`
|
|
5
|
+
* as injected functions.
|
|
6
|
+
*/
|
|
1
7
|
export { urlContextFromClient } from '../revalidation/url-context.js';
|
|
2
8
|
export { verifyWebhookSignature } from '../revalidation/verify.js';
|
|
3
9
|
export { createSeoArtifactHandler } from './artifact-handler.js';
|
package/dist/next/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAEnE,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAEjE,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAElE,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEnE,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC"}
|
package/dist/next/json-ld.d.ts
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inline JSON-LD helpers — React-free object literals so the core keeps zero
|
|
3
|
+
* framework dependencies.
|
|
4
|
+
*/
|
|
5
|
+
/** JSON.stringify with `<` escaped — safe for inline `<script>` embedding. */
|
|
1
6
|
export declare function serializeJsonLd(value: object): string;
|
|
7
|
+
/**
|
|
8
|
+
* Props for a JSON-LD script element:
|
|
9
|
+
* `<script {...jsonLdScriptProps(obj)} />`
|
|
10
|
+
*/
|
|
2
11
|
export declare function jsonLdScriptProps(value: object): {
|
|
3
12
|
type: 'application/ld+json';
|
|
4
13
|
dangerouslySetInnerHTML: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json-ld.d.ts","sourceRoot":"","sources":["../../src/next/json-ld.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"json-ld.d.ts","sourceRoot":"","sources":["../../src/next/json-ld.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,8EAA8E;AAC9E,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG;IAChD,IAAI,EAAE,qBAAqB,CAAC;IAC5B,uBAAuB,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C,CAKA"}
|
package/dist/next/json-ld.js
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inline JSON-LD helpers — React-free object literals so the core keeps zero
|
|
3
|
+
* framework dependencies.
|
|
4
|
+
*/
|
|
5
|
+
/** JSON.stringify with `<` escaped — safe for inline `<script>` embedding. */
|
|
1
6
|
export function serializeJsonLd(value) {
|
|
2
7
|
return JSON.stringify(value).replace(/</g, '\\u003c');
|
|
3
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Props for a JSON-LD script element:
|
|
11
|
+
* `<script {...jsonLdScriptProps(obj)} />`
|
|
12
|
+
*/
|
|
4
13
|
export function jsonLdScriptProps(value) {
|
|
5
14
|
return {
|
|
6
15
|
type: 'application/ld+json',
|
package/dist/next/json-ld.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json-ld.js","sourceRoot":"","sources":["../../src/next/json-ld.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"json-ld.js","sourceRoot":"","sources":["../../src/next/json-ld.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,8EAA8E;AAC9E,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;AACxD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAI7C,OAAO;QACL,IAAI,EAAE,qBAAqB;QAC3B,uBAAuB,EAAE,EAAE,MAAM,EAAE,eAAe,CAAC,KAAK,CAAC,EAAE;KAC5D,CAAC;AACJ,CAAC"}
|
package/dist/next/metadata.d.ts
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapter from the SDK's structured head bundle (`seo.metaTagsFor`) to Next.js
|
|
3
|
+
* App Router `Metadata`. Deliberately ZERO `next` imports: the returned object
|
|
4
|
+
* is typed by a local structural subset (`NextCompatibleMetadata`) that
|
|
5
|
+
* assigns cleanly to Next's `Metadata` — keeping the core framework-agnostic
|
|
6
|
+
* and this subpath dependency-free.
|
|
7
|
+
*
|
|
8
|
+
* Next's typed Metadata API cannot emit arbitrary `property=`-based OG tags
|
|
9
|
+
* (og:type "product", product:price:*, og:locale:alternate). Those come back
|
|
10
|
+
* from `extraOpenGraphTags()` — render them as `<meta property=.../>` in page
|
|
11
|
+
* JSX; React 19 hoists them into <head>.
|
|
12
|
+
*/
|
|
1
13
|
import type { MetaTagsResult, OpenGraphTag } from '../seo/meta-tags.js';
|
|
2
14
|
export interface NextCompatibleMetadata {
|
|
3
15
|
title: string;
|
|
@@ -27,6 +39,12 @@ export interface NextCompatibleMetadata {
|
|
|
27
39
|
images?: string[];
|
|
28
40
|
};
|
|
29
41
|
}
|
|
42
|
+
/** Convert a metaTagsFor() result into a Next `Metadata`-compatible object. */
|
|
30
43
|
export declare function toNextMetadata(result: MetaTagsResult): NextCompatibleMetadata;
|
|
44
|
+
/**
|
|
45
|
+
* OpenGraph tags Next's Metadata API cannot express (og:type=product,
|
|
46
|
+
* product:*, og:locale:alternate). Render each as
|
|
47
|
+
* `<meta property={tag.property} content={tag.content} />` in page JSX.
|
|
48
|
+
*/
|
|
31
49
|
export declare function extraOpenGraphTags(result: MetaTagsResult): OpenGraphTag[];
|
|
32
50
|
//# sourceMappingURL=metadata.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/next/metadata.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/next/metadata.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExE,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE;QACV,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACnC,CAAC;IACF,SAAS,CAAC,EAAE;QACV,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;QAC7B,MAAM,CAAC,EAAE,KAAK,CAAC;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,GAAG,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAC/C,CAAC;IACF,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE,SAAS,GAAG,qBAAqB,GAAG,QAAQ,GAAG,KAAK,CAAC;QAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;CACH;AAmBD,+EAA+E;AAC/E,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,sBAAsB,CA8C7E;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,cAAc,GAAG,YAAY,EAAE,CAUzE"}
|
package/dist/next/metadata.js
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapter from the SDK's structured head bundle (`seo.metaTagsFor`) to Next.js
|
|
3
|
+
* App Router `Metadata`. Deliberately ZERO `next` imports: the returned object
|
|
4
|
+
* is typed by a local structural subset (`NextCompatibleMetadata`) that
|
|
5
|
+
* assigns cleanly to Next's `Metadata` — keeping the core framework-agnostic
|
|
6
|
+
* and this subpath dependency-free.
|
|
7
|
+
*
|
|
8
|
+
* Next's typed Metadata API cannot emit arbitrary `property=`-based OG tags
|
|
9
|
+
* (og:type "product", product:price:*, og:locale:alternate). Those come back
|
|
10
|
+
* from `extraOpenGraphTags()` — render them as `<meta property=.../>` in page
|
|
11
|
+
* JSX; React 19 hoists them into <head>.
|
|
12
|
+
*/
|
|
1
13
|
const OG_HANDLED = new Set([
|
|
2
14
|
'og:title',
|
|
3
15
|
'og:description',
|
|
@@ -12,6 +24,7 @@ const TWITTER_CARDS = new Set(['summary', 'summary_large_image', 'player', 'app'
|
|
|
12
24
|
function ogValue(tags, property) {
|
|
13
25
|
return tags.find((t) => t.property === property)?.content;
|
|
14
26
|
}
|
|
27
|
+
/** Convert a metaTagsFor() result into a Next `Metadata`-compatible object. */
|
|
15
28
|
export function toNextMetadata(result) {
|
|
16
29
|
const languages = {};
|
|
17
30
|
for (const link of result.hreflang) {
|
|
@@ -34,6 +47,8 @@ export function toNextMetadata(result) {
|
|
|
34
47
|
url: ogValue(result.openGraph, 'og:url'),
|
|
35
48
|
siteName: ogValue(result.openGraph, 'og:site_name'),
|
|
36
49
|
locale: ogValue(result.openGraph, 'og:locale'),
|
|
50
|
+
// 'product' is not part of Next's typed union — it rides via
|
|
51
|
+
// extraOpenGraphTags() instead.
|
|
37
52
|
type: ogType === 'website' || ogType === 'article' ? ogType : undefined,
|
|
38
53
|
images: ogImages.length > 0 ? ogImages : undefined,
|
|
39
54
|
};
|
|
@@ -51,10 +66,16 @@ export function toNextMetadata(result) {
|
|
|
51
66
|
}
|
|
52
67
|
return metadata;
|
|
53
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* OpenGraph tags Next's Metadata API cannot express (og:type=product,
|
|
71
|
+
* product:*, og:locale:alternate). Render each as
|
|
72
|
+
* `<meta property={tag.property} content={tag.content} />` in page JSX.
|
|
73
|
+
*/
|
|
54
74
|
export function extraOpenGraphTags(result) {
|
|
55
75
|
const ogType = ogValue(result.openGraph, 'og:type');
|
|
56
76
|
return result.openGraph.filter((tag) => {
|
|
57
77
|
if (tag.property === 'og:type') {
|
|
78
|
+
// Only surface og:type here when toNextMetadata could NOT map it.
|
|
58
79
|
return !(ogType === 'website' || ogType === 'article');
|
|
59
80
|
}
|
|
60
81
|
if (tag.property === 'og:locale:alternate')
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/next/metadata.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/next/metadata.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Middleware factory that applies the tenant's platform-managed redirects.
|
|
3
|
+
*
|
|
4
|
+
* Zero `next` imports by design: it takes a `Request` and returns a plain
|
|
5
|
+
* `Response`, which is exactly what a Next.js middleware may return. It never
|
|
6
|
+
* throws — an unmatched path, a cold cache or an unreachable platform all
|
|
7
|
+
* resolve to `undefined`, meaning "carry on with normal routing".
|
|
8
|
+
*/
|
|
1
9
|
import type { RedirectStore, RedirectStoreConfig } from '../redirects/types.js';
|
|
2
10
|
export interface RedirectMiddlewareOptions extends RedirectStoreConfig {
|
|
11
|
+
/**
|
|
12
|
+
* Carry the incoming query string onto the destination. Default true — a
|
|
13
|
+
* campaign link to a moved page should keep its `utm_*` params. Parameters
|
|
14
|
+
* the destination already sets win.
|
|
15
|
+
*
|
|
16
|
+
* NOTE: this applies to EXTERNAL `https://` destinations too, so the
|
|
17
|
+
* visitor's query string is handed to that third-party origin. If your URLs
|
|
18
|
+
* carry anything you would not want a destination site to see, set this to
|
|
19
|
+
* false — or split those rules onto a middleware instance that has.
|
|
20
|
+
*/
|
|
3
21
|
preserveQuery?: boolean;
|
|
4
22
|
}
|
|
5
23
|
export interface RedirectMiddleware {
|
|
24
|
+
/** Returns a redirect Response, or undefined to fall through. */
|
|
6
25
|
(request: Request): Promise<Response | undefined>;
|
|
26
|
+
/** The underlying store — call `refresh()` from a revalidation webhook. */
|
|
7
27
|
readonly store: RedirectStore;
|
|
8
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Usage (App Router):
|
|
31
|
+
* ```ts
|
|
32
|
+
* // src/middleware.ts
|
|
33
|
+
* import { createRedirectMiddleware } from '@sixtyninecommerce/client/next';
|
|
34
|
+
*
|
|
35
|
+
* const redirects = createRedirectMiddleware({
|
|
36
|
+
* storeCode: process.env.STORE_CODE!,
|
|
37
|
+
* pluginsUrl: process.env.PLUGINS_URL,
|
|
38
|
+
* onError: (error) => console.error('[redirects]', error),
|
|
39
|
+
* });
|
|
40
|
+
*
|
|
41
|
+
* export async function middleware(request: Request) {
|
|
42
|
+
* return (await redirects(request)) ?? undefined;
|
|
43
|
+
* }
|
|
44
|
+
*
|
|
45
|
+
* export const config = { matcher: ['/((?!_next|api|.*\\..*).*)'] };
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
9
48
|
export declare function createRedirectMiddleware(options: RedirectMiddlewareOptions | {
|
|
10
49
|
store: RedirectStore;
|
|
11
50
|
preserveQuery?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redirect-middleware.d.ts","sourceRoot":"","sources":["../../src/next/redirect-middleware.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"redirect-middleware.d.ts","sourceRoot":"","sources":["../../src/next/redirect-middleware.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAEhF,MAAM,WAAW,yBAA0B,SAAQ,mBAAmB;IACpE;;;;;;;;;OASG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,iEAAiE;IACjE,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC;IAClD,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;CAC/B;AAsBD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,yBAAyB,GAAG;IAAE,KAAK,EAAE,aAAa,CAAC;IAAC,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,GACrF,kBAAkB,CAuBpB"}
|