camox 0.48.0 → 0.52.1
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/dist/core/createApp.d.ts +1 -0
- package/dist/core/createApp.js +1 -0
- package/dist/core/editing/contentEdits.js +78 -0
- package/dist/core/editing/createEditableBlock.js +277 -311
- package/dist/core/layoutContext.d.ts +1 -0
- package/dist/core/lib/contentType.js +2 -2
- package/dist/core/recordItem.js +3 -3
- package/dist/features/canvas/CamoxCanvas.js +15 -15
- package/dist/features/canvas/CanvasLoadingScreen.js +15 -11
- package/dist/features/canvas/CanvasPageFrame.js +81 -87
- package/dist/features/canvas/CanvasPreviewPageSlot.js +1 -1
- package/dist/features/canvas/DerivedPagePathInput.js +12 -12
- package/dist/features/canvas/canvasOverlayGeometry.js +1 -1
- package/dist/features/canvas/canvasStore.js +2 -2
- package/dist/features/canvas/sidebar/CanvasInspector.js +1 -1
- package/dist/features/canvas/sidebar/CuratedPageInspector.js +1 -1
- package/dist/features/canvas/sidebar/LayoutPageBlocks.js +23 -31
- package/dist/features/canvas/useCanvasCamera.js +1 -1
- package/dist/features/canvas/useDiscoveredPreviewPaths.js +16 -9
- package/dist/features/content/ContentAssets.js +84 -88
- package/dist/features/page/CuratedPageContent.js +1 -1
- package/dist/features/preview/CamoxPreview.d.ts +8 -4
- package/dist/features/preview/CamoxPreview.js +258 -443
- package/dist/features/preview/EditablePageContent.js +244 -2
- package/dist/features/preview/EditablePageExperience.js +19 -13
- package/dist/features/preview/components/AddBlockSheet.js +55 -15
- package/dist/features/preview/components/BlockActionsPopover.js +23 -51
- package/dist/features/preview/components/BlockPeek.js +66 -0
- package/dist/features/preview/components/BlockThumbnail.js +134 -119
- package/dist/features/preview/components/CanvasPreview.js +1 -1
- package/dist/features/preview/components/CreatePageModal.js +150 -156
- package/dist/features/preview/components/FieldToolbar.js +1 -1
- package/dist/features/preview/components/Frame.js +27 -4
- package/dist/features/preview/components/MobilePreviewDrawer.js +6 -9
- package/dist/features/preview/components/PageInfo.js +161 -126
- package/dist/features/preview/components/PagePicker.js +2 -2
- package/dist/features/preview/components/PageTree.js +174 -190
- package/dist/features/preview/components/PreviewPanel.js +13 -67
- package/dist/features/preview/components/PreviewToolbar.js +1 -1
- package/dist/features/preview/components/ReferenceFieldEditor.js +4 -4
- package/dist/features/preview/components/ReferenceListFieldEditor.js +4 -4
- package/dist/features/preview/components/RemovedBlockPlaceholder.js +37 -70
- package/dist/features/preview/components/RepeatableItemsList.js +1 -1
- package/dist/features/preview/components/SelectionEditor.js +248 -256
- package/dist/features/preview/components/StudioEditingFallback.js +22 -26
- package/dist/features/preview/components/useFieldWriter.js +19 -19
- package/dist/features/preview/components/useRecordView.js +105 -147
- package/dist/features/preview/components/useRepeatableItemActions.js +0 -2
- package/dist/features/preview/pageRecord.js +30 -24
- package/dist/features/preview/previewConstants.js +2 -8
- package/dist/features/preview/previewStore.js +2 -0
- package/dist/features/preview/studioNotice.js +20 -0
- package/dist/features/preview/usePreviewViewportActions.js +1 -1
- package/dist/features/provider/AuthenticatedCamoxProvider.js +47 -31
- package/dist/features/provider/components/CommandPalette.js +2 -5
- package/dist/features/provider/signInShortcut.js +1 -2
- package/dist/features/provider/useAdminShortcuts.js +47 -53
- package/dist/features/renderer/RendererApp.js +542 -0
- package/dist/features/renderer/RendererFrames.js +450 -0
- package/dist/features/renderer/definitionAnswers.js +26 -0
- package/dist/features/renderer/protocol.js +35 -0
- package/dist/features/renderer/rendererHost.js +249 -0
- package/dist/features/renderer/studioConnection.js +186 -0
- package/dist/features/routes/pageRuntime.d.ts +2 -1
- package/dist/features/routes/pageRuntime.js +34 -22
- package/dist/features/runtime/RuntimeChrome.js +2 -5
- package/dist/features/runtime/assetPrefix.js +14 -0
- package/dist/features/runtime/breadcrumbs.js +1 -1
- package/dist/features/runtime/editingFallback.js +4 -8
- package/dist/features/runtime/livePages.js +1 -1
- package/dist/features/runtime/pageApp.js +57 -83
- package/dist/features/runtime/pageClient.js +1 -1
- package/dist/features/runtime/pageNavigation.js +3 -2
- package/dist/features/runtime/publicCache.js +95 -0
- package/dist/features/runtime/publishingDraft.js +23 -0
- package/dist/features/runtime/rendererClient.d.ts +8 -0
- package/dist/features/runtime/rendererClient.js +77 -0
- package/dist/features/runtime/runtime.d.ts +22 -3
- package/dist/features/runtime/runtime.js +209 -96
- package/dist/features/runtime/runtimeRoutes.d.ts +2 -0
- package/dist/features/runtime/runtimeRoutes.js +2 -0
- package/dist/features/runtime/worker.d.ts +14 -1
- package/dist/features/runtime/worker.js +34 -4
- package/dist/features/settings/AnalyticsSettings.js +622 -0
- package/dist/features/settings/CamoxSettings.js +95 -0
- package/dist/features/settings/FaviconSettings.js +254 -0
- package/dist/features/settings/ProjectNameSettings.js +145 -0
- package/dist/features/settings/SettingsPart.js +73 -0
- package/dist/features/settings/SocialProfilesSettings.js +245 -0
- package/dist/features/settings/useProjectMutation.js +61 -0
- package/dist/features/studio/FollowAgentProvider.js +10 -10
- package/dist/features/studio/components/DraftsControl.js +136 -131
- package/dist/features/studio/components/LocalePicker.js +178 -174
- package/dist/features/studio/components/Navbar.js +107 -66
- package/dist/features/studio/components/ProjectMenu.js +119 -171
- package/dist/features/studio/components/ReviewDraftSheet.js +1151 -991
- package/dist/features/studio/components/ThreadMessages.js +100 -65
- package/dist/features/studio/components/UserButton.js +2 -2
- package/dist/features/studio/routes.js +3 -1
- package/dist/features/studio/showInCanvas.js +129 -0
- package/dist/features/vite/definitionsSync.js +5 -6
- package/dist/features/vite/hostedChecks.js +127 -0
- package/dist/features/vite/runtimeDev.js +58 -17
- package/dist/features/vite/staticAssetHeaders.js +52 -0
- package/dist/features/vite/vite.d.ts +1 -1
- package/dist/features/vite/vite.js +49 -9
- package/dist/hooks/use-page-destinations.js +10 -10
- package/dist/lib/api-client-server.d.ts +1 -1
- package/dist/lib/api-client.d.ts +2 -1
- package/dist/lib/draft-scope.d.ts +1 -0
- package/dist/lib/locale-path.d.ts +3 -11
- package/dist/lib/locale-path.js +3 -27
- package/dist/lib/queries.js +7 -1
- package/dist/lib/revisions.js +20 -0
- package/dist/lib/shortcuts.js +29 -0
- package/dist/lib/studio-definitions.js +160 -0
- package/dist/lib/studio-reads.d.ts +1 -0
- package/dist/lib/studio-reads.js +65 -21
- package/dist/lib/use-project-room.js +16 -10
- package/dist/lib/utils.js +1 -104
- package/dist/package.js +1 -1
- package/dist/studio.css +1 -1
- package/package.json +9 -4
- package/skills/camox/SKILL.md +4 -0
- package/skills/camox/references/artifacts.md +1 -1
- package/dist/features/studio/components/FaviconDialog.js +0 -318
- package/dist/features/studio/components/SocialProfilesDialog.js +0 -342
|
@@ -6,13 +6,14 @@ import { draftNamedBy } from "../../lib/draft-scope.js";
|
|
|
6
6
|
import { RUNTIME_ROUTE_PATHS, matchRuntimeOwnedRoute } from "./runtimeRoutes.js";
|
|
7
7
|
import { reads } from "../../lib/studio-reads.js";
|
|
8
8
|
import { asCollectionItem, recordMarkdownTemplate, recordPageValues } from "../../core/recordItem.js";
|
|
9
|
-
import { buildLayoutContext, curatedLayoutContext } from "../../core/layoutContext.js";
|
|
10
9
|
import { PLATFORM_SCRIPT } from "../../lib/platform.js";
|
|
11
|
-
import { STUDIO_ASSETS_PATH, STUDIO_CANVAS_PATH, STUDIO_CONTENT_PATH, matchCollectionContentPath } from "../studio/routes.js";
|
|
10
|
+
import { STUDIO_ASSETS_PATH, STUDIO_CANVAS_PATH, STUDIO_CONTENT_PATH, STUDIO_SETTINGS_PATH, matchCollectionContentPath } from "../studio/routes.js";
|
|
12
11
|
import { STUDIO_THEME_SCRIPT } from "../studio/studioTheme.js";
|
|
13
12
|
import { DefaultPageImage, renderPageImage } from "../og/pageImage.js";
|
|
14
13
|
import { discoverLayoutPages, matchDerivedLayout } from "../../core/derivedRoutes.js";
|
|
15
|
-
import {
|
|
14
|
+
import { buildLayoutContext, curatedLayoutContext } from "../../core/layoutContext.js";
|
|
15
|
+
import { buildCamoxPageHead, buildFaviconUrl, buildPageHead, buildPageMeta, createServerApiClient, createServerStudioCache, curatedMarkdownResponse, declarePage, isNotFoundError, loadCamoxPageForRequest, parseMarkdownPath, prefersMarkdown, readDraftOrLive, readPageMarkdown, readScopeLocales, renderedHref, resolveMemberProject, withFrontMatter } from "../routes/pageRuntime.js";
|
|
16
|
+
import { assetPrefix } from "./assetPrefix.js";
|
|
16
17
|
import { alternatesByPage, findAlternates, hreflangLinks } from "./alternates.js";
|
|
17
18
|
import { configuredProviders, renderAnalyticsScripts } from "./analytics.js";
|
|
18
19
|
import { omitArtifactSources } from "./artifactSources.js";
|
|
@@ -29,6 +30,13 @@ import { createHead, renderSSRHead } from "@unhead/react/server";
|
|
|
29
30
|
|
|
30
31
|
//#region src/features/runtime/runtime.ts
|
|
31
32
|
const DEFAULT_RUNTIME_BASE_PATH = "";
|
|
33
|
+
/** The studio's own routes, rather than a page or the Canvas. */
|
|
34
|
+
const STUDIO_ROUTE_KINDS = [
|
|
35
|
+
"studio",
|
|
36
|
+
"studio-content",
|
|
37
|
+
"studio-settings",
|
|
38
|
+
"studio-nested"
|
|
39
|
+
];
|
|
32
40
|
function normalizeRuntimeBasePath(basePath) {
|
|
33
41
|
if (basePath === void 0) return DEFAULT_RUNTIME_BASE_PATH;
|
|
34
42
|
if (!basePath || basePath === "/") return "";
|
|
@@ -57,6 +65,26 @@ function getRequestDraftId(request, options) {
|
|
|
57
65
|
function isPrivateRender(request, options) {
|
|
58
66
|
return !!getServerAuthCookieHeader(request.headers) || getRequestDraftId(request, options) !== void 0;
|
|
59
67
|
}
|
|
68
|
+
/** The routes whose response is the same for every visitor, unless the request is private. */
|
|
69
|
+
const PUBLIC_ROUTE_KINDS = /* @__PURE__ */ new Set([
|
|
70
|
+
"page",
|
|
71
|
+
"data",
|
|
72
|
+
"og",
|
|
73
|
+
"logo",
|
|
74
|
+
"sitemap",
|
|
75
|
+
"llms-txt"
|
|
76
|
+
]);
|
|
77
|
+
/**
|
|
78
|
+
* Whether a request reads what every visitor sees, so a shared cache may answer it: a GET or
|
|
79
|
+
* HEAD of a page or a public output, with no session, no draft named and no preview handoff. A
|
|
80
|
+
* response that comes out private all the same, such as the Studio's, still says so.
|
|
81
|
+
*/
|
|
82
|
+
function isPublicRequest(request, options = {}) {
|
|
83
|
+
if (request.method !== "GET" && request.method !== "HEAD") return false;
|
|
84
|
+
if (isPrivateRender(request, options) || isPreviewHandoff(request, options)) return false;
|
|
85
|
+
const pathname = getRuntimePathname(request.url, options.runtimeBasePath);
|
|
86
|
+
return pathname !== null && PUBLIC_ROUTE_KINDS.has(matchRuntimeRoute(pathname).kind);
|
|
87
|
+
}
|
|
60
88
|
function escapeXml(value) {
|
|
61
89
|
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """).replaceAll("'", "'");
|
|
62
90
|
}
|
|
@@ -90,6 +118,10 @@ function matchRuntimeRoute(pathname) {
|
|
|
90
118
|
kind: "studio-content",
|
|
91
119
|
pathname
|
|
92
120
|
};
|
|
121
|
+
if (pathname === "/camox/settings" || pathname === `${"/camox/settings"}/`) return {
|
|
122
|
+
kind: "studio-settings",
|
|
123
|
+
pathname
|
|
124
|
+
};
|
|
93
125
|
if (pathname.startsWith("/camox/")) return {
|
|
94
126
|
kind: "studio-nested",
|
|
95
127
|
pathname
|
|
@@ -184,10 +216,7 @@ function createLlmsTxtResponse(request, options) {
|
|
|
184
216
|
pages: website.localizations[0].pages,
|
|
185
217
|
layouts: (website.app?.getLayouts() ?? []).map(({ _internal }) => _internal),
|
|
186
218
|
url: absoluteUrl(request, options)
|
|
187
|
-
}), {
|
|
188
|
-
"Content-Type": "text/plain; charset=utf-8",
|
|
189
|
-
"Cache-Control": "public, max-age=300, stale-while-revalidate=3600"
|
|
190
|
-
}));
|
|
219
|
+
}), { "Content-Type": "text/plain; charset=utf-8" }));
|
|
191
220
|
}
|
|
192
221
|
/** Tells LLM tools fetching a page's HTML where the website's llms.txt is. */
|
|
193
222
|
function llmsTxtLinkHeader(options) {
|
|
@@ -431,8 +460,9 @@ function renderHead(document, pageHead, stylesheetUrl, studioStylesheetUrl, loca
|
|
|
431
460
|
return renderSSRHead(head);
|
|
432
461
|
}
|
|
433
462
|
/**
|
|
434
|
-
*
|
|
435
|
-
* script avoids a request waterfall.
|
|
463
|
+
* A visitor's browser loads a page's blocks before hydrating it. Preloading them alongside the
|
|
464
|
+
* entry script avoids a request waterfall. A member's document loads none: only its renderer
|
|
465
|
+
* frame runs the site's code.
|
|
436
466
|
*/
|
|
437
467
|
function renderBlockPreloads(options, dehydratedState) {
|
|
438
468
|
const preloads = options.blockPreloads;
|
|
@@ -442,24 +472,40 @@ function renderBlockPreloads(options, dehydratedState) {
|
|
|
442
472
|
const modulePath = preloads.modulePaths[type];
|
|
443
473
|
if (!modulePath) continue;
|
|
444
474
|
if (!preloads.chunks) urls.add(modulePath);
|
|
445
|
-
for (const chunk of preloads.chunks?.[modulePath] ?? []) urls.add(
|
|
475
|
+
for (const chunk of preloads.chunks?.[modulePath] ?? []) urls.add(`${assetPrefix()}${chunk}`);
|
|
446
476
|
}
|
|
447
477
|
return [...urls].map((url) => `<link rel="modulepreload" href="${escapeXml(url)}">`).join("");
|
|
448
478
|
}
|
|
479
|
+
/**
|
|
480
|
+
* The renderer frame's document (ADR 0023): an empty document running the renderer's client,
|
|
481
|
+
* which renders the studio's pages into its frames, reading them itself. It holds no content, but
|
|
482
|
+
* is only ever the studio's, so no shared cache keeps it.
|
|
483
|
+
*/
|
|
484
|
+
function createRendererDocumentResponse(options) {
|
|
485
|
+
const input = {
|
|
486
|
+
apiUrl: options.apiUrl,
|
|
487
|
+
authenticationUrl: options.authenticationUrl,
|
|
488
|
+
projectUuid: options.projectUuid,
|
|
489
|
+
runtimeBasePath: normalizeRuntimeBasePath(options.runtimeBasePath)
|
|
490
|
+
};
|
|
491
|
+
return new Response(`<!doctype html><html><head><meta charset="utf-8"><meta name="robots" content="noindex"><title>Camox renderer</title><script id="__CAMOX_DATA__" type="application/json">${serializeJsonForHtml(input)}<\/script></head><body>${renderClientEntryScript(options.rendererClientEntryUrl)}</body></html>`, { headers: {
|
|
492
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
493
|
+
"Cache-Control": "private, no-store",
|
|
494
|
+
"X-Robots-Tag": "noindex"
|
|
495
|
+
} });
|
|
496
|
+
}
|
|
449
497
|
function renderClientEntryScript(src) {
|
|
450
498
|
if (!src) return "";
|
|
451
499
|
return `<script type="module" src="${escapeXml(src)}"><\/script>`;
|
|
452
500
|
}
|
|
453
|
-
|
|
501
|
+
/**
|
|
502
|
+
* The site document the studio's frames load: the site's head and an empty root, which the
|
|
503
|
+
* renderer frame renders the page into. The studio never renders the site's code itself.
|
|
504
|
+
*/
|
|
505
|
+
function preparePreviewDocument(input, options, document) {
|
|
454
506
|
const siteHead = renderHead(document, createPageHeadInput(input.head ?? {}), options.stylesheetUrl, void 0, input.locale);
|
|
455
507
|
const href = new URL(withRuntimeBasePath(input.pathname, options.runtimeBasePath), input.href).href;
|
|
456
|
-
|
|
457
|
-
...input,
|
|
458
|
-
href,
|
|
459
|
-
presentation: "public",
|
|
460
|
-
previewDocument: void 0
|
|
461
|
-
}) : "");
|
|
462
|
-
input.previewDocument = `<!doctype html><html${siteHead.htmlAttrs}><head><base href="${escapeXml(href)}">${siteHead.headTags}</head><body${siteHead.bodyAttrs}>${siteHead.bodyTagsOpen}<div id="root" data-camox-preview-root>${siteHtml}</div>${siteHead.bodyTags}</body></html>`;
|
|
508
|
+
input.previewDocument = `<!doctype html><html${siteHead.htmlAttrs}><head><base href="${escapeXml(href)}">${siteHead.headTags}</head><body${siteHead.bodyAttrs}>${siteHead.bodyTagsOpen}<div id="root" data-camox-preview-root></div>${siteHead.bodyTags}</body></html>`;
|
|
463
509
|
}
|
|
464
510
|
/**
|
|
465
511
|
* The render input a page's HTML embeds for hydration. Visitors load public pages, whose HTML
|
|
@@ -492,8 +538,7 @@ function isPreviewHandoff(request, options) {
|
|
|
492
538
|
* The alternates of the page a request renders, where it exists in each of the scope's locales,
|
|
493
539
|
* and its head with their `hreflang` links. Without a head, there is none to add them to.
|
|
494
540
|
*/
|
|
495
|
-
async function readAlternates(request, options, { located, identity, head, described,
|
|
496
|
-
const localeReads = requestLocaleReads(options, reading);
|
|
541
|
+
async function readAlternates(request, options, { located, identity, head, described, localeReads }) {
|
|
497
542
|
const [alternates, crumbs] = await Promise.all([findRequestAlternates(options, located, identity, localeReads), head ? readRequestBreadcrumb(options, located, described.title, localeReads) : []]);
|
|
498
543
|
const url = absoluteUrl(request, options);
|
|
499
544
|
const links = hreflangLinks(alternates, located.locales, url);
|
|
@@ -565,7 +610,7 @@ function withLocatedTags(head, { url, locale, alternates }) {
|
|
|
565
610
|
}]
|
|
566
611
|
};
|
|
567
612
|
}
|
|
568
|
-
function requestLocaleReads(options, { authCookieHeader, draftId }) {
|
|
613
|
+
function requestLocaleReads(options, { authCookieHeader, draftId, queryClient }) {
|
|
569
614
|
const { apiUrl, projectUuid } = options;
|
|
570
615
|
const reading = {
|
|
571
616
|
authCookieHeader: draftId ? authCookieHeader : void 0,
|
|
@@ -573,9 +618,15 @@ function requestLocaleReads(options, { authCookieHeader, draftId }) {
|
|
|
573
618
|
};
|
|
574
619
|
const source = draftId ? "draft" : "live";
|
|
575
620
|
const pagesByLocale = /* @__PURE__ */ new Map();
|
|
621
|
+
const studioCache = apiUrl && queryClient ? createServerStudioCache(queryClient, { apiUrl }) : void 0;
|
|
576
622
|
return {
|
|
577
623
|
pages: (locale) => {
|
|
578
624
|
if (!apiUrl || !projectUuid) return Promise.resolve([]);
|
|
625
|
+
const loaded = studioCache?.get(reads.pageList({ projectUuid }), {
|
|
626
|
+
in: draftId ?? null,
|
|
627
|
+
locale
|
|
628
|
+
});
|
|
629
|
+
if (loaded) return Promise.resolve(loaded);
|
|
579
630
|
const read = pagesByLocale.get(locale.tag) ?? createServerApiClient(apiUrl, {
|
|
580
631
|
...reading,
|
|
581
632
|
locale
|
|
@@ -670,27 +721,89 @@ async function createPreviewHandoffResponse({ options, pathname, request }) {
|
|
|
670
721
|
"Referrer-Policy": "no-referrer"
|
|
671
722
|
} });
|
|
672
723
|
}
|
|
673
|
-
|
|
724
|
+
/** Starts reading the curated page at a locale-relative path, as the request reads it. */
|
|
725
|
+
function readCuratedPage(options, request, { locale, path }) {
|
|
726
|
+
const queryClient = new QueryClient();
|
|
727
|
+
return {
|
|
728
|
+
queryClient,
|
|
729
|
+
result: loadCamoxPageForRequest({
|
|
730
|
+
apiUrl: options.apiUrl,
|
|
731
|
+
authCookieHeader: getServerAuthCookieHeader(request.headers),
|
|
732
|
+
draftId: getRequestDraftId(request, options),
|
|
733
|
+
locale,
|
|
734
|
+
origin: new URL(request.url).origin,
|
|
735
|
+
pathname: path,
|
|
736
|
+
projectUuid: options.projectUuid,
|
|
737
|
+
queryClient
|
|
738
|
+
})
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
/** A first path segment that could be a locale's prefix: a language tag, in lowercase. */
|
|
742
|
+
const LOCALE_PREFIX_LIKE = /^\/[a-z]{2,3}(?:-[a-z0-9]{1,8})*(?:\/|$)/;
|
|
743
|
+
/**
|
|
744
|
+
* The read of the curated page a path names in the default locale, started while the request's
|
|
745
|
+
* locales are read, or none where it couldn't be the request's page. A default-locale page sits
|
|
746
|
+
* at its own path, so its read needn't wait for the locales: once read, they only confirm the path
|
|
747
|
+
* names no other locale. A path whose first segment looks like a locale's prefix waits for them
|
|
748
|
+
* instead, rather than reading a page it likely doesn't name, and a singleton's path reads no
|
|
749
|
+
* curated page.
|
|
750
|
+
*/
|
|
751
|
+
async function readDefaultLocalePageEarly(options, request, pathname) {
|
|
752
|
+
const { apiUrl, projectUuid } = options;
|
|
753
|
+
if (!apiUrl || !projectUuid) return void 0;
|
|
754
|
+
if (matchLocalizedRoute(pathname)?.kind !== "page" || LOCALE_PREFIX_LIKE.test(pathname)) return;
|
|
755
|
+
const app = await options.getCamoxApp?.().catch(() => void 0);
|
|
756
|
+
if (app && matchDerivedLayout(app.getLayouts(), pathname)?.layout._internal.kind === "singleton") return void 0;
|
|
757
|
+
const read = readCuratedPage({
|
|
758
|
+
...options,
|
|
759
|
+
apiUrl,
|
|
760
|
+
projectUuid
|
|
761
|
+
}, request, {
|
|
762
|
+
locale: UNNAMED_DEFAULT_LOCALE,
|
|
763
|
+
path: pathname
|
|
764
|
+
});
|
|
765
|
+
read.result.catch(() => void 0);
|
|
766
|
+
return read;
|
|
767
|
+
}
|
|
768
|
+
/**
|
|
769
|
+
* The reads of each locale the head of the request's curated page makes, and those it can make
|
|
770
|
+
* while the page is read. When the request reads Live, whatever the page's read finds about its
|
|
771
|
+
* draft, the pages of the locales the page's read doesn't load start loading now. Otherwise they
|
|
772
|
+
* wait for the page's read to settle the draft.
|
|
773
|
+
*/
|
|
774
|
+
function curatedPageLocaleReads(options, request, located, queryClient) {
|
|
775
|
+
const authCookieHeader = getServerAuthCookieHeader(request.headers);
|
|
776
|
+
const forDraft = (draftId) => requestLocaleReads(options, {
|
|
777
|
+
authCookieHeader,
|
|
778
|
+
draftId,
|
|
779
|
+
queryClient
|
|
780
|
+
});
|
|
781
|
+
if (!(!getRequestDraftId(request, options) || !authCookieHeader)) return forDraft;
|
|
782
|
+
const live = forDraft(void 0);
|
|
783
|
+
if (located.locales.length > 1) for (const locale of located.locales) {
|
|
784
|
+
if (locale.tag === located.locale.tag || locale.isDefault) continue;
|
|
785
|
+
live.pages(locale).catch(() => void 0);
|
|
786
|
+
}
|
|
787
|
+
return () => live;
|
|
788
|
+
}
|
|
789
|
+
async function createPageHtmlResponse({ options, pathname, located, request, pageRead }) {
|
|
674
790
|
if (!options.apiUrl || !options.authenticationUrl || !options.projectUuid || !options.renderPage) return createPageDataResponse({
|
|
675
791
|
options,
|
|
676
792
|
pathname,
|
|
677
793
|
located,
|
|
678
|
-
request
|
|
794
|
+
request,
|
|
795
|
+
pageRead
|
|
679
796
|
});
|
|
680
797
|
const singleton = await createDerivedResponse(options, pathname, located, request, { singletonOnly: true });
|
|
681
798
|
if (singleton) return singleton;
|
|
682
|
-
const queryClient =
|
|
799
|
+
const { queryClient, result: reading } = pageRead ?? readCuratedPage({
|
|
800
|
+
...options,
|
|
801
|
+
apiUrl: options.apiUrl,
|
|
802
|
+
projectUuid: options.projectUuid
|
|
803
|
+
}, request, located);
|
|
804
|
+
const localeReads = curatedPageLocaleReads(options, request, located, queryClient);
|
|
683
805
|
try {
|
|
684
|
-
const result = await
|
|
685
|
-
apiUrl: options.apiUrl,
|
|
686
|
-
authCookieHeader: getServerAuthCookieHeader(request.headers),
|
|
687
|
-
draftId: getRequestDraftId(request, options),
|
|
688
|
-
locale: located.locale,
|
|
689
|
-
origin: new URL(request.url).origin,
|
|
690
|
-
pathname: located.path,
|
|
691
|
-
projectUuid: options.projectUuid,
|
|
692
|
-
queryClient
|
|
693
|
-
});
|
|
806
|
+
const result = await reading;
|
|
694
807
|
const headers = new Headers({
|
|
695
808
|
"Content-Type": "text/html; charset=utf-8",
|
|
696
809
|
Vary: "Cookie",
|
|
@@ -708,8 +821,7 @@ async function createPageHtmlResponse({ options, pathname, located, request }) {
|
|
|
708
821
|
},
|
|
709
822
|
head: camoxApp ? buildCamoxPageHead(camoxApp, result.data, located.locale) : {},
|
|
710
823
|
described: curatedPageDescription(camoxApp, result.data.page, located.locale),
|
|
711
|
-
|
|
712
|
-
draftId: result.draftId
|
|
824
|
+
localeReads: localeReads(result.draftId)
|
|
713
825
|
});
|
|
714
826
|
const dehydratedState = dehydrate(queryClient);
|
|
715
827
|
const { project } = result;
|
|
@@ -738,7 +850,7 @@ async function createPageHtmlResponse({ options, pathname, located, request }) {
|
|
|
738
850
|
locale: located.locale,
|
|
739
851
|
locales: located.locales
|
|
740
852
|
};
|
|
741
|
-
|
|
853
|
+
preparePreviewDocument(pageRenderInput, options, document);
|
|
742
854
|
const appHtml = await options.renderPage(pageRenderInput);
|
|
743
855
|
const renderedHead = renderHead(studio ? {} : document, createPageHeadInput(head), studio ? void 0 : options.stylesheetUrl, studio ? options.studioStylesheetUrl : void 0, studio ? void 0 : located.locale);
|
|
744
856
|
return new Response(`<!doctype html>
|
|
@@ -747,7 +859,7 @@ async function createPageHtmlResponse({ options, pathname, located, request }) {
|
|
|
747
859
|
${renderStudioThemeScript(studio)}
|
|
748
860
|
${renderedHead.headTags}
|
|
749
861
|
${renderAnalyticsScripts(analytics)}
|
|
750
|
-
${renderBlockPreloads(options, dehydratedState)}
|
|
862
|
+
${studio ? "" : renderBlockPreloads(options, dehydratedState)}
|
|
751
863
|
<script id="__CAMOX_DATA__" type="application/json">${serializeJsonForHtml(hydrationInputFor(pageRenderInput, appHtml))}<\/script>
|
|
752
864
|
</head>
|
|
753
865
|
<body${renderedHead.bodyAttrs}>
|
|
@@ -982,8 +1094,10 @@ async function createDerivedResponse(options, pathname, located, request, { data
|
|
|
982
1094
|
titles: recordValues?.titles
|
|
983
1095
|
})
|
|
984
1096
|
},
|
|
985
|
-
|
|
986
|
-
|
|
1097
|
+
localeReads: requestLocaleReads(options, {
|
|
1098
|
+
authCookieHeader,
|
|
1099
|
+
draftId: read.draftId
|
|
1100
|
+
})
|
|
987
1101
|
});
|
|
988
1102
|
const analytics = dataOnly ? void 0 : visitorAnalytics(options, {
|
|
989
1103
|
studio,
|
|
@@ -1020,15 +1134,15 @@ async function createDerivedResponse(options, pathname, located, request, { data
|
|
|
1020
1134
|
}
|
|
1021
1135
|
};
|
|
1022
1136
|
const document = await options.getDocument?.() ?? {};
|
|
1023
|
-
|
|
1137
|
+
preparePreviewDocument(input, options, document);
|
|
1024
1138
|
if (dataOnly) return Response.json(input, { headers: {
|
|
1025
|
-
"Cache-Control": "private, no-store",
|
|
1139
|
+
...isPrivateRender(request, options) ? { "Cache-Control": "private, no-store" } : {},
|
|
1026
1140
|
Vary: "Cookie",
|
|
1027
1141
|
...clearAuthCookie ? { "Set-Cookie": buildClearServerAuthCookieHeader() } : {}
|
|
1028
1142
|
} });
|
|
1029
1143
|
const html = await options.renderPage(input);
|
|
1030
1144
|
const head = renderHead(studio ? {} : document, createPageHeadInput(pageHead), studio ? void 0 : options.stylesheetUrl, studio ? options.studioStylesheetUrl : void 0, studio ? void 0 : located.locale);
|
|
1031
|
-
return new Response(`<!doctype html><html${head.htmlAttrs}><head>${renderStudioThemeScript(studio)}${head.headTags}${renderAnalyticsScripts(analytics)}${renderBlockPreloads(options, input.dehydratedState)}<script id="__CAMOX_DATA__" type="application/json">${serializeJsonForHtml(hydrationInputFor(input, html))}<\/script></head><body${head.bodyAttrs}>${head.bodyTagsOpen}<div id="root">${html}</div>${head.bodyTags}${renderClientEntryScript(options.pageClientEntryUrl)}</body></html>`, { headers: {
|
|
1145
|
+
return new Response(`<!doctype html><html${head.htmlAttrs}><head>${renderStudioThemeScript(studio)}${head.headTags}${renderAnalyticsScripts(analytics)}${studio ? "" : renderBlockPreloads(options, input.dehydratedState)}<script id="__CAMOX_DATA__" type="application/json">${serializeJsonForHtml(hydrationInputFor(input, html))}<\/script></head><body${head.bodyAttrs}>${head.bodyTagsOpen}<div id="root">${html}</div>${head.bodyTags}${renderClientEntryScript(options.pageClientEntryUrl)}</body></html>`, { headers: {
|
|
1032
1146
|
"Content-Type": "text/html; charset=utf-8",
|
|
1033
1147
|
Vary: "Cookie",
|
|
1034
1148
|
Link: llmsTxtLinkHeader(options),
|
|
@@ -1136,30 +1250,26 @@ async function createCanvasOnlyResponse({ options, pathname, located, request, d
|
|
|
1136
1250
|
...headers
|
|
1137
1251
|
} });
|
|
1138
1252
|
}
|
|
1139
|
-
async function createPageDataResponse({ options, pathname, located, request }) {
|
|
1253
|
+
async function createPageDataResponse({ options, pathname, located, request, pageRead }) {
|
|
1140
1254
|
if (!options.apiUrl || !options.projectUuid) return Response.json({ message: "Camox page loader is not configured." }, { status: 500 });
|
|
1141
1255
|
const singleton = await createDerivedResponse(options, pathname, located, request, {
|
|
1142
1256
|
dataOnly: true,
|
|
1143
1257
|
singletonOnly: true
|
|
1144
1258
|
});
|
|
1145
1259
|
if (singleton) return singleton;
|
|
1146
|
-
const queryClient =
|
|
1260
|
+
const { queryClient, result: reading } = pageRead ?? readCuratedPage({
|
|
1261
|
+
...options,
|
|
1262
|
+
apiUrl: options.apiUrl,
|
|
1263
|
+
projectUuid: options.projectUuid
|
|
1264
|
+
}, request, located);
|
|
1265
|
+
const localeReads = curatedPageLocaleReads(options, request, located, queryClient);
|
|
1147
1266
|
try {
|
|
1148
|
-
const result = await
|
|
1149
|
-
apiUrl: options.apiUrl,
|
|
1150
|
-
authCookieHeader: getServerAuthCookieHeader(request.headers),
|
|
1151
|
-
draftId: getRequestDraftId(request, options),
|
|
1152
|
-
locale: located.locale,
|
|
1153
|
-
origin: new URL(request.url).origin,
|
|
1154
|
-
pathname: located.path,
|
|
1155
|
-
projectUuid: options.projectUuid,
|
|
1156
|
-
queryClient
|
|
1157
|
-
});
|
|
1267
|
+
const result = await reading;
|
|
1158
1268
|
const headers = new Headers({
|
|
1159
1269
|
"Content-Type": "application/json; charset=utf-8",
|
|
1160
|
-
"Cache-Control": "private, no-store",
|
|
1161
1270
|
Vary: "Cookie"
|
|
1162
1271
|
});
|
|
1272
|
+
if (isPrivateRender(request, options)) headers.set("Cache-Control", "private, no-store");
|
|
1163
1273
|
if (result.shouldClearAuthCookie) headers.append("Set-Cookie", buildClearServerAuthCookieHeader());
|
|
1164
1274
|
const camoxApp = await options.getCamoxApp?.();
|
|
1165
1275
|
const { alternates, head } = await readAlternates(request, options, {
|
|
@@ -1170,8 +1280,7 @@ async function createPageDataResponse({ options, pathname, located, request }) {
|
|
|
1170
1280
|
},
|
|
1171
1281
|
head: camoxApp ? buildCamoxPageHead(camoxApp, result.data, located.locale) : null,
|
|
1172
1282
|
described: curatedPageDescription(camoxApp, result.data.page, located.locale),
|
|
1173
|
-
|
|
1174
|
-
draftId: result.draftId
|
|
1283
|
+
localeReads: localeReads(result.draftId)
|
|
1175
1284
|
});
|
|
1176
1285
|
const dehydratedState = dehydrate(queryClient);
|
|
1177
1286
|
const input = {
|
|
@@ -1193,7 +1302,7 @@ async function createPageDataResponse({ options, pathname, located, request }) {
|
|
|
1193
1302
|
head,
|
|
1194
1303
|
dehydratedState
|
|
1195
1304
|
};
|
|
1196
|
-
|
|
1305
|
+
preparePreviewDocument(input, options, await options.getDocument?.() ?? {});
|
|
1197
1306
|
return Response.json(input, { headers });
|
|
1198
1307
|
} catch (error) {
|
|
1199
1308
|
if (isNotFoundError(error)) {
|
|
@@ -1222,6 +1331,7 @@ async function handleCamoxRequest(request, options = {}) {
|
|
|
1222
1331
|
});
|
|
1223
1332
|
}
|
|
1224
1333
|
if (match.kind === "og") return createOgResponse(request, options);
|
|
1334
|
+
if (match.kind === "renderer") return createRendererDocumentResponse(options);
|
|
1225
1335
|
if (match.kind === "logo") return createProjectLogoResponse(request, options);
|
|
1226
1336
|
if (match.kind === "sitemap") return createSitemapResponse(request, options);
|
|
1227
1337
|
if (match.kind === "llms-txt") return createLlmsTxtResponse(request, options);
|
|
@@ -1239,19 +1349,17 @@ async function handleCamoxRequest(request, options = {}) {
|
|
|
1239
1349
|
const { apiUrl, projectUuid } = options;
|
|
1240
1350
|
const markdownPathname = parseMarkdownPath(pathname);
|
|
1241
1351
|
if (apiUrl && projectUuid && (markdownPathname || prefersMarkdown(request.headers.get("Accept") ?? ""))) {
|
|
1242
|
-
const
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
if (markdownPathname) return new Response("Page not found", { status: 404 });
|
|
1254
|
-
}
|
|
1352
|
+
const markdownResponse = await createPageMarkdownResponse({
|
|
1353
|
+
...options,
|
|
1354
|
+
apiUrl,
|
|
1355
|
+
projectUuid
|
|
1356
|
+
}, {
|
|
1357
|
+
pathname: markdownPathname ?? pathname,
|
|
1358
|
+
request,
|
|
1359
|
+
pagesOnly: !markdownPathname
|
|
1360
|
+
});
|
|
1361
|
+
if (markdownResponse) return markdownResponse;
|
|
1362
|
+
if (markdownPathname) return new Response("Page not found", { status: 404 });
|
|
1255
1363
|
}
|
|
1256
1364
|
return respondInLocale(options, request, pathname);
|
|
1257
1365
|
}
|
|
@@ -1260,7 +1368,7 @@ async function handleCamoxRequest(request, options = {}) {
|
|
|
1260
1368
|
* With `dataOnly`, as the JSON client navigation loads.
|
|
1261
1369
|
*/
|
|
1262
1370
|
async function respondInLocale(options, request, pathname, { dataOnly = false } = {}) {
|
|
1263
|
-
const located = await locateRequest(request, options, pathname);
|
|
1371
|
+
const [early, located] = await Promise.all([readDefaultLocalePageEarly(options, request, pathname), locateRequest(request, options, pathname)]);
|
|
1264
1372
|
const localized = matchLocalizedRoute(located.path);
|
|
1265
1373
|
if (!localized) return new Response("Not found", { status: 404 });
|
|
1266
1374
|
const target = {
|
|
@@ -1278,13 +1386,29 @@ async function respondInLocale(options, request, pathname, { dataOnly = false }
|
|
|
1278
1386
|
match: localized,
|
|
1279
1387
|
dataOnly
|
|
1280
1388
|
});
|
|
1281
|
-
|
|
1389
|
+
const page = {
|
|
1390
|
+
...target,
|
|
1391
|
+
pageRead: located.locale.isDefault ? early : void 0
|
|
1392
|
+
};
|
|
1393
|
+
return dataOnly ? createPageDataResponse(page) : createPageHtmlResponse(page);
|
|
1282
1394
|
}
|
|
1283
1395
|
/**
|
|
1284
1396
|
* A page's Markdown Representation in its locale, with the same precedence as its HTML:
|
|
1285
|
-
* singleton, curated page, then derived layout. Null when the page has none.
|
|
1397
|
+
* singleton, curated page, then derived layout. Null when the page has none. Markdown is a public
|
|
1398
|
+
* output: it reads Live, whoever asks, and one read finds the path's locale and its curated page.
|
|
1286
1399
|
*/
|
|
1287
|
-
async function createPageMarkdownResponse(options, {
|
|
1400
|
+
async function createPageMarkdownResponse(options, { pathname, request, pagesOnly }) {
|
|
1401
|
+
let read;
|
|
1402
|
+
try {
|
|
1403
|
+
read = await readPageMarkdown({
|
|
1404
|
+
...options,
|
|
1405
|
+
path: pathname
|
|
1406
|
+
});
|
|
1407
|
+
} catch {
|
|
1408
|
+
return null;
|
|
1409
|
+
}
|
|
1410
|
+
const { locale, path } = read;
|
|
1411
|
+
if (pagesOnly && matchLocalizedRoute(path)?.kind !== "page") return null;
|
|
1288
1412
|
const page = {
|
|
1289
1413
|
pathname,
|
|
1290
1414
|
url: absoluteUrl(request, options)(pathname)
|
|
@@ -1292,20 +1416,12 @@ async function createPageMarkdownResponse(options, { locale, path }, { pathname,
|
|
|
1292
1416
|
const app = await options.getCamoxApp?.();
|
|
1293
1417
|
const layoutMatch = app && matchDerivedLayout(app.getLayouts(), path);
|
|
1294
1418
|
if (layoutMatch?.layout._internal.kind === "singleton") return createLayoutMarkdownResponse(options, layoutMatch, locale, page);
|
|
1295
|
-
return
|
|
1296
|
-
|
|
1297
|
-
camoxApp: app,
|
|
1298
|
-
locale,
|
|
1299
|
-
pathname: path,
|
|
1300
|
-
projectUuid: options.projectUuid,
|
|
1301
|
-
request,
|
|
1302
|
-
url: page.url,
|
|
1303
|
-
onNotFound: async () => layoutMatch ? createLayoutMarkdownResponse(options, layoutMatch, locale, page) : null
|
|
1304
|
-
});
|
|
1419
|
+
if (read.page) return curatedMarkdownResponse(app, read, page.url);
|
|
1420
|
+
return layoutMatch ? createLayoutMarkdownResponse(options, layoutMatch, locale, page) : null;
|
|
1305
1421
|
}
|
|
1306
1422
|
/** Whether a route is one of the studio's own, rather than a page or the Canvas. */
|
|
1307
1423
|
function isStudioRoute(match) {
|
|
1308
|
-
return
|
|
1424
|
+
return STUDIO_ROUTE_KINDS.includes(match.kind);
|
|
1309
1425
|
}
|
|
1310
1426
|
/**
|
|
1311
1427
|
* The studio or page route a locale-relative path names, or null for a runtime-owned route
|
|
@@ -1317,19 +1433,16 @@ function matchLocalizedRoute(path) {
|
|
|
1317
1433
|
}
|
|
1318
1434
|
/**
|
|
1319
1435
|
* The locale a request's path names, among the locales of the scope it reads: the URL's draft's
|
|
1320
|
-
* for a session naming one, else Live's.
|
|
1321
|
-
*
|
|
1322
|
-
* render.
|
|
1436
|
+
* for a session naming one, else Live's. Without an API there are none to read: every path is the
|
|
1437
|
+
* default locale's, which then says it can't render.
|
|
1323
1438
|
*/
|
|
1324
|
-
async function locateRequest(request, options, pathname
|
|
1439
|
+
async function locateRequest(request, options, pathname) {
|
|
1325
1440
|
const { apiUrl, projectUuid } = options;
|
|
1326
1441
|
const locales = apiUrl && projectUuid ? await readScopeLocales({
|
|
1327
1442
|
apiUrl,
|
|
1328
1443
|
projectUuid,
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
draftId: getRequestDraftId(request, options)
|
|
1332
|
-
}
|
|
1444
|
+
authCookieHeader: getServerAuthCookieHeader(request.headers),
|
|
1445
|
+
draftId: getRequestDraftId(request, options)
|
|
1333
1446
|
}) : [UNNAMED_DEFAULT_LOCALE];
|
|
1334
1447
|
return {
|
|
1335
1448
|
...parseLocalePath(pathname, locales),
|
|
@@ -1338,4 +1451,4 @@ async function locateRequest(request, options, pathname, { live = false } = {})
|
|
|
1338
1451
|
}
|
|
1339
1452
|
|
|
1340
1453
|
//#endregion
|
|
1341
|
-
export { createPageHeadInput, getRuntimePathname, handleCamoxRequest, matchRuntimeRoute };
|
|
1454
|
+
export { createPageHeadInput, getRuntimePathname, handleCamoxRequest, isPublicRequest, matchRuntimeRoute };
|
|
@@ -10,6 +10,8 @@ export declare const RUNTIME_ROUTE_PATHS: {
|
|
|
10
10
|
readonly data: "/_camox/data";
|
|
11
11
|
readonly health: "/_camox/health";
|
|
12
12
|
readonly registry: "/_camox/registry";
|
|
13
|
+
/** The renderer frame's document (ADR 0023), which the studio loads to render its pages. */
|
|
14
|
+
readonly renderer: "/_camox/renderer";
|
|
13
15
|
readonly routes: "/_camox/routes";
|
|
14
16
|
readonly logo: "/_camox/logo.png";
|
|
15
17
|
readonly og: "/og";
|
|
@@ -10,6 +10,8 @@ const RUNTIME_ROUTE_PATHS = {
|
|
|
10
10
|
data: "/_camox/data",
|
|
11
11
|
health: "/_camox/health",
|
|
12
12
|
registry: "/_camox/registry",
|
|
13
|
+
/** The renderer frame's document (ADR 0023), which the studio loads to render its pages. */
|
|
14
|
+
renderer: "/_camox/renderer",
|
|
13
15
|
routes: "/_camox/routes",
|
|
14
16
|
logo: "/_camox/logo.png",
|
|
15
17
|
og: "/og",
|
|
@@ -1,6 +1,19 @@
|
|
|
1
|
+
import { WorkerEntrypoint } from "cloudflare:workers";
|
|
1
2
|
//#region src/features/runtime/worker.d.ts
|
|
3
|
+
/** What the Worker gets with each request: only `waitUntil` matters here. */
|
|
4
|
+
interface WorkerContext {
|
|
5
|
+
waitUntil(promise: Promise<unknown>): void;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The website's Definition Set, for the Worker that loads a revision, which calls it by the name
|
|
9
|
+
* `DEFINITION_SET_ENTRYPOINT` holds. A named `WorkerEntrypoint` takes RPC calls only: no HTTP
|
|
10
|
+
* request reaches it.
|
|
11
|
+
*/
|
|
12
|
+
export declare class CamoxDefinitionSet extends WorkerEntrypoint {
|
|
13
|
+
read(): Promise<unknown>;
|
|
14
|
+
}
|
|
2
15
|
declare const _default: {
|
|
3
|
-
fetch(request: Request): Promise<Response>;
|
|
16
|
+
fetch(request: Request, env?: unknown, context?: WorkerContext): Promise<Response>;
|
|
4
17
|
};
|
|
5
18
|
//#endregion
|
|
6
19
|
export { _default as default };
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { rememberPublishingDraft } from "./publishingDraft.js";
|
|
1
2
|
import { fetchLocalhostOnLoopback } from "./loopbackFetch.js";
|
|
3
|
+
import { PUBLIC_CACHE_NAME, readLiveCacheKey, respondThroughPublicCache } from "./publicCache.js";
|
|
2
4
|
import { shouldHandleRequest, withDevHtml } from "./workerRequest.js";
|
|
3
|
-
import {
|
|
5
|
+
import { WorkerEntrypoint } from "cloudflare:workers";
|
|
6
|
+
import { devHtml, handleCamoxRequest, isPublicRequest, publicCacheSource, readDefinitionSet, runtimeBasePath } from "virtual:camox/server";
|
|
4
7
|
|
|
5
8
|
//#region src/features/runtime/worker.ts
|
|
6
9
|
/**
|
|
@@ -12,12 +15,39 @@ if (devHtml) globalThis.fetch = fetchLocalhostOnLoopback(globalThis.fetch.bind(g
|
|
|
12
15
|
function notFound() {
|
|
13
16
|
return new Response("Not found", { status: 404 });
|
|
14
17
|
}
|
|
15
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Answers a request, from the edge cache when every visitor sees the same. Dev renders the
|
|
20
|
+
* developer's development draft, which nothing shares, and a Worker calling this one without
|
|
21
|
+
* its context can't keep anything past the response.
|
|
22
|
+
*/
|
|
23
|
+
function respond(request, context) {
|
|
24
|
+
const caches = globalThis.caches;
|
|
25
|
+
if (devHtml || !context || !caches || !isPublicRequest(request)) return handleCamoxRequest(request);
|
|
26
|
+
const { apiUrl, projectUuid, build } = publicCacheSource;
|
|
27
|
+
return respondThroughPublicCache(request, {
|
|
28
|
+
cache: () => caches.open(PUBLIC_CACHE_NAME),
|
|
29
|
+
liveCacheKey: () => readLiveCacheKey(apiUrl, projectUuid),
|
|
30
|
+
build,
|
|
31
|
+
waitUntil: (promise) => context.waitUntil(promise)
|
|
32
|
+
}, () => handleCamoxRequest(request));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The website's Definition Set, for the Worker that loads a revision, which calls it by the name
|
|
36
|
+
* `DEFINITION_SET_ENTRYPOINT` holds. A named `WorkerEntrypoint` takes RPC calls only: no HTTP
|
|
37
|
+
* request reaches it.
|
|
38
|
+
*/
|
|
39
|
+
var CamoxDefinitionSet = class extends WorkerEntrypoint {
|
|
40
|
+
read() {
|
|
41
|
+
return readDefinitionSet();
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
var worker_default = { async fetch(request, env, context) {
|
|
45
|
+
rememberPublishingDraft(env);
|
|
16
46
|
if (!shouldHandleRequest(request, runtimeBasePath)) return notFound();
|
|
17
|
-
const response = await
|
|
47
|
+
const response = await respond(request, context);
|
|
18
48
|
if (!response) return notFound();
|
|
19
49
|
return withDevHtml(response, devHtml);
|
|
20
50
|
} };
|
|
21
51
|
|
|
22
52
|
//#endregion
|
|
23
|
-
export { worker_default as default };
|
|
53
|
+
export { CamoxDefinitionSet, worker_default as default };
|