rari 0.5.24 → 0.5.25

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.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { a as headers, i as rariRouter, n as defineRariOptions, o as RariResponse, r as rari, t as defineRariConfig } from "./vite-CXkIpRWF.mjs";
1
+ import { a as headers, i as rariRouter, n as defineRariOptions, o as RariResponse, r as rari, t as defineRariConfig } from "./vite-00sc6n_j.mjs";
2
2
  import { i as writeManifest, n as generateAppRouteManifest, r as loadManifest, t as AppRouteGenerator } from "./app-routes-DZjfJPdB.mjs";
3
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-jOuczfIg.mjs";
4
4
  import "./server-build-CQpjQCX6.mjs";
@@ -3005,6 +3005,7 @@ const ${componentName$1} = registerClientReference(
3005
3005
  resolveId(id) {
3006
3006
  if (id === "virtual:rsc-integration") return id;
3007
3007
  if (id === "virtual:rari-entry-client") return id;
3008
+ if (id === "virtual:react-server-dom-rari-client") return id;
3008
3009
  if (id === "virtual:app-router-provider") return `${id}.tsx`;
3009
3010
  if (id === "./DefaultLoadingIndicator" || id === "./DefaultLoadingIndicator.tsx") return "virtual:default-loading-indicator.tsx";
3010
3011
  if (id === "./LoadingErrorBoundary" || id === "./LoadingErrorBoundary.tsx") return "virtual:loading-error-boundary.tsx";
@@ -3094,6 +3095,7 @@ globalThis['~clientComponentPaths']["${relativePath}"] = "${componentId}";`;
3094
3095
  return "export class LoadingComponentRegistry { loadComponent() { return Promise.resolve(null); } }";
3095
3096
  }
3096
3097
  if (id === "virtual:rsc-integration") return await loadRscClientRuntime();
3098
+ if (id === "virtual:react-server-dom-rari-client") return await loadRuntimeFile("react-server-dom-rari-client.js");
3097
3099
  },
3098
3100
  async handleHotUpdate({ file, server }) {
3099
3101
  if (!/\.(?:tsx?|jsx?)$/.test(file)) return;
package/dist/vite.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { a as headers, i as rariRouter, n as defineRariOptions, o as RariResponse, r as rari, t as defineRariConfig } from "./vite-CXkIpRWF.mjs";
1
+ import { a as headers, i as rariRouter, n as defineRariOptions, o as RariResponse, r as rari, t as defineRariConfig } from "./vite-00sc6n_j.mjs";
2
2
  import { i as writeManifest, n as generateAppRouteManifest, r as loadManifest, t as AppRouteGenerator } from "./app-routes-DZjfJPdB.mjs";
3
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-jOuczfIg.mjs";
4
4
  import "./server-build-CQpjQCX6.mjs";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "rari",
3
3
  "type": "module",
4
- "version": "0.5.24",
4
+ "version": "0.5.25",
5
5
  "description": "Runtime Accelerated Rendering Infrastructure (Rari)",
6
6
  "author": "Ryan Skinner",
7
7
  "license": "MIT",
@@ -89,19 +89,19 @@
89
89
  "picocolors": "^1.1.1"
90
90
  },
91
91
  "optionalDependencies": {
92
- "rari-darwin-arm64": "0.5.18",
93
- "rari-darwin-x64": "0.5.18",
94
- "rari-linux-arm64": "0.5.18",
95
- "rari-linux-x64": "0.5.18",
96
- "rari-win32-x64": "0.5.18"
92
+ "rari-darwin-arm64": "0.5.19",
93
+ "rari-darwin-x64": "0.5.19",
94
+ "rari-linux-arm64": "0.5.19",
95
+ "rari-linux-x64": "0.5.19",
96
+ "rari-win32-x64": "0.5.19"
97
97
  },
98
98
  "devDependencies": {
99
99
  "@types/node": "^25.0.3",
100
100
  "@types/react": "^19.2.7",
101
- "@typescript/native-preview": "7.0.0-dev.20251219.1",
101
+ "@typescript/native-preview": "^7.0.0-dev.20251223.1",
102
102
  "chokidar": "^5.0.0",
103
103
  "eslint": "^9.39.2",
104
- "oxlint": "^1.34.0",
104
+ "oxlint": "^1.35.0",
105
105
  "rolldown-vite": "^7.3.0",
106
106
  "tsdown": "^0.17.3"
107
107
  }
@@ -876,9 +876,7 @@ export function AppRouterProvider({ children, initialPayload, onNavigate }: AppR
876
876
  </div>
877
877
  )}
878
878
 
879
- <div>
880
- {contentToRender}
881
- </div>
879
+ {contentToRender}
882
880
  </>
883
881
  )
884
882
  }
@@ -2,9 +2,16 @@ import { ClientRouter } from 'rari/client'
2
2
  import React from 'react'
3
3
  import { createRoot } from 'react-dom/client'
4
4
  import { AppRouterProvider } from 'virtual:app-router-provider'
5
+ import { createFromReadableStream } from 'virtual:react-server-dom-rari-client'
5
6
  import 'virtual:rsc-integration'
6
7
  import 'virtual:loading-component-map'
7
8
 
9
+ if (typeof globalThis['~rari'] === 'undefined') {
10
+ globalThis['~rari'] = {}
11
+ }
12
+ globalThis['~rari'].AppRouterProvider = AppRouterProvider
13
+ globalThis['~rari'].ClientRouter = ClientRouter
14
+
8
15
  // CLIENT_COMPONENT_IMPORTS_PLACEHOLDER
9
16
 
10
17
  if (typeof globalThis['~clientComponents'] === 'undefined') {
@@ -24,27 +31,62 @@ export async function renderApp() {
24
31
  }
25
32
 
26
33
  try {
27
- const rariServerUrl = window.location.origin.includes(':5173')
28
- ? 'http://localhost:3000'
29
- : window.location.origin
30
- const url = rariServerUrl + window.location.pathname + window.location.search
31
-
32
- const response = await fetch(url, {
33
- headers: {
34
- Accept: 'text/x-component',
35
- },
36
- })
34
+ let element
35
+ let isFullDocument = false
37
36
 
38
- if (!response.ok) {
39
- throw new Error(`Failed to fetch RSC data: ${response.status}`)
37
+ const payloadScript = document.getElementById('__RARI_RSC_PAYLOAD__')
38
+
39
+ if (payloadScript && payloadScript.textContent) {
40
+ try {
41
+ const payloadJson = payloadScript.textContent
42
+
43
+ const stream = new ReadableStream({
44
+ start(controller) {
45
+ controller.enqueue(new TextEncoder().encode(payloadJson))
46
+ controller.close()
47
+ },
48
+ })
49
+
50
+ element = await createFromReadableStream(stream, {
51
+ moduleMap: globalThis['~clientComponents'] || {},
52
+ })
53
+ }
54
+ catch (e) {
55
+ console.error('[Rari] Failed to parse embedded RSC payload:', e)
56
+ element = null
57
+ }
40
58
  }
41
59
 
42
- const rscWireFormat = await response.text()
60
+ if (!element) {
61
+ const rariServerUrl = window.location.origin.includes(':5173')
62
+ ? 'http://localhost:3000'
63
+ : window.location.origin
64
+ const url = rariServerUrl + window.location.pathname + window.location.search
43
65
 
44
- const { element, isFullDocument } = parseRscWireFormat(rscWireFormat)
66
+ const response = await fetch(url, {
67
+ headers: {
68
+ Accept: 'text/x-component',
69
+ },
70
+ })
71
+
72
+ if (!response.ok) {
73
+ throw new Error(`Failed to fetch RSC data: ${response.status}`)
74
+ }
75
+
76
+ const rscWireFormat = await response.text()
77
+ const parsed = parseRscWireFormat(rscWireFormat)
78
+ element = parsed.element
79
+ isFullDocument = parsed.isFullDocument
80
+ }
45
81
 
46
82
  let contentToRender
47
- if (isFullDocument) {
83
+ let hasProviders = false
84
+
85
+ if (payloadScript && element) {
86
+ contentToRender = element
87
+ hasProviders = true
88
+ }
89
+ else if (isFullDocument) {
48
90
  const bodyContent = extractBodyContent(element, false)
49
91
  if (bodyContent) {
50
92
  contentToRender = bodyContent
@@ -60,41 +102,67 @@ export async function renderApp() {
60
102
 
61
103
  let manifest = globalThis['~rari']?.appRoutesManifest
62
104
  if (!manifest) {
63
- try {
64
- const manifestUrl = window.location.origin.includes(':5173')
65
- ? '/app-routes.json'
66
- : '/app-routes.json'
105
+ const manifestScript = document.getElementById('__RARI_MANIFEST__')
67
106
 
68
- const manifestResponse = await fetch(manifestUrl, {
69
- headers: { 'Cache-Control': 'no-cache' },
70
- })
71
- if (manifestResponse.ok) {
72
- const text = await manifestResponse.text()
73
- manifest = JSON.parse(text)
107
+ if (manifestScript && manifestScript.textContent) {
108
+ try {
109
+ manifest = JSON.parse(manifestScript.textContent)
74
110
  if (!globalThis['~rari'])
75
111
  globalThis['~rari'] = {}
76
112
  globalThis['~rari'].appRoutesManifest = manifest
77
113
  }
114
+ catch (e) {
115
+ console.error('[Rari] Failed to parse embedded manifest:', e)
116
+ }
78
117
  }
79
- catch (err) {
80
- console.warn('[Rari] Failed to load manifest:', err)
118
+
119
+ if (!manifest) {
120
+ try {
121
+ const manifestUrl = window.location.origin.includes(':5173')
122
+ ? '/app-routes.json'
123
+ : '/app-routes.json'
124
+
125
+ const manifestResponse = await fetch(manifestUrl, {
126
+ headers: { 'Cache-Control': 'no-cache' },
127
+ })
128
+ if (manifestResponse.ok) {
129
+ const text = await manifestResponse.text()
130
+ manifest = JSON.parse(text)
131
+ if (!globalThis['~rari'])
132
+ globalThis['~rari'] = {}
133
+ globalThis['~rari'].appRoutesManifest = manifest
134
+ }
135
+ }
136
+ catch (err) {
137
+ console.warn('[Rari] Failed to load manifest:', err)
138
+ }
81
139
  }
82
140
  }
83
141
 
84
- let wrappedContent = contentToRender
85
-
86
- wrappedContent = React.createElement(
87
- AppRouterProvider,
88
- { initialPayload: { element, rscWireFormat } },
89
- contentToRender,
90
- )
142
+ let wrappedContent
91
143
 
92
- if (manifest) {
144
+ if (hasProviders) {
145
+ if (!manifest) {
146
+ wrappedContent = contentToRender
147
+ }
148
+ else {
149
+ wrappedContent = contentToRender
150
+ }
151
+ }
152
+ else {
93
153
  wrappedContent = React.createElement(
94
- ClientRouter,
95
- { manifest, initialRoute: window.location.pathname },
96
- wrappedContent,
154
+ AppRouterProvider,
155
+ { initialPayload: { element } },
156
+ contentToRender,
97
157
  )
158
+
159
+ if (manifest) {
160
+ wrappedContent = React.createElement(
161
+ ClientRouter,
162
+ { manifest, initialRoute: window.location.pathname },
163
+ wrappedContent,
164
+ )
165
+ }
98
166
  }
99
167
 
100
168
  const root = createRoot(rootElement)
@@ -0,0 +1,191 @@
1
+ import React from 'react'
2
+
3
+ export async function createFromReadableStream(stream, options = {}) {
4
+ const { moduleMap = {} } = options
5
+
6
+ const reader = stream.getReader()
7
+ const chunks = []
8
+
9
+ while (true) {
10
+ const { done, value } = await reader.read()
11
+ if (done)
12
+ break
13
+ chunks.push(value)
14
+ }
15
+
16
+ const combined = new Uint8Array(chunks.reduce((acc, chunk) => acc + chunk.length, 0))
17
+ let offset = 0
18
+ for (const chunk of chunks) {
19
+ combined.set(chunk, offset)
20
+ offset += chunk.length
21
+ }
22
+
23
+ const text = new TextDecoder().decode(combined)
24
+
25
+ const parsed = parseWireFormat(text)
26
+ return rscToReact(parsed.rootElement, parsed.modules, moduleMap)
27
+ }
28
+
29
+ export async function createFromFetch(fetchPromise, options = {}) {
30
+ const response = await fetchPromise
31
+ const text = await response.text()
32
+
33
+ const parsed = parseWireFormat(text)
34
+ return rscToReact(parsed.rootElement, parsed.modules, options.moduleMap || {})
35
+ }
36
+
37
+ function parseWireFormat(wireFormat) {
38
+ const lines = wireFormat.split('\n').filter(line => line.trim())
39
+ const modules = new Map()
40
+ const chunks = new Map()
41
+ let rootChunkId = null
42
+
43
+ for (const line of lines) {
44
+ const colonIndex = line.indexOf(':')
45
+ if (colonIndex === -1)
46
+ continue
47
+
48
+ const idStr = line.substring(0, colonIndex)
49
+ const content = line.substring(colonIndex + 1)
50
+ const id = idStr
51
+
52
+ try {
53
+ if (content.startsWith('I')) {
54
+ const moduleData = JSON.parse(content.substring(1))
55
+ if (Array.isArray(moduleData) && moduleData.length >= 3) {
56
+ const [path, chunksArray, exportName] = moduleData
57
+ modules.set(`$L${id}`, {
58
+ id: path,
59
+ chunks: chunksArray || [],
60
+ name: exportName || 'default',
61
+ })
62
+ }
63
+ }
64
+ else {
65
+ const data = JSON.parse(content)
66
+ chunks.set(id, data)
67
+
68
+ if (rootChunkId === null) {
69
+ rootChunkId = id
70
+ }
71
+ }
72
+ }
73
+ catch (e) {
74
+ console.error('[RSC Wire Format] Failed to parse line:', line, e)
75
+ }
76
+ }
77
+
78
+ const rootElement = rootChunkId !== null ? chunks.get(rootChunkId) : null
79
+
80
+ return {
81
+ modules,
82
+ chunks,
83
+ rootElement,
84
+ }
85
+ }
86
+
87
+ function rscToReact(rsc, wireModules, moduleMap) {
88
+ if (!rsc)
89
+ return null
90
+
91
+ if (typeof rsc === 'string' || typeof rsc === 'number' || typeof rsc === 'boolean') {
92
+ return rsc
93
+ }
94
+
95
+ if (Array.isArray(rsc)) {
96
+ if (rsc.length >= 4 && rsc[0] === '$') {
97
+ const [, type, key, props] = rsc
98
+
99
+ if (typeof type === 'string' && type.startsWith('$L')) {
100
+ const componentName = type.substring(2)
101
+
102
+ if (componentName === 'ClientRouter' && (!props || !props.manifest)) {
103
+ return props && props.children ? rscToReact(props.children, wireModules, moduleMap) : null
104
+ }
105
+
106
+ const Component = resolveClientComponent(componentName, wireModules, moduleMap)
107
+
108
+ if (Component) {
109
+ const processedProps = processProps(props, wireModules, moduleMap)
110
+ return React.createElement(Component, key ? { ...processedProps, key } : processedProps)
111
+ }
112
+
113
+ return null
114
+ }
115
+
116
+ const processedProps = processProps(props, wireModules, moduleMap)
117
+ return React.createElement(type, key ? { ...processedProps, key } : processedProps)
118
+ }
119
+
120
+ return rsc.map(child => rscToReact(child, wireModules, moduleMap))
121
+ }
122
+
123
+ return rsc
124
+ }
125
+
126
+ function resolveClientComponent(componentName, wireModules, moduleMap) {
127
+ if (componentName === 'AppRouterProvider') {
128
+ const AppRouterProvider = globalThis['~rari']?.AppRouterProvider
129
+ if (AppRouterProvider)
130
+ return AppRouterProvider
131
+ }
132
+
133
+ if (componentName === 'ClientRouter') {
134
+ const ClientRouter = globalThis['~rari']?.ClientRouter
135
+ if (ClientRouter)
136
+ return ClientRouter
137
+ }
138
+
139
+ if (wireModules && wireModules.size > 0) {
140
+ const moduleRef = `$L${componentName}`
141
+ const moduleInfo = wireModules.get(moduleRef)
142
+ if (moduleInfo) {
143
+ const clientComponents = globalThis['~clientComponents'] || {}
144
+ if (clientComponents[moduleInfo.id]) {
145
+ return clientComponents[moduleInfo.id].component
146
+ }
147
+ }
148
+ }
149
+
150
+ if (moduleMap[componentName]) {
151
+ return moduleMap[componentName]
152
+ }
153
+
154
+ const clientComponents = globalThis['~clientComponents'] || {}
155
+ for (const [id, info] of Object.entries(clientComponents)) {
156
+ if (id.includes(componentName) || info.name === componentName) {
157
+ return info.component
158
+ }
159
+ }
160
+
161
+ return null
162
+ }
163
+
164
+ function processProps(props, wireModules, moduleMap) {
165
+ if (!props || typeof props !== 'object')
166
+ return props
167
+
168
+ const processed = {}
169
+ for (const key in props) {
170
+ if (Object.prototype.hasOwnProperty.call(props, key)) {
171
+ if (key.startsWith('$') || key === 'ref') {
172
+ continue
173
+ }
174
+ if (key === 'children') {
175
+ processed[key] = props.children ? rscToReact(props.children, wireModules, moduleMap) : undefined
176
+ }
177
+ else {
178
+ processed[key] = props[key]
179
+ }
180
+ }
181
+ }
182
+ return processed
183
+ }
184
+
185
+ export function encodeReply(value) {
186
+ return JSON.stringify(value)
187
+ }
188
+
189
+ export function decodeReply(text) {
190
+ return JSON.parse(text)
191
+ }
@@ -17,17 +17,17 @@ export function registerClientReference(clientReference, id, exportName) {
17
17
  async: false,
18
18
  })
19
19
 
20
- Object.defineProperty(clientReference, '$typeof', {
20
+ Object.defineProperty(clientReference, '$$typeof', {
21
21
  value: Symbol.for('react.client.reference'),
22
22
  enumerable: false,
23
23
  })
24
24
 
25
- Object.defineProperty(clientReference, '$id', {
25
+ Object.defineProperty(clientReference, '$$id', {
26
26
  value: key,
27
27
  enumerable: false,
28
28
  })
29
29
 
30
- Object.defineProperty(clientReference, '$async', {
30
+ Object.defineProperty(clientReference, '$$async', {
31
31
  value: false,
32
32
  enumerable: false,
33
33
  })
@@ -70,17 +70,17 @@ export function registerServerReference(serverReference, id, exportName) {
70
70
  bound: false,
71
71
  })
72
72
 
73
- Object.defineProperty(serverReference, '$typeof', {
73
+ Object.defineProperty(serverReference, '$$typeof', {
74
74
  value: Symbol.for('react.server.reference'),
75
75
  enumerable: false,
76
76
  })
77
77
 
78
- Object.defineProperty(serverReference, '$id', {
78
+ Object.defineProperty(serverReference, '$$id', {
79
79
  value: key,
80
80
  enumerable: false,
81
81
  })
82
82
 
83
- Object.defineProperty(serverReference, '$bound', {
83
+ Object.defineProperty(serverReference, '$$bound', {
84
84
  value: false,
85
85
  enumerable: false,
86
86
  })
package/src/vite/index.ts CHANGED
@@ -1298,6 +1298,10 @@ const ${componentName} = registerClientReference(
1298
1298
  return id
1299
1299
  }
1300
1300
 
1301
+ if (id === 'virtual:react-server-dom-rari-client') {
1302
+ return id
1303
+ }
1304
+
1301
1305
  if (id === 'virtual:app-router-provider') {
1302
1306
  return `${id}.tsx`
1303
1307
  }
@@ -1460,6 +1464,10 @@ globalThis['~clientComponentPaths']["${relativePath}"] = "${componentId}";`
1460
1464
  if (id === 'virtual:rsc-integration') {
1461
1465
  return await loadRscClientRuntime()
1462
1466
  }
1467
+
1468
+ if (id === 'virtual:react-server-dom-rari-client') {
1469
+ return await loadRuntimeFile('react-server-dom-rari-client.js')
1470
+ }
1463
1471
  },
1464
1472
 
1465
1473
  async handleHotUpdate({ file, server }) {