rari 0.2.21 → 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-D-ZsD18Z.js → server-C3POnIbO.js} +114 -34
- 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 +146 -34
- 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";
|
|
@@ -5108,7 +5108,7 @@ var require_chokidar = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/ch
|
|
|
5108
5108
|
|
|
5109
5109
|
//#endregion
|
|
5110
5110
|
//#region src/router/file-routes.ts
|
|
5111
|
-
var import_chokidar$1 = /* @__PURE__ */ __toESM(require_chokidar());
|
|
5111
|
+
var import_chokidar$1 = /* @__PURE__ */ __toESM(require_chokidar(), 1);
|
|
5112
5112
|
var FileRouteGenerator = class {
|
|
5113
5113
|
pagesDir;
|
|
5114
5114
|
extensions;
|
|
@@ -5417,7 +5417,7 @@ function convertFilePatternToRoutePattern(pattern) {
|
|
|
5417
5417
|
|
|
5418
5418
|
//#endregion
|
|
5419
5419
|
//#region src/router/vite-plugin.ts
|
|
5420
|
-
var import_chokidar = /* @__PURE__ */ __toESM(require_chokidar());
|
|
5420
|
+
var import_chokidar = /* @__PURE__ */ __toESM(require_chokidar(), 1);
|
|
5421
5421
|
const DEFAULT_OPTIONS = {
|
|
5422
5422
|
pagesDir: "src/pages",
|
|
5423
5423
|
extensions: [
|
|
@@ -5636,11 +5636,16 @@ function scanForClientComponents(srcDir) {
|
|
|
5636
5636
|
return clientComponents;
|
|
5637
5637
|
}
|
|
5638
5638
|
function extractCacheConfigFromContent(content) {
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
|
|
5639
|
+
let ast;
|
|
5640
|
+
try {
|
|
5641
|
+
ast = acorn.parse(content, {
|
|
5642
|
+
ecmaVersion: 2022,
|
|
5643
|
+
sourceType: "module",
|
|
5644
|
+
allowImportExportEverywhere: true
|
|
5645
|
+
});
|
|
5646
|
+
} catch {
|
|
5647
|
+
return void 0;
|
|
5648
|
+
}
|
|
5644
5649
|
for (const node of ast.body) if (node.type === "ExportNamedDeclaration" && node.declaration && node.declaration.type === "VariableDeclaration") {
|
|
5645
5650
|
for (const declarator of node.declaration.declarations) if (declarator.id && declarator.id.name === "cacheConfig" && declarator.init && declarator.init.type === "ObjectExpression") {
|
|
5646
5651
|
const config = {};
|
|
@@ -5688,7 +5693,7 @@ function rari(options = {}) {
|
|
|
5688
5693
|
const serverDirectives = ["'use server'", "\"use server\""];
|
|
5689
5694
|
const trimmedCode = code.trim();
|
|
5690
5695
|
const hasServerDirective = serverDirectives.some((directive) => trimmedCode.startsWith(directive) || code.includes(directive));
|
|
5691
|
-
const isInFunctionsDir = filePath.includes("/functions/") || filePath.includes("
|
|
5696
|
+
const isInFunctionsDir = filePath.includes("/functions/") || filePath.includes("\\\\functions\\\\");
|
|
5692
5697
|
const hasServerFunctionSignature = (code.includes("export async function") || code.includes("export function")) && code.includes("'use server'");
|
|
5693
5698
|
if (hasServerDirective || isInFunctionsDir && hasServerFunctionSignature) return true;
|
|
5694
5699
|
return false;
|
|
@@ -5975,6 +5980,11 @@ if (import.meta.hot) {
|
|
|
5975
5980
|
import.meta.hot.accept();
|
|
5976
5981
|
}
|
|
5977
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
|
+
|
|
5978
5988
|
${clientTransformedCode}`;
|
|
5979
5989
|
return clientTransformedCode;
|
|
5980
5990
|
}
|
|
@@ -6060,14 +6070,35 @@ const ${componentName$1} = registerClientReference(
|
|
|
6060
6070
|
const srcDir = path.join(projectRoot, "src");
|
|
6061
6071
|
const discoverAndRegisterComponents = async () => {
|
|
6062
6072
|
try {
|
|
6063
|
-
const { ServerComponentBuilder, scanDirectory } = await import("./server-build-
|
|
6073
|
+
const { ServerComponentBuilder, scanDirectory } = await import("./server-build-Cs2pfA52.js");
|
|
6064
6074
|
const builder = new ServerComponentBuilder(projectRoot, {
|
|
6065
6075
|
outDir: "temp",
|
|
6066
6076
|
serverDir: "server",
|
|
6067
6077
|
manifestPath: "server-manifest.json"
|
|
6068
6078
|
});
|
|
6069
6079
|
const srcDir$1 = path.join(projectRoot, "src");
|
|
6070
|
-
|
|
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
|
+
});
|
|
6071
6102
|
const components = await builder.getTransformedComponentsForDevelopment();
|
|
6072
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);
|
|
6073
6104
|
const baseUrl = `http://localhost:${serverPort}`;
|
|
@@ -6195,7 +6226,7 @@ const ${componentName$1} = registerClientReference(
|
|
|
6195
6226
|
};
|
|
6196
6227
|
const handleServerComponentHMR = async (filePath) => {
|
|
6197
6228
|
try {
|
|
6198
|
-
const { ServerComponentBuilder } = await import("./server-build-
|
|
6229
|
+
const { ServerComponentBuilder } = await import("./server-build-Cs2pfA52.js");
|
|
6199
6230
|
const builder = new ServerComponentBuilder(projectRoot, {
|
|
6200
6231
|
outDir: "temp",
|
|
6201
6232
|
serverDir: "server",
|
|
@@ -6231,8 +6262,14 @@ const ${componentName$1} = registerClientReference(
|
|
|
6231
6262
|
startRustServer();
|
|
6232
6263
|
server.watcher.on("change", async (filePath) => {
|
|
6233
6264
|
if (/\.(?:tsx?|jsx?)$/.test(filePath)) componentTypeCache.delete(filePath);
|
|
6234
|
-
if (/\.(?:tsx?|jsx?)$/.test(filePath) && filePath.includes(srcDir)) if (isServerComponent(filePath))
|
|
6235
|
-
|
|
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);
|
|
6236
6273
|
});
|
|
6237
6274
|
server.middlewares.use("/api/vite/hmr-transform", async (req, res) => {
|
|
6238
6275
|
if (req.method !== "POST") {
|
|
@@ -6586,7 +6623,9 @@ class RscClient {
|
|
|
6586
6623
|
}
|
|
6587
6624
|
|
|
6588
6625
|
async fetchServerComponent(componentId, props = {}) {
|
|
6589
|
-
const
|
|
6626
|
+
const hmrCounter = (typeof window !== 'undefined' && window.__rscRefreshCounters && window.__rscRefreshCounters[componentId]) || 0;
|
|
6627
|
+
const cacheKey = componentId + ':' + JSON.stringify(props) + ':hmr:' + hmrCounter;
|
|
6628
|
+
|
|
6590
6629
|
|
|
6591
6630
|
if (this.componentCache.has(cacheKey)) {
|
|
6592
6631
|
return this.componentCache.get(cacheKey);
|
|
@@ -6832,14 +6871,15 @@ class RscClient {
|
|
|
6832
6871
|
buffered = lines[lines.length - 1];
|
|
6833
6872
|
|
|
6834
6873
|
for (const line of completeLines) {
|
|
6835
|
-
|
|
6874
|
+
if (!line.trim()) continue;
|
|
6875
|
+
|
|
6876
|
+
try {
|
|
6877
|
+
const colonIndex = line.indexOf(':');
|
|
6878
|
+
if (colonIndex === -1) continue;
|
|
6836
6879
|
|
|
6837
|
-
|
|
6838
|
-
|
|
6839
|
-
if (colonIndex === -1) continue;
|
|
6880
|
+
const rowId = line.substring(0, colonIndex);
|
|
6881
|
+
const content = line.substring(colonIndex + 1);
|
|
6840
6882
|
|
|
6841
|
-
const rowId = line.substring(0, colonIndex);
|
|
6842
|
-
const content = line.substring(colonIndex + 1);
|
|
6843
6883
|
|
|
6844
6884
|
if (content.includes('STREAM_COMPLETE')) {
|
|
6845
6885
|
isComplete = true;
|
|
@@ -7374,6 +7414,9 @@ function createServerComponentWrapper(componentName, importPath) {
|
|
|
7374
7414
|
const handleRscInvalidate = (event) => {
|
|
7375
7415
|
const detail = event.detail;
|
|
7376
7416
|
if (detail && detail.filePath && isServerComponent(detail.filePath)) {
|
|
7417
|
+
|
|
7418
|
+
rscClient.clearCache();
|
|
7419
|
+
|
|
7377
7420
|
if (typeof window !== 'undefined') {
|
|
7378
7421
|
window.__rscRefreshCounters[componentName] = (window.__rscRefreshCounters[componentName] || 0) + 1;
|
|
7379
7422
|
setMountKey(window.__rscRefreshCounters[componentName]);
|
|
@@ -7409,17 +7452,48 @@ export const fetchServerComponent = (componentId, props) =>
|
|
|
7409
7452
|
|
|
7410
7453
|
// Helper function to check if a file is a server component (client-side)
|
|
7411
7454
|
function isServerComponent(filePath) {
|
|
7412
|
-
|
|
7413
|
-
|
|
7414
|
-
|
|
7415
|
-
|
|
7416
|
-
|
|
7417
|
-
|
|
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
|
+
}
|
|
7418
7474
|
}
|
|
7419
7475
|
|
|
7420
|
-
// HMR support for RSC cache invalidation
|
|
7421
7476
|
if (import.meta.hot) {
|
|
7422
|
-
|
|
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
|
+
|
|
7423
7497
|
import.meta.hot.on('vite:beforeFullReload', async (data) => {
|
|
7424
7498
|
if (data?.path && isServerComponent(data.path)) {
|
|
7425
7499
|
// Immediately invalidate cache and trigger re-registration before reload
|
|
@@ -7427,13 +7501,17 @@ if (import.meta.hot) {
|
|
|
7427
7501
|
}
|
|
7428
7502
|
});
|
|
7429
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
|
+
|
|
7430
7510
|
|
|
7431
7511
|
|
|
7432
|
-
// Helper function to invalidate RSC cache and trigger component re-registration
|
|
7433
7512
|
async function invalidateRscCache(data) {
|
|
7434
7513
|
const filePath = data?.filePath || data;
|
|
7435
7514
|
|
|
7436
|
-
// Wait for server to be ready
|
|
7437
7515
|
const waitForServerReady = async () => {
|
|
7438
7516
|
for (let i = 0; i < 20; i++) { // Try for up to 2 seconds
|
|
7439
7517
|
try {
|
|
@@ -7530,9 +7608,11 @@ ${registrations.join("\n")}
|
|
|
7530
7608
|
}
|
|
7531
7609
|
},
|
|
7532
7610
|
handleHotUpdate({ file, server }) {
|
|
7533
|
-
|
|
7534
|
-
|
|
7535
|
-
|
|
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",
|
|
7536
7616
|
path: file
|
|
7537
7617
|
});
|
|
7538
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
|
@@ -52,12 +52,20 @@ function scanForClientComponents(srcDir: string): Set<string> {
|
|
|
52
52
|
return clientComponents
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
function extractCacheConfigFromContent(
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
55
|
+
function extractCacheConfigFromContent(
|
|
56
|
+
content: string,
|
|
57
|
+
): PageCacheConfig | undefined {
|
|
58
|
+
let ast: any
|
|
59
|
+
try {
|
|
60
|
+
ast = acorn.parse(content, {
|
|
61
|
+
ecmaVersion: 2022,
|
|
62
|
+
sourceType: 'module',
|
|
63
|
+
allowImportExportEverywhere: true,
|
|
64
|
+
}) as any
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return undefined
|
|
68
|
+
}
|
|
61
69
|
|
|
62
70
|
for (const node of ast.body) {
|
|
63
71
|
if (
|
|
@@ -81,9 +89,11 @@ function extractCacheConfigFromContent(content: string): PageCacheConfig | undef
|
|
|
81
89
|
&& prop.value
|
|
82
90
|
&& prop.value.type === 'Literal'
|
|
83
91
|
) {
|
|
84
|
-
const keyName
|
|
92
|
+
const keyName
|
|
93
|
+
= prop.key.type === 'Literal' ? prop.key.value : prop.key.name
|
|
85
94
|
if (keyName === 'cache-control' || keyName === 'vary') {
|
|
86
|
-
config[keyName as keyof PageCacheConfig] = prop.value
|
|
95
|
+
config[keyName as keyof PageCacheConfig] = prop.value
|
|
96
|
+
.value as string
|
|
87
97
|
}
|
|
88
98
|
}
|
|
89
99
|
}
|
|
@@ -152,7 +162,7 @@ export function rari(options: RariOptions = {}): Plugin[] {
|
|
|
152
162
|
)
|
|
153
163
|
|
|
154
164
|
const isInFunctionsDir
|
|
155
|
-
= filePath.includes('/functions/') || filePath.includes('
|
|
165
|
+
= filePath.includes('/functions/') || filePath.includes('\\\\functions\\\\')
|
|
156
166
|
const hasServerFunctionSignature
|
|
157
167
|
= (code.includes('export async function')
|
|
158
168
|
|| code.includes('export function'))
|
|
@@ -645,6 +655,11 @@ if (import.meta.hot) {
|
|
|
645
655
|
import.meta.hot.accept();
|
|
646
656
|
}
|
|
647
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
|
+
|
|
648
663
|
${clientTransformedCode}`
|
|
649
664
|
}
|
|
650
665
|
|
|
@@ -833,11 +848,41 @@ const ${componentName} = registerClientReference(
|
|
|
833
848
|
})
|
|
834
849
|
|
|
835
850
|
const srcDir = path.join(projectRoot, 'src')
|
|
851
|
+
const serverComponentPaths: string[] = []
|
|
836
852
|
|
|
837
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)
|
|
838
875
|
scanDirectory(srcDir, builder)
|
|
839
876
|
}
|
|
840
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
|
+
|
|
841
886
|
const components
|
|
842
887
|
= await builder.getTransformedComponentsForDevelopment()
|
|
843
888
|
|
|
@@ -1118,6 +1163,11 @@ const ${componentName} = registerClientReference(
|
|
|
1118
1163
|
|
|
1119
1164
|
if (/\.(?:tsx?|jsx?)$/.test(filePath) && filePath.includes(srcDir)) {
|
|
1120
1165
|
if (isServerComponent(filePath)) {
|
|
1166
|
+
server.ws.send({
|
|
1167
|
+
type: 'custom',
|
|
1168
|
+
event: 'rari:register-server-component',
|
|
1169
|
+
data: { filePath },
|
|
1170
|
+
})
|
|
1121
1171
|
await handleServerComponentHMR(filePath)
|
|
1122
1172
|
}
|
|
1123
1173
|
else {
|
|
@@ -1507,7 +1557,9 @@ class RscClient {
|
|
|
1507
1557
|
}
|
|
1508
1558
|
|
|
1509
1559
|
async fetchServerComponent(componentId, props = {}) {
|
|
1510
|
-
const
|
|
1560
|
+
const hmrCounter = (typeof window !== 'undefined' && window.__rscRefreshCounters && window.__rscRefreshCounters[componentId]) || 0;
|
|
1561
|
+
const cacheKey = componentId + ':' + JSON.stringify(props) + ':hmr:' + hmrCounter;
|
|
1562
|
+
|
|
1511
1563
|
|
|
1512
1564
|
if (this.componentCache.has(cacheKey)) {
|
|
1513
1565
|
return this.componentCache.get(cacheKey);
|
|
@@ -1753,14 +1805,15 @@ class RscClient {
|
|
|
1753
1805
|
buffered = lines[lines.length - 1];
|
|
1754
1806
|
|
|
1755
1807
|
for (const line of completeLines) {
|
|
1756
|
-
|
|
1808
|
+
if (!line.trim()) continue;
|
|
1757
1809
|
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
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);
|
|
1761
1816
|
|
|
1762
|
-
const rowId = line.substring(0, colonIndex);
|
|
1763
|
-
const content = line.substring(colonIndex + 1);
|
|
1764
1817
|
|
|
1765
1818
|
if (content.includes('STREAM_COMPLETE')) {
|
|
1766
1819
|
isComplete = true;
|
|
@@ -2295,6 +2348,9 @@ function createServerComponentWrapper(componentName, importPath) {
|
|
|
2295
2348
|
const handleRscInvalidate = (event) => {
|
|
2296
2349
|
const detail = event.detail;
|
|
2297
2350
|
if (detail && detail.filePath && isServerComponent(detail.filePath)) {
|
|
2351
|
+
|
|
2352
|
+
rscClient.clearCache();
|
|
2353
|
+
|
|
2298
2354
|
if (typeof window !== 'undefined') {
|
|
2299
2355
|
window.__rscRefreshCounters[componentName] = (window.__rscRefreshCounters[componentName] || 0) + 1;
|
|
2300
2356
|
setMountKey(window.__rscRefreshCounters[componentName]);
|
|
@@ -2330,17 +2386,48 @@ export const fetchServerComponent = (componentId, props) =>
|
|
|
2330
2386
|
|
|
2331
2387
|
// Helper function to check if a file is a server component (client-side)
|
|
2332
2388
|
function isServerComponent(filePath) {
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
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
|
+
}
|
|
2339
2408
|
}
|
|
2340
2409
|
|
|
2341
|
-
// HMR support for RSC cache invalidation
|
|
2342
2410
|
if (import.meta.hot) {
|
|
2343
|
-
|
|
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
|
+
|
|
2344
2431
|
import.meta.hot.on('vite:beforeFullReload', async (data) => {
|
|
2345
2432
|
if (data?.path && isServerComponent(data.path)) {
|
|
2346
2433
|
// Immediately invalidate cache and trigger re-registration before reload
|
|
@@ -2348,13 +2435,17 @@ if (import.meta.hot) {
|
|
|
2348
2435
|
}
|
|
2349
2436
|
});
|
|
2350
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
|
+
|
|
2351
2444
|
|
|
2352
2445
|
|
|
2353
|
-
// Helper function to invalidate RSC cache and trigger component re-registration
|
|
2354
2446
|
async function invalidateRscCache(data) {
|
|
2355
2447
|
const filePath = data?.filePath || data;
|
|
2356
2448
|
|
|
2357
|
-
// Wait for server to be ready
|
|
2358
2449
|
const waitForServerReady = async () => {
|
|
2359
2450
|
for (let i = 0; i < 20; i++) { // Try for up to 2 seconds
|
|
2360
2451
|
try {
|
|
@@ -2463,9 +2554,12 @@ ${registrations.join('\n')}
|
|
|
2463
2554
|
},
|
|
2464
2555
|
|
|
2465
2556
|
handleHotUpdate({ file, server }) {
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
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',
|
|
2469
2563
|
path: file,
|
|
2470
2564
|
})
|
|
2471
2565
|
return []
|
|
@@ -2489,9 +2583,16 @@ ${registrations.join('\n')}
|
|
|
2489
2583
|
const url = req.url || ''
|
|
2490
2584
|
const pathname = url.split('?')[0]
|
|
2491
2585
|
|
|
2492
|
-
if (
|
|
2586
|
+
if (
|
|
2587
|
+
pathname
|
|
2588
|
+
&& !pathname.includes('.')
|
|
2589
|
+
&& !pathname.startsWith('/api')
|
|
2590
|
+
&& !pathname.startsWith('/rsc')
|
|
2591
|
+
) {
|
|
2493
2592
|
if (options.caching?.routes) {
|
|
2494
|
-
for (const [pattern, cacheControl] of Object.entries(
|
|
2593
|
+
for (const [pattern, cacheControl] of Object.entries(
|
|
2594
|
+
options.caching.routes,
|
|
2595
|
+
)) {
|
|
2495
2596
|
if (matchesPattern(pattern, pathname)) {
|
|
2496
2597
|
res.setHeader('cache-control', cacheControl)
|
|
2497
2598
|
break
|
|
@@ -2500,7 +2601,11 @@ ${registrations.join('\n')}
|
|
|
2500
2601
|
}
|
|
2501
2602
|
|
|
2502
2603
|
const pagePath = pathname === '/' ? '/index' : pathname
|
|
2503
|
-
const pageFilePath = path.join(
|
|
2604
|
+
const pageFilePath = path.join(
|
|
2605
|
+
process.cwd(),
|
|
2606
|
+
'src/pages',
|
|
2607
|
+
`${pagePath.slice(1) || 'index'}.tsx`,
|
|
2608
|
+
)
|
|
2504
2609
|
|
|
2505
2610
|
if (fs.existsSync(pageFilePath)) {
|
|
2506
2611
|
const pageContent = fs.readFileSync(pageFilePath, 'utf-8')
|
|
@@ -2521,8 +2626,15 @@ ${registrations.join('\n')}
|
|
|
2521
2626
|
},
|
|
2522
2627
|
writeBundle() {
|
|
2523
2628
|
if (options.caching) {
|
|
2524
|
-
const cacheConfigPath = path.join(
|
|
2525
|
-
|
|
2629
|
+
const cacheConfigPath = path.join(
|
|
2630
|
+
process.cwd(),
|
|
2631
|
+
'dist',
|
|
2632
|
+
'cache-config.json',
|
|
2633
|
+
)
|
|
2634
|
+
fs.writeFileSync(
|
|
2635
|
+
cacheConfigPath,
|
|
2636
|
+
JSON.stringify(options.caching, null, 2),
|
|
2637
|
+
)
|
|
2526
2638
|
}
|
|
2527
2639
|
},
|
|
2528
2640
|
}
|
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'))
|