@tanstack/start-server-core 1.121.0-alpha.27 → 1.121.0-alpha.28

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.
Files changed (103) hide show
  1. package/dist/esm/constants.d.ts +3 -0
  2. package/dist/esm/constants.js +7 -0
  3. package/dist/esm/constants.js.map +1 -0
  4. package/dist/esm/createStartHandler.d.ts +4 -7
  5. package/dist/esm/createStartHandler.js +169 -102
  6. package/dist/esm/createStartHandler.js.map +1 -1
  7. package/dist/esm/index.d.ts +6 -8
  8. package/dist/esm/index.js +10 -97
  9. package/dist/esm/index.js.map +1 -1
  10. package/dist/esm/loadVirtualModule.js +2 -0
  11. package/dist/esm/loadVirtualModule.js.map +1 -1
  12. package/dist/esm/request-response.d.ts +124 -0
  13. package/dist/esm/request-response.js +177 -0
  14. package/dist/esm/request-response.js.map +1 -0
  15. package/dist/esm/router-manifest.d.ts +1 -0
  16. package/dist/esm/router-manifest.js +17 -17
  17. package/dist/esm/router-manifest.js.map +1 -1
  18. package/dist/esm/server-functions-handler.js +6 -7
  19. package/dist/esm/server-functions-handler.js.map +1 -1
  20. package/dist/esm/serverRoute.d.ts +6 -2
  21. package/dist/esm/serverRoute.js +3 -2
  22. package/dist/esm/serverRoute.js.map +1 -1
  23. package/dist/esm/session.d.ts +66 -0
  24. package/dist/esm/virtual-modules.d.ts +2 -0
  25. package/dist/esm/virtual-modules.js +2 -1
  26. package/dist/esm/virtual-modules.js.map +1 -1
  27. package/package.json +9 -19
  28. package/src/constants.ts +3 -0
  29. package/src/createStartHandler.ts +241 -143
  30. package/src/global.d.ts +10 -2
  31. package/src/index.tsx +42 -13
  32. package/src/loadVirtualModule.ts +2 -0
  33. package/src/request-response.ts +335 -0
  34. package/src/router-manifest.ts +17 -38
  35. package/src/server-functions-handler.ts +6 -5
  36. package/src/serverRoute.ts +22 -3
  37. package/src/session.ts +75 -0
  38. package/src/tanstack-start.d.ts +18 -5
  39. package/src/virtual-modules.ts +2 -0
  40. package/dist/cjs/createRequestHandler.cjs +0 -50
  41. package/dist/cjs/createRequestHandler.cjs.map +0 -1
  42. package/dist/cjs/createRequestHandler.d.cts +0 -8
  43. package/dist/cjs/createStartHandler.cjs +0 -274
  44. package/dist/cjs/createStartHandler.cjs.map +0 -1
  45. package/dist/cjs/createStartHandler.d.cts +0 -10
  46. package/dist/cjs/h3.cjs +0 -355
  47. package/dist/cjs/h3.cjs.map +0 -1
  48. package/dist/cjs/h3.d.cts +0 -109
  49. package/dist/cjs/handlerCallback.cjs +0 -7
  50. package/dist/cjs/handlerCallback.cjs.map +0 -1
  51. package/dist/cjs/handlerCallback.d.cts +0 -9
  52. package/dist/cjs/index.cjs +0 -245
  53. package/dist/cjs/index.cjs.map +0 -1
  54. package/dist/cjs/index.d.cts +0 -12
  55. package/dist/cjs/loadVirtualModule.cjs +0 -39
  56. package/dist/cjs/loadVirtualModule.cjs.map +0 -1
  57. package/dist/cjs/loadVirtualModule.d.cts +0 -6
  58. package/dist/cjs/router-manifest.cjs +0 -49
  59. package/dist/cjs/router-manifest.cjs.map +0 -1
  60. package/dist/cjs/router-manifest.d.cts +0 -16
  61. package/dist/cjs/server-functions-handler.cjs +0 -148
  62. package/dist/cjs/server-functions-handler.cjs.map +0 -1
  63. package/dist/cjs/server-functions-handler.d.cts +0 -3
  64. package/dist/cjs/serverRoute.cjs +0 -102
  65. package/dist/cjs/serverRoute.cjs.map +0 -1
  66. package/dist/cjs/serverRoute.d.cts +0 -120
  67. package/dist/cjs/ssr-server.cjs +0 -247
  68. package/dist/cjs/ssr-server.cjs.map +0 -1
  69. package/dist/cjs/ssr-server.d.cts +0 -29
  70. package/dist/cjs/transformStreamWithRouter.cjs +0 -183
  71. package/dist/cjs/transformStreamWithRouter.cjs.map +0 -1
  72. package/dist/cjs/transformStreamWithRouter.d.cts +0 -6
  73. package/dist/cjs/tsrScript.cjs +0 -4
  74. package/dist/cjs/tsrScript.cjs.map +0 -1
  75. package/dist/cjs/tsrScript.d.cts +0 -1
  76. package/dist/cjs/virtual-modules.cjs +0 -9
  77. package/dist/cjs/virtual-modules.cjs.map +0 -1
  78. package/dist/cjs/virtual-modules.d.cts +0 -10
  79. package/dist/esm/createRequestHandler.d.ts +0 -8
  80. package/dist/esm/createRequestHandler.js +0 -50
  81. package/dist/esm/createRequestHandler.js.map +0 -1
  82. package/dist/esm/h3.d.ts +0 -109
  83. package/dist/esm/h3.js +0 -248
  84. package/dist/esm/h3.js.map +0 -1
  85. package/dist/esm/handlerCallback.d.ts +0 -9
  86. package/dist/esm/handlerCallback.js +0 -7
  87. package/dist/esm/handlerCallback.js.map +0 -1
  88. package/dist/esm/ssr-server.d.ts +0 -29
  89. package/dist/esm/ssr-server.js +0 -247
  90. package/dist/esm/ssr-server.js.map +0 -1
  91. package/dist/esm/transformStreamWithRouter.d.ts +0 -6
  92. package/dist/esm/transformStreamWithRouter.js +0 -183
  93. package/dist/esm/transformStreamWithRouter.js.map +0 -1
  94. package/dist/esm/tsrScript.d.ts +0 -1
  95. package/dist/esm/tsrScript.js +0 -5
  96. package/dist/esm/tsrScript.js.map +0 -1
  97. package/src/createRequestHandler.ts +0 -73
  98. package/src/h3.ts +0 -492
  99. package/src/handlerCallback.ts +0 -15
  100. package/src/ssr-server.ts +0 -352
  101. package/src/transformStreamWithRouter.ts +0 -258
  102. package/src/tsrScript.ts +0 -91
  103. package/src/vite-env.d.ts +0 -4
package/src/ssr-server.ts DELETED
@@ -1,352 +0,0 @@
1
- import { default as warning } from 'tiny-warning'
2
- import {
3
- TSR_DEFERRED_PROMISE,
4
- defer,
5
- isPlainArray,
6
- isPlainObject,
7
- pick,
8
- } from '@tanstack/router-core'
9
- import jsesc from 'jsesc'
10
- import { startSerializer } from '@tanstack/start-client-core'
11
- import minifiedTsrBootStrapScript from './tsrScript?script-string'
12
- import type {
13
- ClientExtractedBaseEntry,
14
- DehydratedRouter,
15
- ResolvePromiseState,
16
- SsrMatch,
17
- } from '@tanstack/start-client-core'
18
- import type {
19
- AnyRouteMatch,
20
- AnyRouter,
21
- DeferredPromise,
22
- Manifest,
23
- } from '@tanstack/router-core'
24
-
25
- export type ServerExtractedEntry =
26
- | ServerExtractedStream
27
- | ServerExtractedPromise
28
-
29
- export interface ServerExtractedBaseEntry extends ClientExtractedBaseEntry {
30
- id: number
31
- matchIndex: number
32
- }
33
-
34
- export interface ServerExtractedStream extends ServerExtractedBaseEntry {
35
- type: 'stream'
36
- stream: ReadableStream
37
- }
38
-
39
- export interface ServerExtractedPromise extends ServerExtractedBaseEntry {
40
- type: 'promise'
41
- promise: DeferredPromise<any>
42
- }
43
-
44
- export function attachRouterServerSsrUtils(
45
- router: AnyRouter,
46
- manifest: Manifest | undefined,
47
- ) {
48
- router.ssr = {
49
- manifest,
50
- serializer: startSerializer,
51
- }
52
-
53
- router.serverSsr = {
54
- injectedHtml: [],
55
- streamedKeys: new Set(),
56
- injectHtml: (getHtml) => {
57
- const promise = Promise.resolve().then(getHtml)
58
- router.serverSsr!.injectedHtml.push(promise)
59
- router.emit({
60
- type: 'onInjectedHtml',
61
- promise,
62
- })
63
-
64
- return promise.then(() => {})
65
- },
66
- injectScript: (getScript, opts) => {
67
- return router.serverSsr!.injectHtml(async () => {
68
- const script = await getScript()
69
- return `<script class='tsr-once'>${script}${
70
- process.env.NODE_ENV === 'development' && (opts?.logScript ?? true)
71
- ? `; console.info(\`Injected From Server:
72
- ${jsesc(script, { quotes: 'backtick' })}\`)`
73
- : ''
74
- }; if (typeof __TSR_SSR__ !== 'undefined') __TSR_SSR__.cleanScripts()</script>`
75
- })
76
- },
77
- streamValue: (key, value) => {
78
- warning(
79
- !router.serverSsr!.streamedKeys.has(key),
80
- 'Key has already been streamed: ' + key,
81
- )
82
-
83
- router.serverSsr!.streamedKeys.add(key)
84
- router.serverSsr!.injectScript(
85
- () =>
86
- `__TSR_SSR__.streamedValues['${key}'] = { value: ${jsesc(
87
- router.ssr!.serializer.stringify(value),
88
- {
89
- isScriptContext: true,
90
- wrap: true,
91
- json: true,
92
- },
93
- )}}`,
94
- )
95
- },
96
- onMatchSettled,
97
- }
98
-
99
- router.serverSsr.injectScript(() => minifiedTsrBootStrapScript, {
100
- logScript: false,
101
- })
102
- }
103
-
104
- export function dehydrateRouter(router: AnyRouter) {
105
- const dehydratedRouter: DehydratedRouter = {
106
- manifest: router.ssr!.manifest,
107
- dehydratedData: router.options.dehydrate?.(),
108
- lastMatchId:
109
- router.state.matches[router.state.matches.length - 1]?.id || '',
110
- }
111
-
112
- router.serverSsr!.injectScript(
113
- () =>
114
- `__TSR_SSR__.dehydrated = ${jsesc(
115
- router.ssr!.serializer.stringify(dehydratedRouter),
116
- {
117
- isScriptContext: true,
118
- wrap: true,
119
- json: true,
120
- },
121
- )}`,
122
- )
123
- }
124
-
125
- export function extractAsyncLoaderData(
126
- loaderData: any,
127
- ctx: {
128
- match: AnyRouteMatch
129
- router: AnyRouter
130
- },
131
- ) {
132
- const extracted: Array<ServerExtractedEntry> = []
133
-
134
- const replaced = replaceBy(loaderData, (value, path) => {
135
- // If it's a stream, we need to tee it so we can read it multiple times
136
- if (value instanceof ReadableStream) {
137
- const [copy1, copy2] = value.tee()
138
- const entry: ServerExtractedStream = {
139
- type: 'stream',
140
- path,
141
- id: extracted.length,
142
- matchIndex: ctx.match.index,
143
- stream: copy2,
144
- }
145
-
146
- extracted.push(entry)
147
- return copy1
148
- } else if (value instanceof Promise) {
149
- const deferredPromise = defer(value)
150
- const entry: ServerExtractedPromise = {
151
- type: 'promise',
152
- path,
153
- id: extracted.length,
154
- matchIndex: ctx.match.index,
155
- promise: deferredPromise,
156
- }
157
- extracted.push(entry)
158
- }
159
-
160
- return value
161
- })
162
-
163
- return { replaced, extracted }
164
- }
165
-
166
- export function onMatchSettled(opts: {
167
- router: AnyRouter
168
- match: AnyRouteMatch
169
- }) {
170
- const { router, match } = opts
171
-
172
- let extracted: Array<ServerExtractedEntry> | undefined = undefined
173
- let serializedLoaderData: any = undefined
174
- if (match.loaderData !== undefined) {
175
- const result = extractAsyncLoaderData(match.loaderData, {
176
- router,
177
- match,
178
- })
179
- match.loaderData = result.replaced
180
- extracted = result.extracted
181
- serializedLoaderData = extracted.reduce(
182
- (acc: any, entry: ServerExtractedEntry) => {
183
- return deepImmutableSetByPath(acc, ['temp', ...entry.path], undefined)
184
- },
185
- { temp: result.replaced },
186
- ).temp
187
- }
188
-
189
- const initCode = `__TSR_SSR__.initMatch(${jsesc(
190
- {
191
- id: match.id,
192
- __beforeLoadContext: router.ssr!.serializer.stringify(
193
- match.__beforeLoadContext,
194
- ),
195
- loaderData: router.ssr!.serializer.stringify(serializedLoaderData),
196
- error: router.ssr!.serializer.stringify(match.error),
197
- extracted: extracted?.map((entry) => pick(entry, ['type', 'path'])),
198
- updatedAt: match.updatedAt,
199
- status: match.status,
200
- } satisfies SsrMatch,
201
- {
202
- isScriptContext: true,
203
- wrap: true,
204
- json: true,
205
- },
206
- )})`
207
-
208
- router.serverSsr!.injectScript(() => initCode)
209
-
210
- if (extracted) {
211
- extracted.forEach((entry) => {
212
- if (entry.type === 'promise') return injectPromise(entry)
213
- return injectStream(entry)
214
- })
215
- }
216
-
217
- function injectPromise(entry: ServerExtractedPromise) {
218
- router.serverSsr!.injectScript(async () => {
219
- await entry.promise
220
-
221
- return `__TSR_SSR__.resolvePromise(${jsesc(
222
- {
223
- matchId: match.id,
224
- id: entry.id,
225
- promiseState: entry.promise[TSR_DEFERRED_PROMISE],
226
- } satisfies ResolvePromiseState,
227
- {
228
- isScriptContext: true,
229
- wrap: true,
230
- json: true,
231
- },
232
- )})`
233
- })
234
- }
235
-
236
- function injectStream(entry: ServerExtractedStream) {
237
- // Inject a promise that resolves when the stream is done
238
- // We do this to keep the stream open until we're done
239
- router.serverSsr!.injectHtml(async () => {
240
- //
241
- try {
242
- const reader = entry.stream.getReader()
243
- let chunk: ReadableStreamReadResult<any> | null = null
244
- while (!(chunk = await reader.read()).done) {
245
- if (chunk.value) {
246
- const code = `__TSR_SSR__.injectChunk(${jsesc(
247
- {
248
- matchId: match.id,
249
- id: entry.id,
250
- chunk: chunk.value,
251
- },
252
- {
253
- isScriptContext: true,
254
- wrap: true,
255
- json: true,
256
- },
257
- )})`
258
-
259
- router.serverSsr!.injectScript(() => code)
260
- }
261
- }
262
-
263
- router.serverSsr!.injectScript(
264
- () =>
265
- `__TSR_SSR__.closeStream(${jsesc(
266
- {
267
- matchId: match.id,
268
- id: entry.id,
269
- },
270
- {
271
- isScriptContext: true,
272
- wrap: true,
273
- json: true,
274
- },
275
- )})`,
276
- )
277
- } catch (err) {
278
- console.error('stream read error', err)
279
- }
280
-
281
- return ''
282
- })
283
- }
284
- }
285
-
286
- function deepImmutableSetByPath<T>(obj: T, path: Array<string>, value: any): T {
287
- // immutable set by path retaining array and object references
288
- if (path.length === 0) {
289
- return value
290
- }
291
-
292
- const [key, ...rest] = path
293
-
294
- if (Array.isArray(obj)) {
295
- return obj.map((item, i) => {
296
- if (i === Number(key)) {
297
- return deepImmutableSetByPath(item, rest, value)
298
- }
299
- return item
300
- }) as T
301
- }
302
-
303
- if (isPlainObject(obj)) {
304
- return {
305
- ...obj,
306
- [key!]: deepImmutableSetByPath((obj as any)[key!], rest, value),
307
- }
308
- }
309
-
310
- return obj
311
- }
312
-
313
- export function replaceBy<T>(
314
- obj: T,
315
- cb: (value: any, path: Array<string>) => any,
316
- path: Array<string> = [],
317
- ): T {
318
- if (isPlainArray(obj)) {
319
- return obj.map((value, i) => replaceBy(value, cb, [...path, `${i}`])) as any
320
- }
321
-
322
- if (isPlainObject(obj)) {
323
- // Do not allow objects with illegal
324
- const newObj: any = {}
325
-
326
- for (const key in obj) {
327
- newObj[key] = replaceBy(obj[key], cb, [...path, key])
328
- }
329
-
330
- return newObj
331
- }
332
-
333
- // // Detect classes, functions, and other non-serializable objects
334
- // // and return undefined. Exclude some known types that are serializable
335
- // if (
336
- // typeof obj === 'function' ||
337
- // (typeof obj === 'object' &&
338
- // ![Object, Promise, ReadableStream].includes((obj as any)?.constructor))
339
- // ) {
340
- // console.info(obj)
341
- // warning(false, `Non-serializable value ☝️ found at ${path.join('.')}`)
342
- // return undefined as any
343
- // }
344
-
345
- const newObj = cb(obj, path)
346
-
347
- if (newObj !== obj) {
348
- return newObj
349
- }
350
-
351
- return obj
352
- }
@@ -1,258 +0,0 @@
1
- import { ReadableStream } from 'node:stream/web'
2
- import { Readable } from 'node:stream'
3
- import { createControlledPromise } from '@tanstack/router-core'
4
- import type { AnyRouter } from '@tanstack/router-core'
5
-
6
- export function transformReadableStreamWithRouter(
7
- router: AnyRouter,
8
- routerStream: ReadableStream,
9
- ) {
10
- return transformStreamWithRouter(router, routerStream)
11
- }
12
-
13
- export function transformPipeableStreamWithRouter(
14
- router: AnyRouter,
15
- routerStream: Readable,
16
- ) {
17
- return Readable.fromWeb(
18
- transformStreamWithRouter(router, Readable.toWeb(routerStream)),
19
- )
20
- }
21
-
22
- // regex pattern for matching closing body and html tags
23
- const patternBodyStart = /(<body)/
24
- const patternBodyEnd = /(<\/body>)/
25
- const patternHtmlEnd = /(<\/html>)/
26
- const patternHeadStart = /(<head.*?>)/
27
- // regex pattern for matching closing tags
28
- const patternClosingTag = /(<\/[a-zA-Z][\w:.-]*?>)/g
29
-
30
- const textDecoder = new TextDecoder()
31
-
32
- type ReadablePassthrough = {
33
- stream: ReadableStream
34
- write: (chunk: string) => void
35
- end: (chunk?: string) => void
36
- destroy: (error: unknown) => void
37
- destroyed: boolean
38
- }
39
-
40
- function createPassthrough() {
41
- let controller: ReadableStreamDefaultController<any>
42
- const encoder = new TextEncoder()
43
- const stream = new ReadableStream({
44
- start(c) {
45
- controller = c
46
- },
47
- })
48
-
49
- const res: ReadablePassthrough = {
50
- stream,
51
- write: (chunk) => {
52
- controller.enqueue(encoder.encode(chunk))
53
- },
54
- end: (chunk) => {
55
- if (chunk) {
56
- controller.enqueue(encoder.encode(chunk))
57
- }
58
- controller.close()
59
- res.destroyed = true
60
- },
61
- destroy: (error) => {
62
- controller.error(error)
63
- },
64
- destroyed: false,
65
- }
66
-
67
- return res
68
- }
69
-
70
- async function readStream(
71
- stream: ReadableStream,
72
- opts: {
73
- onData?: (chunk: ReadableStreamReadValueResult<any>) => void
74
- onEnd?: () => void
75
- onError?: (error: unknown) => void
76
- },
77
- ) {
78
- try {
79
- const reader = stream.getReader()
80
- let chunk
81
- while (!(chunk = await reader.read()).done) {
82
- opts.onData?.(chunk)
83
- }
84
- opts.onEnd?.()
85
- } catch (error) {
86
- opts.onError?.(error)
87
- }
88
- }
89
-
90
- export function transformStreamWithRouter(
91
- router: AnyRouter,
92
- appStream: ReadableStream,
93
- ) {
94
- const finalPassThrough = createPassthrough()
95
-
96
- let isAppRendering = true as boolean
97
- let routerStreamBuffer = ''
98
- let pendingClosingTags = ''
99
- let bodyStarted = false as boolean
100
- let headStarted = false as boolean
101
- let leftover = ''
102
- let leftoverHtml = ''
103
-
104
- function getBufferedRouterStream() {
105
- const html = routerStreamBuffer
106
- routerStreamBuffer = ''
107
- return html
108
- }
109
-
110
- function decodeChunk(chunk: unknown): string {
111
- if (chunk instanceof Uint8Array) {
112
- return textDecoder.decode(chunk)
113
- }
114
- return String(chunk)
115
- }
116
-
117
- const injectedHtmlDonePromise = createControlledPromise<void>()
118
-
119
- let processingCount = 0
120
-
121
- // Process any already-injected HTML
122
- router.serverSsr!.injectedHtml.forEach((promise) => {
123
- handleInjectedHtml(promise)
124
- })
125
-
126
- // Listen for any new injected HTML
127
- const stopListeningToInjectedHtml = router.subscribe(
128
- 'onInjectedHtml',
129
- (e) => {
130
- handleInjectedHtml(e.promise)
131
- },
132
- )
133
-
134
- function handleInjectedHtml(promise: Promise<string>) {
135
- processingCount++
136
-
137
- promise
138
- .then((html) => {
139
- if (!bodyStarted) {
140
- routerStreamBuffer += html
141
- } else {
142
- finalPassThrough.write(html)
143
- }
144
- })
145
- .catch(injectedHtmlDonePromise.reject)
146
- .finally(() => {
147
- processingCount--
148
-
149
- if (!isAppRendering && processingCount === 0) {
150
- stopListeningToInjectedHtml()
151
- injectedHtmlDonePromise.resolve()
152
- }
153
- })
154
- }
155
-
156
- injectedHtmlDonePromise
157
- .then(() => {
158
- const finalHtml =
159
- leftoverHtml + getBufferedRouterStream() + pendingClosingTags
160
-
161
- finalPassThrough.end(finalHtml)
162
- })
163
- .catch((err) => {
164
- console.error('Error reading routerStream:', err)
165
- finalPassThrough.destroy(err)
166
- })
167
-
168
- // Transform the appStream
169
- readStream(appStream, {
170
- onData: (chunk) => {
171
- const text = decodeChunk(chunk.value)
172
-
173
- let chunkString = leftover + text
174
- const bodyEndMatch = chunkString.match(patternBodyEnd)
175
- const htmlEndMatch = chunkString.match(patternHtmlEnd)
176
-
177
- if (!bodyStarted) {
178
- const bodyStartMatch = chunkString.match(patternBodyStart)
179
- if (bodyStartMatch) {
180
- bodyStarted = true
181
- }
182
- }
183
-
184
- if (!headStarted) {
185
- const headStartMatch = chunkString.match(patternHeadStart)
186
- if (headStartMatch) {
187
- headStarted = true
188
- const index = headStartMatch.index!
189
- const headTag = headStartMatch[0]
190
- const remaining = chunkString.slice(index + headTag.length)
191
- finalPassThrough.write(
192
- chunkString.slice(0, index) + headTag + getBufferedRouterStream(),
193
- )
194
- // make sure to only write `remaining` until the next closing tag
195
- chunkString = remaining
196
- }
197
- }
198
-
199
- if (!bodyStarted) {
200
- finalPassThrough.write(chunkString)
201
- leftover = ''
202
- return
203
- }
204
-
205
- // If either the body end or html end is in the chunk,
206
- // We need to get all of our data in asap
207
- if (
208
- bodyEndMatch &&
209
- htmlEndMatch &&
210
- bodyEndMatch.index! < htmlEndMatch.index!
211
- ) {
212
- const bodyEndIndex = bodyEndMatch.index!
213
- pendingClosingTags = chunkString.slice(bodyEndIndex)
214
-
215
- finalPassThrough.write(
216
- chunkString.slice(0, bodyEndIndex) + getBufferedRouterStream(),
217
- )
218
-
219
- leftover = ''
220
- return
221
- }
222
-
223
- let result: RegExpExecArray | null
224
- let lastIndex = 0
225
- while ((result = patternClosingTag.exec(chunkString)) !== null) {
226
- lastIndex = result.index + result[0].length
227
- }
228
-
229
- if (lastIndex > 0) {
230
- const processed =
231
- chunkString.slice(0, lastIndex) +
232
- getBufferedRouterStream() +
233
- leftoverHtml
234
-
235
- finalPassThrough.write(processed)
236
- leftover = chunkString.slice(lastIndex)
237
- } else {
238
- leftover = chunkString
239
- leftoverHtml += getBufferedRouterStream()
240
- }
241
- },
242
- onEnd: () => {
243
- // Mark the app as done rendering
244
- isAppRendering = false
245
-
246
- // If there are no pending promises, resolve the injectedHtmlDonePromise
247
- if (processingCount === 0) {
248
- injectedHtmlDonePromise.resolve()
249
- }
250
- },
251
- onError: (error) => {
252
- console.error('Error reading appStream:', error)
253
- finalPassThrough.destroy(error)
254
- },
255
- })
256
-
257
- return finalPassThrough.stream
258
- }
package/src/tsrScript.ts DELETED
@@ -1,91 +0,0 @@
1
- import type { ControllablePromise } from '@tanstack/router-core'
2
- import type { StartSsrGlobal } from '@tanstack/start-client-core'
3
-
4
- const __TSR_SSR__: StartSsrGlobal = {
5
- matches: [],
6
- streamedValues: {},
7
- initMatch: (match) => {
8
- __TSR_SSR__.matches.push(match)
9
-
10
- match.extracted?.forEach((ex) => {
11
- if (ex.type === 'stream') {
12
- let controller
13
- ex.value = new ReadableStream({
14
- start(c) {
15
- controller = {
16
- enqueue: (chunk: unknown) => {
17
- try {
18
- c.enqueue(chunk)
19
- } catch {}
20
- },
21
- close: () => {
22
- try {
23
- c.close()
24
- } catch {}
25
- },
26
- }
27
- },
28
- })
29
- ex.value.controller = controller
30
- } else {
31
- let resolve: ControllablePromise['reject'] | undefined
32
- let reject: ControllablePromise['reject'] | undefined
33
-
34
- ex.value = new Promise((_resolve, _reject) => {
35
- reject = _reject
36
- resolve = _resolve
37
- }) as ControllablePromise
38
- ex.value.reject = reject!
39
- ex.value.resolve = resolve!
40
- }
41
- })
42
-
43
- return true
44
- },
45
- resolvePromise: ({ matchId, id, promiseState }) => {
46
- const match = __TSR_SSR__.matches.find((m) => m.id === matchId)
47
- if (match) {
48
- const ex = match.extracted?.[id]
49
- if (
50
- ex &&
51
- ex.type === 'promise' &&
52
- ex.value &&
53
- promiseState.status === 'success'
54
- ) {
55
- ex.value.resolve(promiseState.data)
56
- return true
57
- }
58
- }
59
- return false
60
- },
61
- injectChunk: ({ matchId, id, chunk }) => {
62
- const match = __TSR_SSR__.matches.find((m) => m.id === matchId)
63
-
64
- if (match) {
65
- const ex = match.extracted?.[id]
66
- if (ex && ex.type === 'stream' && ex.value?.controller) {
67
- ex.value.controller.enqueue(new TextEncoder().encode(chunk.toString()))
68
- return true
69
- }
70
- }
71
- return false
72
- },
73
- closeStream: ({ matchId, id }) => {
74
- const match = __TSR_SSR__.matches.find((m) => m.id === matchId)
75
- if (match) {
76
- const ex = match.extracted?.[id]
77
- if (ex && ex.type === 'stream' && ex.value?.controller) {
78
- ex.value.controller.close()
79
- return true
80
- }
81
- }
82
- return false
83
- },
84
- cleanScripts: () => {
85
- document.querySelectorAll('.tsr-once').forEach((el) => {
86
- el.remove()
87
- })
88
- },
89
- }
90
-
91
- window.__TSR_SSR__ = __TSR_SSR__
package/src/vite-env.d.ts DELETED
@@ -1,4 +0,0 @@
1
- declare module '*?script-string' {
2
- const content: string
3
- export default content
4
- }