Skip to content
File

Blob: src/sites/react-render-context.ts

typescript84 lines
1/// <reference types="node" />
2 
3import { AsyncLocalStorage } from "node:async_hooks";
4 
5import type {
6 ApexDocumentProps,
7 NotFoundDocumentProps,
8 SiteDocumentAssets,
9 SiteIdentity,
10 SiteNotFoundIdentity,
11 SitePageRenderState,
12 SitesPageMentionResolver,
13} from "./types";
14 
15export type SitesReactRenderContext =
16 | {
17 kind: "page";
18 assets: SiteDocumentAssets;
19 page: SitePageRenderState;
20 headingAnchorIds: readonly (string | null)[];
21 resolvePageMention: SitesPageMentionResolver;
22 }
23 | {
24 kind: "not-found";
25 assets: SiteDocumentAssets;
26 site: SiteNotFoundIdentity | null;
27 }
28 | {
29 kind: "apex";
30 assets: SiteDocumentAssets;
31 };
32 
33export type SitesHeaderRenderState = SiteIdentity;
34 
35const sitesReactRenderContext = new AsyncLocalStorage<SitesReactRenderContext>();
36 
37export function runWithSitesReactRenderContext<T>(context: SitesReactRenderContext, callback: () => T): T {
38 return sitesReactRenderContext.run(context, callback);
39}
40 
41export function readOptionalSitesReactRenderContext(): SitesReactRenderContext | undefined {
42 return sitesReactRenderContext.getStore();
43}
44 
45export function readRequiredSitesReactRenderContext(): SitesReactRenderContext {
46 const context = readOptionalSitesReactRenderContext();
47 if (!context) {
48 throw new Error("Sites React render context is required for Sites SSR components");
49 }
50 return context;
51}
52 
53export function readSitesPageRenderState(): { assets: SiteDocumentAssets; page: SitePageRenderState } {
54 const context = readRequiredSitesReactRenderContext();
55 if (context.kind !== "page") {
56 throw new Error("Sites page render context is required for SitePageDocument");
57 }
58 return { assets: context.assets, page: context.page };
59}
60 
61export function readSitesDocumentAssets(): SiteDocumentAssets {
62 return readRequiredSitesReactRenderContext().assets;
63}
64 
65export function readSitesHeaderRenderState(): SitesHeaderRenderState | null {
66 const context = readRequiredSitesReactRenderContext();
67 
68 if (context.kind === "page") {
69 return context.page.site;
70 }
71 if (context.kind === "not-found" && context.site) {
72 return { ...context.site, currentIsHome: false };
73 }
74 return null;
75}
76 
77export function createSitesNotFoundRenderContext(props: NotFoundDocumentProps): SitesReactRenderContext {
78 return { kind: "not-found", assets: props.assets, site: props.site };
79}
80 
81export function createSitesApexRenderContext(props: ApexDocumentProps): SitesReactRenderContext {
82 return { kind: "apex", assets: props.assets };
83}