@tokenoftrust/storefront-runner 2.2.116 → 2.2.118
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.
|
@@ -2,7 +2,7 @@ import type {
|
|
|
2
2
|
OpenPublicationArtifactV1,
|
|
3
3
|
PublicationRouteRenderPlanV1,
|
|
4
4
|
} from "@tot/public-runtime";
|
|
5
|
-
import type
|
|
5
|
+
import { hasHomeContentShape, type EditorialPage, type HomeContent } from "@/lib/storyblok/content-model.js";
|
|
6
6
|
import type { ChromeConfig } from "@/lib/chrome/model.js";
|
|
7
7
|
import { parseChromeConfig } from "@/lib/chrome/parseConfig.js";
|
|
8
8
|
import { parseChromeAssignments } from "@/lib/chrome/model.js";
|
|
@@ -75,7 +75,7 @@ export class PublicationSpaceContentProvider implements ContentProvider {
|
|
|
75
75
|
async getHome(): Promise<HomeContent> {
|
|
76
76
|
if (!this.ownsRoot) return this.sharedRoot.getHome();
|
|
77
77
|
const home = parseJson<HomeContent>(this.publication.readContent("home.json"));
|
|
78
|
-
if (!home) throw new Error("selected root publication home is unavailable");
|
|
78
|
+
if (!home || !hasHomeContentShape(home)) throw new Error("selected root publication home is unavailable");
|
|
79
79
|
return home;
|
|
80
80
|
}
|
|
81
81
|
|
|
@@ -595,11 +595,9 @@ export class StoryblokContentProvider implements ContentProvider {
|
|
|
595
595
|
|
|
596
596
|
// ---------------------------------------------------------------------------
|
|
597
597
|
// PublishedContentProvider — overlays published customization content for the
|
|
598
|
-
// resolved environment (store->app wiring).
|
|
599
|
-
//
|
|
600
|
-
//
|
|
601
|
-
// Enumeration also follows the selected immutable manifest, so sitemap/blog/page
|
|
602
|
-
// indexes do not need a build-time tenant checkout.
|
|
598
|
+
// resolved environment (store->app wiring). A selected immutable version is
|
|
599
|
+
// authoritative for both individual reads and enumeration. Legacy per-path
|
|
600
|
+
// customization delegates absent files to the base provider (Storyblok/local).
|
|
603
601
|
// ---------------------------------------------------------------------------
|
|
604
602
|
|
|
605
603
|
export interface ContentCustomization {
|
|
@@ -609,13 +607,27 @@ export interface ContentCustomization {
|
|
|
609
607
|
|
|
610
608
|
export class PublishedContentProvider implements ContentProvider {
|
|
611
609
|
readonly perRequestArtifactReads = true;
|
|
610
|
+
private versionedPathsPromise: Promise<string[] | null> | null = null;
|
|
612
611
|
constructor(
|
|
613
612
|
private readonly base: ContentProvider,
|
|
614
613
|
private readonly tenantId: string,
|
|
615
614
|
private readonly cust: ContentCustomization,
|
|
616
615
|
) {}
|
|
617
616
|
|
|
618
|
-
|
|
617
|
+
private versionedPaths(): Promise<string[] | null> {
|
|
618
|
+
return this.versionedPathsPromise ??= listPublishedArtifactPaths(
|
|
619
|
+
this.cust.get,
|
|
620
|
+
this.tenantId,
|
|
621
|
+
this.cust.env,
|
|
622
|
+
contentArtifactPath(this.tenantId, ""),
|
|
623
|
+
);
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
private async usesVersionedContent(): Promise<boolean> {
|
|
627
|
+
return (await this.versionedPaths()) !== null;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
/** Raw published-artifact string for a tenant file, or null when absent. */
|
|
619
631
|
private publishedRaw(relative: string): Promise<string | null> {
|
|
620
632
|
return readPublishedArtifact(
|
|
621
633
|
this.cust.get,
|
|
@@ -636,7 +648,10 @@ export class PublishedContentProvider implements ContentProvider {
|
|
|
636
648
|
}
|
|
637
649
|
|
|
638
650
|
async getHome(): Promise<HomeContent> {
|
|
639
|
-
|
|
651
|
+
const home = await this.published<HomeContent>("home.json");
|
|
652
|
+
if (home && hasHomeContentShape(home)) return home;
|
|
653
|
+
if (await this.usesVersionedContent()) throw new Error("Published version has no renderable home.json");
|
|
654
|
+
return this.base.getHome();
|
|
640
655
|
}
|
|
641
656
|
// Raw whole-page documents (T0 marketing tenants) publish via KV too, so a
|
|
642
657
|
// vendor edit previews / goes live with NO Worker rebuild. Artifact path mirrors
|
|
@@ -650,12 +665,14 @@ export class PublishedContentProvider implements ContentProvider {
|
|
|
650
665
|
// is dt-id-writeback's job.
|
|
651
666
|
async getHomeHtml(): Promise<string | null> {
|
|
652
667
|
const raw = await this.publishedRaw("home.html");
|
|
653
|
-
|
|
668
|
+
if (raw !== null) return stampTrackingIdsAtPublish(raw);
|
|
669
|
+
return (await this.usesVersionedContent()) ? null : this.base.getHomeHtml();
|
|
654
670
|
}
|
|
655
671
|
async getPageHtml(slug: string): Promise<string | null> {
|
|
656
672
|
const rel = `pages-html/${normalizeRawPageSlug(slug)}.html`;
|
|
657
673
|
const raw = await this.publishedRaw(rel);
|
|
658
|
-
|
|
674
|
+
if (raw !== null) return stampTrackingIdsAtPublish(raw);
|
|
675
|
+
return (await this.usesVersionedContent()) ? null : this.base.getPageHtml(slug);
|
|
659
676
|
}
|
|
660
677
|
listPageHtmlSlugs(): Promise<string[]> {
|
|
661
678
|
return this.listArtifactPaths("pages-html/").then((paths) =>
|
|
@@ -682,18 +699,19 @@ export class PublishedContentProvider implements ContentProvider {
|
|
|
682
699
|
const assignments = parseChromeAssignments(await this.published<unknown>("chrome-assignments.json"));
|
|
683
700
|
return renderRawChrome(config, currentPath, assignments);
|
|
684
701
|
}
|
|
685
|
-
//
|
|
686
|
-
return this.base.getChromeHtml(currentPath);
|
|
702
|
+
// Legacy per-path content may use bundled chrome; a selected version owns its chrome.
|
|
703
|
+
return (await this.usesVersionedContent()) ? null : this.base.getChromeHtml(currentPath);
|
|
687
704
|
}
|
|
688
705
|
async getChrome(): Promise<ChromeConfig> {
|
|
689
706
|
// Runs through the SAME fail-closed schema validator as getChromeHtml's
|
|
690
707
|
// chrome.json branch (lib/chrome/parseConfig.ts) — a published artifact is
|
|
691
708
|
// no longer trusted blind (was: JSON.parse + a raw cast to SiteChrome).
|
|
692
709
|
const config = parseChromeConfig(await this.published<unknown>("chrome.json"));
|
|
693
|
-
return config ?? this.base.getChrome();
|
|
710
|
+
return config ?? ((await this.usesVersionedContent()) ? EMPTY_CHROME_CONFIG : this.base.getChrome());
|
|
694
711
|
}
|
|
695
712
|
async getPage(slug: string): Promise<EditorialPage | null> {
|
|
696
|
-
|
|
713
|
+
const page = await this.published<EditorialPage>(`pages/${slug}.json`);
|
|
714
|
+
return page ?? ((await this.usesVersionedContent()) ? null : this.base.getPage(slug));
|
|
697
715
|
}
|
|
698
716
|
async listPages(): Promise<EditorialPage[]> {
|
|
699
717
|
const paths = await this.listArtifactPaths("pages/");
|
|
@@ -720,13 +738,9 @@ export class PublishedContentProvider implements ContentProvider {
|
|
|
720
738
|
|
|
721
739
|
async listArtifactPaths(prefix = ""): Promise<string[] | null> {
|
|
722
740
|
const root = contentArtifactPath(this.tenantId, "");
|
|
723
|
-
const paths = await
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
this.cust.env,
|
|
727
|
-
`${root}${prefix}`,
|
|
728
|
-
);
|
|
729
|
-
return paths?.map((path) => path.slice(root.length)) ?? null;
|
|
741
|
+
const paths = await this.versionedPaths();
|
|
742
|
+
return paths?.filter((path) => path.startsWith(`${root}${prefix}`))
|
|
743
|
+
.map((path) => path.slice(root.length)) ?? null;
|
|
730
744
|
}
|
|
731
745
|
}
|
|
732
746
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tokenoftrust/storefront-runner",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.118",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE",
|
|
5
5
|
"description": "World-shareable storefront runner: multi-tenant renderer on Astro/Cloudflare. No control plane.",
|
|
6
6
|
"packageManager": "pnpm@11.9.0",
|