reroute-js 0.40.2 → 0.41.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/cli/bin.d.ts +1 -1
- package/cli/bin.js +206 -71
- package/cli/bin.js.map +13 -13
- package/cli/index.d.ts +1 -1
- package/cli/index.js +4 -4
- package/cli/index.js.map +1 -1
- package/cli/src/cli.d.ts +1 -1
- package/cli/src/commands/analyze.d.ts +1 -1
- package/cli/src/commands/build.d.ts +1 -1
- package/cli/src/commands/dev.d.ts +1 -1
- package/cli/src/commands/gen.d.ts +1 -1
- package/cli/src/commands/gen.d.ts.map +1 -1
- package/cli/src/commands/index.d.ts +1 -1
- package/cli/src/commands/init.d.ts +1 -1
- package/cli/src/commands/lib/assets.d.ts +1 -1
- package/cli/src/commands/lib/bundler.d.ts +1 -1
- package/cli/src/commands/lib/command.d.ts +1 -1
- package/cli/src/commands/lib/env.d.ts +1 -1
- package/cli/src/commands/lib/index.d.ts +1 -1
- package/cli/src/commands/lib/log.d.ts +1 -1
- package/cli/src/commands/lib/markdown/availability.d.ts +1 -1
- package/cli/src/commands/lib/markdown/index.d.ts +1 -1
- package/cli/src/commands/lib/markdown/processor.d.ts +1 -1
- package/cli/src/commands/lib/production.d.ts +1 -1
- package/cli/src/commands/lib/server.d.ts +1 -1
- package/cli/src/commands/lib/streaming/analyzer.d.ts +1 -1
- package/cli/src/commands/lib/streaming/suspense.d.ts +1 -1
- package/cli/src/commands/lib/tailwind.d.ts +1 -1
- package/cli/src/commands/lib/terminal-ui.d.ts +1 -1
- package/cli/src/commands/lib/version.d.ts +1 -1
- package/cli/src/commands/og.d.ts +1 -1
- package/cli/src/commands/start.d.ts +1 -1
- package/cli/src/index.d.ts +1 -1
- package/core/index.d.ts +1 -1
- package/core/index.js +148 -46
- package/core/index.js.map +12 -12
- package/core/src/bundler/hash.d.ts +1 -1
- package/core/src/bundler/index.d.ts +1 -1
- package/core/src/config.d.ts +42 -2
- package/core/src/config.d.ts.map +1 -1
- package/core/src/content/discovery.d.ts +1 -1
- package/core/src/content/index.d.ts +1 -1
- package/core/src/content/metadata.d.ts +7 -2
- package/core/src/content/metadata.d.ts.map +1 -1
- package/core/src/index.d.ts +1 -1
- package/core/src/llms/extractor.d.ts +1 -1
- package/core/src/llms/formatter.d.ts +1 -1
- package/core/src/llms/full-generator.d.ts +1 -1
- package/core/src/llms/index-generator.d.ts +1 -1
- package/core/src/llms/index.d.ts +1 -1
- package/core/src/og/discovery.d.ts +1 -1
- package/core/src/og/index.d.ts +1 -1
- package/core/src/og/meta.d.ts +1 -1
- package/core/src/og/render.d.ts +1 -1
- package/core/src/og/types.d.ts +1 -1
- package/core/src/robots/discovery.d.ts +1 -1
- package/core/src/robots/generator.d.ts +1 -1
- package/core/src/robots/index.d.ts +1 -1
- package/core/src/robots/policies.d.ts +1 -1
- package/core/src/rss/discovery.d.ts +1 -1
- package/core/src/rss/discovery.d.ts.map +1 -1
- package/core/src/rss/generator.d.ts +1 -1
- package/core/src/rss/index.d.ts +1 -1
- package/core/src/sitemap/discovery.d.ts +1 -1
- package/core/src/sitemap/discovery.d.ts.map +1 -1
- package/core/src/sitemap/generator.d.ts +1 -1
- package/core/src/sitemap/index.d.ts +1 -1
- package/core/src/ssr/index.d.ts +1 -1
- package/core/src/ssr/lib/cache.d.ts +1 -1
- package/core/src/ssr/lib/collections.d.ts +1 -1
- package/core/src/ssr/lib/compression.d.ts +1 -1
- package/core/src/ssr/lib/compute/content.d.ts +1 -1
- package/core/src/ssr/lib/compute/index.d.ts +1 -1
- package/core/src/ssr/lib/compute/layouts.d.ts +1 -1
- package/core/src/ssr/lib/compute/routes.d.ts +1 -1
- package/core/src/ssr/lib/data.d.ts +1 -1
- package/core/src/ssr/lib/html.d.ts +6 -1
- package/core/src/ssr/lib/html.d.ts.map +1 -1
- package/core/src/ssr/lib/imports.d.ts +1 -1
- package/core/src/ssr/lib/index.d.ts +1 -1
- package/core/src/ssr/lib/layouts.d.ts +1 -1
- package/core/src/ssr/lib/metadata.d.ts +3 -3
- package/core/src/ssr/lib/metadata.d.ts.map +1 -1
- package/core/src/ssr/lib/mime.d.ts +1 -1
- package/core/src/ssr/lib/modules.d.ts +1 -1
- package/core/src/ssr/lib/path.d.ts +1 -1
- package/core/src/ssr/lib/preload.d.ts +1 -1
- package/core/src/ssr/lib/scripts/collections.d.ts +1 -1
- package/core/src/ssr/lib/scripts/data.d.ts +1 -1
- package/core/src/ssr/lib/scripts/escape.d.ts +1 -1
- package/core/src/ssr/lib/scripts/feeds.d.ts +1 -1
- package/core/src/ssr/lib/scripts/index.d.ts +1 -1
- package/core/src/ssr/lib/seed.d.ts +1 -1
- package/core/src/ssr/lib/serialize.d.ts +1 -1
- package/core/src/ssr/lib/setup.d.ts +3 -2
- package/core/src/ssr/lib/setup.d.ts.map +1 -1
- package/core/src/ssr/lib/styles.d.ts +1 -1
- package/core/src/ssr/lib/template.d.ts +1 -1
- package/core/src/ssr/lib/types.d.ts +1 -1
- package/core/src/ssr/render.d.ts +3 -2
- package/core/src/ssr/render.d.ts.map +1 -1
- package/core/src/ssr/stream.d.ts +3 -2
- package/core/src/ssr/stream.d.ts.map +1 -1
- package/elysia/index.d.ts +1 -1
- package/elysia/index.js +326 -127
- package/elysia/index.js.map +18 -18
- package/elysia/src/index.d.ts +1 -1
- package/elysia/src/libs/assets.d.ts +1 -1
- package/elysia/src/libs/cache.d.ts +1 -1
- package/elysia/src/libs/caching.d.ts +1 -1
- package/elysia/src/libs/http.d.ts +1 -1
- package/elysia/src/libs/image.d.ts +1 -1
- package/elysia/src/libs/index.d.ts +1 -1
- package/elysia/src/libs/llms.d.ts +1 -1
- package/elysia/src/libs/response.d.ts +1 -1
- package/elysia/src/libs/serving.d.ts +1 -1
- package/elysia/src/plugin.d.ts +1 -1
- package/elysia/src/plugin.d.ts.map +1 -1
- package/elysia/src/routes/artifacts.d.ts +1 -1
- package/elysia/src/routes/content.d.ts +1 -1
- package/elysia/src/routes/image.d.ts +1 -1
- package/elysia/src/routes/index.d.ts +1 -1
- package/elysia/src/routes/internal.d.ts +1 -1
- package/elysia/src/routes/internal.d.ts.map +1 -1
- package/elysia/src/routes/llms.d.ts +1 -1
- package/elysia/src/routes/og.d.ts +1 -1
- package/elysia/src/routes/og.d.ts.map +1 -1
- package/elysia/src/routes/redirects.d.ts +1 -1
- package/elysia/src/routes/robots.d.ts +1 -1
- package/elysia/src/routes/rss.d.ts +2 -2
- package/elysia/src/routes/rss.d.ts.map +1 -1
- package/elysia/src/routes/search.d.ts +1 -1
- package/elysia/src/routes/sitemap.d.ts +2 -2
- package/elysia/src/routes/sitemap.d.ts.map +1 -1
- package/elysia/src/routes/ssr.d.ts +3 -2
- package/elysia/src/routes/ssr.d.ts.map +1 -1
- package/elysia/src/routes/static.d.ts +1 -1
- package/elysia/src/types.d.ts +1 -1
- package/package.json +1 -1
- package/react/index.d.ts +1 -1
- package/react/index.js +2 -2
- package/react/index.js.map +1 -1
- package/react/src/components/ClientOnly.d.ts +1 -1
- package/react/src/components/ContentRoute.d.ts +1 -1
- package/react/src/components/Image.d.ts +1 -1
- package/react/src/components/LazyRoute.d.ts +1 -1
- package/react/src/components/Link.d.ts +1 -1
- package/react/src/components/Markdown.d.ts +1 -1
- package/react/src/components/Outlet.d.ts +1 -1
- package/react/src/components/index.d.ts +1 -1
- package/react/src/hooks/index.d.ts +1 -1
- package/react/src/hooks/useContent.d.ts +1 -1
- package/react/src/hooks/useData.d.ts +1 -1
- package/react/src/hooks/useFeed.d.ts +1 -1
- package/react/src/hooks/useLayoutData.d.ts +1 -1
- package/react/src/hooks/useLlms.d.ts +1 -1
- package/react/src/hooks/useNavigate.d.ts +1 -1
- package/react/src/hooks/useParams.d.ts +1 -1
- package/react/src/hooks/useRouter.d.ts +1 -1
- package/react/src/hooks/useSearch.d.ts +1 -1
- package/react/src/hooks/useSearchParams.d.ts +1 -1
- package/react/src/hooks/useToc.d.ts +1 -1
- package/react/src/index.d.ts +1 -1
- package/react/src/lib/collection.d.ts +1 -1
- package/react/src/lib/content.d.ts +1 -1
- package/react/src/lib/head.d.ts +1 -1
- package/react/src/lib/index.d.ts +1 -1
- package/react/src/lib/lazy-route.d.ts +1 -1
- package/react/src/lib/route-loader.d.ts +1 -1
- package/react/src/providers/ContentProvider.d.ts +1 -1
- package/react/src/providers/RerouteProvider.d.ts +1 -1
- package/react/src/providers/RouterProvider.d.ts +1 -1
- package/react/src/providers/index.d.ts +1 -1
- package/react/src/types/any.d.ts +1 -1
- package/react/src/types/index.d.ts +1 -1
- package/react/src/types/router.d.ts +1 -1
- package/telemetry/react.d.ts +1 -1
- package/telemetry/react.js +2 -2
- package/telemetry/react.js.map +1 -1
- package/telemetry/server.d.ts +1 -1
- package/telemetry/server.js +2 -2
- package/telemetry/server.js.map +8 -8
- package/telemetry/src/react/api.d.ts +1 -1
- package/telemetry/src/react/context.d.ts +1 -1
- package/telemetry/src/react/index.d.ts +1 -1
- package/telemetry/src/react/telemetry.d.ts +1 -1
- package/telemetry/src/server/context.d.ts +1 -1
- package/telemetry/src/server/headers/extractor.d.ts +1 -1
- package/telemetry/src/server/headers/index.d.ts +1 -1
- package/telemetry/src/server/headers/presets.d.ts +1 -1
- package/telemetry/src/server/index.d.ts +1 -1
- package/telemetry/src/server/instrumentation.d.ts +1 -1
- package/telemetry/src/server/plugin.d.ts +1 -1
- package/telemetry/src/server/sourcemap.d.ts +1 -1
package/elysia/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* reroute-js v0.
|
|
2
|
+
* reroute-js v0.41.1
|
|
3
3
|
*
|
|
4
4
|
* @license MIT
|
|
5
5
|
* @copyright 2026 stewones <hi@stewan.io>
|
|
@@ -168,7 +168,7 @@ async function getContentMeta(absPath, isWatchMode) {
|
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
|
-
function buildHeadFromMeta(meta) {
|
|
171
|
+
function buildHeadFromMeta(meta, ogConfig) {
|
|
172
172
|
if (!meta || typeof meta !== "object")
|
|
173
173
|
return "";
|
|
174
174
|
const parts = [];
|
|
@@ -178,6 +178,23 @@ function buildHeadFromMeta(meta) {
|
|
|
178
178
|
parts.push(`<title>${escapeHtml(title)}</title>`);
|
|
179
179
|
if (description)
|
|
180
180
|
parts.push(`<meta name="description" content="${escapeHtml(description)}" />`);
|
|
181
|
+
const ogType = typeof meta.ogType === "string" ? meta.ogType : ogConfig?.defaultType || "website";
|
|
182
|
+
parts.push(`<meta property="og:type" content="${escapeHtml(ogType)}" />`);
|
|
183
|
+
if (title) {
|
|
184
|
+
parts.push(`<meta property="og:title" content="${escapeHtml(title)}" />`);
|
|
185
|
+
}
|
|
186
|
+
const finalDescription = description || ogConfig?.siteDescription;
|
|
187
|
+
if (finalDescription) {
|
|
188
|
+
parts.push(`<meta property="og:description" content="${escapeHtml(finalDescription)}" />`);
|
|
189
|
+
}
|
|
190
|
+
const twitterCard = ogConfig?.twitterCard || "summary_large_image";
|
|
191
|
+
parts.push(`<meta name="twitter:card" content="${twitterCard}" />`);
|
|
192
|
+
if (title) {
|
|
193
|
+
parts.push(`<meta name="twitter:title" content="${escapeHtml(title)}" />`);
|
|
194
|
+
}
|
|
195
|
+
if (finalDescription) {
|
|
196
|
+
parts.push(`<meta name="twitter:description" content="${escapeHtml(finalDescription)}" />`);
|
|
197
|
+
}
|
|
181
198
|
return parts.length ? `
|
|
182
199
|
${parts.join(`
|
|
183
200
|
`)}` : "";
|
|
@@ -1640,6 +1657,28 @@ function removeDefaultMetaTags(templateHtml) {
|
|
|
1640
1657
|
} catch {}
|
|
1641
1658
|
return result;
|
|
1642
1659
|
}
|
|
1660
|
+
function removeOverriddenMetaTags(templateHtml, injectedHead) {
|
|
1661
|
+
let result = templateHtml;
|
|
1662
|
+
try {
|
|
1663
|
+
const injectedOgProps = [
|
|
1664
|
+
...injectedHead.matchAll(/<meta\s+property\s*=\s*['"]([^'"]+)['"][^>]*>/gi)
|
|
1665
|
+
].map((m) => m[1].toLowerCase());
|
|
1666
|
+
const injectedNameMetas = [
|
|
1667
|
+
...injectedHead.matchAll(/<meta\s+name\s*=\s*['"]([^'"]+)['"][^>]*>/gi)
|
|
1668
|
+
].map((m) => m[1].toLowerCase());
|
|
1669
|
+
for (const prop of injectedOgProps) {
|
|
1670
|
+
const escapedProp = prop.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1671
|
+
const regex = new RegExp(`<meta\\s+property\\s*=\\s*['"]${escapedProp}['"][^>]*>`, "gi");
|
|
1672
|
+
result = result.replace(regex, "");
|
|
1673
|
+
}
|
|
1674
|
+
for (const name of injectedNameMetas) {
|
|
1675
|
+
const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1676
|
+
const regex = new RegExp(`<meta\\s+name\\s*=\\s*['"]${escapedName}['"][^>]*>`, "gi");
|
|
1677
|
+
result = result.replace(regex, "");
|
|
1678
|
+
}
|
|
1679
|
+
} catch {}
|
|
1680
|
+
return result;
|
|
1681
|
+
}
|
|
1643
1682
|
function deduplicateHeadContent(templateHtml, headToInject) {
|
|
1644
1683
|
let cleanedTemplate = templateHtml;
|
|
1645
1684
|
let cleanedHead = headToInject;
|
|
@@ -1650,6 +1689,7 @@ function deduplicateHeadContent(templateHtml, headToInject) {
|
|
|
1650
1689
|
} else if (/<meta\s+name\s*=\s*['"]description['"][^>]*>/i.test(cleanedHead)) {
|
|
1651
1690
|
cleanedTemplate = cleanedTemplate.replace(/<meta\s+name\s*=\s*['"]description['"][^>]*>/i, "");
|
|
1652
1691
|
}
|
|
1692
|
+
cleanedTemplate = removeOverriddenMetaTags(cleanedTemplate, cleanedHead);
|
|
1653
1693
|
} catch {}
|
|
1654
1694
|
return { cleanedTemplate, cleanedHead };
|
|
1655
1695
|
}
|
|
@@ -1768,7 +1808,6 @@ async function generateOGImageMetaTags(pathname, clientDir, ogConfig) {
|
|
|
1768
1808
|
return `<meta property="og:image" content="${ogImagePath}" />
|
|
1769
1809
|
<meta property="og:image:width" content="${width}" />
|
|
1770
1810
|
<meta property="og:image:height" content="${height}" />
|
|
1771
|
-
<meta name="twitter:card" content="summary_large_image" />
|
|
1772
1811
|
<meta name="twitter:image" content="${ogImagePath}" />`;
|
|
1773
1812
|
}
|
|
1774
1813
|
var init_meta = __esm(() => {
|
|
@@ -1806,7 +1845,25 @@ function generateOgUrl(baseUrl, pathname) {
|
|
|
1806
1845
|
const ogUrl = `${cleanBaseUrl}${normalizedPath}`;
|
|
1807
1846
|
return `<meta property="og:url" content="${ogUrl}" />`;
|
|
1808
1847
|
}
|
|
1809
|
-
|
|
1848
|
+
function generateGlobalOGTags(ogConfig) {
|
|
1849
|
+
const tags = [];
|
|
1850
|
+
if (ogConfig.siteName) {
|
|
1851
|
+
tags.push(`<meta property="og:site_name" content="${escapeHtml2(ogConfig.siteName)}" />`);
|
|
1852
|
+
}
|
|
1853
|
+
if (ogConfig.locale) {
|
|
1854
|
+
tags.push(`<meta property="og:locale" content="${escapeHtml2(ogConfig.locale)}" />`);
|
|
1855
|
+
}
|
|
1856
|
+
if (ogConfig.twitterSite) {
|
|
1857
|
+
const handle = ogConfig.twitterSite.startsWith("@") ? ogConfig.twitterSite : `@${ogConfig.twitterSite}`;
|
|
1858
|
+
tags.push(`<meta name="twitter:site" content="${escapeHtml2(handle)}" />`);
|
|
1859
|
+
}
|
|
1860
|
+
return tags.length ? tags.join(`
|
|
1861
|
+
`) : "";
|
|
1862
|
+
}
|
|
1863
|
+
function escapeHtml2(input) {
|
|
1864
|
+
return input.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
1865
|
+
}
|
|
1866
|
+
async function extractPageMetadata(pathname, clientDir, cwd, isWatchMode, currentStatusOverride, ogImageConfig, ogConfig, baseUrl, autoCanonical, ssrData) {
|
|
1810
1867
|
let perPageHead = "";
|
|
1811
1868
|
let pageLang;
|
|
1812
1869
|
let statusOverride = currentStatusOverride;
|
|
@@ -1815,7 +1872,7 @@ async function extractPageMetadata(pathname, clientDir, cwd, isWatchMode, curren
|
|
|
1815
1872
|
}, (lang) => {
|
|
1816
1873
|
if (!pageLang)
|
|
1817
1874
|
pageLang = lang;
|
|
1818
|
-
});
|
|
1875
|
+
}, ogConfig);
|
|
1819
1876
|
const shouldGenerateCanonical = autoCanonical !== false && baseUrl !== undefined;
|
|
1820
1877
|
if (shouldGenerateCanonical) {
|
|
1821
1878
|
const canonicalTag = generateCanonicalUrl(baseUrl, pathname);
|
|
@@ -1825,8 +1882,15 @@ ${canonicalTag}`;
|
|
|
1825
1882
|
perPageHead += `
|
|
1826
1883
|
${ogUrlTag}`;
|
|
1827
1884
|
}
|
|
1885
|
+
if (ogConfig) {
|
|
1886
|
+
const ogGlobalTags = generateGlobalOGTags(ogConfig);
|
|
1887
|
+
if (ogGlobalTags) {
|
|
1888
|
+
perPageHead += `
|
|
1889
|
+
${ogGlobalTags}`;
|
|
1890
|
+
}
|
|
1891
|
+
}
|
|
1828
1892
|
try {
|
|
1829
|
-
const ogMetaTags = await generateOGImageMetaTags(pathname, clientDir,
|
|
1893
|
+
const ogMetaTags = await generateOGImageMetaTags(pathname, clientDir, ogImageConfig);
|
|
1830
1894
|
if (ogMetaTags) {
|
|
1831
1895
|
perPageHead += `
|
|
1832
1896
|
${ogMetaTags}`;
|
|
@@ -1838,22 +1902,22 @@ ${ogMetaTags}`;
|
|
|
1838
1902
|
perPageHead += head;
|
|
1839
1903
|
}, (lang) => {
|
|
1840
1904
|
pageLang = lang;
|
|
1841
|
-
});
|
|
1842
|
-
const routeResult = await extractRouteMetadata(pathname, clientDir, cwd, isWatchMode, statusOverride, ssrData);
|
|
1905
|
+
}, ogConfig);
|
|
1906
|
+
const routeResult = await extractRouteMetadata(pathname, clientDir, cwd, isWatchMode, statusOverride, ssrData, ogConfig);
|
|
1843
1907
|
perPageHead += routeResult.head;
|
|
1844
1908
|
if (routeResult.lang)
|
|
1845
1909
|
pageLang = routeResult.lang;
|
|
1846
1910
|
statusOverride = routeResult.statusOverride;
|
|
1847
1911
|
return { perPageHead, pageLang, statusOverride };
|
|
1848
1912
|
}
|
|
1849
|
-
async function processLayoutForMetadata(layout, clientDir, isWatchMode, addHead, setLang) {
|
|
1913
|
+
async function processLayoutForMetadata(layout, clientDir, isWatchMode, addHead, setLang, ogConfig) {
|
|
1850
1914
|
if (typeof layout?.path !== "string")
|
|
1851
1915
|
return;
|
|
1852
1916
|
try {
|
|
1853
1917
|
const abs = join(clientDir, "routes", String(layout.path));
|
|
1854
1918
|
const { meta, ssr } = await loadModuleMetaAndSSR(layout, abs, isWatchMode);
|
|
1855
1919
|
if (meta)
|
|
1856
|
-
addHead(buildHeadFromMeta(meta));
|
|
1920
|
+
addHead(buildHeadFromMeta(meta, ogConfig));
|
|
1857
1921
|
if (ssr) {
|
|
1858
1922
|
const ssrHead = extractSSRHead(ssr);
|
|
1859
1923
|
if (ssrHead)
|
|
@@ -1865,16 +1929,16 @@ ${ssrHead}`);
|
|
|
1865
1929
|
}
|
|
1866
1930
|
} catch {}
|
|
1867
1931
|
}
|
|
1868
|
-
async function extractLayoutMetadata(pathname, clientDir, cwd, isWatchMode, addHead, setLang) {
|
|
1932
|
+
async function extractLayoutMetadata(pathname, clientDir, cwd, isWatchMode, addHead, setLang, ogConfig) {
|
|
1869
1933
|
try {
|
|
1870
1934
|
const m = await loadRoutesModule(cwd, isWatchMode);
|
|
1871
1935
|
const matchingLayouts = getMatchingLayouts(pathname, m?.layouts);
|
|
1872
1936
|
for (const layout of matchingLayouts) {
|
|
1873
|
-
await processLayoutForMetadata(layout, clientDir, isWatchMode, addHead, setLang);
|
|
1937
|
+
await processLayoutForMetadata(layout, clientDir, isWatchMode, addHead, setLang, ogConfig);
|
|
1874
1938
|
}
|
|
1875
1939
|
} catch {}
|
|
1876
1940
|
}
|
|
1877
|
-
function extractContentMetadata(pathname, addHead, setLang) {
|
|
1941
|
+
function extractContentMetadata(pathname, addHead, setLang, ogConfig) {
|
|
1878
1942
|
try {
|
|
1879
1943
|
const parts = pathname.split("/").filter(Boolean);
|
|
1880
1944
|
if (parts.length < 2)
|
|
@@ -1884,7 +1948,7 @@ function extractContentMetadata(pathname, addHead, setLang) {
|
|
|
1884
1948
|
const exp = g.__REROUTE_SSR_EXPORTS__?.[key];
|
|
1885
1949
|
const meta = exp?.meta;
|
|
1886
1950
|
const ssr = exp?.ssr;
|
|
1887
|
-
addHead(buildHeadFromMeta(meta));
|
|
1951
|
+
addHead(buildHeadFromMeta(meta, ogConfig));
|
|
1888
1952
|
const ssrHead = extractSSRHead(ssr);
|
|
1889
1953
|
if (ssrHead)
|
|
1890
1954
|
addHead(`
|
|
@@ -1894,7 +1958,7 @@ ${ssrHead}`);
|
|
|
1894
1958
|
setLang(lang);
|
|
1895
1959
|
} catch {}
|
|
1896
1960
|
}
|
|
1897
|
-
async function extractMatchedRouteMetadata(pathname, clientDir, m, isWatchMode, statusOverride, ssrData) {
|
|
1961
|
+
async function extractMatchedRouteMetadata(pathname, clientDir, m, isWatchMode, statusOverride, ssrData, ogConfig) {
|
|
1898
1962
|
const pathnameOnly = pathname.split("?")[0];
|
|
1899
1963
|
const match = typeof m.matchRoute === "function" ? m.matchRoute(pathnameOnly) : null;
|
|
1900
1964
|
const r = match?.route;
|
|
@@ -1907,7 +1971,7 @@ async function extractMatchedRouteMetadata(pathname, clientDir, m, isWatchMode,
|
|
|
1907
1971
|
const { meta, ssr } = await loadModuleMetaAndSSR(r, abs, isWatchMode);
|
|
1908
1972
|
let head = "";
|
|
1909
1973
|
if (meta)
|
|
1910
|
-
head += buildHeadFromMeta(meta);
|
|
1974
|
+
head += buildHeadFromMeta(meta, ogConfig);
|
|
1911
1975
|
if (ssr) {
|
|
1912
1976
|
const routeData = ssrData && typeof ssrData === "object" ? ssrData[pathname] : undefined;
|
|
1913
1977
|
const ssrHead = extractSSRHead(ssr, routeData);
|
|
@@ -1921,7 +1985,7 @@ ${ssrHead}`;
|
|
|
1921
1985
|
}
|
|
1922
1986
|
return { head: "", statusOverride };
|
|
1923
1987
|
}
|
|
1924
|
-
async function extractRouteMetadata(pathname, clientDir, cwd, isWatchMode, currentStatusOverride, ssrData) {
|
|
1988
|
+
async function extractRouteMetadata(pathname, clientDir, cwd, isWatchMode, currentStatusOverride, ssrData, ogConfig) {
|
|
1925
1989
|
let head = "";
|
|
1926
1990
|
let lang;
|
|
1927
1991
|
let statusOverride = currentStatusOverride;
|
|
@@ -1937,14 +2001,14 @@ async function extractRouteMetadata(pathname, clientDir, cwd, isWatchMode, curre
|
|
|
1937
2001
|
statusOverride = statusOverride || 404;
|
|
1938
2002
|
}
|
|
1939
2003
|
if (r && typeof r.path === "string") {
|
|
1940
|
-
const result = await extractMatchedRouteMetadata(pathname, clientDir, m, isWatchMode, statusOverride, ssrData);
|
|
2004
|
+
const result = await extractMatchedRouteMetadata(pathname, clientDir, m, isWatchMode, statusOverride, ssrData, ogConfig);
|
|
1941
2005
|
head = result.head;
|
|
1942
2006
|
lang = result.lang;
|
|
1943
2007
|
statusOverride = result.statusOverride;
|
|
1944
2008
|
} else {
|
|
1945
2009
|
head += await extractNotFoundMetadata(pathname, clientDir, m, isWatchMode, (l) => {
|
|
1946
2010
|
lang = l;
|
|
1947
|
-
});
|
|
2011
|
+
}, ogConfig);
|
|
1948
2012
|
}
|
|
1949
2013
|
} catch {}
|
|
1950
2014
|
return { head, lang, statusOverride };
|
|
@@ -1964,7 +2028,7 @@ function findBestNotFoundRoute(list, pathname) {
|
|
|
1964
2028
|
}
|
|
1965
2029
|
return chosen;
|
|
1966
2030
|
}
|
|
1967
|
-
async function extractNotFoundMetadata(pathname, clientDir, routesModule, isWatchMode, setLang) {
|
|
2031
|
+
async function extractNotFoundMetadata(pathname, clientDir, routesModule, isWatchMode, setLang, ogConfig) {
|
|
1968
2032
|
let head = "";
|
|
1969
2033
|
try {
|
|
1970
2034
|
const list = routesModule?.notFoundRoutes;
|
|
@@ -1975,7 +2039,7 @@ async function extractNotFoundMetadata(pathname, clientDir, routesModule, isWatc
|
|
|
1975
2039
|
const abs = join(clientDir, "routes", String(chosen.path));
|
|
1976
2040
|
const { meta, ssr } = await loadModuleMetaAndSSR(chosen, abs, isWatchMode);
|
|
1977
2041
|
if (meta)
|
|
1978
|
-
head += buildHeadFromMeta(meta);
|
|
2042
|
+
head += buildHeadFromMeta(meta, ogConfig);
|
|
1979
2043
|
const ssrHead = extractSSRHead(ssr);
|
|
1980
2044
|
if (ssrHead)
|
|
1981
2045
|
head += `
|
|
@@ -2562,7 +2626,7 @@ async function performSSRSetupInternal(options, streaming) {
|
|
|
2562
2626
|
statusOverride = computeResult.statusContainer.value;
|
|
2563
2627
|
}
|
|
2564
2628
|
const metadataResult = await withSpan("ssr.extract.metadata", async (span) => {
|
|
2565
|
-
const result = await extractPageMetadata(pathname, clientDir, cwd, isWatchMode, statusOverride, ogConfig, options.baseUrl, options.autoCanonical, computeResult.data);
|
|
2629
|
+
const result = await extractPageMetadata(pathname, clientDir, cwd, isWatchMode, statusOverride, ogConfig, options.ogMetaConfig, options.baseUrl, options.autoCanonical, computeResult.data);
|
|
2566
2630
|
span.setAttributes({
|
|
2567
2631
|
"reroute.pathname": pathname,
|
|
2568
2632
|
"reroute.metadata.exists": !!result.perPageHead
|
|
@@ -2732,6 +2796,7 @@ async function renderSSRDocument(options) {
|
|
|
2732
2796
|
maxAge,
|
|
2733
2797
|
searchParams,
|
|
2734
2798
|
ogConfig,
|
|
2799
|
+
ogMetaConfig: options.ogMetaConfig,
|
|
2735
2800
|
baseUrl: options.baseUrl,
|
|
2736
2801
|
autoCanonical: options.autoCanonical,
|
|
2737
2802
|
cachedCollections: options.cachedCollections,
|
|
@@ -3996,13 +4061,13 @@ async function discoverSSRDataRoutes2(cwd, staticRoutes, isWatchMode, baseUrl, s
|
|
|
3996
4061
|
const ssrDataRoutes = new Map;
|
|
3997
4062
|
const bundledRoutes = globalThis.__REROUTE_ROUTES__;
|
|
3998
4063
|
if (bundledRoutes && Array.isArray(bundledRoutes)) {
|
|
3999
|
-
|
|
4064
|
+
const routePromises = staticRoutes.map(async (route) => {
|
|
4000
4065
|
if (sitemapConfig?.excludeDiscovery?.some((excluded) => route.pattern.startsWith(excluded))) {
|
|
4001
|
-
|
|
4066
|
+
return null;
|
|
4002
4067
|
}
|
|
4003
4068
|
const bundledRoute = bundledRoutes.find((r) => r?.pattern === route.pattern);
|
|
4004
4069
|
if (!bundledRoute)
|
|
4005
|
-
|
|
4070
|
+
return null;
|
|
4006
4071
|
const ssr = bundledRoute?.ssr;
|
|
4007
4072
|
const dataFn = ssr?.data;
|
|
4008
4073
|
if (typeof dataFn === "function") {
|
|
@@ -4015,15 +4080,22 @@ async function discoverSSRDataRoutes2(cwd, staticRoutes, isWatchMode, baseUrl, s
|
|
|
4015
4080
|
});
|
|
4016
4081
|
const entries = extractEntriesFromData(result, route.pattern, baseUrl, sitemapConfig);
|
|
4017
4082
|
if (entries.length > 0) {
|
|
4018
|
-
|
|
4083
|
+
return { pattern: route.pattern, entries };
|
|
4019
4084
|
}
|
|
4020
4085
|
} catch {}
|
|
4021
4086
|
}
|
|
4087
|
+
return null;
|
|
4088
|
+
});
|
|
4089
|
+
const results = await Promise.all(routePromises);
|
|
4090
|
+
for (const result of results) {
|
|
4091
|
+
if (result) {
|
|
4092
|
+
ssrDataRoutes.set(result.pattern, result.entries);
|
|
4093
|
+
}
|
|
4022
4094
|
}
|
|
4023
4095
|
} else {
|
|
4024
|
-
|
|
4096
|
+
const routePromises = staticRoutes.map(async (route) => {
|
|
4025
4097
|
if (sitemapConfig?.excludeDiscovery?.some((excluded) => route.pattern.startsWith(excluded))) {
|
|
4026
|
-
|
|
4098
|
+
return null;
|
|
4027
4099
|
}
|
|
4028
4100
|
try {
|
|
4029
4101
|
const routeModulePath = join(cwd, "src", "client", "routes", route.path);
|
|
@@ -4039,10 +4111,17 @@ async function discoverSSRDataRoutes2(cwd, staticRoutes, isWatchMode, baseUrl, s
|
|
|
4039
4111
|
});
|
|
4040
4112
|
const entries = extractEntriesFromData(result, route.pattern, baseUrl, sitemapConfig);
|
|
4041
4113
|
if (entries.length > 0) {
|
|
4042
|
-
|
|
4114
|
+
return { pattern: route.pattern, entries };
|
|
4043
4115
|
}
|
|
4044
4116
|
}
|
|
4045
4117
|
} catch {}
|
|
4118
|
+
return null;
|
|
4119
|
+
});
|
|
4120
|
+
const results = await Promise.all(routePromises);
|
|
4121
|
+
for (const result of results) {
|
|
4122
|
+
if (result) {
|
|
4123
|
+
ssrDataRoutes.set(result.pattern, result.entries);
|
|
4124
|
+
}
|
|
4046
4125
|
}
|
|
4047
4126
|
}
|
|
4048
4127
|
return ssrDataRoutes;
|
|
@@ -4418,24 +4497,28 @@ function createRSSItemFromData(item, routePattern, baseUrl, rssConfig) {
|
|
|
4418
4497
|
}
|
|
4419
4498
|
async function discoverRSSData(cwd, collections2, baseUrl, isWatchMode, rssConfig) {
|
|
4420
4499
|
const collectionsMap = new Map;
|
|
4421
|
-
|
|
4500
|
+
const collectionPromises = collections2.map(async (collection) => {
|
|
4422
4501
|
const items = await discoverCollectionFeedItems(cwd, collection, isWatchMode, baseUrl, rssConfig);
|
|
4423
|
-
|
|
4424
|
-
|
|
4502
|
+
return items.length > 0 ? { collection, items } : null;
|
|
4503
|
+
});
|
|
4504
|
+
const collectionResults = await Promise.all(collectionPromises);
|
|
4505
|
+
for (const result of collectionResults) {
|
|
4506
|
+
if (result) {
|
|
4507
|
+
collectionsMap.set(result.collection, result.items);
|
|
4425
4508
|
}
|
|
4426
4509
|
}
|
|
4427
4510
|
const ssrDataFeeds = new Map;
|
|
4428
4511
|
const bundledRoutes = globalThis.__REROUTE_ROUTES__;
|
|
4512
|
+
const { discoverRoutes: discoverRoutes2 } = await Promise.resolve().then(() => (init_discovery4(), exports_discovery));
|
|
4513
|
+
const { staticRoutes } = await discoverRoutes2(cwd, isWatchMode);
|
|
4429
4514
|
if (bundledRoutes && Array.isArray(bundledRoutes)) {
|
|
4430
|
-
const
|
|
4431
|
-
const { staticRoutes } = await discoverRoutes2(cwd, isWatchMode);
|
|
4432
|
-
for (const route of staticRoutes) {
|
|
4515
|
+
const routePromises = staticRoutes.map(async (route) => {
|
|
4433
4516
|
if (rssConfig?.excludeDiscovery?.some((excluded) => route.pattern.startsWith(excluded))) {
|
|
4434
|
-
|
|
4517
|
+
return null;
|
|
4435
4518
|
}
|
|
4436
4519
|
const bundledRoute = bundledRoutes.find((r) => r?.pattern === route.pattern);
|
|
4437
4520
|
if (!bundledRoute)
|
|
4438
|
-
|
|
4521
|
+
return null;
|
|
4439
4522
|
const ssr = bundledRoute?.ssr;
|
|
4440
4523
|
const dataFn = ssr?.data;
|
|
4441
4524
|
if (typeof dataFn === "function") {
|
|
@@ -4448,21 +4531,33 @@ async function discoverRSSData(cwd, collections2, baseUrl, isWatchMode, rssConfi
|
|
|
4448
4531
|
});
|
|
4449
4532
|
const items = extractRSSItemsFromData(result, route.pattern, baseUrl, rssConfig);
|
|
4450
4533
|
if (items.length > 0) {
|
|
4451
|
-
|
|
4534
|
+
return { pattern: route.pattern, items };
|
|
4452
4535
|
}
|
|
4453
4536
|
} catch {}
|
|
4454
4537
|
}
|
|
4538
|
+
return null;
|
|
4539
|
+
});
|
|
4540
|
+
const results = await Promise.all(routePromises);
|
|
4541
|
+
for (const result of results) {
|
|
4542
|
+
if (result) {
|
|
4543
|
+
ssrDataFeeds.set(result.pattern, result.items);
|
|
4544
|
+
}
|
|
4455
4545
|
}
|
|
4456
4546
|
} else {
|
|
4457
|
-
const
|
|
4458
|
-
const { staticRoutes } = await discoverRoutes2(cwd, isWatchMode);
|
|
4459
|
-
for (const route of staticRoutes) {
|
|
4547
|
+
const routePromises = staticRoutes.map(async (route) => {
|
|
4460
4548
|
if (rssConfig?.excludeDiscovery?.some((excluded) => route.pattern.startsWith(excluded))) {
|
|
4461
|
-
|
|
4549
|
+
return null;
|
|
4462
4550
|
}
|
|
4463
4551
|
const items = await discoverSSRDataFeedItems(cwd, route.pattern, route.path, isWatchMode, baseUrl, rssConfig);
|
|
4464
4552
|
if (items.length > 0) {
|
|
4465
|
-
|
|
4553
|
+
return { pattern: route.pattern, items };
|
|
4554
|
+
}
|
|
4555
|
+
return null;
|
|
4556
|
+
});
|
|
4557
|
+
const results = await Promise.all(routePromises);
|
|
4558
|
+
for (const result of results) {
|
|
4559
|
+
if (result) {
|
|
4560
|
+
ssrDataFeeds.set(result.pattern, result.items);
|
|
4466
4561
|
}
|
|
4467
4562
|
}
|
|
4468
4563
|
}
|
|
@@ -4842,6 +4937,7 @@ async function renderSSRDocumentStream(options) {
|
|
|
4842
4937
|
maxAge,
|
|
4843
4938
|
searchParams,
|
|
4844
4939
|
ogConfig,
|
|
4940
|
+
ogMetaConfig: options.ogMetaConfig,
|
|
4845
4941
|
baseUrl: options.baseUrl,
|
|
4846
4942
|
autoCanonical: options.autoCanonical,
|
|
4847
4943
|
cachedCollections: options.cachedCollections,
|
|
@@ -4876,7 +4972,11 @@ async function renderSSRDocumentStream(options) {
|
|
|
4876
4972
|
};
|
|
4877
4973
|
});
|
|
4878
4974
|
const pageLang = setup2.metadataResult.pageLang || lang;
|
|
4879
|
-
let headWithLang = htmlHead.replace(/<html([^>]*)>/i,
|
|
4975
|
+
let headWithLang = htmlHead.replace(/<html([^>]*)>/i, (_m, attrs) => {
|
|
4976
|
+
const hasLang = /(^|\s)lang\s*=/.test(attrs);
|
|
4977
|
+
const newAttrs = hasLang ? attrs.replace(/lang\s*=\s*("[^"]*"|'[^']*'|[^\s>]+)/i, `lang="${pageLang}"`) : `${attrs} lang="${pageLang}"`;
|
|
4978
|
+
return `<html${newAttrs}>`;
|
|
4979
|
+
});
|
|
4880
4980
|
const extraHead = setup2.bundlePreload + setup2.preloadExtraHead + setup2.metadataResult.perPageHead;
|
|
4881
4981
|
if (/<title[\s\S]*?<\/title>/i.test(extraHead)) {
|
|
4882
4982
|
headWithLang = headWithLang.replace(/<title[\s\S]*?<\/title>/i, "");
|
|
@@ -4884,6 +4984,7 @@ async function renderSSRDocumentStream(options) {
|
|
|
4884
4984
|
if (/<meta\s+name\s*=\s*['"]description['"][^>]*>/i.test(extraHead)) {
|
|
4885
4985
|
headWithLang = headWithLang.replace(/<meta\s+name\s*=\s*['"]description['"][^>]*>/i, "");
|
|
4886
4986
|
}
|
|
4987
|
+
headWithLang = removeOverriddenMetaTags(headWithLang, extraHead);
|
|
4887
4988
|
const config = await loadConfig(cwd);
|
|
4888
4989
|
const browserTelemetryConfigRaw = config.telemetry?.browser;
|
|
4889
4990
|
const { serializeBrowserTelemetryConfig: serializeBrowserTelemetryConfig2 } = await Promise.resolve().then(() => exports_serialize);
|
|
@@ -4932,7 +5033,7 @@ async function streamSSRContent(writer, encoder, ctx) {
|
|
|
4932
5033
|
try {
|
|
4933
5034
|
const combinedHead = deduplicateMetaTags([ctx.inlineStyleTag, ctx.head, ctx.extraHead].filter(Boolean).join(`
|
|
4934
5035
|
`));
|
|
4935
|
-
const headWithLangAndContent = ctx.headWithLang.replace(
|
|
5036
|
+
const headWithLangAndContent = ctx.headWithLang.replace(/<\/head>/i, `${combinedHead ? `${combinedHead}
|
|
4936
5037
|
` : ""}</head>`);
|
|
4937
5038
|
const headContent = `${headWithLangAndContent}`;
|
|
4938
5039
|
await writer.write(encoder.encode(headContent));
|
|
@@ -5072,6 +5173,7 @@ __export(exports_core, {
|
|
|
5072
5173
|
renderSSRDocumentStream: () => renderSSRDocumentStream,
|
|
5073
5174
|
renderSSRDocument: () => renderSSRDocument,
|
|
5074
5175
|
renderOGImageToPNG: () => renderOGImageToPNG,
|
|
5176
|
+
removeOverriddenMetaTags: () => removeOverriddenMetaTags,
|
|
5075
5177
|
processCollections: () => processCollections,
|
|
5076
5178
|
preloadContentModule: () => preloadContentModule,
|
|
5077
5179
|
performSSRSetup: () => performSSRSetup,
|
|
@@ -5970,6 +6072,8 @@ let hasConnected = false;
|
|
|
5970
6072
|
let wasDisconnected = false;
|
|
5971
6073
|
let reloadTriggered = false;
|
|
5972
6074
|
let rebuildNotice = null;
|
|
6075
|
+
let reconnectAttempts = 0;
|
|
6076
|
+
let isReconnecting = false;
|
|
5973
6077
|
|
|
5974
6078
|
function showRebuildNotice() {
|
|
5975
6079
|
if (rebuildNotice) return;
|
|
@@ -6047,6 +6151,43 @@ function hideRebuildNotice() {
|
|
|
6047
6151
|
}
|
|
6048
6152
|
}
|
|
6049
6153
|
|
|
6154
|
+
// Check if server is ready before attempting SSE connection
|
|
6155
|
+
async function waitForServer() {
|
|
6156
|
+
const maxAttempts = 60; // 30 seconds max
|
|
6157
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
6158
|
+
try {
|
|
6159
|
+
const res = await fetch('/__reroute_watch.js', { method: 'HEAD' });
|
|
6160
|
+
if (res.ok) return true;
|
|
6161
|
+
} catch {
|
|
6162
|
+
// Server not ready, continue waiting
|
|
6163
|
+
}
|
|
6164
|
+
await new Promise(r => setTimeout(r, 500));
|
|
6165
|
+
}
|
|
6166
|
+
return false;
|
|
6167
|
+
}
|
|
6168
|
+
|
|
6169
|
+
async function scheduleReconnect() {
|
|
6170
|
+
if (reloadTriggered || isReconnecting) return;
|
|
6171
|
+
isReconnecting = true;
|
|
6172
|
+
|
|
6173
|
+
// Exponential backoff: 300ms, 600ms, 1200ms, max 2000ms
|
|
6174
|
+
const delay = Math.min(300 * Math.pow(2, reconnectAttempts), 2000);
|
|
6175
|
+
reconnectAttempts++;
|
|
6176
|
+
|
|
6177
|
+
await new Promise(r => setTimeout(r, delay));
|
|
6178
|
+
|
|
6179
|
+
// Wait for server to be ready before creating EventSource
|
|
6180
|
+
const ready = await waitForServer();
|
|
6181
|
+
isReconnecting = false;
|
|
6182
|
+
|
|
6183
|
+
if (ready && !reloadTriggered) {
|
|
6184
|
+
connect();
|
|
6185
|
+
} else if (!reloadTriggered) {
|
|
6186
|
+
// Server still not ready, try again
|
|
6187
|
+
scheduleReconnect();
|
|
6188
|
+
}
|
|
6189
|
+
}
|
|
6190
|
+
|
|
6050
6191
|
function connect() {
|
|
6051
6192
|
if (reloadTriggered) return;
|
|
6052
6193
|
|
|
@@ -6054,6 +6195,7 @@ function connect() {
|
|
|
6054
6195
|
|
|
6055
6196
|
eventSource.addEventListener('message', (e) => {
|
|
6056
6197
|
if (e.data === 'connected') {
|
|
6198
|
+
reconnectAttempts = 0; // Reset backoff on successful connection
|
|
6057
6199
|
if (hasConnected && wasDisconnected && !reloadTriggered) {
|
|
6058
6200
|
console.log('[reroute] ✓ Server restarted, reloading...');
|
|
6059
6201
|
reloadTriggered = true;
|
|
@@ -6077,11 +6219,12 @@ function connect() {
|
|
|
6077
6219
|
if (reloadTriggered) return;
|
|
6078
6220
|
wasDisconnected = true;
|
|
6079
6221
|
eventSource?.close();
|
|
6080
|
-
if (hasConnected) {
|
|
6222
|
+
if (hasConnected && reconnectAttempts === 0) {
|
|
6223
|
+
// Only log on first disconnect to reduce console spam
|
|
6081
6224
|
console.log('[reroute] \uD83D\uDD04 Server restarting...');
|
|
6082
6225
|
showRebuildNotice();
|
|
6083
6226
|
}
|
|
6084
|
-
|
|
6227
|
+
scheduleReconnect();
|
|
6085
6228
|
});
|
|
6086
6229
|
}
|
|
6087
6230
|
|
|
@@ -6704,6 +6847,7 @@ function registerOGRoutes(app, options) {
|
|
|
6704
6847
|
const width = ogConfig.width ?? 1200;
|
|
6705
6848
|
const height = ogConfig.height ?? 630;
|
|
6706
6849
|
const maxAge = ogConfig.maxAge ?? 3600;
|
|
6850
|
+
const generatingImages = new Set;
|
|
6707
6851
|
function normalizeOgPathname(urlPathname) {
|
|
6708
6852
|
let pathname = urlPathname.replace(/^\/__reroute_og/, "").replace(/\.png$/, "");
|
|
6709
6853
|
if (pathname === "/index" || pathname === "index") {
|
|
@@ -6725,7 +6869,7 @@ function registerOGRoutes(app, options) {
|
|
|
6725
6869
|
}
|
|
6726
6870
|
return;
|
|
6727
6871
|
}
|
|
6728
|
-
async function generateOgImage(pathname, clientDir2, cwd2, isWatchMode2, ogConfig2, width2, height2
|
|
6872
|
+
async function generateOgImage(pathname, clientDir2, cwd2, isWatchMode2, ogConfig2, width2, height2) {
|
|
6729
6873
|
const ogPath = await findOGImageForPath(pathname, clientDir2);
|
|
6730
6874
|
const Component = await loadOgComponent(ogPath, ogConfig2, cwd2, isWatchMode2);
|
|
6731
6875
|
if (!Component) {
|
|
@@ -6795,10 +6939,6 @@ function registerOGRoutes(app, options) {
|
|
|
6795
6939
|
if (maxAge > 0) {
|
|
6796
6940
|
ogCache.set(pathname, { buffer, exp: Date.now() + maxAge * 1000 });
|
|
6797
6941
|
}
|
|
6798
|
-
set.headers["content-type"] = "image/png";
|
|
6799
|
-
set.headers["cache-control"] = `public, max-age=${maxAge}`;
|
|
6800
|
-
set.headers["Reroute-Cache"] = "MISS";
|
|
6801
|
-
return new Response(buffer);
|
|
6802
6942
|
}
|
|
6803
6943
|
app.get("/__reroute_og/*", async ({ request, set }) => {
|
|
6804
6944
|
try {
|
|
@@ -6807,9 +6947,30 @@ function registerOGRoutes(app, options) {
|
|
|
6807
6947
|
const cachedResponse = checkOgCache(pathname, set);
|
|
6808
6948
|
if (cachedResponse)
|
|
6809
6949
|
return cachedResponse;
|
|
6810
|
-
|
|
6950
|
+
if (generatingImages.has(pathname)) {
|
|
6951
|
+
set.status = 404;
|
|
6952
|
+
set.headers["Retry-After"] = "2";
|
|
6953
|
+
return new Response("Image generation in progress", {
|
|
6954
|
+
status: 404,
|
|
6955
|
+
headers: { "Content-Type": "text/plain" }
|
|
6956
|
+
});
|
|
6957
|
+
}
|
|
6958
|
+
generatingImages.add(pathname);
|
|
6959
|
+
generateOgImage(pathname, clientDir, cwd, isWatchMode, ogConfig, width, height).then(() => {
|
|
6960
|
+
console.log(`[reroute/og] Generated image for: ${pathname}`);
|
|
6961
|
+
}).catch((error) => {
|
|
6962
|
+
console.error(`[reroute/og] Failed to generate image for ${pathname}:`, error);
|
|
6963
|
+
}).finally(() => {
|
|
6964
|
+
generatingImages.delete(pathname);
|
|
6965
|
+
});
|
|
6966
|
+
set.status = 404;
|
|
6967
|
+
set.headers["Retry-After"] = "2";
|
|
6968
|
+
return new Response("Image not yet available, please retry", {
|
|
6969
|
+
status: 404,
|
|
6970
|
+
headers: { "Content-Type": "text/plain" }
|
|
6971
|
+
});
|
|
6811
6972
|
} catch (error) {
|
|
6812
|
-
console.error("[reroute] Failed to
|
|
6973
|
+
console.error("[reroute] Failed to handle OG image request:", error);
|
|
6813
6974
|
set.status = 500;
|
|
6814
6975
|
return new Response("Internal Server Error", {
|
|
6815
6976
|
status: 500,
|
|
@@ -6953,6 +7114,23 @@ function registerRobotsRoute(app, options) {
|
|
|
6953
7114
|
// packages/elysia/src/routes/rss.ts
|
|
6954
7115
|
init_core();
|
|
6955
7116
|
import { NotFoundError as NotFoundError8 } from "elysia";
|
|
7117
|
+
var rssDiscoveryCache = new LRUCache(1);
|
|
7118
|
+
async function getOrDiscoverRSSData(cwd, collections2, baseUrl, isWatchMode, rssConfig) {
|
|
7119
|
+
if (isWatchMode) {
|
|
7120
|
+
return discoverRSSData(cwd, collections2, baseUrl, isWatchMode, rssConfig);
|
|
7121
|
+
}
|
|
7122
|
+
const cacheKey = "rss:discovery";
|
|
7123
|
+
const cached = rssDiscoveryCache.get(cacheKey);
|
|
7124
|
+
if (cached && cached.exp > Date.now()) {
|
|
7125
|
+
return cached.discovery;
|
|
7126
|
+
}
|
|
7127
|
+
const discovery5 = await discoverRSSData(cwd, collections2, baseUrl, isWatchMode, rssConfig);
|
|
7128
|
+
rssDiscoveryCache.set(cacheKey, {
|
|
7129
|
+
discovery: discovery5,
|
|
7130
|
+
exp: Date.now() + 5 * 60 * 1000
|
|
7131
|
+
});
|
|
7132
|
+
return discovery5;
|
|
7133
|
+
}
|
|
6956
7134
|
function createFeedTitle(configTitle, name) {
|
|
6957
7135
|
return configTitle ?? `${name.charAt(0).toUpperCase() + name.slice(1)} Feed`;
|
|
6958
7136
|
}
|
|
@@ -6983,7 +7161,7 @@ async function registerMainFeedRoute(app, cwd, collections2, baseUrl, isWatchMod
|
|
|
6983
7161
|
if (cached) {
|
|
6984
7162
|
return feedResponse(cached.xml, format, { maxAge, cacheStatus: "HIT" });
|
|
6985
7163
|
}
|
|
6986
|
-
const discovery5 = await
|
|
7164
|
+
const discovery5 = await getOrDiscoverRSSData(cwd, collections2, baseUrl, isWatchMode, rssConfig);
|
|
6987
7165
|
const allItems = [
|
|
6988
7166
|
...Array.from(discovery5.collections.values()).flat(),
|
|
6989
7167
|
...Array.from(discovery5.ssrDataFeeds.values()).flat()
|
|
@@ -7022,7 +7200,7 @@ function registerCollectionFeedRoutes(app, collections2, options) {
|
|
|
7022
7200
|
cacheStatus: "HIT"
|
|
7023
7201
|
});
|
|
7024
7202
|
}
|
|
7025
|
-
const discovery5 = await
|
|
7203
|
+
const discovery5 = await getOrDiscoverRSSData(options.cwd, [collection], options.baseUrl, options.isWatchMode, options.rssConfig);
|
|
7026
7204
|
const items = discovery5.collections.get(collection) ?? [];
|
|
7027
7205
|
if (items.length === 0)
|
|
7028
7206
|
throw new NotFoundError8;
|
|
@@ -7083,7 +7261,7 @@ async function generateSSRDataFeed(route, options) {
|
|
|
7083
7261
|
}
|
|
7084
7262
|
let items = await discoverSSRDataFeedItems(options.cwd, route.pattern, route.path, options.isWatchMode, options.baseUrl, options.rssConfig);
|
|
7085
7263
|
if (items.length === 0 && route.isLayout) {
|
|
7086
|
-
const discovery5 = await
|
|
7264
|
+
const discovery5 = await getOrDiscoverRSSData(options.cwd, [], options.baseUrl, options.isWatchMode, options.rssConfig);
|
|
7087
7265
|
items = discovery5.ssrDataFeeds.get(route.pattern) ?? [];
|
|
7088
7266
|
}
|
|
7089
7267
|
if (items.length === 0)
|
|
@@ -7140,7 +7318,6 @@ async function registerRSSRoutes(app, options) {
|
|
|
7140
7318
|
const feedDescription = rssConfig?.description ?? "Latest updates";
|
|
7141
7319
|
const availableFeeds = ["/feed.xml"];
|
|
7142
7320
|
registerMainFeedRoute(app, cwd, collections2, baseUrl, isWatchMode, rssCache, format, limit, maxAge, ttlMs, feedTitle, feedDescription, rssConfig);
|
|
7143
|
-
const ssrDataRoutes = await discoverSSRRoutes(cwd, isWatchMode);
|
|
7144
7321
|
registerCollectionFeedRoutes(app, collections2, {
|
|
7145
7322
|
cwd,
|
|
7146
7323
|
clientDir,
|
|
@@ -7154,6 +7331,11 @@ async function registerRSSRoutes(app, options) {
|
|
|
7154
7331
|
rssConfig,
|
|
7155
7332
|
availableFeeds
|
|
7156
7333
|
});
|
|
7334
|
+
if (isWatchMode) {
|
|
7335
|
+
globalThis.__REROUTE_AVAILABLE_FEEDS__ = availableFeeds;
|
|
7336
|
+
return app;
|
|
7337
|
+
}
|
|
7338
|
+
const ssrDataRoutes = await discoverSSRRoutes(cwd, isWatchMode);
|
|
7157
7339
|
const routesWithFeeds = await discoverRoutesWithFeeds(ssrDataRoutes, collections2, {
|
|
7158
7340
|
cwd,
|
|
7159
7341
|
clientDir,
|
|
@@ -7304,9 +7486,26 @@ function registerSearchRoute(app, cwd, directive, maxAge, searchConfig) {
|
|
|
7304
7486
|
// packages/elysia/src/routes/sitemap.ts
|
|
7305
7487
|
init_core();
|
|
7306
7488
|
import { NotFoundError as NotFoundError9 } from "elysia";
|
|
7489
|
+
var sitemapDiscoveryCache = new LRUCache(1);
|
|
7490
|
+
async function getOrDiscoverSitemapData(cwd, collections2, baseUrl, isWatchMode, sitemapConfig) {
|
|
7491
|
+
if (isWatchMode) {
|
|
7492
|
+
return discoverSitemapData(cwd, collections2, baseUrl, isWatchMode, sitemapConfig);
|
|
7493
|
+
}
|
|
7494
|
+
const cacheKey = "sitemap:discovery";
|
|
7495
|
+
const cached = sitemapDiscoveryCache.get(cacheKey);
|
|
7496
|
+
if (cached && cached.exp > Date.now()) {
|
|
7497
|
+
return cached.discovery;
|
|
7498
|
+
}
|
|
7499
|
+
const discovery5 = await discoverSitemapData(cwd, collections2, baseUrl, isWatchMode, sitemapConfig);
|
|
7500
|
+
sitemapDiscoveryCache.set(cacheKey, {
|
|
7501
|
+
discovery: discovery5,
|
|
7502
|
+
exp: Date.now() + 5 * 60 * 1000
|
|
7503
|
+
});
|
|
7504
|
+
return discovery5;
|
|
7505
|
+
}
|
|
7307
7506
|
async function generateAndCacheSitemap(options, _ttlMs) {
|
|
7308
7507
|
const { cwd, collections: collections2, baseUrl, isWatchMode, sitemapConfig } = options;
|
|
7309
|
-
const discovery5 = await
|
|
7508
|
+
const discovery5 = await getOrDiscoverSitemapData(cwd, collections2, baseUrl, isWatchMode, sitemapConfig);
|
|
7310
7509
|
const result = await generateSitemap(discovery5, baseUrl, {
|
|
7311
7510
|
changefreq: sitemapConfig?.changefreq,
|
|
7312
7511
|
priority: sitemapConfig?.priority,
|
|
@@ -7552,6 +7751,7 @@ function registerSSRRoutes(app, options) {
|
|
|
7552
7751
|
maxAge,
|
|
7553
7752
|
searchParams,
|
|
7554
7753
|
ogConfig: options.ogConfig,
|
|
7754
|
+
ogMetaConfig: options.ogMetaConfig,
|
|
7555
7755
|
baseUrl: options.baseUrl,
|
|
7556
7756
|
autoCanonical: options.autoCanonical,
|
|
7557
7757
|
parentSpan: renderSpan,
|
|
@@ -7730,6 +7930,7 @@ function registerSSRRoutes(app, options) {
|
|
|
7730
7930
|
maxAge,
|
|
7731
7931
|
searchParams,
|
|
7732
7932
|
ogConfig: options.ogConfig,
|
|
7933
|
+
ogMetaConfig: options.ogMetaConfig,
|
|
7733
7934
|
baseUrl: options.baseUrl,
|
|
7734
7935
|
autoCanonical: options.autoCanonical,
|
|
7735
7936
|
parentSpan: renderSpan,
|
|
@@ -8033,8 +8234,24 @@ var reroute = () => async (app) => {
|
|
|
8033
8234
|
const shouldIgnore = !ignorePatterns.length ? () => false : (file) => ignorePatterns.find((pattern) => typeof pattern === "string" ? file.includes(pattern) : pattern.test(file));
|
|
8034
8235
|
const isWatchMode = Array.isArray(process.execArgv) && process.execArgv.includes("--watch") || Array.isArray(process.argv) && process.argv.includes("--watch");
|
|
8035
8236
|
const dataCacheControl = `${directive}, max-age=${maxAge}`;
|
|
8036
|
-
if (isWatchMode)
|
|
8237
|
+
if (isWatchMode) {
|
|
8037
8238
|
console.log(`[reroute] Live reload enabled`);
|
|
8239
|
+
registerLiveReloadRoutes(app, liveReloadState);
|
|
8240
|
+
app.post("/__reroute_rebuilding", () => {
|
|
8241
|
+
console.log("[reroute] Rebuild notification received, notifying browsers...");
|
|
8242
|
+
notifyRebuilding();
|
|
8243
|
+
return new Response(JSON.stringify({ ok: true, clients: liveReloadState.clients.size }), {
|
|
8244
|
+
headers: { "content-type": "application/json" }
|
|
8245
|
+
});
|
|
8246
|
+
});
|
|
8247
|
+
app.post("/__reroute_reload", () => {
|
|
8248
|
+
console.log(`[reroute] Reload notification received, notifying ${liveReloadState.clients.size} browser(s)...`);
|
|
8249
|
+
notifyReload();
|
|
8250
|
+
return new Response(JSON.stringify({ ok: true, clients: liveReloadState.clients.size }), {
|
|
8251
|
+
headers: { "content-type": "application/json" }
|
|
8252
|
+
});
|
|
8253
|
+
});
|
|
8254
|
+
}
|
|
8038
8255
|
const readBundleUrl = async () => {
|
|
8039
8256
|
const bundlesDir = `${cwd}/.reroute/bundles`;
|
|
8040
8257
|
const maxAttempts = isWatchMode ? 500 : 10;
|
|
@@ -8081,25 +8298,6 @@ var reroute = () => async (app) => {
|
|
|
8081
8298
|
isWatchMode,
|
|
8082
8299
|
maxAge
|
|
8083
8300
|
});
|
|
8084
|
-
if (isWatchMode) {
|
|
8085
|
-
registerLiveReloadRoutes(app, liveReloadState);
|
|
8086
|
-
}
|
|
8087
|
-
if (isWatchMode) {
|
|
8088
|
-
app.post("/__reroute_rebuilding", () => {
|
|
8089
|
-
console.log("[reroute] Rebuild notification received, notifying browsers...");
|
|
8090
|
-
notifyRebuilding();
|
|
8091
|
-
return new Response(JSON.stringify({ ok: true, clients: liveReloadState.clients.size }), {
|
|
8092
|
-
headers: { "content-type": "application/json" }
|
|
8093
|
-
});
|
|
8094
|
-
});
|
|
8095
|
-
app.post("/__reroute_reload", () => {
|
|
8096
|
-
console.log(`[reroute] Reload notification received, notifying ${liveReloadState.clients.size} browser(s)...`);
|
|
8097
|
-
notifyReload();
|
|
8098
|
-
return new Response(JSON.stringify({ ok: true, clients: liveReloadState.clients.size }), {
|
|
8099
|
-
headers: { "content-type": "application/json" }
|
|
8100
|
-
});
|
|
8101
|
-
});
|
|
8102
|
-
}
|
|
8103
8301
|
registerArtifactsRoutes(app, cwd, fileCache, {
|
|
8104
8302
|
bundleMaxAge,
|
|
8105
8303
|
directive,
|
|
@@ -8148,6 +8346,39 @@ var reroute = () => async (app) => {
|
|
|
8148
8346
|
console.error("[reroute] Failed to register robots route:", error);
|
|
8149
8347
|
}
|
|
8150
8348
|
}
|
|
8349
|
+
if (sitemapEnabled && sitemapBaseUrl) {
|
|
8350
|
+
try {
|
|
8351
|
+
registerSitemapRoutes(app, {
|
|
8352
|
+
cwd,
|
|
8353
|
+
collections: collections2,
|
|
8354
|
+
baseUrl: sitemapBaseUrl,
|
|
8355
|
+
maxAge,
|
|
8356
|
+
isWatchMode,
|
|
8357
|
+
sitemapCache,
|
|
8358
|
+
sitemapConfig
|
|
8359
|
+
});
|
|
8360
|
+
console.log(`[reroute] Sitemap enabled at ${sitemapBaseUrl}/sitemap.xml`);
|
|
8361
|
+
} catch (error) {
|
|
8362
|
+
console.error("[reroute] Failed to register sitemap routes:", error);
|
|
8363
|
+
}
|
|
8364
|
+
}
|
|
8365
|
+
if (rssEnabled && rssBaseUrl) {
|
|
8366
|
+
try {
|
|
8367
|
+
await registerRSSRoutes(app, {
|
|
8368
|
+
cwd,
|
|
8369
|
+
clientDir,
|
|
8370
|
+
collections: collections2,
|
|
8371
|
+
baseUrl: rssBaseUrl,
|
|
8372
|
+
maxAge,
|
|
8373
|
+
isWatchMode,
|
|
8374
|
+
rssCache,
|
|
8375
|
+
rssConfig
|
|
8376
|
+
});
|
|
8377
|
+
console.log(`[reroute] RSS feeds enabled at ${rssBaseUrl}/feed.xml`);
|
|
8378
|
+
} catch (error) {
|
|
8379
|
+
console.error("[reroute] Failed to register RSS routes:", error);
|
|
8380
|
+
}
|
|
8381
|
+
}
|
|
8151
8382
|
if (llmsEnabled && llmsConfig) {
|
|
8152
8383
|
try {
|
|
8153
8384
|
registerLLMsRoutes(app, {
|
|
@@ -8178,6 +8409,20 @@ var reroute = () => async (app) => {
|
|
|
8178
8409
|
console.error("[reroute] Failed to register LLMs routes:", error);
|
|
8179
8410
|
}
|
|
8180
8411
|
}
|
|
8412
|
+
if (ogEnabled && ogConfig) {
|
|
8413
|
+
try {
|
|
8414
|
+
registerOGRoutes(app, {
|
|
8415
|
+
clientDir,
|
|
8416
|
+
cwd,
|
|
8417
|
+
isWatchMode,
|
|
8418
|
+
ogConfig,
|
|
8419
|
+
ogCache
|
|
8420
|
+
});
|
|
8421
|
+
console.log("[reroute] OG image generation enabled");
|
|
8422
|
+
} catch (error) {
|
|
8423
|
+
console.error("[reroute] Failed to register OG routes:", error);
|
|
8424
|
+
}
|
|
8425
|
+
}
|
|
8181
8426
|
registerSSRRoutes(app, {
|
|
8182
8427
|
rootComponent,
|
|
8183
8428
|
clientDir,
|
|
@@ -8197,56 +8442,10 @@ var reroute = () => async (app) => {
|
|
|
8197
8442
|
streamingEnabled,
|
|
8198
8443
|
streamingTimeout: globalConfig.streaming?.timeout,
|
|
8199
8444
|
ogConfig,
|
|
8445
|
+
ogMetaConfig: globalConfig.og,
|
|
8200
8446
|
baseUrl,
|
|
8201
8447
|
autoCanonical
|
|
8202
8448
|
});
|
|
8203
|
-
if (sitemapEnabled && sitemapBaseUrl) {
|
|
8204
|
-
try {
|
|
8205
|
-
registerSitemapRoutes(app, {
|
|
8206
|
-
cwd,
|
|
8207
|
-
collections: collections2,
|
|
8208
|
-
baseUrl: sitemapBaseUrl,
|
|
8209
|
-
maxAge,
|
|
8210
|
-
isWatchMode,
|
|
8211
|
-
sitemapCache,
|
|
8212
|
-
sitemapConfig
|
|
8213
|
-
});
|
|
8214
|
-
console.log(`[reroute] Sitemap enabled at ${sitemapBaseUrl}/sitemap.xml`);
|
|
8215
|
-
} catch (error) {
|
|
8216
|
-
console.error("[reroute] Failed to register sitemap routes:", error);
|
|
8217
|
-
}
|
|
8218
|
-
}
|
|
8219
|
-
if (rssEnabled && rssBaseUrl) {
|
|
8220
|
-
try {
|
|
8221
|
-
await registerRSSRoutes(app, {
|
|
8222
|
-
cwd,
|
|
8223
|
-
clientDir,
|
|
8224
|
-
collections: collections2,
|
|
8225
|
-
baseUrl: rssBaseUrl,
|
|
8226
|
-
maxAge,
|
|
8227
|
-
isWatchMode,
|
|
8228
|
-
rssCache,
|
|
8229
|
-
rssConfig
|
|
8230
|
-
});
|
|
8231
|
-
console.log(`[reroute] RSS feeds enabled at ${rssBaseUrl}/feed.xml`);
|
|
8232
|
-
} catch (error) {
|
|
8233
|
-
console.error("[reroute] Failed to register RSS routes:", error);
|
|
8234
|
-
}
|
|
8235
|
-
}
|
|
8236
|
-
if (ogEnabled && ogConfig) {
|
|
8237
|
-
try {
|
|
8238
|
-
registerOGRoutes(app, {
|
|
8239
|
-
clientDir,
|
|
8240
|
-
cwd,
|
|
8241
|
-
isWatchMode,
|
|
8242
|
-
ogConfig,
|
|
8243
|
-
ogCache
|
|
8244
|
-
});
|
|
8245
|
-
console.log("[reroute] OG image generation enabled");
|
|
8246
|
-
} catch (error) {
|
|
8247
|
-
console.error("[reroute] Failed to register OG routes:", error);
|
|
8248
|
-
}
|
|
8249
|
-
}
|
|
8250
8449
|
} catch (error) {
|
|
8251
8450
|
console.error("[reroute] Failed to register SSR routes:", error);
|
|
8252
8451
|
throw error;
|
|
@@ -8267,4 +8466,4 @@ export {
|
|
|
8267
8466
|
reroute
|
|
8268
8467
|
};
|
|
8269
8468
|
|
|
8270
|
-
//# debugId=
|
|
8469
|
+
//# debugId=B3B56B145A0DCF8164756E2164756E21
|