rari 0.5.15 → 0.5.17
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/client.mjs +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +3 -3
- package/dist/{runtime-client-AtnJSL0q.mjs → runtime-client-DCkfDJpL.mjs} +116 -1
- package/dist/server-build-Br9CwaA7.mjs +3 -0
- package/dist/{server-build-MmIJHCpL.mjs → server-build-ChAPR3tl.mjs} +83 -4
- package/dist/{vite-CEX_9o-t.d.mts → vite-BOlxeo_Q.d.mts} +1 -0
- package/dist/{vite-7bcdKkub.mjs → vite-B_QMp3M4.mjs} +37 -11
- package/dist/vite.d.mts +1 -1
- package/dist/vite.mjs +3 -3
- package/package.json +6 -6
- package/src/router/ClientRouter.tsx +199 -0
- package/src/router/index.ts +2 -0
- package/src/router/props-extractor.ts +77 -4
- package/src/vite/index.ts +46 -12
- package/src/vite/server-build.ts +91 -3
- package/dist/server-build-BqMz9o5w.mjs +0 -3
package/dist/client.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { C as fetchWithTimeout, S as createNavigationError, _ as LayoutErrorBoundary, a as LoadingSpinner, b as NavigationErrorOverlay, c as createHttpRuntimeClient, d as clearPropsCacheForComponent, f as extractMetadata, g as hasServerSideDataFetching, h as extractStaticParams, i as HttpRuntimeClient, l as createLoadingBoundary, m as extractServerPropsWithCache, n as DefaultLoading, o as NotFound, p as extractServerProps, r as ErrorBoundary, s as createErrorBoundary, t as DefaultError, u as clearPropsCache, v as ClientRouter, w as LayoutManager, x as NavigationErrorHandler, y as StatePreserver } from "./runtime-client-
|
|
1
|
+
import { C as fetchWithTimeout, S as createNavigationError, _ as LayoutErrorBoundary, a as LoadingSpinner, b as NavigationErrorOverlay, c as createHttpRuntimeClient, d as clearPropsCacheForComponent, f as extractMetadata, g as hasServerSideDataFetching, h as extractStaticParams, i as HttpRuntimeClient, l as createLoadingBoundary, m as extractServerPropsWithCache, n as DefaultLoading, o as NotFound, p as extractServerProps, r as ErrorBoundary, s as createErrorBoundary, t as DefaultError, u as clearPropsCache, v as ClientRouter, w as LayoutManager, x as NavigationErrorHandler, y as StatePreserver } from "./runtime-client-DCkfDJpL.mjs";
|
|
2
2
|
|
|
3
3
|
export { ClientRouter, DefaultError, DefaultLoading, ErrorBoundary, HttpRuntimeClient, LayoutErrorBoundary, LayoutManager, LoadingSpinner, NavigationErrorHandler, NavigationErrorOverlay, NotFound, StatePreserver, clearPropsCache, clearPropsCacheForComponent, createErrorBoundary, createHttpRuntimeClient, createLoadingBoundary, createNavigationError, extractMetadata, extractServerProps, extractServerPropsWithCache, extractStaticParams, fetchWithTimeout, hasServerSideDataFetching };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { $ as RouteSegment, B as AppRouteManifest, C as extractStaticParams, G as GenerateStaticParams, H as ErrorEntry, J as LoadingEntry, K as LayoutEntry, Q as PageProps, S as extractServerPropsWithCache, U as ErrorProps, V as AppRouteMatch, W as GenerateMetadata, X as NotFoundEntry, Y as LoadingProps, Z as NotFoundProps, _ as StaticParamsResult, b as extractMetadata, et as RouteSegmentType, g as ServerPropsResult, h as MetadataResult, i as HttpRuntimeClient, l as createHttpRuntimeClient, q as LayoutProps, s as RuntimeClient, v as clearPropsCache, w as hasServerSideDataFetching, x as extractServerProps, y as clearPropsCacheForComponent, z as AppRouteEntry } from "./runtime-client-DrRcA8ca.mjs";
|
|
2
|
-
import { a as rari, c as generateAppRouteManifest, d as headers, f as ApiRouteHandlers, h as RouteHandler, i as defineRariOptions, l as loadManifest, m as RouteContext, n as Response, o as rariRouter, p as RariResponse, r as defineRariConfig, s as AppRouteGenerator, t as Request, u as writeManifest } from "./vite-
|
|
2
|
+
import { a as rari, c as generateAppRouteManifest, d as headers, f as ApiRouteHandlers, h as RouteHandler, i as defineRariOptions, l as loadManifest, m as RouteContext, n as Response, o as rariRouter, p as RariResponse, r as defineRariConfig, s as AppRouteGenerator, t as Request, u as writeManifest } from "./vite-BOlxeo_Q.mjs";
|
|
3
3
|
export { ApiRouteHandlers, AppRouteEntry, AppRouteGenerator, AppRouteManifest, AppRouteMatch, ErrorEntry, ErrorProps, GenerateMetadata, GenerateStaticParams, HttpRuntimeClient, LayoutEntry, LayoutProps, LoadingEntry, LoadingProps, MetadataResult, NotFoundEntry, NotFoundProps, PageProps, RariResponse, Request, Response, RouteContext, RouteHandler, RouteSegment, RouteSegmentType, RuntimeClient, ServerPropsResult, StaticParamsResult, clearPropsCache, clearPropsCacheForComponent, createHttpRuntimeClient, defineRariConfig, defineRariOptions, extractMetadata, extractServerProps, extractServerPropsWithCache, extractStaticParams, generateAppRouteManifest, hasServerSideDataFetching, headers, loadManifest, rari, rariRouter, writeManifest };
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as headers, i as rariRouter, n as defineRariOptions, o as RariResponse, r as rari, t as defineRariConfig } from "./vite-
|
|
1
|
+
import { a as headers, i as rariRouter, n as defineRariOptions, o as RariResponse, r as rari, t as defineRariConfig } from "./vite-B_QMp3M4.mjs";
|
|
2
2
|
import { i as writeManifest, n as generateAppRouteManifest, r as loadManifest, t as AppRouteGenerator } from "./app-routes-DZjfJPdB.mjs";
|
|
3
|
-
import { c as createHttpRuntimeClient, d as clearPropsCacheForComponent, f as extractMetadata, g as hasServerSideDataFetching, h as extractStaticParams, i as HttpRuntimeClient, m as extractServerPropsWithCache, p as extractServerProps, u as clearPropsCache } from "./runtime-client-
|
|
4
|
-
import "./server-build-
|
|
3
|
+
import { c as createHttpRuntimeClient, d as clearPropsCacheForComponent, f as extractMetadata, g as hasServerSideDataFetching, h as extractStaticParams, i as HttpRuntimeClient, m as extractServerPropsWithCache, p as extractServerProps, u as clearPropsCache } from "./runtime-client-DCkfDJpL.mjs";
|
|
4
|
+
import "./server-build-ChAPR3tl.mjs";
|
|
5
5
|
|
|
6
6
|
export { AppRouteGenerator, HttpRuntimeClient, RariResponse, clearPropsCache, clearPropsCacheForComponent, createHttpRuntimeClient, defineRariConfig, defineRariOptions, extractMetadata, extractServerProps, extractServerPropsWithCache, extractStaticParams, generateAppRouteManifest, hasServerSideDataFetching, headers, loadManifest, rari, rariRouter, writeManifest };
|
|
@@ -923,6 +923,112 @@ var StatePreserver = class {
|
|
|
923
923
|
|
|
924
924
|
//#endregion
|
|
925
925
|
//#region src/router/ClientRouter.tsx
|
|
926
|
+
function updateDocumentMetadata(metadata) {
|
|
927
|
+
if (metadata.title) document.title = metadata.title;
|
|
928
|
+
const updateOrCreateMetaTag = (selector, attributes) => {
|
|
929
|
+
let element = document.querySelector(selector);
|
|
930
|
+
if (!element) {
|
|
931
|
+
element = document.createElement("meta");
|
|
932
|
+
for (const [key, value] of Object.entries(attributes)) element.setAttribute(key, value);
|
|
933
|
+
document.head.appendChild(element);
|
|
934
|
+
} else if (attributes.content) element.setAttribute("content", attributes.content);
|
|
935
|
+
};
|
|
936
|
+
if (metadata.description) updateOrCreateMetaTag("meta[name=\"description\"]", {
|
|
937
|
+
name: "description",
|
|
938
|
+
content: metadata.description
|
|
939
|
+
});
|
|
940
|
+
if (metadata.keywords && metadata.keywords.length > 0) updateOrCreateMetaTag("meta[name=\"keywords\"]", {
|
|
941
|
+
name: "keywords",
|
|
942
|
+
content: metadata.keywords.join(", ")
|
|
943
|
+
});
|
|
944
|
+
if (metadata.viewport) updateOrCreateMetaTag("meta[name=\"viewport\"]", {
|
|
945
|
+
name: "viewport",
|
|
946
|
+
content: metadata.viewport
|
|
947
|
+
});
|
|
948
|
+
if (metadata.canonical) {
|
|
949
|
+
let canonical = document.querySelector("link[rel=\"canonical\"]");
|
|
950
|
+
if (!canonical) {
|
|
951
|
+
canonical = document.createElement("link");
|
|
952
|
+
canonical.setAttribute("rel", "canonical");
|
|
953
|
+
document.head.appendChild(canonical);
|
|
954
|
+
}
|
|
955
|
+
canonical.setAttribute("href", metadata.canonical);
|
|
956
|
+
}
|
|
957
|
+
if (metadata.robots) {
|
|
958
|
+
const robotsContent = [];
|
|
959
|
+
if (metadata.robots.index !== void 0) robotsContent.push(metadata.robots.index ? "index" : "noindex");
|
|
960
|
+
if (metadata.robots.follow !== void 0) robotsContent.push(metadata.robots.follow ? "follow" : "nofollow");
|
|
961
|
+
if (metadata.robots.nocache) robotsContent.push("nocache");
|
|
962
|
+
if (robotsContent.length > 0) updateOrCreateMetaTag("meta[name=\"robots\"]", {
|
|
963
|
+
name: "robots",
|
|
964
|
+
content: robotsContent.join(", ")
|
|
965
|
+
});
|
|
966
|
+
}
|
|
967
|
+
if (metadata.openGraph) {
|
|
968
|
+
const og = metadata.openGraph;
|
|
969
|
+
if (og.title) updateOrCreateMetaTag("meta[property=\"og:title\"]", {
|
|
970
|
+
property: "og:title",
|
|
971
|
+
content: og.title
|
|
972
|
+
});
|
|
973
|
+
if (og.description) updateOrCreateMetaTag("meta[property=\"og:description\"]", {
|
|
974
|
+
property: "og:description",
|
|
975
|
+
content: og.description
|
|
976
|
+
});
|
|
977
|
+
if (og.url) updateOrCreateMetaTag("meta[property=\"og:url\"]", {
|
|
978
|
+
property: "og:url",
|
|
979
|
+
content: og.url
|
|
980
|
+
});
|
|
981
|
+
if (og.siteName) updateOrCreateMetaTag("meta[property=\"og:site_name\"]", {
|
|
982
|
+
property: "og:site_name",
|
|
983
|
+
content: og.siteName
|
|
984
|
+
});
|
|
985
|
+
if (og.type) updateOrCreateMetaTag("meta[property=\"og:type\"]", {
|
|
986
|
+
property: "og:type",
|
|
987
|
+
content: og.type
|
|
988
|
+
});
|
|
989
|
+
if (og.images && og.images.length > 0) {
|
|
990
|
+
document.querySelectorAll("meta[property=\"og:image\"]").forEach((el) => el.remove());
|
|
991
|
+
for (const image of og.images) {
|
|
992
|
+
const meta = document.createElement("meta");
|
|
993
|
+
meta.setAttribute("property", "og:image");
|
|
994
|
+
meta.setAttribute("content", image);
|
|
995
|
+
document.head.appendChild(meta);
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
if (metadata.twitter) {
|
|
1000
|
+
const twitter = metadata.twitter;
|
|
1001
|
+
if (twitter.card) updateOrCreateMetaTag("meta[name=\"twitter:card\"]", {
|
|
1002
|
+
name: "twitter:card",
|
|
1003
|
+
content: twitter.card
|
|
1004
|
+
});
|
|
1005
|
+
if (twitter.site) updateOrCreateMetaTag("meta[name=\"twitter:site\"]", {
|
|
1006
|
+
name: "twitter:site",
|
|
1007
|
+
content: twitter.site
|
|
1008
|
+
});
|
|
1009
|
+
if (twitter.creator) updateOrCreateMetaTag("meta[name=\"twitter:creator\"]", {
|
|
1010
|
+
name: "twitter:creator",
|
|
1011
|
+
content: twitter.creator
|
|
1012
|
+
});
|
|
1013
|
+
if (twitter.title) updateOrCreateMetaTag("meta[name=\"twitter:title\"]", {
|
|
1014
|
+
name: "twitter:title",
|
|
1015
|
+
content: twitter.title
|
|
1016
|
+
});
|
|
1017
|
+
if (twitter.description) updateOrCreateMetaTag("meta[name=\"twitter:description\"]", {
|
|
1018
|
+
name: "twitter:description",
|
|
1019
|
+
content: twitter.description
|
|
1020
|
+
});
|
|
1021
|
+
if (twitter.images && twitter.images.length > 0) {
|
|
1022
|
+
document.querySelectorAll("meta[name=\"twitter:image\"]").forEach((el) => el.remove());
|
|
1023
|
+
for (const image of twitter.images) {
|
|
1024
|
+
const meta = document.createElement("meta");
|
|
1025
|
+
meta.setAttribute("name", "twitter:image");
|
|
1026
|
+
meta.setAttribute("content", image);
|
|
1027
|
+
document.head.appendChild(meta);
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
926
1032
|
function ClientRouter({ children, manifest, initialRoute }) {
|
|
927
1033
|
const [navigationState, setNavigationState] = useState(() => ({
|
|
928
1034
|
currentRoute: normalizePath(initialRoute),
|
|
@@ -1083,6 +1189,15 @@ function ClientRouter({ children, manifest, initialRoute }) {
|
|
|
1083
1189
|
cleanupAbortedNavigation(targetPath, navigationId);
|
|
1084
1190
|
return;
|
|
1085
1191
|
}
|
|
1192
|
+
try {
|
|
1193
|
+
const metadataHeader = response.headers.get("x-rari-metadata");
|
|
1194
|
+
if (metadataHeader) {
|
|
1195
|
+
const decodedMetadata = decodeURIComponent(metadataHeader);
|
|
1196
|
+
updateDocumentMetadata(JSON.parse(decodedMetadata));
|
|
1197
|
+
}
|
|
1198
|
+
} catch (metadataError) {
|
|
1199
|
+
console.warn("[ClientRouter] Failed to extract/apply metadata:", metadataError);
|
|
1200
|
+
}
|
|
1086
1201
|
const rscWireFormat = await response.text();
|
|
1087
1202
|
window.dispatchEvent(new CustomEvent("rari:navigate", { detail: {
|
|
1088
1203
|
from: fromRoute,
|
|
@@ -1443,7 +1558,6 @@ async function extractMetadata(componentPath, params, searchParams) {
|
|
|
1443
1558
|
/* @vite-ignore */
|
|
1444
1559
|
componentPath
|
|
1445
1560
|
);
|
|
1446
|
-
if (module.metadata && typeof module.metadata === "object") return module.metadata;
|
|
1447
1561
|
if (typeof module.generateMetadata === "function") {
|
|
1448
1562
|
const metadata = await module.generateMetadata({
|
|
1449
1563
|
params,
|
|
@@ -1451,6 +1565,7 @@ async function extractMetadata(componentPath, params, searchParams) {
|
|
|
1451
1565
|
});
|
|
1452
1566
|
if (metadata && typeof metadata === "object") return metadata;
|
|
1453
1567
|
}
|
|
1568
|
+
if (module.metadata && typeof module.metadata === "object") return module.metadata;
|
|
1454
1569
|
return {};
|
|
1455
1570
|
} catch (error) {
|
|
1456
1571
|
console.error(`Failed to extract metadata from ${componentPath}:`, error);
|
|
@@ -52,7 +52,8 @@ var ServerComponentBuilder = class {
|
|
|
52
52
|
outDir: options.outDir || path.join(projectRoot, "dist"),
|
|
53
53
|
serverDir: options.serverDir || "server",
|
|
54
54
|
manifestPath: options.manifestPath || "server-manifest.json",
|
|
55
|
-
minify: options.minify ?? process.env.NODE_ENV === "production"
|
|
55
|
+
minify: options.minify ?? process.env.NODE_ENV === "production",
|
|
56
|
+
alias: options.alias || {}
|
|
56
57
|
};
|
|
57
58
|
}
|
|
58
59
|
isServerComponent(filePath) {
|
|
@@ -263,6 +264,38 @@ const ${importName} = (props) => {
|
|
|
263
264
|
metafile: false,
|
|
264
265
|
write: false,
|
|
265
266
|
plugins: [
|
|
267
|
+
{
|
|
268
|
+
name: "resolve-aliases",
|
|
269
|
+
setup: (build$1) => {
|
|
270
|
+
const aliases = this.options.alias || {};
|
|
271
|
+
for (const [alias, replacement] of Object.entries(aliases)) {
|
|
272
|
+
const escapedAlias = alias.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
273
|
+
const filter = /* @__PURE__ */ new RegExp(`^${escapedAlias}(/|$)`);
|
|
274
|
+
build$1.onResolve({ filter }, (args) => {
|
|
275
|
+
const relativePath = args.path.slice(alias.length);
|
|
276
|
+
const newPath = path.join(replacement, relativePath);
|
|
277
|
+
const resolvedPath = path.isAbsolute(newPath) ? newPath : path.resolve(args.resolveDir, newPath);
|
|
278
|
+
for (const ext$1 of [
|
|
279
|
+
"",
|
|
280
|
+
".ts",
|
|
281
|
+
".tsx",
|
|
282
|
+
".js",
|
|
283
|
+
".jsx"
|
|
284
|
+
]) {
|
|
285
|
+
const pathWithExt = resolvedPath + ext$1;
|
|
286
|
+
if (fs.existsSync(pathWithExt) && fs.statSync(pathWithExt).isFile()) {
|
|
287
|
+
if (this.isClientComponent(pathWithExt)) return {
|
|
288
|
+
path: args.path,
|
|
289
|
+
external: true
|
|
290
|
+
};
|
|
291
|
+
return { path: pathWithExt };
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return { path: resolvedPath };
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
},
|
|
266
299
|
{
|
|
267
300
|
name: "replace-react-imports",
|
|
268
301
|
setup(build$1) {
|
|
@@ -451,6 +484,32 @@ const ${importName} = (props) => {
|
|
|
451
484
|
metafile: false,
|
|
452
485
|
write: false,
|
|
453
486
|
plugins: [
|
|
487
|
+
{
|
|
488
|
+
name: "resolve-aliases",
|
|
489
|
+
setup: (build$1) => {
|
|
490
|
+
const aliases = this.options.alias || {};
|
|
491
|
+
for (const [alias, replacement] of Object.entries(aliases)) {
|
|
492
|
+
const escapedAlias = alias.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
493
|
+
const filter = /* @__PURE__ */ new RegExp(`^${escapedAlias}(/|$)`);
|
|
494
|
+
build$1.onResolve({ filter }, (args) => {
|
|
495
|
+
const relativePath = args.path.slice(alias.length);
|
|
496
|
+
const newPath = path.join(replacement, relativePath);
|
|
497
|
+
const resolvedPath = path.isAbsolute(newPath) ? newPath : path.resolve(args.resolveDir, newPath);
|
|
498
|
+
for (const ext$1 of [
|
|
499
|
+
"",
|
|
500
|
+
".ts",
|
|
501
|
+
".tsx",
|
|
502
|
+
".js",
|
|
503
|
+
".jsx"
|
|
504
|
+
]) {
|
|
505
|
+
const pathWithExt = resolvedPath + ext$1;
|
|
506
|
+
if (fs.existsSync(pathWithExt) && fs.statSync(pathWithExt).isFile()) return { path: pathWithExt };
|
|
507
|
+
}
|
|
508
|
+
return { path: resolvedPath };
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
},
|
|
454
513
|
{
|
|
455
514
|
name: "replace-react-imports",
|
|
456
515
|
setup(build$1) {
|
|
@@ -667,7 +726,7 @@ if (!globalThis["${componentId}"]) {
|
|
|
667
726
|
}
|
|
668
727
|
transformClientImports(code, inputPath) {
|
|
669
728
|
let transformedCode = code;
|
|
670
|
-
const importRegex = /import\s+(\w+)(?:\s*,\s*\{[^}]*\})?\s+from\s+['"]([
|
|
729
|
+
const importRegex = /import\s+(\w+)(?:\s*,\s*\{[^}]*\})?\s+from\s+['"]([^'"]+)['"];?\s*$/gm;
|
|
671
730
|
let match;
|
|
672
731
|
const replacements = [];
|
|
673
732
|
let hasClientComponents = false;
|
|
@@ -727,7 +786,14 @@ function registerClientReference(clientReference, id, exportName) {
|
|
|
727
786
|
return transformedCode;
|
|
728
787
|
}
|
|
729
788
|
resolveImportPath(importPath, importerPath) {
|
|
730
|
-
|
|
789
|
+
let resolvedPath = importPath;
|
|
790
|
+
const aliases = this.options.alias || {};
|
|
791
|
+
for (const [alias, replacement] of Object.entries(aliases)) if (importPath.startsWith(`${alias}/`) || importPath === alias) {
|
|
792
|
+
const relativePath = importPath.slice(alias.length);
|
|
793
|
+
resolvedPath = path.join(replacement, relativePath);
|
|
794
|
+
break;
|
|
795
|
+
}
|
|
796
|
+
if (!path.isAbsolute(resolvedPath)) resolvedPath = path.resolve(path.dirname(importerPath), resolvedPath);
|
|
731
797
|
const extensions = [
|
|
732
798
|
".tsx",
|
|
733
799
|
".jsx",
|
|
@@ -907,7 +973,20 @@ function createServerBuildPlugin(options = {}) {
|
|
|
907
973
|
configResolved(config) {
|
|
908
974
|
projectRoot = config.root;
|
|
909
975
|
isDev = config.command === "serve";
|
|
910
|
-
|
|
976
|
+
const alias = {};
|
|
977
|
+
if (config.resolve?.alias) {
|
|
978
|
+
const aliasConfig = config.resolve.alias;
|
|
979
|
+
if (Array.isArray(aliasConfig)) aliasConfig.forEach((entry) => {
|
|
980
|
+
if (typeof entry.find === "string" && typeof entry.replacement === "string") alias[entry.find] = entry.replacement;
|
|
981
|
+
});
|
|
982
|
+
else if (typeof aliasConfig === "object") Object.entries(aliasConfig).forEach(([key, value]) => {
|
|
983
|
+
if (typeof value === "string") alias[key] = value;
|
|
984
|
+
});
|
|
985
|
+
}
|
|
986
|
+
builder = new ServerComponentBuilder(projectRoot, {
|
|
987
|
+
...options,
|
|
988
|
+
alias
|
|
989
|
+
});
|
|
911
990
|
},
|
|
912
991
|
buildStart() {
|
|
913
992
|
if (!builder) return;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __require } from "./chunk-DFPPfDFE.mjs";
|
|
2
|
-
import { n as createServerBuildPlugin } from "./server-build-
|
|
2
|
+
import { n as createServerBuildPlugin } from "./server-build-ChAPR3tl.mjs";
|
|
3
3
|
import fs, { promises, stat, unwatchFile, watch, watchFile } from "node:fs";
|
|
4
4
|
import * as sp from "node:path";
|
|
5
5
|
import path, { join, relative, resolve, sep } from "node:path";
|
|
@@ -2326,6 +2326,7 @@ function rari(options = {}) {
|
|
|
2326
2326
|
let rustServerProcess = null;
|
|
2327
2327
|
const serverImportedClientComponents = /* @__PURE__ */ new Set();
|
|
2328
2328
|
let hmrCoordinator = null;
|
|
2329
|
+
const resolvedAlias = {};
|
|
2329
2330
|
function isServerComponent(filePath) {
|
|
2330
2331
|
if (filePath.includes("node_modules")) return false;
|
|
2331
2332
|
if (filePath.includes("/rari/dist/") || filePath.includes("\\rari\\dist\\")) return false;
|
|
@@ -2509,7 +2510,12 @@ if (import.meta.hot) {
|
|
|
2509
2510
|
const existingDedupe = Array.isArray(config.resolve.dedupe) ? config.resolve.dedupe : [];
|
|
2510
2511
|
const toAdd = ["react", "react-dom"];
|
|
2511
2512
|
config.resolve.dedupe = Array.from(new Set([...existingDedupe || [], ...toAdd]));
|
|
2512
|
-
|
|
2513
|
+
let existingAlias = [];
|
|
2514
|
+
if (Array.isArray(config.resolve.alias)) existingAlias = config.resolve.alias;
|
|
2515
|
+
else if (config.resolve.alias && typeof config.resolve.alias === "object") existingAlias = Object.entries(config.resolve.alias).map(([key, value]) => ({
|
|
2516
|
+
find: key,
|
|
2517
|
+
replacement: value
|
|
2518
|
+
}));
|
|
2513
2519
|
const aliasFinds = new Set(existingAlias.map((a) => String(a.find)));
|
|
2514
2520
|
try {
|
|
2515
2521
|
const reactPath = __require.resolve("react");
|
|
@@ -2563,7 +2569,7 @@ if (import.meta.hot) {
|
|
|
2563
2569
|
"client"
|
|
2564
2570
|
]) {
|
|
2565
2571
|
const env = config.environments[envName];
|
|
2566
|
-
if (env && env.build) env.build.
|
|
2572
|
+
if (env && env.build) env.build.rolldownOptions = env.build.rolldownOptions || {};
|
|
2567
2573
|
}
|
|
2568
2574
|
config.server = config.server || {};
|
|
2569
2575
|
config.server.proxy = config.server.proxy || {};
|
|
@@ -2589,16 +2595,34 @@ if (import.meta.hot) {
|
|
|
2589
2595
|
};
|
|
2590
2596
|
if (command === "build") {
|
|
2591
2597
|
config.build = config.build || {};
|
|
2592
|
-
config.build.
|
|
2593
|
-
if (!config.build.
|
|
2598
|
+
config.build.rolldownOptions = config.build.rolldownOptions || {};
|
|
2599
|
+
if (!config.build.rolldownOptions.input) config.build.rolldownOptions.input = { main: "./index.html" };
|
|
2594
2600
|
}
|
|
2595
2601
|
if (config.environments && config.environments.client) {
|
|
2596
2602
|
if (!config.environments.client.build) config.environments.client.build = {};
|
|
2597
|
-
if (!config.environments.client.build.
|
|
2598
|
-
if (!config.environments.client.build.
|
|
2603
|
+
if (!config.environments.client.build.rolldownOptions) config.environments.client.build.rolldownOptions = {};
|
|
2604
|
+
if (!config.environments.client.build.rolldownOptions.input) config.environments.client.build.rolldownOptions.input = {};
|
|
2599
2605
|
}
|
|
2600
2606
|
return config;
|
|
2601
2607
|
},
|
|
2608
|
+
configResolved(config) {
|
|
2609
|
+
const excludeAliases = new Set([
|
|
2610
|
+
"react",
|
|
2611
|
+
"react-dom",
|
|
2612
|
+
"react/jsx-runtime",
|
|
2613
|
+
"react/jsx-dev-runtime",
|
|
2614
|
+
"react-dom/client"
|
|
2615
|
+
]);
|
|
2616
|
+
if (config.resolve?.alias) {
|
|
2617
|
+
const aliasConfig = config.resolve.alias;
|
|
2618
|
+
if (Array.isArray(aliasConfig)) aliasConfig.forEach((entry) => {
|
|
2619
|
+
if (typeof entry.find === "string" && typeof entry.replacement === "string" && !excludeAliases.has(entry.find)) resolvedAlias[entry.find] = entry.replacement;
|
|
2620
|
+
});
|
|
2621
|
+
else if (typeof aliasConfig === "object") Object.entries(aliasConfig).forEach(([key, value]) => {
|
|
2622
|
+
if (typeof value === "string" && !excludeAliases.has(key)) resolvedAlias[key] = value;
|
|
2623
|
+
});
|
|
2624
|
+
}
|
|
2625
|
+
},
|
|
2602
2626
|
transform(code, id) {
|
|
2603
2627
|
if (!/\.(?:tsx?|jsx?)$/.test(id)) return null;
|
|
2604
2628
|
const environment = this.environment;
|
|
@@ -2716,11 +2740,12 @@ const ${componentName$1} = registerClientReference(
|
|
|
2716
2740
|
let serverComponentBuilder = null;
|
|
2717
2741
|
const discoverAndRegisterComponents = async () => {
|
|
2718
2742
|
try {
|
|
2719
|
-
const { ServerComponentBuilder, scanDirectory } = await import("./server-build-
|
|
2743
|
+
const { ServerComponentBuilder, scanDirectory } = await import("./server-build-Br9CwaA7.mjs");
|
|
2720
2744
|
const builder = new ServerComponentBuilder(projectRoot, {
|
|
2721
2745
|
outDir: "dist",
|
|
2722
2746
|
serverDir: "server",
|
|
2723
|
-
manifestPath: "server-manifest.json"
|
|
2747
|
+
manifestPath: "server-manifest.json",
|
|
2748
|
+
alias: resolvedAlias
|
|
2724
2749
|
});
|
|
2725
2750
|
serverComponentBuilder = builder;
|
|
2726
2751
|
if (!hmrCoordinator && serverComponentBuilder) {
|
|
@@ -2877,11 +2902,12 @@ const ${componentName$1} = registerClientReference(
|
|
|
2877
2902
|
const handleServerComponentHMR = async (filePath) => {
|
|
2878
2903
|
try {
|
|
2879
2904
|
if (!isServerComponent(filePath)) return;
|
|
2880
|
-
const { ServerComponentBuilder } = await import("./server-build-
|
|
2905
|
+
const { ServerComponentBuilder } = await import("./server-build-Br9CwaA7.mjs");
|
|
2881
2906
|
const builder = new ServerComponentBuilder(projectRoot, {
|
|
2882
2907
|
outDir: "dist",
|
|
2883
2908
|
serverDir: "server",
|
|
2884
|
-
manifestPath: "server-manifest.json"
|
|
2909
|
+
manifestPath: "server-manifest.json",
|
|
2910
|
+
alias: resolvedAlias
|
|
2885
2911
|
});
|
|
2886
2912
|
builder.addServerComponent(filePath);
|
|
2887
2913
|
const components = await builder.getTransformedComponentsForDevelopment();
|
package/dist/vite.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { $ as RouteSegment, B as AppRouteManifest, C as extractStaticParams, G as GenerateStaticParams, H as ErrorEntry, J as LoadingEntry, K as LayoutEntry, Q as PageProps, S as extractServerPropsWithCache, U as ErrorProps, V as AppRouteMatch, W as GenerateMetadata, X as NotFoundEntry, Y as LoadingProps, Z as NotFoundProps, _ as StaticParamsResult, b as extractMetadata, et as RouteSegmentType, g as ServerPropsResult, h as MetadataResult, i as HttpRuntimeClient, l as createHttpRuntimeClient, q as LayoutProps, s as RuntimeClient, v as clearPropsCache, w as hasServerSideDataFetching, x as extractServerProps, y as clearPropsCacheForComponent, z as AppRouteEntry } from "./runtime-client-DrRcA8ca.mjs";
|
|
2
|
-
import { a as rari, c as generateAppRouteManifest, d as headers, f as ApiRouteHandlers, h as RouteHandler, i as defineRariOptions, l as loadManifest, m as RouteContext, n as Response, o as rariRouter, p as RariResponse, r as defineRariConfig, s as AppRouteGenerator, t as Request, u as writeManifest } from "./vite-
|
|
2
|
+
import { a as rari, c as generateAppRouteManifest, d as headers, f as ApiRouteHandlers, h as RouteHandler, i as defineRariOptions, l as loadManifest, m as RouteContext, n as Response, o as rariRouter, p as RariResponse, r as defineRariConfig, s as AppRouteGenerator, t as Request, u as writeManifest } from "./vite-BOlxeo_Q.mjs";
|
|
3
3
|
export { ApiRouteHandlers, AppRouteEntry, AppRouteGenerator, AppRouteManifest, AppRouteMatch, ErrorEntry, ErrorProps, GenerateMetadata, GenerateStaticParams, HttpRuntimeClient, LayoutEntry, LayoutProps, LoadingEntry, LoadingProps, MetadataResult, NotFoundEntry, NotFoundProps, PageProps, RariResponse, Request, Response, RouteContext, RouteHandler, RouteSegment, RouteSegmentType, RuntimeClient, ServerPropsResult, StaticParamsResult, clearPropsCache, clearPropsCacheForComponent, createHttpRuntimeClient, defineRariConfig, defineRariOptions, extractMetadata, extractServerProps, extractServerPropsWithCache, extractStaticParams, generateAppRouteManifest, hasServerSideDataFetching, headers, loadManifest, rari, rariRouter, writeManifest };
|
package/dist/vite.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as headers, i as rariRouter, n as defineRariOptions, o as RariResponse, r as rari, t as defineRariConfig } from "./vite-
|
|
1
|
+
import { a as headers, i as rariRouter, n as defineRariOptions, o as RariResponse, r as rari, t as defineRariConfig } from "./vite-B_QMp3M4.mjs";
|
|
2
2
|
import { i as writeManifest, n as generateAppRouteManifest, r as loadManifest, t as AppRouteGenerator } from "./app-routes-DZjfJPdB.mjs";
|
|
3
|
-
import { c as createHttpRuntimeClient, d as clearPropsCacheForComponent, f as extractMetadata, g as hasServerSideDataFetching, h as extractStaticParams, i as HttpRuntimeClient, m as extractServerPropsWithCache, p as extractServerProps, u as clearPropsCache } from "./runtime-client-
|
|
4
|
-
import "./server-build-
|
|
3
|
+
import { c as createHttpRuntimeClient, d as clearPropsCacheForComponent, f as extractMetadata, g as hasServerSideDataFetching, h as extractStaticParams, i as HttpRuntimeClient, m as extractServerPropsWithCache, p as extractServerProps, u as clearPropsCache } from "./runtime-client-DCkfDJpL.mjs";
|
|
4
|
+
import "./server-build-ChAPR3tl.mjs";
|
|
5
5
|
|
|
6
6
|
export { AppRouteGenerator, HttpRuntimeClient, RariResponse, clearPropsCache, clearPropsCacheForComponent, createHttpRuntimeClient, defineRariConfig, defineRariOptions, extractMetadata, extractServerProps, extractServerPropsWithCache, extractStaticParams, generateAppRouteManifest, hasServerSideDataFetching, headers, loadManifest, rari, rariRouter, writeManifest };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rari",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.17",
|
|
5
5
|
"description": "Runtime Accelerated Rendering Infrastructure (Rari)",
|
|
6
6
|
"author": "Ryan Skinner",
|
|
7
7
|
"license": "MIT",
|
|
@@ -89,11 +89,11 @@
|
|
|
89
89
|
"picocolors": "^1.1.1"
|
|
90
90
|
},
|
|
91
91
|
"optionalDependencies": {
|
|
92
|
-
"rari-darwin-arm64": "0.5.
|
|
93
|
-
"rari-darwin-x64": "0.5.
|
|
94
|
-
"rari-linux-arm64": "0.5.
|
|
95
|
-
"rari-linux-x64": "0.5.
|
|
96
|
-
"rari-win32-x64": "0.5.
|
|
92
|
+
"rari-darwin-arm64": "0.5.11",
|
|
93
|
+
"rari-darwin-x64": "0.5.11",
|
|
94
|
+
"rari-linux-arm64": "0.5.11",
|
|
95
|
+
"rari-linux-x64": "0.5.11",
|
|
96
|
+
"rari-win32-x64": "0.5.11"
|
|
97
97
|
},
|
|
98
98
|
"devDependencies": {
|
|
99
99
|
"@types/node": "^25.0.1",
|
|
@@ -12,6 +12,193 @@ import { extractPathname, findLayoutChain, isExternalUrl, matchRouteParams, norm
|
|
|
12
12
|
import { NavigationErrorOverlay } from './NavigationErrorOverlay'
|
|
13
13
|
import { StatePreserver } from './StatePreserver'
|
|
14
14
|
|
|
15
|
+
interface PageMetadata {
|
|
16
|
+
title?: string
|
|
17
|
+
description?: string
|
|
18
|
+
keywords?: string[]
|
|
19
|
+
viewport?: string
|
|
20
|
+
canonical?: string
|
|
21
|
+
openGraph?: {
|
|
22
|
+
title?: string
|
|
23
|
+
description?: string
|
|
24
|
+
url?: string
|
|
25
|
+
siteName?: string
|
|
26
|
+
images?: string[]
|
|
27
|
+
type?: string
|
|
28
|
+
}
|
|
29
|
+
twitter?: {
|
|
30
|
+
card?: string
|
|
31
|
+
site?: string
|
|
32
|
+
creator?: string
|
|
33
|
+
title?: string
|
|
34
|
+
description?: string
|
|
35
|
+
images?: string[]
|
|
36
|
+
}
|
|
37
|
+
robots?: {
|
|
38
|
+
index?: boolean
|
|
39
|
+
follow?: boolean
|
|
40
|
+
nocache?: boolean
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function updateDocumentMetadata(metadata: PageMetadata): void {
|
|
45
|
+
if (metadata.title) {
|
|
46
|
+
document.title = metadata.title
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const updateOrCreateMetaTag = (selector: string, attributes: Record<string, string>) => {
|
|
50
|
+
let element = document.querySelector(selector) as HTMLMetaElement | null
|
|
51
|
+
if (!element) {
|
|
52
|
+
element = document.createElement('meta')
|
|
53
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
54
|
+
element.setAttribute(key, value)
|
|
55
|
+
}
|
|
56
|
+
document.head.appendChild(element)
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
if (attributes.content) {
|
|
60
|
+
element.setAttribute('content', attributes.content)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (metadata.description) {
|
|
66
|
+
updateOrCreateMetaTag('meta[name="description"]', {
|
|
67
|
+
name: 'description',
|
|
68
|
+
content: metadata.description,
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (metadata.keywords && metadata.keywords.length > 0) {
|
|
73
|
+
updateOrCreateMetaTag('meta[name="keywords"]', {
|
|
74
|
+
name: 'keywords',
|
|
75
|
+
content: metadata.keywords.join(', '),
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (metadata.viewport) {
|
|
80
|
+
updateOrCreateMetaTag('meta[name="viewport"]', {
|
|
81
|
+
name: 'viewport',
|
|
82
|
+
content: metadata.viewport,
|
|
83
|
+
})
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (metadata.canonical) {
|
|
87
|
+
let canonical = document.querySelector('link[rel="canonical"]') as HTMLLinkElement | null
|
|
88
|
+
if (!canonical) {
|
|
89
|
+
canonical = document.createElement('link')
|
|
90
|
+
canonical.setAttribute('rel', 'canonical')
|
|
91
|
+
document.head.appendChild(canonical)
|
|
92
|
+
}
|
|
93
|
+
canonical.setAttribute('href', metadata.canonical)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (metadata.robots) {
|
|
97
|
+
const robotsContent: string[] = []
|
|
98
|
+
if (metadata.robots.index !== undefined) {
|
|
99
|
+
robotsContent.push(metadata.robots.index ? 'index' : 'noindex')
|
|
100
|
+
}
|
|
101
|
+
if (metadata.robots.follow !== undefined) {
|
|
102
|
+
robotsContent.push(metadata.robots.follow ? 'follow' : 'nofollow')
|
|
103
|
+
}
|
|
104
|
+
if (metadata.robots.nocache) {
|
|
105
|
+
robotsContent.push('nocache')
|
|
106
|
+
}
|
|
107
|
+
if (robotsContent.length > 0) {
|
|
108
|
+
updateOrCreateMetaTag('meta[name="robots"]', {
|
|
109
|
+
name: 'robots',
|
|
110
|
+
content: robotsContent.join(', '),
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (metadata.openGraph) {
|
|
116
|
+
const og = metadata.openGraph
|
|
117
|
+
if (og.title) {
|
|
118
|
+
updateOrCreateMetaTag('meta[property="og:title"]', {
|
|
119
|
+
property: 'og:title',
|
|
120
|
+
content: og.title,
|
|
121
|
+
})
|
|
122
|
+
}
|
|
123
|
+
if (og.description) {
|
|
124
|
+
updateOrCreateMetaTag('meta[property="og:description"]', {
|
|
125
|
+
property: 'og:description',
|
|
126
|
+
content: og.description,
|
|
127
|
+
})
|
|
128
|
+
}
|
|
129
|
+
if (og.url) {
|
|
130
|
+
updateOrCreateMetaTag('meta[property="og:url"]', {
|
|
131
|
+
property: 'og:url',
|
|
132
|
+
content: og.url,
|
|
133
|
+
})
|
|
134
|
+
}
|
|
135
|
+
if (og.siteName) {
|
|
136
|
+
updateOrCreateMetaTag('meta[property="og:site_name"]', {
|
|
137
|
+
property: 'og:site_name',
|
|
138
|
+
content: og.siteName,
|
|
139
|
+
})
|
|
140
|
+
}
|
|
141
|
+
if (og.type) {
|
|
142
|
+
updateOrCreateMetaTag('meta[property="og:type"]', {
|
|
143
|
+
property: 'og:type',
|
|
144
|
+
content: og.type,
|
|
145
|
+
})
|
|
146
|
+
}
|
|
147
|
+
if (og.images && og.images.length > 0) {
|
|
148
|
+
document.querySelectorAll('meta[property="og:image"]').forEach(el => el.remove())
|
|
149
|
+
for (const image of og.images) {
|
|
150
|
+
const meta = document.createElement('meta')
|
|
151
|
+
meta.setAttribute('property', 'og:image')
|
|
152
|
+
meta.setAttribute('content', image)
|
|
153
|
+
document.head.appendChild(meta)
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (metadata.twitter) {
|
|
159
|
+
const twitter = metadata.twitter
|
|
160
|
+
if (twitter.card) {
|
|
161
|
+
updateOrCreateMetaTag('meta[name="twitter:card"]', {
|
|
162
|
+
name: 'twitter:card',
|
|
163
|
+
content: twitter.card,
|
|
164
|
+
})
|
|
165
|
+
}
|
|
166
|
+
if (twitter.site) {
|
|
167
|
+
updateOrCreateMetaTag('meta[name="twitter:site"]', {
|
|
168
|
+
name: 'twitter:site',
|
|
169
|
+
content: twitter.site,
|
|
170
|
+
})
|
|
171
|
+
}
|
|
172
|
+
if (twitter.creator) {
|
|
173
|
+
updateOrCreateMetaTag('meta[name="twitter:creator"]', {
|
|
174
|
+
name: 'twitter:creator',
|
|
175
|
+
content: twitter.creator,
|
|
176
|
+
})
|
|
177
|
+
}
|
|
178
|
+
if (twitter.title) {
|
|
179
|
+
updateOrCreateMetaTag('meta[name="twitter:title"]', {
|
|
180
|
+
name: 'twitter:title',
|
|
181
|
+
content: twitter.title,
|
|
182
|
+
})
|
|
183
|
+
}
|
|
184
|
+
if (twitter.description) {
|
|
185
|
+
updateOrCreateMetaTag('meta[name="twitter:description"]', {
|
|
186
|
+
name: 'twitter:description',
|
|
187
|
+
content: twitter.description,
|
|
188
|
+
})
|
|
189
|
+
}
|
|
190
|
+
if (twitter.images && twitter.images.length > 0) {
|
|
191
|
+
document.querySelectorAll('meta[name="twitter:image"]').forEach(el => el.remove())
|
|
192
|
+
for (const image of twitter.images) {
|
|
193
|
+
const meta = document.createElement('meta')
|
|
194
|
+
meta.setAttribute('name', 'twitter:image')
|
|
195
|
+
meta.setAttribute('content', image)
|
|
196
|
+
document.head.appendChild(meta)
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
15
202
|
export interface ClientRouterProps {
|
|
16
203
|
children: React.ReactNode
|
|
17
204
|
manifest: AppRouteManifest
|
|
@@ -305,6 +492,18 @@ export function ClientRouter({ children, manifest, initialRoute }: ClientRouterP
|
|
|
305
492
|
return
|
|
306
493
|
}
|
|
307
494
|
|
|
495
|
+
try {
|
|
496
|
+
const metadataHeader = response.headers.get('x-rari-metadata')
|
|
497
|
+
if (metadataHeader) {
|
|
498
|
+
const decodedMetadata = decodeURIComponent(metadataHeader)
|
|
499
|
+
const metadata = JSON.parse(decodedMetadata) as PageMetadata
|
|
500
|
+
updateDocumentMetadata(metadata)
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
catch (metadataError) {
|
|
504
|
+
console.warn('[ClientRouter] Failed to extract/apply metadata:', metadataError)
|
|
505
|
+
}
|
|
506
|
+
|
|
308
507
|
const rscWireFormat = await response.text()
|
|
309
508
|
|
|
310
509
|
window.dispatchEvent(new CustomEvent('rari:navigate', {
|
package/src/router/index.ts
CHANGED
|
@@ -80,11 +80,13 @@ export type { NavigationErrorOverlayProps } from './NavigationErrorOverlay'
|
|
|
80
80
|
export {
|
|
81
81
|
clearPropsCache,
|
|
82
82
|
clearPropsCacheForComponent,
|
|
83
|
+
collectMetadataFromChain,
|
|
83
84
|
extractMetadata,
|
|
84
85
|
extractServerProps,
|
|
85
86
|
extractServerPropsWithCache,
|
|
86
87
|
extractStaticParams,
|
|
87
88
|
hasServerSideDataFetching,
|
|
89
|
+
mergeMetadata,
|
|
88
90
|
} from './props-extractor'
|
|
89
91
|
|
|
90
92
|
export type {
|
|
@@ -162,10 +162,6 @@ export async function extractMetadata(
|
|
|
162
162
|
try {
|
|
163
163
|
const module = await import(/* @vite-ignore */ componentPath)
|
|
164
164
|
|
|
165
|
-
if (module.metadata && typeof module.metadata === 'object') {
|
|
166
|
-
return module.metadata
|
|
167
|
-
}
|
|
168
|
-
|
|
169
165
|
if (typeof module.generateMetadata === 'function') {
|
|
170
166
|
const metadata = await module.generateMetadata({ params, searchParams })
|
|
171
167
|
if (metadata && typeof metadata === 'object') {
|
|
@@ -173,6 +169,10 @@ export async function extractMetadata(
|
|
|
173
169
|
}
|
|
174
170
|
}
|
|
175
171
|
|
|
172
|
+
if (module.metadata && typeof module.metadata === 'object') {
|
|
173
|
+
return module.metadata
|
|
174
|
+
}
|
|
175
|
+
|
|
176
176
|
return {}
|
|
177
177
|
}
|
|
178
178
|
catch (error) {
|
|
@@ -181,6 +181,60 @@ export async function extractMetadata(
|
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
+
export function mergeMetadata(
|
|
185
|
+
parentMetadata: MetadataResult,
|
|
186
|
+
childMetadata: MetadataResult,
|
|
187
|
+
): MetadataResult {
|
|
188
|
+
const merged: MetadataResult = { ...parentMetadata }
|
|
189
|
+
|
|
190
|
+
if (childMetadata.title !== undefined) {
|
|
191
|
+
if (typeof childMetadata.title === 'string') {
|
|
192
|
+
if (typeof parentMetadata.title === 'object' && parentMetadata.title?.template) {
|
|
193
|
+
merged.title = parentMetadata.title.template.replace('%s', childMetadata.title)
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
merged.title = childMetadata.title
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
merged.title = childMetadata.title
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (childMetadata.description !== undefined) {
|
|
205
|
+
merged.description = childMetadata.description
|
|
206
|
+
}
|
|
207
|
+
if (childMetadata.keywords !== undefined) {
|
|
208
|
+
merged.keywords = childMetadata.keywords
|
|
209
|
+
}
|
|
210
|
+
if (childMetadata.openGraph !== undefined) {
|
|
211
|
+
merged.openGraph = { ...parentMetadata.openGraph, ...childMetadata.openGraph }
|
|
212
|
+
}
|
|
213
|
+
if (childMetadata.twitter !== undefined) {
|
|
214
|
+
merged.twitter = { ...parentMetadata.twitter, ...childMetadata.twitter }
|
|
215
|
+
}
|
|
216
|
+
if (childMetadata.robots !== undefined) {
|
|
217
|
+
merged.robots = { ...parentMetadata.robots, ...childMetadata.robots }
|
|
218
|
+
}
|
|
219
|
+
if (childMetadata.icons !== undefined) {
|
|
220
|
+
merged.icons = { ...parentMetadata.icons, ...childMetadata.icons }
|
|
221
|
+
}
|
|
222
|
+
if (childMetadata.manifest !== undefined) {
|
|
223
|
+
merged.manifest = childMetadata.manifest
|
|
224
|
+
}
|
|
225
|
+
if (childMetadata.viewport !== undefined) {
|
|
226
|
+
merged.viewport = { ...parentMetadata.viewport, ...childMetadata.viewport }
|
|
227
|
+
}
|
|
228
|
+
if (childMetadata.verification !== undefined) {
|
|
229
|
+
merged.verification = { ...parentMetadata.verification, ...childMetadata.verification }
|
|
230
|
+
}
|
|
231
|
+
if (childMetadata.alternates !== undefined) {
|
|
232
|
+
merged.alternates = { ...parentMetadata.alternates, ...childMetadata.alternates }
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return merged
|
|
236
|
+
}
|
|
237
|
+
|
|
184
238
|
export async function extractStaticParams(
|
|
185
239
|
componentPath: string,
|
|
186
240
|
): Promise<StaticParamsResult> {
|
|
@@ -260,3 +314,22 @@ export function clearPropsCacheForComponent(componentPath: string): void {
|
|
|
260
314
|
}
|
|
261
315
|
}
|
|
262
316
|
}
|
|
317
|
+
|
|
318
|
+
export async function collectMetadataFromChain(
|
|
319
|
+
layoutPaths: string[],
|
|
320
|
+
pagePath: string,
|
|
321
|
+
params: Record<string, string>,
|
|
322
|
+
searchParams: Record<string, string>,
|
|
323
|
+
): Promise<MetadataResult> {
|
|
324
|
+
let metadata: MetadataResult = {}
|
|
325
|
+
|
|
326
|
+
for (const layoutPath of layoutPaths) {
|
|
327
|
+
const layoutMetadata = await extractMetadata(layoutPath, params, searchParams)
|
|
328
|
+
metadata = mergeMetadata(metadata, layoutMetadata)
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const pageMetadata = await extractMetadata(pagePath, params, searchParams)
|
|
332
|
+
metadata = mergeMetadata(metadata, pageMetadata)
|
|
333
|
+
|
|
334
|
+
return metadata
|
|
335
|
+
}
|
package/src/vite/index.ts
CHANGED
|
@@ -103,6 +103,7 @@ export function rari(options: RariOptions = {}): Plugin[] {
|
|
|
103
103
|
const serverImportedClientComponents = new Set<string>()
|
|
104
104
|
|
|
105
105
|
let hmrCoordinator: HMRCoordinator | null = null
|
|
106
|
+
const resolvedAlias: Record<string, string> = {}
|
|
106
107
|
|
|
107
108
|
function isServerComponent(filePath: string): boolean {
|
|
108
109
|
if (filePath.includes('node_modules')) {
|
|
@@ -434,12 +435,21 @@ if (import.meta.hot) {
|
|
|
434
435
|
new Set([...(existingDedupe || []), ...toAdd]),
|
|
435
436
|
)
|
|
436
437
|
|
|
437
|
-
|
|
438
|
+
let existingAlias: Array<{
|
|
438
439
|
find: string | RegExp
|
|
439
440
|
replacement: string
|
|
440
|
-
}> =
|
|
441
|
-
|
|
442
|
-
|
|
441
|
+
}> = []
|
|
442
|
+
|
|
443
|
+
if (Array.isArray((config.resolve as any).alias)) {
|
|
444
|
+
existingAlias = (config.resolve as any).alias
|
|
445
|
+
}
|
|
446
|
+
else if ((config.resolve as any).alias && typeof (config.resolve as any).alias === 'object') {
|
|
447
|
+
existingAlias = Object.entries((config.resolve as any).alias).map(([key, value]) => ({
|
|
448
|
+
find: key,
|
|
449
|
+
replacement: value as string,
|
|
450
|
+
}))
|
|
451
|
+
}
|
|
452
|
+
|
|
443
453
|
const aliasFinds = new Set(existingAlias.map(a => String(a.find)))
|
|
444
454
|
try {
|
|
445
455
|
const reactPath = require.resolve('react')
|
|
@@ -516,7 +526,7 @@ if (import.meta.hot) {
|
|
|
516
526
|
for (const envName of ['rsc', 'ssr', 'client']) {
|
|
517
527
|
const env = config.environments[envName]
|
|
518
528
|
if (env && env.build) {
|
|
519
|
-
env.build.
|
|
529
|
+
env.build.rolldownOptions = env.build.rolldownOptions || {}
|
|
520
530
|
}
|
|
521
531
|
}
|
|
522
532
|
}
|
|
@@ -552,10 +562,10 @@ if (import.meta.hot) {
|
|
|
552
562
|
|
|
553
563
|
if (command === 'build') {
|
|
554
564
|
config.build = config.build || {}
|
|
555
|
-
config.build.
|
|
565
|
+
config.build.rolldownOptions = config.build.rolldownOptions || {}
|
|
556
566
|
|
|
557
|
-
if (!config.build.
|
|
558
|
-
config.build.
|
|
567
|
+
if (!config.build.rolldownOptions.input) {
|
|
568
|
+
config.build.rolldownOptions.input = {
|
|
559
569
|
main: './index.html',
|
|
560
570
|
}
|
|
561
571
|
}
|
|
@@ -565,17 +575,39 @@ if (import.meta.hot) {
|
|
|
565
575
|
if (!config.environments.client.build) {
|
|
566
576
|
config.environments.client.build = {}
|
|
567
577
|
}
|
|
568
|
-
if (!config.environments.client.build.
|
|
569
|
-
config.environments.client.build.
|
|
578
|
+
if (!config.environments.client.build.rolldownOptions) {
|
|
579
|
+
config.environments.client.build.rolldownOptions = {}
|
|
570
580
|
}
|
|
571
|
-
if (!config.environments.client.build.
|
|
572
|
-
config.environments.client.build.
|
|
581
|
+
if (!config.environments.client.build.rolldownOptions.input) {
|
|
582
|
+
config.environments.client.build.rolldownOptions.input = {}
|
|
573
583
|
}
|
|
574
584
|
}
|
|
575
585
|
|
|
576
586
|
return config
|
|
577
587
|
},
|
|
578
588
|
|
|
589
|
+
configResolved(config) {
|
|
590
|
+
const excludeAliases = new Set(['react', 'react-dom', 'react/jsx-runtime', 'react/jsx-dev-runtime', 'react-dom/client'])
|
|
591
|
+
|
|
592
|
+
if (config.resolve?.alias) {
|
|
593
|
+
const aliasConfig = config.resolve.alias
|
|
594
|
+
if (Array.isArray(aliasConfig)) {
|
|
595
|
+
aliasConfig.forEach((entry) => {
|
|
596
|
+
if (typeof entry.find === 'string' && typeof entry.replacement === 'string' && !excludeAliases.has(entry.find)) {
|
|
597
|
+
resolvedAlias[entry.find] = entry.replacement
|
|
598
|
+
}
|
|
599
|
+
})
|
|
600
|
+
}
|
|
601
|
+
else if (typeof aliasConfig === 'object') {
|
|
602
|
+
Object.entries(aliasConfig).forEach(([key, value]) => {
|
|
603
|
+
if (typeof value === 'string' && !excludeAliases.has(key)) {
|
|
604
|
+
resolvedAlias[key] = value
|
|
605
|
+
}
|
|
606
|
+
})
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
},
|
|
610
|
+
|
|
579
611
|
transform(code, id) {
|
|
580
612
|
if (!/\.(?:tsx?|jsx?)$/.test(id)) {
|
|
581
613
|
return null
|
|
@@ -819,6 +851,7 @@ const ${componentName} = registerClientReference(
|
|
|
819
851
|
outDir: 'dist',
|
|
820
852
|
serverDir: 'server',
|
|
821
853
|
manifestPath: 'server-manifest.json',
|
|
854
|
+
alias: resolvedAlias,
|
|
822
855
|
})
|
|
823
856
|
|
|
824
857
|
serverComponentBuilder = builder
|
|
@@ -1093,6 +1126,7 @@ const ${componentName} = registerClientReference(
|
|
|
1093
1126
|
outDir: 'dist',
|
|
1094
1127
|
serverDir: 'server',
|
|
1095
1128
|
manifestPath: 'server-manifest.json',
|
|
1129
|
+
alias: resolvedAlias,
|
|
1096
1130
|
})
|
|
1097
1131
|
|
|
1098
1132
|
builder.addServerComponent(filePath)
|
package/src/vite/server-build.ts
CHANGED
|
@@ -60,6 +60,7 @@ export interface ServerBuildOptions {
|
|
|
60
60
|
serverDir?: string
|
|
61
61
|
manifestPath?: string
|
|
62
62
|
minify?: boolean
|
|
63
|
+
alias?: Record<string, string>
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
export interface ComponentRebuildResult {
|
|
@@ -110,6 +111,7 @@ export class ServerComponentBuilder {
|
|
|
110
111
|
serverDir: options.serverDir || 'server',
|
|
111
112
|
manifestPath: options.manifestPath || 'server-manifest.json',
|
|
112
113
|
minify: options.minify ?? process.env.NODE_ENV === 'production',
|
|
114
|
+
alias: options.alias || {},
|
|
113
115
|
}
|
|
114
116
|
}
|
|
115
117
|
|
|
@@ -419,6 +421,34 @@ const ${importName} = (props) => {
|
|
|
419
421
|
metafile: false,
|
|
420
422
|
write: false,
|
|
421
423
|
plugins: [
|
|
424
|
+
{
|
|
425
|
+
name: 'resolve-aliases',
|
|
426
|
+
setup: (build) => {
|
|
427
|
+
const aliases = this.options.alias || {}
|
|
428
|
+
for (const [alias, replacement] of Object.entries(aliases)) {
|
|
429
|
+
const escapedAlias = alias.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
430
|
+
const filter = new RegExp(`^${escapedAlias}(/|$)`)
|
|
431
|
+
build.onResolve({ filter }, (args) => {
|
|
432
|
+
const relativePath = args.path.slice(alias.length)
|
|
433
|
+
const newPath = path.join(replacement, relativePath)
|
|
434
|
+
const resolvedPath = path.isAbsolute(newPath) ? newPath : path.resolve(args.resolveDir, newPath)
|
|
435
|
+
|
|
436
|
+
const possibleExtensions = ['', '.ts', '.tsx', '.js', '.jsx']
|
|
437
|
+
for (const ext of possibleExtensions) {
|
|
438
|
+
const pathWithExt = resolvedPath + ext
|
|
439
|
+
if (fs.existsSync(pathWithExt) && fs.statSync(pathWithExt).isFile()) {
|
|
440
|
+
if (this.isClientComponent(pathWithExt)) {
|
|
441
|
+
return { path: args.path, external: true }
|
|
442
|
+
}
|
|
443
|
+
return { path: pathWithExt }
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
return { path: resolvedPath }
|
|
448
|
+
})
|
|
449
|
+
}
|
|
450
|
+
},
|
|
451
|
+
},
|
|
422
452
|
{
|
|
423
453
|
name: 'replace-react-imports',
|
|
424
454
|
setup(build) {
|
|
@@ -671,6 +701,31 @@ const ${importName} = (props) => {
|
|
|
671
701
|
metafile: false,
|
|
672
702
|
write: false,
|
|
673
703
|
plugins: [
|
|
704
|
+
{
|
|
705
|
+
name: 'resolve-aliases',
|
|
706
|
+
setup: (build) => {
|
|
707
|
+
const aliases = this.options.alias || {}
|
|
708
|
+
for (const [alias, replacement] of Object.entries(aliases)) {
|
|
709
|
+
const escapedAlias = alias.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
710
|
+
const filter = new RegExp(`^${escapedAlias}(/|$)`)
|
|
711
|
+
build.onResolve({ filter }, (args) => {
|
|
712
|
+
const relativePath = args.path.slice(alias.length)
|
|
713
|
+
const newPath = path.join(replacement, relativePath)
|
|
714
|
+
const resolvedPath = path.isAbsolute(newPath) ? newPath : path.resolve(args.resolveDir, newPath)
|
|
715
|
+
|
|
716
|
+
const possibleExtensions = ['', '.ts', '.tsx', '.js', '.jsx']
|
|
717
|
+
for (const ext of possibleExtensions) {
|
|
718
|
+
const pathWithExt = resolvedPath + ext
|
|
719
|
+
if (fs.existsSync(pathWithExt) && fs.statSync(pathWithExt).isFile()) {
|
|
720
|
+
return { path: pathWithExt }
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
return { path: resolvedPath }
|
|
725
|
+
})
|
|
726
|
+
}
|
|
727
|
+
},
|
|
728
|
+
},
|
|
674
729
|
{
|
|
675
730
|
name: 'replace-react-imports',
|
|
676
731
|
setup(build) {
|
|
@@ -1024,7 +1079,7 @@ if (!globalThis["${componentId}"]) {
|
|
|
1024
1079
|
let transformedCode = code
|
|
1025
1080
|
|
|
1026
1081
|
const importRegex
|
|
1027
|
-
= /import\s+(\w+)(?:\s*,\s*\{[^}]*\})?\s+from\s+['"]([
|
|
1082
|
+
= /import\s+(\w+)(?:\s*,\s*\{[^}]*\})?\s+from\s+['"]([^'"]+)['"];?\s*$/gm
|
|
1028
1083
|
let match
|
|
1029
1084
|
|
|
1030
1085
|
const replacements: Array<{ original: string, replacement: string }> = []
|
|
@@ -1099,7 +1154,20 @@ function registerClientReference(clientReference, id, exportName) {
|
|
|
1099
1154
|
}
|
|
1100
1155
|
|
|
1101
1156
|
private resolveImportPath(importPath: string, importerPath: string): string {
|
|
1102
|
-
|
|
1157
|
+
let resolvedPath = importPath
|
|
1158
|
+
const aliases = this.options.alias || {}
|
|
1159
|
+
|
|
1160
|
+
for (const [alias, replacement] of Object.entries(aliases)) {
|
|
1161
|
+
if (importPath.startsWith(`${alias}/`) || importPath === alias) {
|
|
1162
|
+
const relativePath = importPath.slice(alias.length)
|
|
1163
|
+
resolvedPath = path.join(replacement, relativePath)
|
|
1164
|
+
break
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
if (!path.isAbsolute(resolvedPath)) {
|
|
1169
|
+
resolvedPath = path.resolve(path.dirname(importerPath), resolvedPath)
|
|
1170
|
+
}
|
|
1103
1171
|
|
|
1104
1172
|
const extensions = ['.tsx', '.jsx', '.ts', '.js']
|
|
1105
1173
|
for (const ext of extensions) {
|
|
@@ -1412,7 +1480,27 @@ export function createServerBuildPlugin(
|
|
|
1412
1480
|
configResolved(config) {
|
|
1413
1481
|
projectRoot = config.root
|
|
1414
1482
|
isDev = config.command === 'serve'
|
|
1415
|
-
|
|
1483
|
+
|
|
1484
|
+
const alias: Record<string, string> = {}
|
|
1485
|
+
if (config.resolve?.alias) {
|
|
1486
|
+
const aliasConfig = config.resolve.alias
|
|
1487
|
+
if (Array.isArray(aliasConfig)) {
|
|
1488
|
+
aliasConfig.forEach((entry) => {
|
|
1489
|
+
if (typeof entry.find === 'string' && typeof entry.replacement === 'string') {
|
|
1490
|
+
alias[entry.find] = entry.replacement
|
|
1491
|
+
}
|
|
1492
|
+
})
|
|
1493
|
+
}
|
|
1494
|
+
else if (typeof aliasConfig === 'object') {
|
|
1495
|
+
Object.entries(aliasConfig).forEach(([key, value]) => {
|
|
1496
|
+
if (typeof value === 'string') {
|
|
1497
|
+
alias[key] = value
|
|
1498
|
+
}
|
|
1499
|
+
})
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
|
|
1503
|
+
builder = new ServerComponentBuilder(projectRoot, { ...options, alias })
|
|
1416
1504
|
},
|
|
1417
1505
|
|
|
1418
1506
|
buildStart() {
|