@agence-zef/astro 0.5.0 → 0.6.0-pilot.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/components/routes/cache.ts +10 -0
- package/components/routes/llms.ts +4 -1
- package/components/routes/page-cached.astro +69 -0
- package/components/routes/revalidate.ts +33 -0
- package/components/routes/robots.ts +4 -1
- package/components/routes/sitemap.ts +4 -1
- package/dist/helpers.d.ts +6 -0
- package/dist/helpers.js +81 -22
- package/dist/index.js +48 -6
- package/package.json +7 -4
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Rendu à la demande (`rendering: "cached"`) : règles de cache des pages du CMS. Le CDN garde
|
|
3
|
+
* une page un an ; une publication l'invalide par le tag `zef` (le CDN sert l'ancienne version
|
|
4
|
+
* le temps d'en rendre une nouvelle, `swr`).
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/** Tag posé sur toutes les réponses du site rendues depuis le CMS. */
|
|
8
|
+
export const CACHE_TAG = "zef";
|
|
9
|
+
|
|
10
|
+
export const PAGE_CACHE = { maxAge: 60 * 60 * 24 * 365, swr: 60 * 60 * 24 * 7 };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import config from "virtual:zef/config";
|
|
2
2
|
import { getClient, llmsTxt, siteOrigin, zefSiteIndex } from "@agence-zef/astro";
|
|
3
3
|
import type { APIRoute } from "astro";
|
|
4
|
+
import { CACHE_TAG, PAGE_CACHE } from "./cache";
|
|
4
5
|
|
|
5
6
|
/*
|
|
6
7
|
* `llms.txt` injecté par `@agence-zef/astro` (§ 5.13, format llmstxt.org) : le site présenté aux
|
|
@@ -9,7 +10,9 @@ import type { APIRoute } from "astro";
|
|
|
9
10
|
|
|
10
11
|
export const prerender = true;
|
|
11
12
|
|
|
12
|
-
export const GET: APIRoute = async ({ site: astroSite }) => {
|
|
13
|
+
export const GET: APIRoute = async ({ site: astroSite, cache }) => {
|
|
14
|
+
// Rendu à la demande (`rendering: "cached"`) : gardé en cache, invalidé par une publication.
|
|
15
|
+
cache.set({ ...PAGE_CACHE, tags: [CACHE_TAG] });
|
|
13
16
|
const site = await getClient().site();
|
|
14
17
|
const collections = (config.collections ?? [])
|
|
15
18
|
.filter((c) => c.page)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
import Layout from "virtual:zef/layout";
|
|
3
|
+
/**
|
|
4
|
+
* Rendu à la demande (`defineConfig({ rendering: "cached" })`) : chaque page du CMS ou élément
|
|
5
|
+
* de collection est rendu à la première visite puis gardé en cache par le CDN (route caching
|
|
6
|
+
* d'Astro), avec le tag `zef`. Une publication invalide ce tag (`/__zef/revalidate`) : les pages
|
|
7
|
+
* sont rafraîchies à la visite suivante, sans build. Contenu réservé : jamais en cache.
|
|
8
|
+
* Adresse inconnue : redirection du CMS (C-17) si elle existe, sinon 404.
|
|
9
|
+
*/
|
|
10
|
+
import { getClient, type RouteProps, zefRouteProps } from "@agence-zef/astro";
|
|
11
|
+
import { visitorOf } from "@agence-zef/astro/accounts";
|
|
12
|
+
import ReservedNotice from "../ReservedNotice.astro";
|
|
13
|
+
import ZefSections from "../ZefSections.astro";
|
|
14
|
+
import { CACHE_TAG, PAGE_CACHE } from "./cache";
|
|
15
|
+
|
|
16
|
+
const path = decodeURI(Astro.url.pathname);
|
|
17
|
+
let props: RouteProps | null;
|
|
18
|
+
try {
|
|
19
|
+
props = await zefRouteProps(path, visitorOf(Astro));
|
|
20
|
+
} catch {
|
|
21
|
+
// CMS injoignable : 503 sans cache, le CDN continue de servir la version qu'il a.
|
|
22
|
+
Astro.cache.set(false);
|
|
23
|
+
return new Response("Service momentanément indisponible.", { status: 503 });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (!props) {
|
|
27
|
+
const redirect = (
|
|
28
|
+
await getClient()
|
|
29
|
+
.redirects()
|
|
30
|
+
.catch(() => [])
|
|
31
|
+
).find((r) => r.from === path || r.from === path.replace(/\/$/, ""));
|
|
32
|
+
Astro.cache.set({ maxAge: 60, tags: [CACHE_TAG] });
|
|
33
|
+
if (redirect) return Astro.redirect(redirect.to, redirect.status === 302 ? 302 : 301);
|
|
34
|
+
return new Response(null, { status: 404 });
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const doc = props.kind === "page" ? props.page : props.item;
|
|
38
|
+
const reserved = doc.access?.reserved === true;
|
|
39
|
+
// Le contenu réservé dépend du visiteur : jamais en cache.
|
|
40
|
+
if (reserved) Astro.cache.set(false);
|
|
41
|
+
else Astro.cache.set({ ...PAGE_CACHE, tags: [CACHE_TAG] });
|
|
42
|
+
|
|
43
|
+
// Site en développement (§ 5.11) : aucune page n'est indexable.
|
|
44
|
+
const seo =
|
|
45
|
+
props.site.indexable === false || reserved ? { ...props.seo, noindex: true } : props.seo;
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
<Layout
|
|
49
|
+
site={props.site}
|
|
50
|
+
locale={props.locale}
|
|
51
|
+
title={props.title}
|
|
52
|
+
seo={seo}
|
|
53
|
+
alternates={props.alternates}
|
|
54
|
+
url={props.url}
|
|
55
|
+
breadcrumbs={props.breadcrumbs}
|
|
56
|
+
item={props.kind === "item" ? props.item : undefined}
|
|
57
|
+
header={props.header}
|
|
58
|
+
footer={props.footer}
|
|
59
|
+
>
|
|
60
|
+
{
|
|
61
|
+
reserved && !doc.access?.granted ? (
|
|
62
|
+
<ReservedNotice title={props.title} products={doc.access?.products ?? []} />
|
|
63
|
+
) : props.kind === "page" ? (
|
|
64
|
+
<ZefSections sections={props.page.sections} />
|
|
65
|
+
) : (
|
|
66
|
+
<ZefSections sections={props.item.sections ?? []} item={props.item} />
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
</Layout>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { createClient } from "@agence-zef/sdk";
|
|
2
|
+
import type { APIRoute } from "astro";
|
|
3
|
+
import { CACHE_TAG } from "./cache";
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
* Invalidation du cache après une publication (`rendering: "cached"`) : le CMS appelle
|
|
7
|
+
* `POST /__zef/revalidate` avec un jeton d'aperçu de ce site (`Authorization: Bearer …`). Le site
|
|
8
|
+
* vérifie le jeton auprès de son CMS (`ZEF_URL` désigne le client : un jeton accepté là est
|
|
9
|
+
* forcément le sien), puis invalide le tag `zef` : toutes les pages sont rafraîchies à leur
|
|
10
|
+
* prochaine visite.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export const prerender = false;
|
|
14
|
+
|
|
15
|
+
export const POST: APIRoute = async ({ request, cache }) => {
|
|
16
|
+
const token = request.headers.get("authorization")?.replace(/^Bearer\s+/i, "");
|
|
17
|
+
const url = process.env.ZEF_URL;
|
|
18
|
+
if (!token || !url) return json(401, { ok: false, error: "Jeton manquant." });
|
|
19
|
+
const valid = await createClient({ url, apiKey: token })
|
|
20
|
+
.site()
|
|
21
|
+
.then(() => true)
|
|
22
|
+
.catch(() => false);
|
|
23
|
+
if (!valid) return json(403, { ok: false, error: "Jeton refusé." });
|
|
24
|
+
if (!cache.enabled) return json(200, { ok: true, invalidated: false });
|
|
25
|
+
await cache.invalidate({ tags: [CACHE_TAG] });
|
|
26
|
+
return json(200, { ok: true, invalidated: true });
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const json = (status: number, body: unknown) =>
|
|
30
|
+
new Response(JSON.stringify(body), {
|
|
31
|
+
status,
|
|
32
|
+
headers: { "content-type": "application/json", "cache-control": "no-store" },
|
|
33
|
+
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getClient, robotsTxt, siteOrigin } from "@agence-zef/astro";
|
|
2
2
|
import type { APIRoute } from "astro";
|
|
3
|
+
import { CACHE_TAG, PAGE_CACHE } from "./cache";
|
|
3
4
|
|
|
4
5
|
/*
|
|
5
6
|
* `robots.txt` injecté par `@agence-zef/astro` (§ 5.11, § 5.13) : tout est bloqué tant que le site
|
|
@@ -9,7 +10,9 @@ import type { APIRoute } from "astro";
|
|
|
9
10
|
|
|
10
11
|
export const prerender = true;
|
|
11
12
|
|
|
12
|
-
export const GET: APIRoute = async ({ site: astroSite }) => {
|
|
13
|
+
export const GET: APIRoute = async ({ site: astroSite, cache }) => {
|
|
14
|
+
// Rendu à la demande (`rendering: "cached"`) : gardé en cache, invalidé par une publication.
|
|
15
|
+
cache.set({ ...PAGE_CACHE, tags: [CACHE_TAG] });
|
|
13
16
|
const site = await getClient().site();
|
|
14
17
|
const body = robotsTxt(site, siteOrigin(site, astroSite?.origin));
|
|
15
18
|
return new Response(body, { headers: { "Content-Type": "text/plain; charset=utf-8" } });
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import config from "virtual:zef/config";
|
|
2
2
|
import { getClient, sitemapXml, siteOrigin, zefSiteIndex } from "@agence-zef/astro";
|
|
3
3
|
import type { APIRoute } from "astro";
|
|
4
|
+
import { CACHE_TAG, PAGE_CACHE } from "./cache";
|
|
4
5
|
|
|
5
6
|
/*
|
|
6
7
|
* `sitemap.xml` injecté par `@agence-zef/astro` (§ 5.13) : pages et éléments publiés et
|
|
@@ -9,7 +10,9 @@ import type { APIRoute } from "astro";
|
|
|
9
10
|
|
|
10
11
|
export const prerender = true;
|
|
11
12
|
|
|
12
|
-
export const GET: APIRoute = async ({ site: astroSite }) => {
|
|
13
|
+
export const GET: APIRoute = async ({ site: astroSite, cache }) => {
|
|
14
|
+
// Rendu à la demande (`rendering: "cached"`) : gardé en cache, invalidé par une publication.
|
|
15
|
+
cache.set({ ...PAGE_CACHE, tags: [CACHE_TAG] });
|
|
13
16
|
const site = await getClient().site();
|
|
14
17
|
const body = sitemapXml(await zefSiteIndex(config), siteOrigin(site, astroSite?.origin));
|
|
15
18
|
return new Response(body, { headers: { "Content-Type": "application/xml; charset=utf-8" } });
|
package/dist/helpers.d.ts
CHANGED
|
@@ -56,6 +56,12 @@ export declare function zefLayoutProps(opts: {
|
|
|
56
56
|
locale?: string;
|
|
57
57
|
noindex?: boolean;
|
|
58
58
|
}): Promise<LayoutProps>;
|
|
59
|
+
/**
|
|
60
|
+
* Rendu à la demande (`rendering: "cached"`) : les props du gabarit pour une adresse, page ou
|
|
61
|
+
* élément de collection, sans parcourir tout le site. `null` si rien n'est publié à cette
|
|
62
|
+
* adresse ; une erreur du CMS remonte (la page en cache reste servie).
|
|
63
|
+
*/
|
|
64
|
+
export declare function zefRouteProps(path: string, visitor?: Parameters<ZefClient["document"]>[1]): Promise<RouteProps | null>;
|
|
59
65
|
/**
|
|
60
66
|
* Toutes les routes du site : pages publiées, puis éléments des collections avec page. Calculé
|
|
61
67
|
* une fois par build : la route des pages, le sitemap et `llms.txt` partagent le résultat.
|
package/dist/helpers.js
CHANGED
|
@@ -43,6 +43,85 @@ export async function zefLayoutProps(opts) {
|
|
|
43
43
|
};
|
|
44
44
|
}
|
|
45
45
|
const toParam = (url) => url.replace(/^\/+|\/+$/g, "") || undefined;
|
|
46
|
+
/** Arborescence des pages : fil d'Ariane d'une page, accueil de chaque langue. */
|
|
47
|
+
function pageTree(entries, site) {
|
|
48
|
+
const byId = new Map(entries.map((e) => [e.id, e]));
|
|
49
|
+
const homeOf = (locale) => entries.find((e) => e.urls[locale] === "/" || e.urls[locale] === `/${locale}`);
|
|
50
|
+
/** Accueil, puis les pages parentes, puis la page elle-même. */
|
|
51
|
+
const trail = (id, locale) => {
|
|
52
|
+
const out = [];
|
|
53
|
+
for (let e = byId.get(id); e; e = e.parentId ? byId.get(e.parentId) : undefined) {
|
|
54
|
+
const url = e.urls[locale];
|
|
55
|
+
if (url)
|
|
56
|
+
out.unshift({ title: e.titles[locale] || e.titles[site.defaultLocale] || "", url });
|
|
57
|
+
}
|
|
58
|
+
const home = homeOf(locale);
|
|
59
|
+
if (home && out[0]?.url !== home.urls[locale]) {
|
|
60
|
+
out.unshift({ title: home.titles[locale] || site.name, url: home.urls[locale] });
|
|
61
|
+
}
|
|
62
|
+
return out;
|
|
63
|
+
};
|
|
64
|
+
return { trail, homeOf };
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Rendu à la demande (`rendering: "cached"`) : les props du gabarit pour une adresse, page ou
|
|
68
|
+
* élément de collection, sans parcourir tout le site. `null` si rien n'est publié à cette
|
|
69
|
+
* adresse ; une erreur du CMS remonte (la page en cache reste servie).
|
|
70
|
+
*/
|
|
71
|
+
export async function zefRouteProps(path, visitor) {
|
|
72
|
+
const api = getClient();
|
|
73
|
+
const [found, site, entries] = await Promise.all([
|
|
74
|
+
api.document(path, visitor).catch((error) => {
|
|
75
|
+
if (error.status === 404)
|
|
76
|
+
return null;
|
|
77
|
+
throw error;
|
|
78
|
+
}),
|
|
79
|
+
api.site(),
|
|
80
|
+
api.pages(),
|
|
81
|
+
]);
|
|
82
|
+
if (!found)
|
|
83
|
+
return null;
|
|
84
|
+
const { trail, homeOf } = pageTree(entries, site);
|
|
85
|
+
if (found.kind === "page") {
|
|
86
|
+
const { page } = found;
|
|
87
|
+
const layout = await api.layout({ locale: page.locale });
|
|
88
|
+
const entry = entries.find((e) => e.id === page.id);
|
|
89
|
+
return {
|
|
90
|
+
kind: "page",
|
|
91
|
+
page,
|
|
92
|
+
site,
|
|
93
|
+
locale: page.locale,
|
|
94
|
+
title: page.seo.title ?? page.title,
|
|
95
|
+
seo: page.seo,
|
|
96
|
+
alternates: page.alternates,
|
|
97
|
+
url: page.url,
|
|
98
|
+
breadcrumbs: entry ? trail(entry.id, page.locale) : [],
|
|
99
|
+
header: layout.header,
|
|
100
|
+
footer: layout.footer,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
const { item, collection, titleField } = found;
|
|
104
|
+
const locale = Object.entries(item.alternates ?? {}).find(([, url]) => url === item.url)?.[0] ??
|
|
105
|
+
site.defaultLocale;
|
|
106
|
+
const layout = await api.layout({ locale });
|
|
107
|
+
const title = String(item[titleField] ?? "");
|
|
108
|
+
const listingPath = item.url?.replace(/\/[^/]+\/?$/, "") ?? "";
|
|
109
|
+
const listing = entries.find((e) => e.urls[locale] === listingPath) ?? homeOf(locale);
|
|
110
|
+
return {
|
|
111
|
+
kind: "item",
|
|
112
|
+
collection,
|
|
113
|
+
item,
|
|
114
|
+
site,
|
|
115
|
+
locale,
|
|
116
|
+
title: item.seo?.title ?? title,
|
|
117
|
+
seo: item.seo,
|
|
118
|
+
alternates: item.alternates ?? {},
|
|
119
|
+
url: item.url ?? path,
|
|
120
|
+
breadcrumbs: [...(listing ? trail(listing.id, locale) : []), { title, url: item.url ?? path }],
|
|
121
|
+
header: layout.header,
|
|
122
|
+
footer: layout.footer,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
46
125
|
let staticPaths;
|
|
47
126
|
/**
|
|
48
127
|
* Toutes les routes du site : pages publiées, puis éléments des collections avec page. Calculé
|
|
@@ -61,22 +140,7 @@ async function buildStaticPaths(config) {
|
|
|
61
140
|
const paths = [];
|
|
62
141
|
const layouts = new Map(await Promise.all(site.locales.map(async (l) => [l, await api.layout({ locale: l })])));
|
|
63
142
|
const entries = await api.pages();
|
|
64
|
-
const
|
|
65
|
-
const homeOf = (locale) => entries.find((e) => e.urls[locale] === "/" || e.urls[locale] === `/${locale}`);
|
|
66
|
-
/** Accueil, puis les pages parentes, puis la page elle-même. */
|
|
67
|
-
const trail = (id, locale) => {
|
|
68
|
-
const out = [];
|
|
69
|
-
for (let e = byId.get(id); e; e = e.parentId ? byId.get(e.parentId) : undefined) {
|
|
70
|
-
const url = e.urls[locale];
|
|
71
|
-
if (url)
|
|
72
|
-
out.unshift({ title: e.titles[locale] || e.titles[site.defaultLocale] || "", url });
|
|
73
|
-
}
|
|
74
|
-
const home = homeOf(locale);
|
|
75
|
-
if (home && out[0]?.url !== home.urls[locale]) {
|
|
76
|
-
out.unshift({ title: home.titles[locale] || site.name, url: home.urls[locale] });
|
|
77
|
-
}
|
|
78
|
-
return out;
|
|
79
|
-
};
|
|
143
|
+
const { trail, homeOf } = pageTree(entries, site);
|
|
80
144
|
for (const entry of entries) {
|
|
81
145
|
for (const [locale, url] of Object.entries(entry.urls)) {
|
|
82
146
|
const page = await api.page(url);
|
|
@@ -111,12 +175,7 @@ async function buildStaticPaths(config) {
|
|
|
111
175
|
for (const item of list.items) {
|
|
112
176
|
if (!item.url || item.access?.reserved)
|
|
113
177
|
continue;
|
|
114
|
-
const alternates = {};
|
|
115
|
-
for (const other of byLocale) {
|
|
116
|
-
const url = other.list.items.find((i) => i.id === item.id)?.url;
|
|
117
|
-
if (url)
|
|
118
|
-
alternates[other.locale] = url;
|
|
119
|
-
}
|
|
178
|
+
const alternates = { ...item.alternates };
|
|
120
179
|
// Fil d'Ariane : accueil, page de la liste si elle existe (`/vins`), puis l'élément.
|
|
121
180
|
const listing = entries.find((e) => e.urls[locale] === def.page.path || e.urls[locale] === `/${locale}${def.page.path}`) ?? homeOf(locale);
|
|
122
181
|
const title = String(item[def.titleField] ?? "");
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,20 @@ export * from "./helpers.js";
|
|
|
8
8
|
export * from "./seo.js";
|
|
9
9
|
export * from "./shop.js";
|
|
10
10
|
const MEDIA_URL = "https://medias.agence-zef.fr";
|
|
11
|
+
/** `rendering` de `zef.config.ts` (lu comme la CLI, avec jiti) ; `static` en cas de doute. */
|
|
12
|
+
async function readRendering(file) {
|
|
13
|
+
if (!existsSync(file))
|
|
14
|
+
return "static";
|
|
15
|
+
try {
|
|
16
|
+
const { createJiti } = await import("jiti");
|
|
17
|
+
const jiti = createJiti(import.meta.url, { moduleCache: false, fsCache: false });
|
|
18
|
+
const config = await jiti.import(file, { default: true });
|
|
19
|
+
return config?.rendering === "cached" ? "cached" : "static";
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return "static";
|
|
23
|
+
}
|
|
24
|
+
}
|
|
11
25
|
/** Domaines autorisés pour l'optimisation des images distantes (`image.remotePatterns`). */
|
|
12
26
|
function mediaPatterns(urls) {
|
|
13
27
|
return urls.flatMap((raw) => {
|
|
@@ -93,27 +107,55 @@ export default function zef(options = {}) {
|
|
|
93
107
|
addWatchFile(join(root, ".env"));
|
|
94
108
|
const layout = join(root, options.layout ?? "src/layouts/Page.astro");
|
|
95
109
|
const configFile = join(root, "zef.config.ts");
|
|
110
|
+
// Rendu des pages (`defineConfig({ rendering })`) : construites au build (`static`), ou
|
|
111
|
+
// rendues à la demande et gardées en cache par le CDN, invalidé par une publication
|
|
112
|
+
// (`cached`, demande un adaptateur).
|
|
113
|
+
const rendering = await readRendering(configFile);
|
|
114
|
+
const cached = rendering === "cached" && Boolean(config.adapter || command === "dev");
|
|
115
|
+
if (rendering === "cached" && !cached) {
|
|
116
|
+
logger.warn("rendering « cached » sans adaptateur : pages construites au build");
|
|
117
|
+
}
|
|
118
|
+
if (cached && !config.cache?.provider) {
|
|
119
|
+
// Cache du CDN de l'hébergeur : Vercel (tags, invalidation), sinon en mémoire.
|
|
120
|
+
const vercelProvider = config.adapter?.name === "@astrojs/vercel";
|
|
121
|
+
updateConfig({
|
|
122
|
+
cache: {
|
|
123
|
+
provider: vercelProvider
|
|
124
|
+
? { name: "vercel", entrypoint: "@astrojs/vercel/cache/provider" }
|
|
125
|
+
: { name: "memory", entrypoint: "astro/cache/memory" },
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
}
|
|
96
129
|
injectRoute({
|
|
97
130
|
pattern: "/[...path]",
|
|
98
|
-
entrypoint:
|
|
99
|
-
|
|
131
|
+
entrypoint: cached
|
|
132
|
+
? "@agence-zef/astro/routes/page-cached.astro"
|
|
133
|
+
: "@agence-zef/astro/routes/page.astro",
|
|
134
|
+
prerender: !cached,
|
|
100
135
|
});
|
|
101
136
|
injectRoute({
|
|
102
137
|
pattern: "/robots.txt",
|
|
103
138
|
entrypoint: "@agence-zef/astro/routes/robots.ts",
|
|
104
|
-
prerender:
|
|
139
|
+
prerender: !cached,
|
|
105
140
|
});
|
|
106
141
|
// Référencement prêt à l'emploi (§ 5.13) : sitemap et présentation pour les IA.
|
|
107
142
|
injectRoute({
|
|
108
143
|
pattern: "/sitemap.xml",
|
|
109
144
|
entrypoint: "@agence-zef/astro/routes/sitemap.ts",
|
|
110
|
-
prerender:
|
|
145
|
+
prerender: !cached,
|
|
111
146
|
});
|
|
112
147
|
injectRoute({
|
|
113
148
|
pattern: "/llms.txt",
|
|
114
149
|
entrypoint: "@agence-zef/astro/routes/llms.ts",
|
|
115
|
-
prerender:
|
|
150
|
+
prerender: !cached,
|
|
116
151
|
});
|
|
152
|
+
if (cached) {
|
|
153
|
+
injectRoute({
|
|
154
|
+
pattern: "/__zef/revalidate",
|
|
155
|
+
entrypoint: "@agence-zef/astro/routes/revalidate.ts",
|
|
156
|
+
prerender: false,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
117
159
|
// Aperçu de l'éditeur : rendu à la demande, donc avec un adaptateur (Vercel) ou en dev.
|
|
118
160
|
if (command === "dev" || config.adapter) {
|
|
119
161
|
injectRoute({
|
|
@@ -137,7 +179,7 @@ export default function zef(options = {}) {
|
|
|
137
179
|
}
|
|
138
180
|
// Contenu réservé (lot 14e5c) : les adresses que la route statique n'a pas générées
|
|
139
181
|
// (pages et éléments réservés) sont rendues à la demande, avec la session du compte.
|
|
140
|
-
if (options.shop && (command === "dev" || config.adapter)) {
|
|
182
|
+
if (options.shop && !cached && (command === "dev" || config.adapter)) {
|
|
141
183
|
injectRoute({
|
|
142
184
|
pattern: "/[...zefReserved]",
|
|
143
185
|
entrypoint: "@agence-zef/astro/routes/reserved.astro",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agence-zef/astro",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0-pilot.0",
|
|
4
4
|
"description": "Intégration Astro du CMS ZEF : routes, rendu des sections, aperçu, composants réutilisables sans style.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -63,7 +63,9 @@
|
|
|
63
63
|
"./ui": {
|
|
64
64
|
"types": "./dist/ui.d.ts",
|
|
65
65
|
"import": "./dist/ui.js"
|
|
66
|
-
}
|
|
66
|
+
},
|
|
67
|
+
"./routes/page-cached.astro": "./components/routes/page-cached.astro",
|
|
68
|
+
"./routes/revalidate.ts": "./components/routes/revalidate.ts"
|
|
67
69
|
},
|
|
68
70
|
"files": [
|
|
69
71
|
"dist",
|
|
@@ -81,8 +83,9 @@
|
|
|
81
83
|
"@types/node": "^24.0.0"
|
|
82
84
|
},
|
|
83
85
|
"dependencies": {
|
|
84
|
-
"
|
|
85
|
-
"@agence-zef/
|
|
86
|
+
"jiti": "^2.6.1",
|
|
87
|
+
"@agence-zef/schema": "0.6.0-pilot.0",
|
|
88
|
+
"@agence-zef/sdk": "0.6.0-pilot.0"
|
|
86
89
|
},
|
|
87
90
|
"homepage": "https://agence-zef.fr",
|
|
88
91
|
"scripts": {
|