rari 0.2.22 → 0.2.23
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/index.js +2 -2
- package/dist/{server-BK7rNurU.js → server-C3POnIbO.js} +102 -27
- package/dist/server-build-Cs2pfA52.js +3 -0
- package/dist/{server-build-BM8_GFF5.js → server-build-DeJfuJb8.js} +1 -1
- package/dist/server.js +2 -2
- package/package.json +6 -6
- package/src/vite/index.ts +105 -21
- package/src/vite/server-build.ts +1 -1
- package/dist/server-build-DcbOtG3e.js +0 -3
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HttpRuntimeClient, Link, Navigate, Outlet, RouteComponent, RouterProvider, Routes, buildSearchString, buildUrl, createHttpRuntimeClient, extractParamNames, findMatchingRoute, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, normalizePathname, parseSearchParams, parseUrl, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, withRouter } from "./runtime-client-BXoadxa8.js";
|
|
2
|
-
import { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, defineRariOptions, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes } from "./server-
|
|
3
|
-
import "./server-build-
|
|
2
|
+
import { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, defineRariOptions, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes } from "./server-C3POnIbO.js";
|
|
3
|
+
import "./server-build-DeJfuJb8.js";
|
|
4
4
|
|
|
5
5
|
export { FileRouteGenerator, HttpRuntimeClient, Link, Navigate, Outlet, RouteComponent as Route, RouterProvider, Routes, buildSearchString, buildUrl, convertFilePatternToRoutePattern, createHttpRuntimeClient, createRouteManifest, defineRariConfig, defineRariOptions, extractParamNames, findMatchingRoute, generateFileRoutes, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, loadRouteManifest, normalizePathname, parseSearchParams, parseUrl, rari, rariRouter, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, validateRoutes, watchFileRoutes, withRouter };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { __commonJS, __require, __toESM } from "./chunk-BLXvPPr8.js";
|
|
2
2
|
import { analyzeFilePath } from "./runtime-client-BXoadxa8.js";
|
|
3
|
-
import { createServerBuildPlugin } from "./server-build-
|
|
3
|
+
import { createServerBuildPlugin } from "./server-build-DeJfuJb8.js";
|
|
4
4
|
import fs, { promises } from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import process$1 from "node:process";
|
|
@@ -5693,7 +5693,7 @@ function rari(options = {}) {
|
|
|
5693
5693
|
const serverDirectives = ["'use server'", "\"use server\""];
|
|
5694
5694
|
const trimmedCode = code.trim();
|
|
5695
5695
|
const hasServerDirective = serverDirectives.some((directive) => trimmedCode.startsWith(directive) || code.includes(directive));
|
|
5696
|
-
const isInFunctionsDir = filePath.includes("/functions/") || filePath.includes("
|
|
5696
|
+
const isInFunctionsDir = filePath.includes("/functions/") || filePath.includes("\\\\functions\\\\");
|
|
5697
5697
|
const hasServerFunctionSignature = (code.includes("export async function") || code.includes("export function")) && code.includes("'use server'");
|
|
5698
5698
|
if (hasServerDirective || isInFunctionsDir && hasServerFunctionSignature) return true;
|
|
5699
5699
|
return false;
|
|
@@ -5980,6 +5980,11 @@ if (import.meta.hot) {
|
|
|
5980
5980
|
import.meta.hot.accept();
|
|
5981
5981
|
}
|
|
5982
5982
|
|
|
5983
|
+
if (typeof globalThis !== 'undefined') {
|
|
5984
|
+
globalThis.__rari_server_components = globalThis.__rari_server_components || new Set();
|
|
5985
|
+
globalThis.__rari_server_components.add(${JSON.stringify(id)});
|
|
5986
|
+
}
|
|
5987
|
+
|
|
5983
5988
|
${clientTransformedCode}`;
|
|
5984
5989
|
return clientTransformedCode;
|
|
5985
5990
|
}
|
|
@@ -6065,14 +6070,35 @@ const ${componentName$1} = registerClientReference(
|
|
|
6065
6070
|
const srcDir = path.join(projectRoot, "src");
|
|
6066
6071
|
const discoverAndRegisterComponents = async () => {
|
|
6067
6072
|
try {
|
|
6068
|
-
const { ServerComponentBuilder, scanDirectory } = await import("./server-build-
|
|
6073
|
+
const { ServerComponentBuilder, scanDirectory } = await import("./server-build-Cs2pfA52.js");
|
|
6069
6074
|
const builder = new ServerComponentBuilder(projectRoot, {
|
|
6070
6075
|
outDir: "temp",
|
|
6071
6076
|
serverDir: "server",
|
|
6072
6077
|
manifestPath: "server-manifest.json"
|
|
6073
6078
|
});
|
|
6074
6079
|
const srcDir$1 = path.join(projectRoot, "src");
|
|
6075
|
-
|
|
6080
|
+
const serverComponentPaths = [];
|
|
6081
|
+
if (fs.existsSync(srcDir$1)) {
|
|
6082
|
+
const collectServerComponents = (dir) => {
|
|
6083
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
6084
|
+
for (const entry of entries) {
|
|
6085
|
+
const fullPath = path.join(dir, entry.name);
|
|
6086
|
+
if (entry.isDirectory()) collectServerComponents(fullPath);
|
|
6087
|
+
else if (entry.isFile() && /\.(?:tsx?|jsx?)$/.test(entry.name)) try {
|
|
6088
|
+
if (isServerComponent(fullPath)) serverComponentPaths.push(fullPath);
|
|
6089
|
+
} catch (error) {
|
|
6090
|
+
console.warn(`[RARI] Error checking ${fullPath}:`, error);
|
|
6091
|
+
}
|
|
6092
|
+
}
|
|
6093
|
+
};
|
|
6094
|
+
collectServerComponents(srcDir$1);
|
|
6095
|
+
scanDirectory(srcDir$1, builder);
|
|
6096
|
+
}
|
|
6097
|
+
if (serverComponentPaths.length > 0) server.ws.send({
|
|
6098
|
+
type: "custom",
|
|
6099
|
+
event: "rari:server-components-registry",
|
|
6100
|
+
data: { serverComponents: serverComponentPaths }
|
|
6101
|
+
});
|
|
6076
6102
|
const components = await builder.getTransformedComponentsForDevelopment();
|
|
6077
6103
|
const serverPort = process$1.env.SERVER_PORT ? Number(process$1.env.SERVER_PORT) : Number(process$1.env.PORT || process$1.env.RSC_PORT || 3e3);
|
|
6078
6104
|
const baseUrl = `http://localhost:${serverPort}`;
|
|
@@ -6200,7 +6226,7 @@ const ${componentName$1} = registerClientReference(
|
|
|
6200
6226
|
};
|
|
6201
6227
|
const handleServerComponentHMR = async (filePath) => {
|
|
6202
6228
|
try {
|
|
6203
|
-
const { ServerComponentBuilder } = await import("./server-build-
|
|
6229
|
+
const { ServerComponentBuilder } = await import("./server-build-Cs2pfA52.js");
|
|
6204
6230
|
const builder = new ServerComponentBuilder(projectRoot, {
|
|
6205
6231
|
outDir: "temp",
|
|
6206
6232
|
serverDir: "server",
|
|
@@ -6236,8 +6262,14 @@ const ${componentName$1} = registerClientReference(
|
|
|
6236
6262
|
startRustServer();
|
|
6237
6263
|
server.watcher.on("change", async (filePath) => {
|
|
6238
6264
|
if (/\.(?:tsx?|jsx?)$/.test(filePath)) componentTypeCache.delete(filePath);
|
|
6239
|
-
if (/\.(?:tsx?|jsx?)$/.test(filePath) && filePath.includes(srcDir)) if (isServerComponent(filePath))
|
|
6240
|
-
|
|
6265
|
+
if (/\.(?:tsx?|jsx?)$/.test(filePath) && filePath.includes(srcDir)) if (isServerComponent(filePath)) {
|
|
6266
|
+
server.ws.send({
|
|
6267
|
+
type: "custom",
|
|
6268
|
+
event: "rari:register-server-component",
|
|
6269
|
+
data: { filePath }
|
|
6270
|
+
});
|
|
6271
|
+
await handleServerComponentHMR(filePath);
|
|
6272
|
+
} else setTimeout(discoverAndRegisterComponents, 1e3);
|
|
6241
6273
|
});
|
|
6242
6274
|
server.middlewares.use("/api/vite/hmr-transform", async (req, res) => {
|
|
6243
6275
|
if (req.method !== "POST") {
|
|
@@ -6591,7 +6623,9 @@ class RscClient {
|
|
|
6591
6623
|
}
|
|
6592
6624
|
|
|
6593
6625
|
async fetchServerComponent(componentId, props = {}) {
|
|
6594
|
-
const
|
|
6626
|
+
const hmrCounter = (typeof window !== 'undefined' && window.__rscRefreshCounters && window.__rscRefreshCounters[componentId]) || 0;
|
|
6627
|
+
const cacheKey = componentId + ':' + JSON.stringify(props) + ':hmr:' + hmrCounter;
|
|
6628
|
+
|
|
6595
6629
|
|
|
6596
6630
|
if (this.componentCache.has(cacheKey)) {
|
|
6597
6631
|
return this.componentCache.get(cacheKey);
|
|
@@ -6837,14 +6871,15 @@ class RscClient {
|
|
|
6837
6871
|
buffered = lines[lines.length - 1];
|
|
6838
6872
|
|
|
6839
6873
|
for (const line of completeLines) {
|
|
6840
|
-
|
|
6874
|
+
if (!line.trim()) continue;
|
|
6875
|
+
|
|
6876
|
+
try {
|
|
6877
|
+
const colonIndex = line.indexOf(':');
|
|
6878
|
+
if (colonIndex === -1) continue;
|
|
6841
6879
|
|
|
6842
|
-
|
|
6843
|
-
|
|
6844
|
-
if (colonIndex === -1) continue;
|
|
6880
|
+
const rowId = line.substring(0, colonIndex);
|
|
6881
|
+
const content = line.substring(colonIndex + 1);
|
|
6845
6882
|
|
|
6846
|
-
const rowId = line.substring(0, colonIndex);
|
|
6847
|
-
const content = line.substring(colonIndex + 1);
|
|
6848
6883
|
|
|
6849
6884
|
if (content.includes('STREAM_COMPLETE')) {
|
|
6850
6885
|
isComplete = true;
|
|
@@ -7379,6 +7414,9 @@ function createServerComponentWrapper(componentName, importPath) {
|
|
|
7379
7414
|
const handleRscInvalidate = (event) => {
|
|
7380
7415
|
const detail = event.detail;
|
|
7381
7416
|
if (detail && detail.filePath && isServerComponent(detail.filePath)) {
|
|
7417
|
+
|
|
7418
|
+
rscClient.clearCache();
|
|
7419
|
+
|
|
7382
7420
|
if (typeof window !== 'undefined') {
|
|
7383
7421
|
window.__rscRefreshCounters[componentName] = (window.__rscRefreshCounters[componentName] || 0) + 1;
|
|
7384
7422
|
setMountKey(window.__rscRefreshCounters[componentName]);
|
|
@@ -7414,17 +7452,48 @@ export const fetchServerComponent = (componentId, props) =>
|
|
|
7414
7452
|
|
|
7415
7453
|
// Helper function to check if a file is a server component (client-side)
|
|
7416
7454
|
function isServerComponent(filePath) {
|
|
7417
|
-
|
|
7418
|
-
|
|
7419
|
-
|
|
7420
|
-
|
|
7421
|
-
|
|
7422
|
-
|
|
7455
|
+
if (!filePath) {
|
|
7456
|
+
return false;
|
|
7457
|
+
}
|
|
7458
|
+
|
|
7459
|
+
try {
|
|
7460
|
+
if (typeof globalThis !== 'undefined' && globalThis.__rari_server_components) {
|
|
7461
|
+
return globalThis.__rari_server_components.has(filePath);
|
|
7462
|
+
}
|
|
7463
|
+
|
|
7464
|
+
const hasServerPattern = (
|
|
7465
|
+
filePath.includes('/functions/') ||
|
|
7466
|
+
filePath.includes('\\\\functions\\\\')
|
|
7467
|
+
);
|
|
7468
|
+
|
|
7469
|
+
return hasServerPattern;
|
|
7470
|
+
} catch (error) {
|
|
7471
|
+
console.warn('Error checking if file is server component:', error);
|
|
7472
|
+
return false;
|
|
7473
|
+
}
|
|
7423
7474
|
}
|
|
7424
7475
|
|
|
7425
|
-
// HMR support for RSC cache invalidation
|
|
7426
7476
|
if (import.meta.hot) {
|
|
7427
|
-
|
|
7477
|
+
import.meta.hot.on('rari:register-server-component', (data) => {
|
|
7478
|
+
if (data?.filePath) {
|
|
7479
|
+
if (typeof globalThis !== 'undefined') {
|
|
7480
|
+
globalThis.__rari_server_components = globalThis.__rari_server_components || new Set();
|
|
7481
|
+
globalThis.__rari_server_components.add(data.filePath);
|
|
7482
|
+
}
|
|
7483
|
+
}
|
|
7484
|
+
});
|
|
7485
|
+
|
|
7486
|
+
import.meta.hot.on('rari:server-components-registry', (data) => {
|
|
7487
|
+
if (data?.serverComponents && Array.isArray(data.serverComponents)) {
|
|
7488
|
+
if (typeof globalThis !== 'undefined') {
|
|
7489
|
+
globalThis.__rari_server_components = globalThis.__rari_server_components || new Set();
|
|
7490
|
+
data.serverComponents.forEach(path => {
|
|
7491
|
+
globalThis.__rari_server_components.add(path);
|
|
7492
|
+
});
|
|
7493
|
+
}
|
|
7494
|
+
}
|
|
7495
|
+
});
|
|
7496
|
+
|
|
7428
7497
|
import.meta.hot.on('vite:beforeFullReload', async (data) => {
|
|
7429
7498
|
if (data?.path && isServerComponent(data.path)) {
|
|
7430
7499
|
// Immediately invalidate cache and trigger re-registration before reload
|
|
@@ -7432,13 +7501,17 @@ if (import.meta.hot) {
|
|
|
7432
7501
|
}
|
|
7433
7502
|
});
|
|
7434
7503
|
|
|
7504
|
+
import.meta.hot.on('rari:server-component-updated', async (data) => {
|
|
7505
|
+
if (data?.path && isServerComponent(data.path)) {
|
|
7506
|
+
await invalidateRscCache({ filePath: data.path, forceReload: false });
|
|
7507
|
+
}
|
|
7508
|
+
});
|
|
7509
|
+
|
|
7435
7510
|
|
|
7436
7511
|
|
|
7437
|
-
// Helper function to invalidate RSC cache and trigger component re-registration
|
|
7438
7512
|
async function invalidateRscCache(data) {
|
|
7439
7513
|
const filePath = data?.filePath || data;
|
|
7440
7514
|
|
|
7441
|
-
// Wait for server to be ready
|
|
7442
7515
|
const waitForServerReady = async () => {
|
|
7443
7516
|
for (let i = 0; i < 20; i++) { // Try for up to 2 seconds
|
|
7444
7517
|
try {
|
|
@@ -7535,9 +7608,11 @@ ${registrations.join("\n")}
|
|
|
7535
7608
|
}
|
|
7536
7609
|
},
|
|
7537
7610
|
handleHotUpdate({ file, server }) {
|
|
7538
|
-
|
|
7539
|
-
|
|
7540
|
-
|
|
7611
|
+
const isReactFile = /\.(?:tsx?|jsx?)$/.test(file);
|
|
7612
|
+
const isServerComp = isServerComponent(file);
|
|
7613
|
+
if (isReactFile && isServerComp) {
|
|
7614
|
+
server.hot.send("rari:server-component-updated", {
|
|
7615
|
+
type: "rari-hmr",
|
|
7541
7616
|
path: file
|
|
7542
7617
|
});
|
|
7543
7618
|
return [];
|
|
@@ -32,7 +32,7 @@ var ServerComponentBuilder = class {
|
|
|
32
32
|
];
|
|
33
33
|
const trimmedCode = code.trim();
|
|
34
34
|
const hasServerDirective = serverDirectives.some((directive) => trimmedCode.startsWith(directive) || code.includes(directive));
|
|
35
|
-
const isInFunctionsDir = filePath.includes("/functions/") || filePath.includes("
|
|
35
|
+
const isInFunctionsDir = filePath.includes("/functions/") || filePath.includes("\\\\functions\\\\");
|
|
36
36
|
const hasServerFunctionSignature = (code.includes("export async function") || code.includes("export function")) && code.includes("'use server'");
|
|
37
37
|
const hasNodeImports = code.includes("from 'node:") || code.includes("from \"node:") || code.includes("from 'fs'") || code.includes("from \"fs\"") || code.includes("from 'path'") || code.includes("from \"path\"");
|
|
38
38
|
const hasAsyncDefaultExport = /export\s+default\s+async\s+function/.test(code);
|
package/dist/server.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HttpRuntimeClient, Link, Navigate, Outlet, RouteComponent, RouterProvider, Routes, buildSearchString, buildUrl, createHttpRuntimeClient, extractParamNames, findMatchingRoute, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, normalizePathname, parseSearchParams, parseUrl, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, withRouter } from "./runtime-client-BXoadxa8.js";
|
|
2
|
-
import { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, defineRariOptions, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes } from "./server-
|
|
3
|
-
import "./server-build-
|
|
2
|
+
import { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, defineRariOptions, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes } from "./server-C3POnIbO.js";
|
|
3
|
+
import "./server-build-DeJfuJb8.js";
|
|
4
4
|
|
|
5
5
|
export { FileRouteGenerator, HttpRuntimeClient, Link, Navigate, Outlet, RouteComponent as Route, RouterProvider, Routes, buildSearchString, buildUrl, convertFilePatternToRoutePattern, createHttpRuntimeClient, createRouteManifest, defineRariConfig, defineRariOptions, extractParamNames, findMatchingRoute, generateFileRoutes, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, loadRouteManifest, normalizePathname, parseSearchParams, parseUrl, rari, rariRouter, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, validateRoutes, watchFileRoutes, withRouter };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rari",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.23",
|
|
5
5
|
"description": "Runtime Accelerated Rendering Infrastructure (Rari)",
|
|
6
6
|
"author": "Ryan Skinner",
|
|
7
7
|
"license": "MIT",
|
|
@@ -77,11 +77,11 @@
|
|
|
77
77
|
"picocolors": "^1.1.1"
|
|
78
78
|
},
|
|
79
79
|
"optionalDependencies": {
|
|
80
|
-
"rari-darwin-arm64": "0.2.
|
|
81
|
-
"rari-darwin-x64": "0.2.
|
|
82
|
-
"rari-linux-arm64": "0.2.
|
|
83
|
-
"rari-linux-x64": "0.2.
|
|
84
|
-
"rari-win32-x64": "0.2.
|
|
80
|
+
"rari-darwin-arm64": "0.2.16",
|
|
81
|
+
"rari-darwin-x64": "0.2.16",
|
|
82
|
+
"rari-linux-arm64": "0.2.16",
|
|
83
|
+
"rari-linux-x64": "0.2.16",
|
|
84
|
+
"rari-win32-x64": "0.2.16"
|
|
85
85
|
},
|
|
86
86
|
"devDependencies": {
|
|
87
87
|
"@types/node": "^24.3.1",
|
package/src/vite/index.ts
CHANGED
|
@@ -162,7 +162,7 @@ export function rari(options: RariOptions = {}): Plugin[] {
|
|
|
162
162
|
)
|
|
163
163
|
|
|
164
164
|
const isInFunctionsDir
|
|
165
|
-
= filePath.includes('/functions/') || filePath.includes('
|
|
165
|
+
= filePath.includes('/functions/') || filePath.includes('\\\\functions\\\\')
|
|
166
166
|
const hasServerFunctionSignature
|
|
167
167
|
= (code.includes('export async function')
|
|
168
168
|
|| code.includes('export function'))
|
|
@@ -655,6 +655,11 @@ if (import.meta.hot) {
|
|
|
655
655
|
import.meta.hot.accept();
|
|
656
656
|
}
|
|
657
657
|
|
|
658
|
+
if (typeof globalThis !== 'undefined') {
|
|
659
|
+
globalThis.__rari_server_components = globalThis.__rari_server_components || new Set();
|
|
660
|
+
globalThis.__rari_server_components.add(${JSON.stringify(id)});
|
|
661
|
+
}
|
|
662
|
+
|
|
658
663
|
${clientTransformedCode}`
|
|
659
664
|
}
|
|
660
665
|
|
|
@@ -843,11 +848,41 @@ const ${componentName} = registerClientReference(
|
|
|
843
848
|
})
|
|
844
849
|
|
|
845
850
|
const srcDir = path.join(projectRoot, 'src')
|
|
851
|
+
const serverComponentPaths: string[] = []
|
|
846
852
|
|
|
847
853
|
if (fs.existsSync(srcDir)) {
|
|
854
|
+
const collectServerComponents = (dir: string) => {
|
|
855
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true })
|
|
856
|
+
for (const entry of entries) {
|
|
857
|
+
const fullPath = path.join(dir, entry.name)
|
|
858
|
+
if (entry.isDirectory()) {
|
|
859
|
+
collectServerComponents(fullPath)
|
|
860
|
+
}
|
|
861
|
+
else if (entry.isFile() && /\.(?:tsx?|jsx?)$/.test(entry.name)) {
|
|
862
|
+
try {
|
|
863
|
+
if (isServerComponent(fullPath)) {
|
|
864
|
+
serverComponentPaths.push(fullPath)
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
catch (error) {
|
|
868
|
+
console.warn(`[RARI] Error checking ${fullPath}:`, error)
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
collectServerComponents(srcDir)
|
|
848
875
|
scanDirectory(srcDir, builder)
|
|
849
876
|
}
|
|
850
877
|
|
|
878
|
+
if (serverComponentPaths.length > 0) {
|
|
879
|
+
server.ws.send({
|
|
880
|
+
type: 'custom',
|
|
881
|
+
event: 'rari:server-components-registry',
|
|
882
|
+
data: { serverComponents: serverComponentPaths },
|
|
883
|
+
})
|
|
884
|
+
}
|
|
885
|
+
|
|
851
886
|
const components
|
|
852
887
|
= await builder.getTransformedComponentsForDevelopment()
|
|
853
888
|
|
|
@@ -1128,6 +1163,11 @@ const ${componentName} = registerClientReference(
|
|
|
1128
1163
|
|
|
1129
1164
|
if (/\.(?:tsx?|jsx?)$/.test(filePath) && filePath.includes(srcDir)) {
|
|
1130
1165
|
if (isServerComponent(filePath)) {
|
|
1166
|
+
server.ws.send({
|
|
1167
|
+
type: 'custom',
|
|
1168
|
+
event: 'rari:register-server-component',
|
|
1169
|
+
data: { filePath },
|
|
1170
|
+
})
|
|
1131
1171
|
await handleServerComponentHMR(filePath)
|
|
1132
1172
|
}
|
|
1133
1173
|
else {
|
|
@@ -1517,7 +1557,9 @@ class RscClient {
|
|
|
1517
1557
|
}
|
|
1518
1558
|
|
|
1519
1559
|
async fetchServerComponent(componentId, props = {}) {
|
|
1520
|
-
const
|
|
1560
|
+
const hmrCounter = (typeof window !== 'undefined' && window.__rscRefreshCounters && window.__rscRefreshCounters[componentId]) || 0;
|
|
1561
|
+
const cacheKey = componentId + ':' + JSON.stringify(props) + ':hmr:' + hmrCounter;
|
|
1562
|
+
|
|
1521
1563
|
|
|
1522
1564
|
if (this.componentCache.has(cacheKey)) {
|
|
1523
1565
|
return this.componentCache.get(cacheKey);
|
|
@@ -1763,14 +1805,15 @@ class RscClient {
|
|
|
1763
1805
|
buffered = lines[lines.length - 1];
|
|
1764
1806
|
|
|
1765
1807
|
for (const line of completeLines) {
|
|
1766
|
-
|
|
1808
|
+
if (!line.trim()) continue;
|
|
1767
1809
|
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1810
|
+
try {
|
|
1811
|
+
const colonIndex = line.indexOf(':');
|
|
1812
|
+
if (colonIndex === -1) continue;
|
|
1813
|
+
|
|
1814
|
+
const rowId = line.substring(0, colonIndex);
|
|
1815
|
+
const content = line.substring(colonIndex + 1);
|
|
1771
1816
|
|
|
1772
|
-
const rowId = line.substring(0, colonIndex);
|
|
1773
|
-
const content = line.substring(colonIndex + 1);
|
|
1774
1817
|
|
|
1775
1818
|
if (content.includes('STREAM_COMPLETE')) {
|
|
1776
1819
|
isComplete = true;
|
|
@@ -2305,6 +2348,9 @@ function createServerComponentWrapper(componentName, importPath) {
|
|
|
2305
2348
|
const handleRscInvalidate = (event) => {
|
|
2306
2349
|
const detail = event.detail;
|
|
2307
2350
|
if (detail && detail.filePath && isServerComponent(detail.filePath)) {
|
|
2351
|
+
|
|
2352
|
+
rscClient.clearCache();
|
|
2353
|
+
|
|
2308
2354
|
if (typeof window !== 'undefined') {
|
|
2309
2355
|
window.__rscRefreshCounters[componentName] = (window.__rscRefreshCounters[componentName] || 0) + 1;
|
|
2310
2356
|
setMountKey(window.__rscRefreshCounters[componentName]);
|
|
@@ -2340,17 +2386,48 @@ export const fetchServerComponent = (componentId, props) =>
|
|
|
2340
2386
|
|
|
2341
2387
|
// Helper function to check if a file is a server component (client-side)
|
|
2342
2388
|
function isServerComponent(filePath) {
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2389
|
+
if (!filePath) {
|
|
2390
|
+
return false;
|
|
2391
|
+
}
|
|
2392
|
+
|
|
2393
|
+
try {
|
|
2394
|
+
if (typeof globalThis !== 'undefined' && globalThis.__rari_server_components) {
|
|
2395
|
+
return globalThis.__rari_server_components.has(filePath);
|
|
2396
|
+
}
|
|
2397
|
+
|
|
2398
|
+
const hasServerPattern = (
|
|
2399
|
+
filePath.includes('/functions/') ||
|
|
2400
|
+
filePath.includes('\\\\functions\\\\')
|
|
2401
|
+
);
|
|
2402
|
+
|
|
2403
|
+
return hasServerPattern;
|
|
2404
|
+
} catch (error) {
|
|
2405
|
+
console.warn('Error checking if file is server component:', error);
|
|
2406
|
+
return false;
|
|
2407
|
+
}
|
|
2349
2408
|
}
|
|
2350
2409
|
|
|
2351
|
-
// HMR support for RSC cache invalidation
|
|
2352
2410
|
if (import.meta.hot) {
|
|
2353
|
-
|
|
2411
|
+
import.meta.hot.on('rari:register-server-component', (data) => {
|
|
2412
|
+
if (data?.filePath) {
|
|
2413
|
+
if (typeof globalThis !== 'undefined') {
|
|
2414
|
+
globalThis.__rari_server_components = globalThis.__rari_server_components || new Set();
|
|
2415
|
+
globalThis.__rari_server_components.add(data.filePath);
|
|
2416
|
+
}
|
|
2417
|
+
}
|
|
2418
|
+
});
|
|
2419
|
+
|
|
2420
|
+
import.meta.hot.on('rari:server-components-registry', (data) => {
|
|
2421
|
+
if (data?.serverComponents && Array.isArray(data.serverComponents)) {
|
|
2422
|
+
if (typeof globalThis !== 'undefined') {
|
|
2423
|
+
globalThis.__rari_server_components = globalThis.__rari_server_components || new Set();
|
|
2424
|
+
data.serverComponents.forEach(path => {
|
|
2425
|
+
globalThis.__rari_server_components.add(path);
|
|
2426
|
+
});
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2429
|
+
});
|
|
2430
|
+
|
|
2354
2431
|
import.meta.hot.on('vite:beforeFullReload', async (data) => {
|
|
2355
2432
|
if (data?.path && isServerComponent(data.path)) {
|
|
2356
2433
|
// Immediately invalidate cache and trigger re-registration before reload
|
|
@@ -2358,13 +2435,17 @@ if (import.meta.hot) {
|
|
|
2358
2435
|
}
|
|
2359
2436
|
});
|
|
2360
2437
|
|
|
2438
|
+
import.meta.hot.on('rari:server-component-updated', async (data) => {
|
|
2439
|
+
if (data?.path && isServerComponent(data.path)) {
|
|
2440
|
+
await invalidateRscCache({ filePath: data.path, forceReload: false });
|
|
2441
|
+
}
|
|
2442
|
+
});
|
|
2443
|
+
|
|
2361
2444
|
|
|
2362
2445
|
|
|
2363
|
-
// Helper function to invalidate RSC cache and trigger component re-registration
|
|
2364
2446
|
async function invalidateRscCache(data) {
|
|
2365
2447
|
const filePath = data?.filePath || data;
|
|
2366
2448
|
|
|
2367
|
-
// Wait for server to be ready
|
|
2368
2449
|
const waitForServerReady = async () => {
|
|
2369
2450
|
for (let i = 0; i < 20; i++) { // Try for up to 2 seconds
|
|
2370
2451
|
try {
|
|
@@ -2473,9 +2554,12 @@ ${registrations.join('\n')}
|
|
|
2473
2554
|
},
|
|
2474
2555
|
|
|
2475
2556
|
handleHotUpdate({ file, server }) {
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2557
|
+
const isReactFile = /\.(?:tsx?|jsx?)$/.test(file)
|
|
2558
|
+
const isServerComp = isServerComponent(file)
|
|
2559
|
+
|
|
2560
|
+
if (isReactFile && isServerComp) {
|
|
2561
|
+
server.hot.send('rari:server-component-updated', {
|
|
2562
|
+
type: 'rari-hmr',
|
|
2479
2563
|
path: file,
|
|
2480
2564
|
})
|
|
2481
2565
|
return []
|
package/src/vite/server-build.ts
CHANGED
|
@@ -80,7 +80,7 @@ export class ServerComponentBuilder {
|
|
|
80
80
|
)
|
|
81
81
|
|
|
82
82
|
const isInFunctionsDir
|
|
83
|
-
= filePath.includes('/functions/') || filePath.includes('
|
|
83
|
+
= filePath.includes('/functions/') || filePath.includes('\\\\functions\\\\')
|
|
84
84
|
const hasServerFunctionSignature
|
|
85
85
|
= (code.includes('export async function')
|
|
86
86
|
|| code.includes('export function'))
|