Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.cursorindexingignore
.specstory/
95 changes: 95 additions & 0 deletions website/pages/Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ import {
import { logger } from "@deco/deco/o11y";
import { Component, JSX } from "preact";
import ErrorPageComponent from "../../utils/defaultErrorPage.tsx";
import {
DECO_PAGE_CACHE_ALLOW_HEADER,
DECO_PAGE_CACHE_CONTROL_HEADER,
normalizeCacheControlHeader,
} from "@deco/deco/utils";
Comment on lines +19 to +23
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix missing exports before merge

The CI run for November 12, 2025 is failing with TS2305 because @deco/[email protected]/utils does not export DECO_PAGE_CACHE_ALLOW_HEADER, DECO_PAGE_CACHE_CONTROL_HEADER, or normalizeCacheControlHeader. Please point these imports at a module that actually exports them (or update the dependency to a version that does) so the project compiles.

🧰 Tools
🪛 GitHub Actions: ci

[error] 20-20: TS2305: Module 'https://jsr.io/@deco/deco/1.128.2/utils/mod.ts' has no exported member 'DECO_PAGE_CACHE_ALLOW_HEADER'.


[error] 21-21: TS2305: Module 'https://jsr.io/@deco/deco/1.128.2/utils/mod.ts' has no exported member 'DECO_PAGE_CACHE_CONTROL_HEADER'.


[error] 22-22: TS2305: Module 'https://jsr.io/@deco/deco/1.128.2/utils/mod.ts' has no exported member 'normalizeCacheControlHeader'.

🤖 Prompt for AI Agents
In website/pages/Page.tsx around lines 19 to 23, the current import targets
DECO_PAGE_CACHE_ALLOW_HEADER, DECO_PAGE_CACHE_CONTROL_HEADER, and
normalizeCacheControlHeader from "@deco/deco/utils", but that module version
(1.128.2) does not export those symbols; either update the dependency to a
release that exports them or change the import to the module that actually
exports them (e.g., import from the correct path in @deco/deco such as
"@deco/deco/cache" or the module where those names live). Modify the import
statement to reference the correct module, then run the lockfile install
(npm/yarn/pnpm install) and re-run TypeScript to ensure TS2305 is resolved.

import OneDollarStats from "../components/OneDollarStats.tsx";
import Events from "../components/Events.tsx";
import { SEOSection } from "../components/Seo.tsx";
Expand Down Expand Up @@ -50,9 +55,55 @@ export interface Props {
/** @hide true */
seo?: Section<SEOSection>;
sections: Sections;
/**
* @title Cache this page in CDN
* @description When enabled, the page is cached at the CDN edge. Only device and time variants are respected while caching; any other variant types will be ignored. If any uncached loader is preset, this will be automatically disabled.
* @default false
*/
cacheControl?: boolean;
/**
* @title Cache-Control header
* @description Choose the default safe header or provide a custom one
*/
cacheHeader?: CacheHeaderConfig;
/** @hide true */
unindexedDomain?: boolean;
}
/**
* @title Cache-Control header
*/
export type CacheHeaderConfig = CacheHeaderDefault | CacheHeaderCustom;

/**
* @title Default
*/
interface CacheHeaderDefault {
/**
* @title Mode
* @default default
* @hide true
* @readOnly true
*/
mode?: "default";
}

/**
* @title Custom
*/
interface CacheHeaderCustom {
/**
* @title Mode
* @default custom
* @hide true
* @readOnly true
*/
mode?: "custom";
/**
* @title Cache-Control header
* @description Example: public, s-maxage=60, max-age=10, stale-while-revalidate=3600, stale-if-error=86400
*/
value: string;
}
export function renderSection(section: Props["sections"][number]) {
if (section === undefined || section === null) {
return <div></div>;
Expand Down Expand Up @@ -174,6 +225,50 @@ export const loader = async (
? [ctx.theme, ...resolvedGlobals]
: resolvedGlobals;

// Page-level cache-control: if configured, set headers early so render-time matchers can react.
const normalizedCC = (() => {
// Primary: boolean|string cacheControl + header options
const cc = (restProps as unknown as { cacheControl?: boolean | string })
?.cacheControl;
if (cc === true) {
const headerCfg = (restProps as unknown as {
cacheHeader?: CacheHeaderConfig;
})?.cacheHeader;
if (
(headerCfg as CacheHeaderCustom)?.mode === "custom" &&
(headerCfg as CacheHeaderCustom)?.value
) {
return normalizeCacheControlHeader(
(headerCfg as CacheHeaderCustom).value,
);
}
return normalizeCacheControlHeader(true);
}

// Backward compatibility: union object previously used
const legacyUnion = (restProps as unknown as {
cache?:
| { mode?: "off" | "default" | "custom"; value?: string }
| undefined;
})?.cache;
if (legacyUnion?.mode === "default") {
return normalizeCacheControlHeader(true);
}
if (legacyUnion?.mode === "custom" && legacyUnion.value) {
return normalizeCacheControlHeader(legacyUnion.value);
}
// Legacy direct string support
if (typeof cc === "string") {
return normalizeCacheControlHeader(cc);
}
return undefined; // off or not set
})();
if (normalizedCC) {
ctx.response.headers.set(DECO_PAGE_CACHE_CONTROL_HEADER, normalizedCC);
// Only device/time variants are allowed when page cache-control is on
ctx.response.headers.set(DECO_PAGE_CACHE_ALLOW_HEADER, "device,time");
}

return {
...restProps,
sections: [...globalSections, ...(Array.isArray(sections) ? sections : [])],
Expand Down
Loading