rari 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/dist/{server-BvGV8m79.js → server-CpI87WFQ.js} +485 -49
- package/dist/server.js +1 -1
- package/package.json +12 -12
- package/src/vite/index.ts +560 -82
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HttpRuntimeClient, Link, Navigate, Outlet, RouteComponent, Routes, buildSearchString, buildUrl, createHttpRuntimeClient, extractParamNames, findMatchingRoute, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, normalizePathname, parseSearchParams, parseUrl, router_default, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, withRouter } from "./runtime-client-CC4YQweh.js";
|
|
2
|
-
import { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes } from "./server-
|
|
2
|
+
import { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes } from "./server-CpI87WFQ.js";
|
|
3
3
|
import "./server-build-DaBgiV55.js";
|
|
4
4
|
|
|
5
5
|
export { FileRouteGenerator, HttpRuntimeClient, Link, Navigate, Outlet, RouteComponent as Route, router_default as RouterProvider, Routes, buildSearchString, buildUrl, convertFilePatternToRoutePattern, createHttpRuntimeClient, createRouteManifest, defineRariConfig, extractParamNames, findMatchingRoute, generateFileRoutes, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, loadRouteManifest, normalizePathname, parseSearchParams, parseUrl, rari, rariRouter, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, validateRoutes, watchFileRoutes, withRouter };
|
|
@@ -5683,14 +5683,33 @@ function rari(options = {}) {
|
|
|
5683
5683
|
}
|
|
5684
5684
|
if (node.specifiers) for (const specifier of node.specifiers) exportedNames.push(specifier.exported.name);
|
|
5685
5685
|
break;
|
|
5686
|
+
case "ExportAllDeclaration":
|
|
5687
|
+
if (node.exported && node.exported.type === "Identifier") exportedNames.push(node.exported.name);
|
|
5688
|
+
break;
|
|
5686
5689
|
}
|
|
5687
5690
|
return exportedNames;
|
|
5688
5691
|
} catch {
|
|
5689
5692
|
return [];
|
|
5690
5693
|
}
|
|
5691
5694
|
}
|
|
5695
|
+
function hasTopLevelDirective(code, directive) {
|
|
5696
|
+
try {
|
|
5697
|
+
const ast = acorn.parse(code, {
|
|
5698
|
+
ecmaVersion: 2024,
|
|
5699
|
+
sourceType: "module",
|
|
5700
|
+
locations: false
|
|
5701
|
+
});
|
|
5702
|
+
for (const node of ast.body) {
|
|
5703
|
+
if (node.type !== "ExpressionStatement" || !node.directive) break;
|
|
5704
|
+
if (node.directive === directive) return true;
|
|
5705
|
+
}
|
|
5706
|
+
return false;
|
|
5707
|
+
} catch {
|
|
5708
|
+
return false;
|
|
5709
|
+
}
|
|
5710
|
+
}
|
|
5692
5711
|
function transformServerModule(code, id) {
|
|
5693
|
-
if (!code
|
|
5712
|
+
if (!hasTopLevelDirective(code, "use server")) return code;
|
|
5694
5713
|
const exportedNames = parseExportedNames(code);
|
|
5695
5714
|
if (exportedNames.length === 0) return code;
|
|
5696
5715
|
let newCode = code;
|
|
@@ -5732,7 +5751,7 @@ if (import.meta.hot) {
|
|
|
5732
5751
|
return newCode;
|
|
5733
5752
|
}
|
|
5734
5753
|
function transformClientModule(code, id) {
|
|
5735
|
-
if (code
|
|
5754
|
+
if (hasTopLevelDirective(code, "use server")) {
|
|
5736
5755
|
const exportedNames$1 = parseExportedNames(code);
|
|
5737
5756
|
if (exportedNames$1.length === 0) return "";
|
|
5738
5757
|
const relativePath = path.relative(process$1.cwd(), id);
|
|
@@ -5742,7 +5761,7 @@ if (import.meta.hot) {
|
|
|
5742
5761
|
else newCode$1 += `export const ${name} = createServerComponentWrapper("${componentId}_${name}", ${JSON.stringify(id)});\n`;
|
|
5743
5762
|
return newCode$1;
|
|
5744
5763
|
}
|
|
5745
|
-
if (!code
|
|
5764
|
+
if (!hasTopLevelDirective(code, "use client")) return code;
|
|
5746
5765
|
const exportedNames = parseExportedNames(code);
|
|
5747
5766
|
if (exportedNames.length === 0) return "";
|
|
5748
5767
|
let newCode = "import {registerClientReference} from \"react-server-dom-rari/server\";\n";
|
|
@@ -5763,7 +5782,7 @@ if (import.meta.hot) {
|
|
|
5763
5782
|
return newCode;
|
|
5764
5783
|
}
|
|
5765
5784
|
function transformClientModuleForClient(code, id) {
|
|
5766
|
-
if (!code
|
|
5785
|
+
if (!hasTopLevelDirective(code, "use client")) return code;
|
|
5767
5786
|
const exportedNames = parseExportedNames(code);
|
|
5768
5787
|
if (exportedNames.length === 0) return code;
|
|
5769
5788
|
let newCode = code.replace(/^['"]use client['"];?\s*$/gm, "");
|
|
@@ -5809,6 +5828,38 @@ if (import.meta.hot) {
|
|
|
5809
5828
|
const mainPlugin = {
|
|
5810
5829
|
name: "rari",
|
|
5811
5830
|
config(config, { command }) {
|
|
5831
|
+
config.resolve = config.resolve || {};
|
|
5832
|
+
const existingDedupe = Array.isArray(config.resolve.dedupe) ? config.resolve.dedupe : [];
|
|
5833
|
+
const toAdd = ["react", "react-dom"];
|
|
5834
|
+
config.resolve.dedupe = Array.from(new Set([...existingDedupe || [], ...toAdd]));
|
|
5835
|
+
const existingAlias = Array.isArray(config.resolve.alias) ? config.resolve.alias : [];
|
|
5836
|
+
const aliasFinds = new Set(existingAlias.map((a) => String(a.find)));
|
|
5837
|
+
try {
|
|
5838
|
+
const reactPath = __require.resolve("react");
|
|
5839
|
+
const reactDomClientPath = __require.resolve("react-dom/client");
|
|
5840
|
+
const reactJsxRuntimePath = __require.resolve("react/jsx-runtime");
|
|
5841
|
+
const aliasesToAppend = [];
|
|
5842
|
+
if (!aliasFinds.has("react/jsx-runtime")) aliasesToAppend.push({
|
|
5843
|
+
find: "react/jsx-runtime",
|
|
5844
|
+
replacement: reactJsxRuntimePath
|
|
5845
|
+
});
|
|
5846
|
+
try {
|
|
5847
|
+
const reactJsxDevRuntimePath = __require.resolve("react/jsx-dev-runtime");
|
|
5848
|
+
if (!aliasFinds.has("react/jsx-dev-runtime")) aliasesToAppend.push({
|
|
5849
|
+
find: "react/jsx-dev-runtime",
|
|
5850
|
+
replacement: reactJsxDevRuntimePath
|
|
5851
|
+
});
|
|
5852
|
+
} catch {}
|
|
5853
|
+
if (!aliasFinds.has("react")) aliasesToAppend.push({
|
|
5854
|
+
find: "react",
|
|
5855
|
+
replacement: reactPath
|
|
5856
|
+
});
|
|
5857
|
+
if (!aliasFinds.has("react-dom/client")) aliasesToAppend.push({
|
|
5858
|
+
find: "react-dom/client",
|
|
5859
|
+
replacement: reactDomClientPath
|
|
5860
|
+
});
|
|
5861
|
+
if (aliasesToAppend.length > 0) config.resolve.alias = [...existingAlias, ...aliasesToAppend];
|
|
5862
|
+
} catch {}
|
|
5812
5863
|
config.environments = config.environments || {};
|
|
5813
5864
|
config.environments.rsc = {
|
|
5814
5865
|
resolve: { conditions: [
|
|
@@ -5875,19 +5926,19 @@ if (import.meta.hot) {
|
|
|
5875
5926
|
transform(code, id) {
|
|
5876
5927
|
if (!/\.(?:tsx?|jsx?)$/.test(id)) return null;
|
|
5877
5928
|
const environment = this.environment;
|
|
5878
|
-
if (code
|
|
5929
|
+
if (hasTopLevelDirective(code, "use client")) {
|
|
5879
5930
|
componentTypeCache.set(id, "client");
|
|
5880
5931
|
clientComponents.add(id);
|
|
5881
5932
|
if (environment && (environment.name === "rsc" || environment.name === "ssr")) return transformClientModule(code, id);
|
|
5882
5933
|
else return transformClientModuleForClient(code, id);
|
|
5883
5934
|
}
|
|
5884
|
-
if (code
|
|
5935
|
+
if (hasTopLevelDirective(code, "use server")) {
|
|
5885
5936
|
componentTypeCache.set(id, "server");
|
|
5886
5937
|
serverComponents.add(id);
|
|
5887
5938
|
if (environment && (environment.name === "rsc" || environment.name === "ssr")) return transformServerModule(code, id);
|
|
5888
5939
|
else {
|
|
5889
5940
|
let clientTransformedCode = transformClientModule(code, id);
|
|
5890
|
-
if (code
|
|
5941
|
+
if (hasTopLevelDirective(code, "use server")) clientTransformedCode = `// HMR acceptance for server component
|
|
5891
5942
|
if (import.meta.hot) {
|
|
5892
5943
|
import.meta.hot.accept();
|
|
5893
5944
|
}
|
|
@@ -6455,11 +6506,24 @@ async function loadRscClient() {
|
|
|
6455
6506
|
|
|
6456
6507
|
rscClientLoadPromise = (async () => {
|
|
6457
6508
|
try {
|
|
6458
|
-
const rscModule = await import('react-dom/
|
|
6509
|
+
const rscModule = await import('react-dom/client');
|
|
6459
6510
|
createFromFetch = rscModule.createFromFetch;
|
|
6460
6511
|
createFromReadableStream = rscModule.createFromReadableStream;
|
|
6512
|
+
|
|
6513
|
+
if (typeof createFromReadableStream !== 'function') {
|
|
6514
|
+
console.warn('createFromReadableStream is not available in react-dom/client');
|
|
6515
|
+
createFromReadableStream = null;
|
|
6516
|
+
}
|
|
6517
|
+
if (typeof createFromFetch !== 'function') {
|
|
6518
|
+
console.warn('createFromFetch is not available in react-dom/client');
|
|
6519
|
+
createFromFetch = null;
|
|
6520
|
+
}
|
|
6521
|
+
|
|
6461
6522
|
return rscModule;
|
|
6462
6523
|
} catch (error) {
|
|
6524
|
+
console.warn('Failed to load react-dom/client RSC functions:', error);
|
|
6525
|
+
createFromFetch = null;
|
|
6526
|
+
createFromReadableStream = null;
|
|
6463
6527
|
return null;
|
|
6464
6528
|
}
|
|
6465
6529
|
})()
|
|
@@ -6471,8 +6535,9 @@ class RscClient {
|
|
|
6471
6535
|
constructor() {
|
|
6472
6536
|
this.componentCache = new Map();
|
|
6473
6537
|
this.moduleCache = new Map();
|
|
6538
|
+
this.inflightRequests = new Map();
|
|
6474
6539
|
this.config = {
|
|
6475
|
-
enableStreaming:
|
|
6540
|
+
enableStreaming: true,
|
|
6476
6541
|
maxRetries: 5,
|
|
6477
6542
|
retryDelay: 500,
|
|
6478
6543
|
timeout: 10000,
|
|
@@ -6495,48 +6560,394 @@ class RscClient {
|
|
|
6495
6560
|
return this.componentCache.get(cacheKey);
|
|
6496
6561
|
}
|
|
6497
6562
|
|
|
6498
|
-
|
|
6499
|
-
|
|
6500
|
-
|
|
6501
|
-
const fetchUrl = '/rsc/render/' + componentId + '?props=' + encodedProps + '&_t=' + cacheBuster;
|
|
6563
|
+
if (this.inflightRequests.has(cacheKey)) {
|
|
6564
|
+
return this.inflightRequests.get(cacheKey);
|
|
6565
|
+
}
|
|
6502
6566
|
|
|
6567
|
+
let requestPromise;
|
|
6568
|
+
if (this.config.enableStreaming) {
|
|
6569
|
+
requestPromise = this.fetchServerComponentStreamV2(componentId, props);
|
|
6570
|
+
} else {
|
|
6571
|
+
requestPromise = (async () => {
|
|
6572
|
+
const encodedProps = encodeURIComponent(JSON.stringify(props));
|
|
6573
|
+
const cacheBuster = Date.now();
|
|
6574
|
+
const fetchUrl = '/rsc/render/' + componentId + '?props=' + encodedProps + '&_t=' + cacheBuster;
|
|
6575
|
+
await this.waitForServerReady();
|
|
6576
|
+
const response = await this.fetchWithTimeout(fetchUrl, {
|
|
6577
|
+
method: 'GET',
|
|
6578
|
+
headers: {
|
|
6579
|
+
...this.buildRequestHeaders(),
|
|
6580
|
+
'Cache-Control': 'no-cache, no-store, must-revalidate',
|
|
6581
|
+
'Pragma': 'no-cache',
|
|
6582
|
+
'Expires': '0'
|
|
6583
|
+
},
|
|
6584
|
+
});
|
|
6585
|
+
if (!response.ok) {
|
|
6586
|
+
throw new Error('Server responded with ' + response.status + ': ' + response.statusText);
|
|
6587
|
+
}
|
|
6588
|
+
try {
|
|
6589
|
+
return await this.processRscResponseManually(response);
|
|
6590
|
+
} catch (manualError) {
|
|
6591
|
+
const fallback = await this.processRscResponse(response);
|
|
6592
|
+
return fallback;
|
|
6593
|
+
}
|
|
6594
|
+
})();
|
|
6595
|
+
}
|
|
6596
|
+
|
|
6597
|
+
this.inflightRequests.set(cacheKey, requestPromise);
|
|
6503
6598
|
try {
|
|
6504
|
-
await
|
|
6505
|
-
|
|
6506
|
-
|
|
6507
|
-
|
|
6508
|
-
|
|
6509
|
-
|
|
6510
|
-
'Cache-Control': 'no-cache, no-store, must-revalidate',
|
|
6511
|
-
'Pragma': 'no-cache',
|
|
6512
|
-
'Expires': '0'
|
|
6513
|
-
},
|
|
6514
|
-
});
|
|
6599
|
+
const result = await requestPromise;
|
|
6600
|
+
this.componentCache.set(cacheKey, result);
|
|
6601
|
+
return result;
|
|
6602
|
+
} finally {
|
|
6603
|
+
this.inflightRequests.delete(cacheKey);
|
|
6604
|
+
}
|
|
6515
6605
|
|
|
6516
|
-
|
|
6517
|
-
throw new Error('Server responded with ' + response.status + ': ' + response.statusText);
|
|
6518
|
-
}
|
|
6606
|
+
}
|
|
6519
6607
|
|
|
6520
|
-
|
|
6608
|
+
async fetchServerComponentStreamV2(componentId, props = {}) {
|
|
6609
|
+
await loadRscClient();
|
|
6521
6610
|
|
|
6522
|
-
|
|
6523
|
-
|
|
6524
|
-
|
|
6611
|
+
const endpoints = (() => {
|
|
6612
|
+
const list = [
|
|
6613
|
+
'http://127.0.0.1:3000/api/rsc/stream',
|
|
6614
|
+
'http://localhost:3000/api/rsc/stream',
|
|
6615
|
+
'/api/rsc/stream',
|
|
6616
|
+
];
|
|
6617
|
+
return list;
|
|
6618
|
+
})();
|
|
6619
|
+
let response = null;
|
|
6620
|
+
let lastError = null;
|
|
6621
|
+
const attempt = async () => {
|
|
6622
|
+
for (const url of endpoints) {
|
|
6525
6623
|
try {
|
|
6526
|
-
|
|
6527
|
-
|
|
6528
|
-
|
|
6529
|
-
|
|
6624
|
+
const r = await this.fetchWithTimeout(url, {
|
|
6625
|
+
method: 'POST',
|
|
6626
|
+
headers: {
|
|
6627
|
+
'Content-Type': 'application/json',
|
|
6628
|
+
...this.buildRequestHeaders(),
|
|
6629
|
+
},
|
|
6630
|
+
body: JSON.stringify({ component_id: componentId, props }),
|
|
6631
|
+
});
|
|
6632
|
+
if (r.ok) {
|
|
6633
|
+
return r;
|
|
6634
|
+
}
|
|
6635
|
+
lastError = new Error('HTTP ' + r.status + ': ' + (await r.text()));
|
|
6636
|
+
} catch (e) {
|
|
6637
|
+
lastError = e;
|
|
6530
6638
|
}
|
|
6531
6639
|
}
|
|
6640
|
+
return null;
|
|
6641
|
+
};
|
|
6532
6642
|
|
|
6533
|
-
|
|
6534
|
-
|
|
6535
|
-
|
|
6536
|
-
|
|
6643
|
+
const abortController = new AbortController();
|
|
6644
|
+
const abortTimeout = setTimeout(() => abortController.abort(), this.config.timeout);
|
|
6645
|
+
|
|
6646
|
+
response = await attempt();
|
|
6647
|
+
if (!response) {
|
|
6648
|
+
await new Promise(r => setTimeout(r, 150));
|
|
6649
|
+
response = await attempt();
|
|
6650
|
+
}
|
|
6651
|
+
if (!response) {
|
|
6652
|
+
throw lastError || new Error('Failed to reach stream endpoint');
|
|
6653
|
+
}
|
|
6654
|
+
|
|
6655
|
+
if (!response.ok) {
|
|
6656
|
+
const errorText = await response.text();
|
|
6657
|
+
throw new Error('Server responded with ' + response.status + ': ' + errorText);
|
|
6537
6658
|
}
|
|
6659
|
+
|
|
6660
|
+
const stream = response.body;
|
|
6661
|
+
if (!stream) {
|
|
6662
|
+
throw new Error('No ReadableStream from stream response');
|
|
6663
|
+
}
|
|
6664
|
+
|
|
6665
|
+
if (false && createFromReadableStream) {
|
|
6666
|
+
try {
|
|
6667
|
+
const rscPromise = createFromReadableStream(stream);
|
|
6668
|
+
return {
|
|
6669
|
+
_isRscResponse: true,
|
|
6670
|
+
_rscPromise: rscPromise,
|
|
6671
|
+
readRoot() {
|
|
6672
|
+
return rscPromise;
|
|
6673
|
+
}
|
|
6674
|
+
};
|
|
6675
|
+
} catch (error) {
|
|
6676
|
+
console.warn('Failed to use createFromReadableStream:', error);
|
|
6677
|
+
}
|
|
6678
|
+
}
|
|
6679
|
+
|
|
6680
|
+
const reader = stream.getReader();
|
|
6681
|
+
const decoder = new TextDecoder();
|
|
6682
|
+
let content = '';
|
|
6683
|
+
const modules = new Map();
|
|
6684
|
+
const boundaryRowMap = new Map();
|
|
6685
|
+
|
|
6686
|
+
const convertRscToReact = (element) => {
|
|
6687
|
+
if (!React) {
|
|
6688
|
+
console.warn('React not available for RSC conversion');
|
|
6689
|
+
return null;
|
|
6690
|
+
}
|
|
6691
|
+
|
|
6692
|
+
if (!element) {
|
|
6693
|
+
return null;
|
|
6694
|
+
}
|
|
6695
|
+
|
|
6696
|
+
if (typeof element === 'string' || typeof element === 'number' || typeof element === 'boolean') {
|
|
6697
|
+
return element;
|
|
6698
|
+
}
|
|
6699
|
+
|
|
6700
|
+
if (Array.isArray(element)) {
|
|
6701
|
+
if (element.length >= 3 && element[0] === '$') {
|
|
6702
|
+
const [, type, key, props] = element;
|
|
6703
|
+
|
|
6704
|
+
if (type === 'react.suspense' || type === 'suspense') {
|
|
6705
|
+
|
|
6706
|
+
const suspenseWrapper = React.createElement('div',
|
|
6707
|
+
{
|
|
6708
|
+
'data-boundary-id': props?.boundaryId,
|
|
6709
|
+
boundaryId: props?.boundaryId,
|
|
6710
|
+
'data-suspense-boundary': true
|
|
6711
|
+
},
|
|
6712
|
+
convertRscToReact(props?.fallback || props?.children)
|
|
6713
|
+
);
|
|
6714
|
+
|
|
6715
|
+
return suspenseWrapper;
|
|
6716
|
+
}
|
|
6717
|
+
|
|
6718
|
+
let processedProps = props ? { ...props } : {};
|
|
6719
|
+
if (props?.children) {
|
|
6720
|
+
const child = convertRscToReact(props.children);
|
|
6721
|
+
if (Array.isArray(child)) {
|
|
6722
|
+
processedProps.children = child.map((c, i) => React.isValidElement(c) ? React.cloneElement(c, { key: (c.key ?? i) }) : c);
|
|
6723
|
+
} else {
|
|
6724
|
+
processedProps.children = child;
|
|
6725
|
+
}
|
|
6726
|
+
}
|
|
6727
|
+
|
|
6728
|
+
if (typeof type === 'string') {
|
|
6729
|
+
if (type.startsWith('$L')) {
|
|
6730
|
+
const mod = modules.get(type);
|
|
6731
|
+
if (mod) {
|
|
6732
|
+
const clientKey = mod.id + '#' + (mod.name || 'default');
|
|
6733
|
+
const clientComponent = getClientComponent(clientKey);
|
|
6734
|
+
if (clientComponent) {
|
|
6735
|
+
const reactElement = React.createElement(clientComponent, key ? { ...processedProps, key } : processedProps);
|
|
6736
|
+
return reactElement;
|
|
6737
|
+
}
|
|
6738
|
+
}
|
|
6739
|
+
return processedProps && processedProps.children ? processedProps.children : null;
|
|
6740
|
+
}
|
|
6741
|
+
if (type.includes('.tsx#') || type.includes('.jsx#')) {
|
|
6742
|
+
const clientComponent = getClientComponent(type);
|
|
6743
|
+
if (clientComponent) {
|
|
6744
|
+
const reactElement = React.createElement(clientComponent, key ? { ...processedProps, key } : processedProps);
|
|
6745
|
+
return reactElement;
|
|
6746
|
+
} else {
|
|
6747
|
+
console.warn('Failed to resolve client component:', type);
|
|
6748
|
+
return null;
|
|
6749
|
+
}
|
|
6750
|
+
} else {
|
|
6751
|
+
if (processedProps && Object.prototype.hasOwnProperty.call(processedProps, 'boundaryId')) {
|
|
6752
|
+
const { boundaryId, ...rest } = processedProps;
|
|
6753
|
+
processedProps = rest;
|
|
6754
|
+
}
|
|
6755
|
+
const reactElement = React.createElement(type, key ? { ...processedProps, key } : processedProps);
|
|
6756
|
+
return reactElement;
|
|
6757
|
+
}
|
|
6758
|
+
} else {
|
|
6759
|
+
console.warn('Unknown RSC element type:', type);
|
|
6760
|
+
}
|
|
6761
|
+
}
|
|
6762
|
+
|
|
6763
|
+
return element.map((child, index) => {
|
|
6764
|
+
const converted = convertRscToReact(child);
|
|
6765
|
+
return converted;
|
|
6766
|
+
});
|
|
6767
|
+
}
|
|
6768
|
+
|
|
6769
|
+
if (typeof element === 'object') {
|
|
6770
|
+
console.warn('Unexpected object in RSC conversion:', element);
|
|
6771
|
+
return null;
|
|
6772
|
+
}
|
|
6773
|
+
|
|
6774
|
+
return element;
|
|
6775
|
+
};
|
|
6776
|
+
|
|
6777
|
+
let initialContent = null;
|
|
6778
|
+
let boundaryUpdates = new Map();
|
|
6779
|
+
let isComplete = false;
|
|
6780
|
+
let buffered = '';
|
|
6781
|
+
|
|
6782
|
+
const processStream = async () => {
|
|
6783
|
+
const newlineChar = String.fromCharCode(10);
|
|
6784
|
+
|
|
6785
|
+
try {
|
|
6786
|
+
while (true) {
|
|
6787
|
+
const { value, done } = await reader.read();
|
|
6788
|
+
if (done) {
|
|
6789
|
+
isComplete = true;
|
|
6790
|
+
break;
|
|
6791
|
+
}
|
|
6792
|
+
|
|
6793
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
6794
|
+
buffered += chunk;
|
|
6795
|
+
|
|
6796
|
+
const lines = buffered.split(newlineChar);
|
|
6797
|
+
const completeLines = lines.slice(0, -1);
|
|
6798
|
+
buffered = lines[lines.length - 1];
|
|
6799
|
+
|
|
6800
|
+
for (const line of completeLines) {
|
|
6801
|
+
if (!line.trim()) continue;
|
|
6802
|
+
|
|
6803
|
+
try {
|
|
6804
|
+
const colonIndex = line.indexOf(':');
|
|
6805
|
+
if (colonIndex === -1) continue;
|
|
6806
|
+
|
|
6807
|
+
const rowId = line.substring(0, colonIndex);
|
|
6808
|
+
const content = line.substring(colonIndex + 1);
|
|
6809
|
+
|
|
6810
|
+
if (content.includes('STREAM_COMPLETE')) {
|
|
6811
|
+
isComplete = true;
|
|
6812
|
+
} else if (content.startsWith('I[')) {
|
|
6813
|
+
try {
|
|
6814
|
+
const importData = JSON.parse(content.substring(1));
|
|
6815
|
+
if (Array.isArray(importData) && importData.length >= 3) {
|
|
6816
|
+
const [path, chunks, exportName] = importData;
|
|
6817
|
+
modules.set('$L' + rowId, {
|
|
6818
|
+
id: path,
|
|
6819
|
+
chunks: Array.isArray(chunks) ? chunks : [chunks],
|
|
6820
|
+
name: exportName || 'default'
|
|
6821
|
+
});
|
|
6822
|
+
}
|
|
6823
|
+
} catch (e) {
|
|
6824
|
+
console.warn('Failed to parse import row:', content, e);
|
|
6825
|
+
}
|
|
6826
|
+
} else if (content.startsWith('E{')) {
|
|
6827
|
+
try {
|
|
6828
|
+
const err = JSON.parse(content.substring(1));
|
|
6829
|
+
console.error('RSC stream error:', err);
|
|
6830
|
+
} catch (e) {
|
|
6831
|
+
console.error('Failed to parse error row:', content, e);
|
|
6832
|
+
}
|
|
6833
|
+
} else if (content.startsWith('Symbol.for(')) {
|
|
6834
|
+
continue;
|
|
6835
|
+
} else if (content.startsWith('[')) {
|
|
6836
|
+
const parsed = JSON.parse(content);
|
|
6837
|
+
if (Array.isArray(parsed) && parsed.length >= 4) {
|
|
6838
|
+
const [marker, selector, key, props] = parsed;
|
|
6839
|
+
if (marker === '$' && (selector === 'react.suspense' || selector === 'suspense') && props && props.boundaryId) {
|
|
6840
|
+
boundaryRowMap.set('$L' + rowId, props.boundaryId);
|
|
6841
|
+
}
|
|
6842
|
+
if (marker === '$' && props && Object.prototype.hasOwnProperty.call(props, 'children')) {
|
|
6843
|
+
if (typeof selector === 'string' && selector.startsWith('$L')) {
|
|
6844
|
+
const target = boundaryRowMap.get(selector) || null;
|
|
6845
|
+
if (target) {
|
|
6846
|
+
const resolvedContent = convertRscToReact(props.children);
|
|
6847
|
+
boundaryUpdates.set(target, resolvedContent);
|
|
6848
|
+
if (streamingComponent) {
|
|
6849
|
+
streamingComponent.updateBoundary(target, resolvedContent);
|
|
6850
|
+
}
|
|
6851
|
+
continue;
|
|
6852
|
+
}
|
|
6853
|
+
}
|
|
6854
|
+
}
|
|
6855
|
+
}
|
|
6856
|
+
if (!initialContent) {
|
|
6857
|
+
let canUseAsRoot = true;
|
|
6858
|
+
if (Array.isArray(parsed) && parsed.length >= 4 && parsed[0] === '$') {
|
|
6859
|
+
const sel = parsed[1];
|
|
6860
|
+
const p = parsed[3];
|
|
6861
|
+
if (typeof sel === 'string' && (sel === 'react.suspense' || sel === 'suspense') && p && p.boundaryId) {
|
|
6862
|
+
canUseAsRoot = false;
|
|
6863
|
+
}
|
|
6864
|
+
}
|
|
6865
|
+
if (canUseAsRoot) {
|
|
6866
|
+
initialContent = convertRscToReact(parsed);
|
|
6867
|
+
if (streamingComponent && typeof streamingComponent.updateRoot === 'function') {
|
|
6868
|
+
streamingComponent.updateRoot();
|
|
6869
|
+
}
|
|
6870
|
+
}
|
|
6871
|
+
}
|
|
6872
|
+
}
|
|
6873
|
+
} catch (e) {
|
|
6874
|
+
console.warn('Failed to parse stream line:', line, e);
|
|
6875
|
+
}
|
|
6876
|
+
}
|
|
6877
|
+
}
|
|
6878
|
+
} catch (error) {
|
|
6879
|
+
console.error('Error processing stream:', error);
|
|
6880
|
+
isComplete = true;
|
|
6881
|
+
}
|
|
6882
|
+
};
|
|
6883
|
+
|
|
6884
|
+
let streamingComponent = null;
|
|
6885
|
+
|
|
6886
|
+
const StreamingWrapper = () => {
|
|
6887
|
+
const [renderTrigger, setRenderTrigger] = React.useState(0);
|
|
6888
|
+
|
|
6889
|
+
React.useEffect(() => {
|
|
6890
|
+
streamingComponent = {
|
|
6891
|
+
updateBoundary: (boundaryId, resolvedContent) => {
|
|
6892
|
+
boundaryUpdates.set(boundaryId, resolvedContent);
|
|
6893
|
+
setRenderTrigger(prev => prev + 1);
|
|
6894
|
+
},
|
|
6895
|
+
updateRoot: () => {
|
|
6896
|
+
setRenderTrigger(prev => prev + 1);
|
|
6897
|
+
}
|
|
6898
|
+
};
|
|
6899
|
+
|
|
6900
|
+
return () => {
|
|
6901
|
+
streamingComponent = null;
|
|
6902
|
+
};
|
|
6903
|
+
}, []);
|
|
6904
|
+
|
|
6905
|
+
const renderWithBoundaryUpdates = (element) => {
|
|
6906
|
+
if (!element) return null;
|
|
6907
|
+
|
|
6908
|
+
if (React.isValidElement(element)) {
|
|
6909
|
+
if (element.props && element.props.boundaryId) {
|
|
6910
|
+
const boundaryId = element.props.boundaryId;
|
|
6911
|
+
const resolvedContent = boundaryUpdates.get(boundaryId);
|
|
6912
|
+
if (resolvedContent) {
|
|
6913
|
+
return resolvedContent;
|
|
6914
|
+
}
|
|
6915
|
+
}
|
|
6916
|
+
|
|
6917
|
+
if (element.props && element.props.children) {
|
|
6918
|
+
const updatedChildren = renderWithBoundaryUpdates(element.props.children);
|
|
6919
|
+
if (updatedChildren !== element.props.children) {
|
|
6920
|
+
return React.cloneElement(element, { ...element.props, children: updatedChildren });
|
|
6921
|
+
}
|
|
6922
|
+
}
|
|
6923
|
+
|
|
6924
|
+
return element;
|
|
6925
|
+
}
|
|
6926
|
+
|
|
6927
|
+
if (Array.isArray(element)) {
|
|
6928
|
+
return element.map((child, index) => renderWithBoundaryUpdates(child));
|
|
6929
|
+
}
|
|
6930
|
+
|
|
6931
|
+
return element;
|
|
6932
|
+
};
|
|
6933
|
+
|
|
6934
|
+
const renderedContent = renderWithBoundaryUpdates(initialContent);
|
|
6935
|
+
return renderedContent;
|
|
6936
|
+
};
|
|
6937
|
+
|
|
6938
|
+
processStream();
|
|
6939
|
+
|
|
6940
|
+
return {
|
|
6941
|
+
_isRscResponse: true,
|
|
6942
|
+
_rscPromise: Promise.resolve(React.createElement(StreamingWrapper)),
|
|
6943
|
+
readRoot() {
|
|
6944
|
+
return Promise.resolve(React.createElement(StreamingWrapper));
|
|
6945
|
+
}
|
|
6946
|
+
};
|
|
6538
6947
|
}
|
|
6539
6948
|
|
|
6949
|
+
|
|
6950
|
+
|
|
6540
6951
|
buildRequestHeaders() {
|
|
6541
6952
|
const headers = {
|
|
6542
6953
|
'Accept': 'text/x-component',
|
|
@@ -6645,11 +7056,14 @@ class RscClient {
|
|
|
6645
7056
|
|
|
6646
7057
|
let rootElement = null;
|
|
6647
7058
|
|
|
6648
|
-
const elementKeys = Array.from(elements.keys()).sort((a, b) => parseInt(
|
|
6649
|
-
|
|
7059
|
+
const elementKeys = Array.from(elements.keys()).sort((a, b) => parseInt(a) - parseInt(b));
|
|
6650
7060
|
for (const key of elementKeys) {
|
|
6651
7061
|
const element = elements.get(key);
|
|
6652
|
-
if (Array.isArray(element) && element[0] === '$') {
|
|
7062
|
+
if (Array.isArray(element) && element.length >= 2 && element[0] === '$') {
|
|
7063
|
+
const [, type, , props] = element;
|
|
7064
|
+
if (type === 'react.suspense' && props && props.boundaryId) {
|
|
7065
|
+
continue;
|
|
7066
|
+
}
|
|
6653
7067
|
rootElement = element;
|
|
6654
7068
|
break;
|
|
6655
7069
|
}
|
|
@@ -6678,7 +7092,30 @@ class RscClient {
|
|
|
6678
7092
|
|
|
6679
7093
|
let actualType = type;
|
|
6680
7094
|
|
|
6681
|
-
if (typeof type === 'string' && type.
|
|
7095
|
+
if (typeof type === 'string' && type.includes('#')) {
|
|
7096
|
+
const clientComponent = getClientComponent(type);
|
|
7097
|
+
if (clientComponent) {
|
|
7098
|
+
actualType = clientComponent;
|
|
7099
|
+
} else {
|
|
7100
|
+
actualType = ({ children, ...restProps }) => React.createElement(
|
|
7101
|
+
'div',
|
|
7102
|
+
{
|
|
7103
|
+
...restProps,
|
|
7104
|
+
'data-client-component': type,
|
|
7105
|
+
style: {
|
|
7106
|
+
border: '2px dashed #f00',
|
|
7107
|
+
padding: '8px',
|
|
7108
|
+
margin: '4px',
|
|
7109
|
+
backgroundColor: '#fff0f0'
|
|
7110
|
+
}
|
|
7111
|
+
},
|
|
7112
|
+
React.createElement('small', { style: { color: '#c00' } },
|
|
7113
|
+
'Missing Client Component: ' + type
|
|
7114
|
+
),
|
|
7115
|
+
children
|
|
7116
|
+
);
|
|
7117
|
+
}
|
|
7118
|
+
} else if (typeof type === 'string' && type.startsWith('$L')) {
|
|
6682
7119
|
if (modules.has(type)) {
|
|
6683
7120
|
const moduleData = modules.get(type);
|
|
6684
7121
|
const clientComponentKey = moduleData.id + '#' + moduleData.name;
|
|
@@ -6856,9 +7293,7 @@ function ServerComponentWrapper({
|
|
|
6856
7293
|
}, [componentId, JSON.stringify(props)]);
|
|
6857
7294
|
|
|
6858
7295
|
if (loading) {
|
|
6859
|
-
return fallback ||
|
|
6860
|
-
'Loading ' + componentId + '...'
|
|
6861
|
-
);
|
|
7296
|
+
return fallback || null;
|
|
6862
7297
|
}
|
|
6863
7298
|
|
|
6864
7299
|
if (error) {
|
|
@@ -6871,7 +7306,7 @@ function ServerComponentWrapper({
|
|
|
6871
7306
|
if (data) {
|
|
6872
7307
|
if (data._isRscResponse) {
|
|
6873
7308
|
return React.createElement(Suspense,
|
|
6874
|
-
{ fallback: fallback ||
|
|
7309
|
+
{ fallback: fallback || null },
|
|
6875
7310
|
data.readRoot()
|
|
6876
7311
|
);
|
|
6877
7312
|
} else if (data) {
|
|
@@ -6919,11 +7354,12 @@ function createServerComponentWrapper(componentName, importPath) {
|
|
|
6919
7354
|
}, []);
|
|
6920
7355
|
|
|
6921
7356
|
return React.createElement(Suspense, {
|
|
6922
|
-
fallback:
|
|
7357
|
+
fallback: null
|
|
6923
7358
|
}, React.createElement(ServerComponentWrapper, {
|
|
6924
7359
|
key: componentName + '-' + mountKey, // Force re-mount with key change
|
|
6925
7360
|
componentId: componentName,
|
|
6926
|
-
props: props
|
|
7361
|
+
props: props,
|
|
7362
|
+
fallback: null
|
|
6927
7363
|
}));
|
|
6928
7364
|
};
|
|
6929
7365
|
|
package/dist/server.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HttpRuntimeClient, Link, Navigate, Outlet, RouteComponent, Routes, buildSearchString, buildUrl, createHttpRuntimeClient, extractParamNames, findMatchingRoute, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, normalizePathname, parseSearchParams, parseUrl, router_default, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, withRouter } from "./runtime-client-CC4YQweh.js";
|
|
2
|
-
import { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes } from "./server-
|
|
2
|
+
import { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes } from "./server-CpI87WFQ.js";
|
|
3
3
|
import "./server-build-DaBgiV55.js";
|
|
4
4
|
|
|
5
5
|
export { FileRouteGenerator, HttpRuntimeClient, Link, Navigate, Outlet, RouteComponent as Route, router_default as RouterProvider, Routes, buildSearchString, buildUrl, convertFilePatternToRoutePattern, createHttpRuntimeClient, createRouteManifest, defineRariConfig, extractParamNames, findMatchingRoute, generateFileRoutes, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, loadRouteManifest, normalizePathname, parseSearchParams, parseUrl, rari, rariRouter, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, validateRoutes, watchFileRoutes, withRouter };
|