@tanstack/start-server-core 1.121.0-alpha.26 → 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
@@ -0,0 +1,335 @@
1
+ import { AsyncLocalStorage } from 'node:async_hooks'
2
+
3
+ import {
4
+ H3Event,
5
+ clearSession as h3_clearSession,
6
+ deleteCookie as h3_deleteCookie,
7
+ getRequestHost as h3_getRequestHost,
8
+ getRequestIP as h3_getRequestIP,
9
+ getRequestProtocol as h3_getRequestProtocol,
10
+ getRequestURL as h3_getRequestURL,
11
+ getSession as h3_getSession,
12
+ getValidatedQuery as h3_getValidatedQuery,
13
+ parseCookies as h3_parseCookies,
14
+ sanitizeStatusCode as h3_sanitizeStatusCode,
15
+ sanitizeStatusMessage as h3_sanitizeStatusMessage,
16
+ sealSession as h3_sealSession,
17
+ setCookie as h3_setCookie,
18
+ toResponse as h3_toResponse,
19
+ unsealSession as h3_unsealSession,
20
+ updateSession as h3_updateSession,
21
+ useSession as h3_useSession,
22
+ } from 'h3'
23
+ import type {
24
+ RequestHeaderMap,
25
+ RequestHeaderName,
26
+ ResponseHeaderMap,
27
+ ResponseHeaderName,
28
+ TypedHeaders,
29
+ } from 'fetchdts'
30
+
31
+ import type { CookieSerializeOptions } from 'cookie-es'
32
+ import type {
33
+ Session,
34
+ SessionConfig,
35
+ SessionData,
36
+ SessionManager,
37
+ SessionUpdate,
38
+ } from './session'
39
+ import type { StandardSchemaV1 } from '@standard-schema/spec'
40
+
41
+ interface StartEvent {
42
+ h3Event: H3Event
43
+ }
44
+ const eventStorage = new AsyncLocalStorage<StartEvent>()
45
+
46
+ export type RequestHandler = (request: Request) => Promise<Response> | Response
47
+
48
+ export type { ResponseHeaderName, RequestHeaderName }
49
+
50
+ export function requestHandler(handler: RequestHandler) {
51
+ return (request: Request): Promise<Response> | Response => {
52
+ const h3Event = new H3Event(request)
53
+
54
+ const response = eventStorage.run({ h3Event }, () => handler(request))
55
+ return h3_toResponse(response, h3Event)
56
+ }
57
+ }
58
+
59
+ function getH3Event() {
60
+ const event = eventStorage.getStore()
61
+ if (!event) {
62
+ throw new Error(
63
+ `No StartEvent found in AsyncLocalStorage. Make sure you are using the function within the server runtime.`,
64
+ )
65
+ }
66
+ return event.h3Event
67
+ }
68
+
69
+ export function getRequest(): Request {
70
+ const event = getH3Event()
71
+ return event.req
72
+ }
73
+
74
+ export function getRequestHeaders(): TypedHeaders<RequestHeaderMap> {
75
+ // TODO `as any` not needed when fetchdts is updated
76
+ return getH3Event().req.headers as any
77
+ }
78
+
79
+ export function getRequestHeader(name: RequestHeaderName): string | undefined {
80
+ return getRequestHeaders().get(name) || undefined
81
+ }
82
+
83
+ export function getRequestIP(opts?: {
84
+ /**
85
+ * Use the X-Forwarded-For HTTP header set by proxies.
86
+ *
87
+ * Note: Make sure that this header can be trusted (your application running behind a CDN or reverse proxy) before enabling.
88
+ */
89
+ xForwardedFor?: boolean
90
+ }) {
91
+ return h3_getRequestIP(getH3Event(), opts)
92
+ }
93
+
94
+ /**
95
+ * Get the request hostname.
96
+ *
97
+ * If `xForwardedHost` is `true`, it will use the `x-forwarded-host` header if it exists.
98
+ *
99
+ * If no host header is found, it will default to "localhost".
100
+ */
101
+ export function getRequestHost(opts?: { xForwardedHost?: boolean }) {
102
+ return h3_getRequestHost(getH3Event(), opts)
103
+ }
104
+
105
+ /**
106
+ * Get the full incoming request URL.
107
+ *
108
+ * If `xForwardedHost` is `true`, it will use the `x-forwarded-host` header if it exists.
109
+ *
110
+ * If `xForwardedProto` is `false`, it will not use the `x-forwarded-proto` header.
111
+ */
112
+ export function getRequestUrl(opts?: {
113
+ xForwardedHost?: boolean
114
+ xForwardedProto?: boolean
115
+ }) {
116
+ return h3_getRequestURL(getH3Event(), opts)
117
+ }
118
+
119
+ /**
120
+ * Get the request protocol.
121
+ *
122
+ * If `x-forwarded-proto` header is set to "https", it will return "https". You can disable this behavior by setting `xForwardedProto` to `false`.
123
+ *
124
+ * If protocol cannot be determined, it will default to "http".
125
+ */
126
+ export function getRequestProtocol(opts?: {
127
+ xForwardedProto?: boolean
128
+ }): 'http' | 'https' | (string & {}) {
129
+ return h3_getRequestProtocol(getH3Event(), opts)
130
+ }
131
+
132
+ export function setResponseHeaders(
133
+ headers: TypedHeaders<ResponseHeaderMap>,
134
+ ): void {
135
+ const event = getH3Event()
136
+ for (const [name, value] of Object.entries(headers)) {
137
+ event.res.headers.set(name, value)
138
+ }
139
+ }
140
+
141
+ export function getResponseHeaders(): TypedHeaders<ResponseHeaderMap> {
142
+ const event = getH3Event()
143
+ return Object.fromEntries(event.res.headers.entries()) as any
144
+ }
145
+
146
+ export function getResponseHeader(
147
+ name: ResponseHeaderName,
148
+ ): string | undefined {
149
+ const event = getH3Event()
150
+ return event.res.headers.get(name) || undefined
151
+ }
152
+
153
+ export function setResponseHeader(
154
+ name: ResponseHeaderName,
155
+ value: string | Array<string>,
156
+ ): void {
157
+ const event = getH3Event()
158
+ if (Array.isArray(value)) {
159
+ event.res.headers.delete(name)
160
+ for (const valueItem of value) {
161
+ event.res.headers.append(name, valueItem)
162
+ }
163
+ } else {
164
+ event.res.headers.set(name, value)
165
+ }
166
+ }
167
+ export function removeResponseHeader(name: ResponseHeaderName): void {
168
+ const event = getH3Event()
169
+ event.res.headers.delete(name)
170
+ }
171
+
172
+ export function clearResponseHeaders(
173
+ headerNames?: Array<ResponseHeaderName>,
174
+ ): void {
175
+ const event = getH3Event()
176
+ // If headerNames is provided, clear only those headers
177
+ if (headerNames && headerNames.length > 0) {
178
+ for (const name of headerNames) {
179
+ event.res.headers.delete(name)
180
+ }
181
+ // Otherwise, clear all headers
182
+ } else {
183
+ for (const name of event.res.headers.keys()) {
184
+ event.res.headers.delete(name)
185
+ }
186
+ }
187
+ }
188
+
189
+ export function getResponseStatus(): number {
190
+ return getH3Event().res.status || 200
191
+ }
192
+
193
+ export function setResponseStatus(code?: number, text?: string): void {
194
+ const event = getH3Event()
195
+ if (code) {
196
+ event.res.status = h3_sanitizeStatusCode(code, event.res.status)
197
+ }
198
+ if (text) {
199
+ event.res.statusText = h3_sanitizeStatusMessage(text)
200
+ }
201
+ }
202
+
203
+ /**
204
+ * Parse the request to get HTTP Cookie header string and return an object of all cookie name-value pairs.
205
+ * @returns Object of cookie name-value pairs
206
+ * ```ts
207
+ * const cookies = getCookies()
208
+ * ```
209
+ */
210
+ export function getCookies(): Record<string, string> {
211
+ const event = getH3Event()
212
+ return h3_parseCookies(event)
213
+ }
214
+
215
+ /**
216
+ * Get a cookie value by name.
217
+ * @param name Name of the cookie to get
218
+ * @returns {*} Value of the cookie (String or undefined)
219
+ * ```ts
220
+ * const authorization = getCookie('Authorization')
221
+ * ```
222
+ */
223
+ export function getCookie(name: string): string | undefined {
224
+ return getCookies()[name] || undefined
225
+ }
226
+
227
+ /**
228
+ * Set a cookie value by name.
229
+ * @param name Name of the cookie to set
230
+ * @param value Value of the cookie to set
231
+ * @param options {CookieSerializeOptions} Options for serializing the cookie
232
+ * ```ts
233
+ * setCookie('Authorization', '1234567')
234
+ * ```
235
+ */
236
+ export function setCookie(
237
+ name: string,
238
+ value: string,
239
+ options?: CookieSerializeOptions,
240
+ ): void {
241
+ const event = getH3Event()
242
+ h3_setCookie(event, name, value, options)
243
+ }
244
+
245
+ /**
246
+ * Remove a cookie by name.
247
+ * @param name Name of the cookie to delete
248
+ * @param serializeOptions {CookieSerializeOptions} Cookie options
249
+ * ```ts
250
+ * deleteCookie('SessionId')
251
+ * ```
252
+ */
253
+ export function deleteCookie(
254
+ name: string,
255
+ options?: CookieSerializeOptions,
256
+ ): void {
257
+ const event = getH3Event()
258
+ h3_deleteCookie(event, name, options)
259
+ }
260
+
261
+ function getDefaultSessionConfig(config: SessionConfig): SessionConfig {
262
+ return {
263
+ name: 'start',
264
+ ...config,
265
+ }
266
+ }
267
+
268
+ /**
269
+ * Create a session manager for the current request.
270
+ */
271
+ export function useSession<TSessionData extends SessionData = SessionData>(
272
+ config: SessionConfig,
273
+ ): Promise<SessionManager<TSessionData>> {
274
+ const event = getH3Event()
275
+ return h3_useSession(event, getDefaultSessionConfig(config))
276
+ }
277
+ /**
278
+ * Get the session for the current request
279
+ */
280
+ export function getSession<TSessionData extends SessionData = SessionData>(
281
+ config: SessionConfig,
282
+ ): Promise<Session<TSessionData>> {
283
+ const event = getH3Event()
284
+ return h3_getSession(event, getDefaultSessionConfig(config))
285
+ }
286
+
287
+ /**
288
+ * Update the session data for the current request.
289
+ */
290
+ export function updateSession<TSessionData extends SessionData = SessionData>(
291
+ config: SessionConfig,
292
+ update?: SessionUpdate<TSessionData>,
293
+ ): Promise<Session<TSessionData>> {
294
+ const event = getH3Event()
295
+ return h3_updateSession(event, getDefaultSessionConfig(config), update)
296
+ }
297
+
298
+ /**
299
+ * Encrypt and sign the session data for the current request.
300
+ */
301
+ export function sealSession(config: SessionConfig): Promise<string> {
302
+ const event = getH3Event()
303
+ return h3_sealSession(event, getDefaultSessionConfig(config))
304
+ }
305
+ /**
306
+ * Decrypt and verify the session data for the current request.
307
+ */
308
+ export function unsealSession(
309
+ config: SessionConfig,
310
+ sealed: string,
311
+ ): Promise<Partial<Session>> {
312
+ const event = getH3Event()
313
+ return h3_unsealSession(event, getDefaultSessionConfig(config), sealed)
314
+ }
315
+
316
+ /**
317
+ * Clear the session data for the current request.
318
+ */
319
+ export function clearSession(config: Partial<SessionConfig>): Promise<void> {
320
+ const event = getH3Event()
321
+ return h3_clearSession(event, { name: 'start', ...config })
322
+ }
323
+
324
+ // not public API
325
+ export function getResponse() {
326
+ const event = getH3Event()
327
+ return event._res
328
+ }
329
+
330
+ // not public API (yet)
331
+ export function getValidatedQuery<TSchema extends StandardSchemaV1>(
332
+ schema: StandardSchemaV1,
333
+ ): Promise<StandardSchemaV1.InferOutput<TSchema>> {
334
+ return h3_getValidatedQuery(getH3Event(), schema)
335
+ }
@@ -1,4 +1,4 @@
1
- import { joinPaths, rootRouteId } from '@tanstack/router-core'
1
+ import { rootRouteId } from '@tanstack/router-core'
2
2
  import { VIRTUAL_MODULES } from './virtual-modules'
3
3
  import { loadVirtualModule } from './loadVirtualModule'
4
4
 
@@ -19,45 +19,24 @@ export async function getStartManifest(opts: { basePath: string }) {
19
19
 
20
20
  rootRoute.assets = rootRoute.assets || []
21
21
 
22
- // Get the entry for the client
23
- // const ClientManifest = getManifest('client')
24
-
25
- // const importPath =
26
- // ClientManifest.inputs[ClientManifest.handler]?.output.path
27
- // if (!importPath) {
28
- // invariant(importPath, 'Could not find client entry in manifest')
29
- // }
30
-
31
- if (process.env.NODE_ENV === 'development' && !process.env.TSS_CLIENT_ENTRY) {
32
- throw new Error(
33
- 'tanstack/start-server-core: TSS_CLIENT_ENTRY must be defined in your environment for getStartManifest()',
22
+ let script = `import('${startManifest.clientEntry}')`
23
+ if (process.env.TSS_DEV_SERVER === 'true') {
24
+ const { injectedHeadScripts } = await loadVirtualModule(
25
+ VIRTUAL_MODULES.injectedHeadScripts,
34
26
  )
27
+ if (injectedHeadScripts) {
28
+ script = `${injectedHeadScripts + ';'}${script}`
29
+ }
35
30
  }
36
-
37
- if (process.env.NODE_ENV === 'development') {
38
- // Always fake that HMR is ready
39
- // const CLIENT_BASE = sanitizeBase(process.env.TSS_CLIENT_BASE || '')
40
-
41
- // if (!CLIENT_BASE) {
42
- // throw new Error(
43
- // 'tanstack/start-router-manifest: TSS_CLIENT_BASE must be defined in your environment for getFullRouterManifest()',
44
- // )
45
- // }
46
-
47
- const clientEntry = joinPaths([opts.basePath, process.env.TSS_CLIENT_ENTRY])
48
-
49
- const script = `${globalThis.TSS_INJECTED_HEAD_SCRIPTS ? globalThis.TSS_INJECTED_HEAD_SCRIPTS + '; ' : ''}import('${clientEntry}')`
50
-
51
- rootRoute.assets.push({
52
- tag: 'script',
53
- attrs: {
54
- type: 'module',
55
- suppressHydrationWarning: true,
56
- async: true,
57
- },
58
- children: script,
59
- })
60
- }
31
+ rootRoute.assets.push({
32
+ tag: 'script',
33
+ attrs: {
34
+ type: 'module',
35
+ suppressHydrationWarning: true,
36
+ async: true,
37
+ },
38
+ children: script,
39
+ })
61
40
 
62
41
  const manifest = {
63
42
  ...startManifest,
@@ -1,9 +1,9 @@
1
1
  import { isNotFound } from '@tanstack/router-core'
2
2
  import invariant from 'tiny-invariant'
3
3
  import { startSerializer } from '@tanstack/start-client-core'
4
- import { getEvent, getResponseStatus } from './h3'
5
4
  import { VIRTUAL_MODULES } from './virtual-modules'
6
5
  import { loadVirtualModule } from './loadVirtualModule'
6
+ import { getResponse } from './request-response'
7
7
 
8
8
  function sanitizeBase(base: string | undefined) {
9
9
  if (!base) {
@@ -55,8 +55,7 @@ export const handleServerAction = async ({ request }: { request: Request }) => {
55
55
  throw new Error('Server function info not found for ' + serverFnId)
56
56
  }
57
57
 
58
- const fnModule: undefined | { [key: string]: any } =
59
- await serverFnInfo.importer()
58
+ const fnModule = await serverFnInfo.importer()
60
59
 
61
60
  if (!fnModule) {
62
61
  console.info('serverFnInfo', serverFnInfo)
@@ -188,10 +187,12 @@ export const handleServerAction = async ({ request }: { request: Request }) => {
188
187
  return isNotFoundResponse(result)
189
188
  }
190
189
 
190
+ const response = getResponse()
191
191
  return new Response(
192
192
  result !== undefined ? startSerializer.stringify(result) : undefined,
193
193
  {
194
- status: getResponseStatus(getEvent()),
194
+ status: response?.status,
195
+ statusText: response?.statusText,
195
196
  headers: {
196
197
  'Content-Type': 'application/json',
197
198
  },
@@ -246,7 +247,7 @@ function isNotFoundResponse(error: any) {
246
247
  const { headers, ...rest } = error
247
248
 
248
249
  return new Response(JSON.stringify(rest), {
249
- status: 200,
250
+ status: 404,
250
251
  headers: {
251
252
  'Content-Type': 'application/json',
252
253
  ...(headers || {}),
@@ -42,10 +42,25 @@ export interface ServerRouteOptions<
42
42
  pathname: TFullPath
43
43
  originalIndex: number
44
44
  getParentRoute?: () => TParentRoute
45
- middleware: Constrain<TMiddlewares, ReadonlyArray<AnyRequestMiddleware>>
46
- methods: Record<
45
+ middleware?: Constrain<TMiddlewares, ReadonlyArray<AnyRequestMiddleware>>
46
+ methods?: Record<
47
47
  string,
48
- ServerRouteMethodHandlerFn<TParentRoute, TFullPath, TMiddlewares, any, any>
48
+ | ServerRouteMethodHandlerFn<
49
+ TParentRoute,
50
+ TFullPath,
51
+ TMiddlewares,
52
+ any,
53
+ any
54
+ >
55
+ | {
56
+ _options: ServerRouteMethodBuilderOptions<
57
+ TParentRoute,
58
+ TFullPath,
59
+ TMiddlewares,
60
+ unknown,
61
+ unknown
62
+ >
63
+ }
49
64
  >
50
65
  caseSensitive?: boolean
51
66
  }
@@ -70,6 +85,7 @@ export function createServerRoute<
70
85
  const options = __opts || {}
71
86
 
72
87
  const route: ServerRoute<TParentRoute, TId, TPath, TFullPath, TChildren> = {
88
+ isRoot: false as any,
73
89
  path: '' as TPath,
74
90
  id: '' as TId,
75
91
  fullPath: '' as TFullPath,
@@ -162,6 +178,7 @@ export function createServerRoute<
162
178
  route.id = id as TId
163
179
  route.fullPath = fullPath as TFullPath
164
180
  route.to = fullPath as TrimPathRight<TFullPath>
181
+ route.isRoot = isRoot as any
165
182
  },
166
183
 
167
184
  _addFileChildren: (children) => {
@@ -290,6 +307,7 @@ export interface ServerRouteWithTypes<
290
307
  TMiddlewares,
291
308
  TMethods
292
309
  >
310
+ isRoot: TParentRoute extends AnyServerRouteWithTypes ? true : false
293
311
  path: TPath
294
312
  id: TId
295
313
  fullPath: TFullPath
@@ -329,6 +347,7 @@ export interface ServerRouteTypes<
329
347
  TMiddlewares,
330
348
  TMethods,
331
349
  > {
350
+ isRoot: TParentRoute extends AnyServerRouteWithTypes ? true : false
332
351
  id: TId
333
352
  path: TPath
334
353
  fullPath: TFullPath
package/src/session.ts ADDED
@@ -0,0 +1,75 @@
1
+ // TODO discuss do we want to copy this interface into Start we well?
2
+ import type { CookieSerializeOptions } from 'cookie-es'
3
+
4
+ // TODO discuss do we want to copy this interface into Start as shown below?
5
+
6
+ /** Algorithm used for encryption and decryption. */
7
+ type EncryptionAlgorithm = 'aes-128-ctr' | 'aes-256-cbc'
8
+ /** Algorithm used for integrity verification. */
9
+ type IntegrityAlgorithm = 'sha256'
10
+ /** @internal */
11
+ type _Algorithm = EncryptionAlgorithm | IntegrityAlgorithm
12
+ /**
13
+ * Options for customizing the key derivation algorithm used to generate encryption and integrity verification keys as well as the algorithms and salt sizes used.
14
+ */
15
+ type SealOptions = Readonly<{
16
+ /** Encryption step options. */
17
+ encryption: SealOptionsSub<EncryptionAlgorithm>
18
+ /** Integrity step options. */
19
+ integrity: SealOptionsSub<IntegrityAlgorithm>
20
+ /* Sealed object lifetime in milliseconds where 0 means forever. Defaults to 0. */
21
+ ttl: number
22
+ /** Number of seconds of permitted clock skew for incoming expirations. Defaults to 60 seconds. */
23
+ timestampSkewSec: number
24
+ /**
25
+ * Local clock time offset, expressed in number of milliseconds (positive or negative). Defaults to 0.
26
+ */
27
+ localtimeOffsetMsec: number
28
+ }>
29
+ /** `seal()` method options. */
30
+ type SealOptionsSub<TAlgorithm extends _Algorithm = _Algorithm> = Readonly<{
31
+ /** The length of the salt (random buffer used to ensure that two identical objects will generate a different encrypted result). Defaults to 256. */
32
+ saltBits: number
33
+ /** The algorithm used. Defaults to 'aes-256-cbc' for encryption and 'sha256' for integrity. */
34
+ algorithm: TAlgorithm
35
+ /** The number of iterations used to derive a key from the password. Defaults to 1. */
36
+ iterations: number
37
+ /** Minimum password size. Defaults to 32. */
38
+ minPasswordlength: number
39
+ }>
40
+ /** Password secret string or buffer.*/
41
+
42
+ type SessionDataT = Record<string, any>
43
+ export type SessionData<T extends SessionDataT = SessionDataT> = Partial<T>
44
+ export interface Session<T extends SessionDataT = SessionDataT> {
45
+ id: string
46
+ createdAt: number
47
+ data: SessionData<T>
48
+ }
49
+
50
+ export type SessionUpdate<T extends SessionData = SessionData> =
51
+ | Partial<SessionData<T>>
52
+ | ((oldData: SessionData<T>) => Partial<SessionData<T>> | undefined)
53
+
54
+ export interface SessionManager<T extends SessionDataT = SessionDataT> {
55
+ readonly id: string | undefined
56
+ readonly data: SessionData<T>
57
+ update: (update: SessionUpdate<T>) => Promise<SessionManager<T>>
58
+ clear: () => Promise<SessionManager<T>>
59
+ }
60
+ export interface SessionConfig {
61
+ /** Private key used to encrypt session tokens */
62
+ password: string
63
+ /** Session expiration time in seconds */
64
+ maxAge?: number
65
+ /** default is 'start' */
66
+ name?: string
67
+ /** Default is secure, httpOnly, / */
68
+ cookie?: false | CookieSerializeOptions
69
+ /** Default is x-start-session / x-{name}-session */
70
+ sessionHeader?: false | string
71
+ seal?: SealOptions
72
+ crypto?: Crypto
73
+ /** Default is Crypto.randomUUID */
74
+ generateId?: () => string
75
+ }
@@ -1,18 +1,31 @@
1
1
  declare module 'tanstack-start-manifest:v' {
2
2
  import type { Manifest } from '@tanstack/router-core'
3
3
 
4
- export const tsrStartManifest: () => Manifest
4
+ export const tsrStartManifest: () => Manifest & { clientEntry: string }
5
5
  }
6
6
 
7
7
  declare module 'tanstack-start-route-tree:v' {
8
- import type { AnyServerRoute } from '@tanstack/start-server-core'
8
+ import type { AnyServerRouteWithTypes } from '@tanstack/start-server-core'
9
+ import type { AnyRoute } from '@tanstack/router-core'
9
10
 
10
- export const serverRouteTree: AnyServerRoute | undefined
11
+ export const routeTree: AnyRoute | undefined
12
+ export const serverRouteTree: AnyServerRouteWithTypes | undefined
11
13
  }
12
14
 
13
15
  declare module 'tanstack-start-server-fn-manifest:v' {
14
- import type { DirectiveFn } from '@tanstack/directive-functions-plugin'
16
+ const serverFnManifest: Record<
17
+ string,
18
+ {
19
+ importer: () => Promise<
20
+ Record<string, (...args: Array<any>) => Promise<any>> | undefined
21
+ >
22
+ functionName: string
23
+ }
24
+ >
15
25
 
16
- const serverFnManifest: Record<string, DirectiveFn>
17
26
  export default serverFnManifest
18
27
  }
28
+
29
+ declare module 'tanstack-start-injected-head-scripts:v' {
30
+ export const injectedHeadScripts: string | undefined
31
+ }
@@ -4,10 +4,12 @@ export const VIRTUAL_MODULES = {
4
4
  routeTree: 'tanstack-start-route-tree:v',
5
5
  startManifest: 'tanstack-start-manifest:v',
6
6
  serverFnManifest: 'tanstack-start-server-fn-manifest:v',
7
+ injectedHeadScripts: 'tanstack-start-injected-head-scripts:v',
7
8
  } as const
8
9
 
9
10
  export type VirtualModules = {
10
11
  [VIRTUAL_MODULES.routeTree]: typeof import('tanstack-start-route-tree:v')
11
12
  [VIRTUAL_MODULES.startManifest]: typeof import('tanstack-start-manifest:v')
12
13
  [VIRTUAL_MODULES.serverFnManifest]: typeof import('tanstack-start-server-fn-manifest:v')
14
+ [VIRTUAL_MODULES.injectedHeadScripts]: typeof import('tanstack-start-injected-head-scripts:v')
13
15
  }
@@ -1,50 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const history = require("@tanstack/history");
4
- const startClientCore = require("@tanstack/start-client-core");
5
- const ssrServer = require("./ssr-server.cjs");
6
- function createRequestHandler({
7
- createRouter,
8
- request,
9
- getRouterManifest
10
- }) {
11
- return async (cb) => {
12
- const router = createRouter();
13
- ssrServer.attachRouterServerSsrUtils(router, await (getRouterManifest == null ? void 0 : getRouterManifest()));
14
- const url = new URL(request.url, "http://localhost");
15
- const href = url.href.replace(url.origin, "");
16
- const history$1 = history.createMemoryHistory({
17
- initialEntries: [href]
18
- });
19
- router.update({
20
- history: history$1
21
- });
22
- await router.load();
23
- ssrServer.dehydrateRouter(router);
24
- const responseHeaders = getRequestHeaders({
25
- router
26
- });
27
- return cb({
28
- request,
29
- router,
30
- responseHeaders
31
- });
32
- };
33
- }
34
- function getRequestHeaders(opts) {
35
- let headers = startClientCore.mergeHeaders(
36
- {
37
- "Content-Type": "text/html; charset=UTF-8"
38
- },
39
- ...opts.router.state.matches.map((match) => {
40
- return match.headers;
41
- })
42
- );
43
- const { redirect } = opts.router.state;
44
- if (redirect) {
45
- headers = startClientCore.mergeHeaders(headers, redirect.headers);
46
- }
47
- return headers;
48
- }
49
- exports.createRequestHandler = createRequestHandler;
50
- //# sourceMappingURL=createRequestHandler.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"createRequestHandler.cjs","sources":["../../src/createRequestHandler.ts"],"sourcesContent":["import { createMemoryHistory } from '@tanstack/history'\nimport { mergeHeaders } from '@tanstack/start-client-core'\nimport { attachRouterServerSsrUtils, dehydrateRouter } from './ssr-server'\nimport type { HandlerCallback } from './handlerCallback'\nimport type { AnyRouter, Manifest } from '@tanstack/router-core'\n\nexport type RequestHandler<TRouter extends AnyRouter> = (\n cb: HandlerCallback<TRouter>,\n) => Promise<Response>\n\nexport function createRequestHandler<TRouter extends AnyRouter>({\n createRouter,\n request,\n getRouterManifest,\n}: {\n createRouter: () => TRouter\n request: Request\n getRouterManifest?: () => Manifest | Promise<Manifest>\n}): RequestHandler<TRouter> {\n return async (cb) => {\n const router = createRouter()\n\n attachRouterServerSsrUtils(router, await getRouterManifest?.())\n\n const url = new URL(request.url, 'http://localhost')\n\n const href = url.href.replace(url.origin, '')\n\n // Create a history for the router\n const history = createMemoryHistory({\n initialEntries: [href],\n })\n\n // Update the router with the history and context\n router.update({\n history,\n })\n\n await router.load()\n\n dehydrateRouter(router)\n\n const responseHeaders = getRequestHeaders({\n router,\n })\n\n return cb({\n request,\n router,\n responseHeaders,\n } as any)\n }\n}\n\nfunction getRequestHeaders(opts: { router: AnyRouter }): Headers {\n let headers = mergeHeaders(\n {\n 'Content-Type': 'text/html; charset=UTF-8',\n },\n ...opts.router.state.matches.map((match) => {\n return match.headers\n }),\n )\n\n // Handle Redirects\n const { redirect } = opts.router.state\n\n if (redirect) {\n headers = mergeHeaders(headers, redirect.headers)\n }\n\n return headers\n}\n"],"names":["attachRouterServerSsrUtils","history","createMemoryHistory","dehydrateRouter","mergeHeaders"],"mappings":";;;;;AAUO,SAAS,qBAAgD;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AACF,GAI4B;AAC1B,SAAO,OAAO,OAAO;AACnB,UAAM,SAAS,aAAa;AAEDA,yCAAA,QAAQ,OAAM,yDAAqB;AAE9D,UAAM,MAAM,IAAI,IAAI,QAAQ,KAAK,kBAAkB;AAEnD,UAAM,OAAO,IAAI,KAAK,QAAQ,IAAI,QAAQ,EAAE;AAG5C,UAAMC,YAAUC,QAAAA,oBAAoB;AAAA,MAClC,gBAAgB,CAAC,IAAI;AAAA,IAAA,CACtB;AAGD,WAAO,OAAO;AAAA,MACZD,SAAAA;AAAAA,IAAA,CACD;AAED,UAAM,OAAO,KAAK;AAElBE,cAAAA,gBAAgB,MAAM;AAEtB,UAAM,kBAAkB,kBAAkB;AAAA,MACxC;AAAA,IAAA,CACD;AAED,WAAO,GAAG;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IAAA,CACM;AAAA,EACV;AACF;AAEA,SAAS,kBAAkB,MAAsC;AAC/D,MAAI,UAAUC,gBAAA;AAAA,IACZ;AAAA,MACE,gBAAgB;AAAA,IAClB;AAAA,IACA,GAAG,KAAK,OAAO,MAAM,QAAQ,IAAI,CAAC,UAAU;AAC1C,aAAO,MAAM;AAAA,IACd,CAAA;AAAA,EACH;AAGA,QAAM,EAAE,SAAA,IAAa,KAAK,OAAO;AAEjC,MAAI,UAAU;AACF,cAAAA,gBAAA,aAAa,SAAS,SAAS,OAAO;AAAA,EAAA;AAG3C,SAAA;AACT;;"}