@tanstack/start-server-core 1.166.11 → 1.166.12
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/bin/intent.js +25 -0
- package/package.json +12 -5
- package/skills/start-server-core/SKILL.md +262 -0
package/bin/intent.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Auto-generated by @tanstack/intent setup
|
|
3
|
+
// Exposes the intent end-user CLI for consumers of this library.
|
|
4
|
+
// Commit this file, then add to your package.json:
|
|
5
|
+
// "bin": { "intent": "./bin/intent.js" }
|
|
6
|
+
try {
|
|
7
|
+
await import('@tanstack/intent/intent-library')
|
|
8
|
+
} catch (e) {
|
|
9
|
+
const isModuleNotFound =
|
|
10
|
+
e?.code === 'ERR_MODULE_NOT_FOUND' || e?.code === 'MODULE_NOT_FOUND'
|
|
11
|
+
const missingIntentLibrary =
|
|
12
|
+
typeof e?.message === 'string' && e.message.includes('@tanstack/intent')
|
|
13
|
+
|
|
14
|
+
if (isModuleNotFound && missingIntentLibrary) {
|
|
15
|
+
console.error('@tanstack/intent is not installed.')
|
|
16
|
+
console.error('')
|
|
17
|
+
console.error('Install it as a dev dependency:')
|
|
18
|
+
console.error(' npm add -D @tanstack/intent')
|
|
19
|
+
console.error('')
|
|
20
|
+
console.error('Or run directly:')
|
|
21
|
+
console.error(' npx @tanstack/intent@latest list')
|
|
22
|
+
process.exit(1)
|
|
23
|
+
}
|
|
24
|
+
throw e
|
|
25
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/start-server-core",
|
|
3
|
-
"version": "1.166.
|
|
3
|
+
"version": "1.166.12",
|
|
4
4
|
"description": "Modern and scalable routing for React applications",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -54,7 +54,10 @@
|
|
|
54
54
|
"sideEffects": false,
|
|
55
55
|
"files": [
|
|
56
56
|
"dist",
|
|
57
|
-
"src"
|
|
57
|
+
"src",
|
|
58
|
+
"skills",
|
|
59
|
+
"bin",
|
|
60
|
+
"!skills/_artifacts"
|
|
58
61
|
],
|
|
59
62
|
"engines": {
|
|
60
63
|
"node": ">=22.12.0"
|
|
@@ -64,16 +67,20 @@
|
|
|
64
67
|
"seroval": "^1.4.2",
|
|
65
68
|
"tiny-invariant": "^1.3.3",
|
|
66
69
|
"@tanstack/history": "1.161.6",
|
|
67
|
-
"@tanstack/router-core": "1.167.
|
|
68
|
-
"@tanstack/start-client-core": "1.166.
|
|
69
|
-
"@tanstack/start-storage-context": "1.166.
|
|
70
|
+
"@tanstack/router-core": "1.167.4",
|
|
71
|
+
"@tanstack/start-client-core": "1.166.12",
|
|
72
|
+
"@tanstack/start-storage-context": "1.166.12"
|
|
70
73
|
},
|
|
71
74
|
"devDependencies": {
|
|
72
75
|
"@standard-schema/spec": "^1.0.0",
|
|
76
|
+
"@tanstack/intent": "^0.0.14",
|
|
73
77
|
"cookie-es": "^2.0.0",
|
|
74
78
|
"fetchdts": "^0.1.6",
|
|
75
79
|
"vite": "*"
|
|
76
80
|
},
|
|
81
|
+
"bin": {
|
|
82
|
+
"intent": "./bin/intent.js"
|
|
83
|
+
},
|
|
77
84
|
"scripts": {
|
|
78
85
|
"clean": "rimraf ./dist && rimraf ./coverage",
|
|
79
86
|
"test": "pnpm test:eslint && pnpm test:types && pnpm test:build && pnpm test:unit",
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: start-server-core
|
|
3
|
+
description: >-
|
|
4
|
+
Server-side runtime for TanStack Start: createStartHandler,
|
|
5
|
+
request/response utilities (getRequest, setResponseHeader,
|
|
6
|
+
setCookie, getCookie, useSession), three-phase request handling,
|
|
7
|
+
AsyncLocalStorage context.
|
|
8
|
+
type: core
|
|
9
|
+
library: tanstack-start
|
|
10
|
+
library_version: '1.166.2'
|
|
11
|
+
sources:
|
|
12
|
+
- TanStack/router:packages/start-server-core/src
|
|
13
|
+
- TanStack/router:docs/start/framework/react/guide/server-entry-point.md
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# Start Server Core (`@tanstack/start-server-core`)
|
|
17
|
+
|
|
18
|
+
Server-side runtime for TanStack Start. Provides the request handler, request/response utilities, cookie management, and session management. All utilities are available anywhere in the call stack during a request via AsyncLocalStorage.
|
|
19
|
+
|
|
20
|
+
> **CRITICAL**: These utilities are SERVER-ONLY. Import them from `@tanstack/<framework>-start/server`, not from the main entry point. They throw if called outside a server request context.
|
|
21
|
+
>
|
|
22
|
+
> **CRITICAL**: Types are FULLY INFERRED. Never cast, never annotate inferred values.
|
|
23
|
+
|
|
24
|
+
## `createStartHandler`
|
|
25
|
+
|
|
26
|
+
Creates the main request handler that processes all incoming requests through three phases: server functions, server routes, then app SSR.
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
// src/server.ts
|
|
30
|
+
// Use @tanstack/<framework>-start for your framework (react, solid, vue)
|
|
31
|
+
import { createStartHandler } from '@tanstack/react-start/server'
|
|
32
|
+
import { defaultStreamHandler } from '@tanstack/react-start/server'
|
|
33
|
+
|
|
34
|
+
export default createStartHandler({
|
|
35
|
+
handler: defaultStreamHandler,
|
|
36
|
+
})
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
With asset URL transforms (CDN):
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
export default createStartHandler({
|
|
43
|
+
handler: defaultStreamHandler,
|
|
44
|
+
transformAssetUrls: 'https://cdn.example.com',
|
|
45
|
+
})
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Request Utilities
|
|
49
|
+
|
|
50
|
+
All imported from `@tanstack/<framework>-start/server`. Available anywhere during request handling — no parameter passing needed.
|
|
51
|
+
|
|
52
|
+
### Reading Request Data
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
// Use @tanstack/<framework>-start for your framework (react, solid, vue)
|
|
56
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
57
|
+
import {
|
|
58
|
+
getRequest,
|
|
59
|
+
getRequestHeaders,
|
|
60
|
+
getRequestHeader,
|
|
61
|
+
getRequestIP,
|
|
62
|
+
getRequestHost,
|
|
63
|
+
getRequestUrl,
|
|
64
|
+
getRequestProtocol,
|
|
65
|
+
} from '@tanstack/react-start/server'
|
|
66
|
+
|
|
67
|
+
const serverFn = createServerFn({ method: 'GET' }).handler(async () => {
|
|
68
|
+
const request = getRequest()
|
|
69
|
+
const headers = getRequestHeaders()
|
|
70
|
+
const auth = getRequestHeader('authorization')
|
|
71
|
+
const ip = getRequestIP({ xForwardedFor: true })
|
|
72
|
+
const host = getRequestHost()
|
|
73
|
+
const url = getRequestUrl()
|
|
74
|
+
const protocol = getRequestProtocol()
|
|
75
|
+
|
|
76
|
+
return { ip, host }
|
|
77
|
+
})
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Setting Response Data
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
// Use @tanstack/<framework>-start for your framework (react, solid, vue)
|
|
84
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
85
|
+
import {
|
|
86
|
+
setResponseHeader,
|
|
87
|
+
setResponseHeaders,
|
|
88
|
+
setResponseStatus,
|
|
89
|
+
getResponseHeaders,
|
|
90
|
+
getResponseHeader,
|
|
91
|
+
getResponseStatus,
|
|
92
|
+
removeResponseHeader,
|
|
93
|
+
clearResponseHeaders,
|
|
94
|
+
} from '@tanstack/react-start/server'
|
|
95
|
+
|
|
96
|
+
const serverFn = createServerFn({ method: 'POST' }).handler(async () => {
|
|
97
|
+
setResponseStatus(201)
|
|
98
|
+
setResponseHeader('x-custom', 'value')
|
|
99
|
+
setResponseHeaders({ 'cache-control': 'no-store' })
|
|
100
|
+
|
|
101
|
+
return { created: true }
|
|
102
|
+
})
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Cookie Management
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
// Use @tanstack/<framework>-start for your framework (react, solid, vue)
|
|
109
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
110
|
+
import {
|
|
111
|
+
getCookies,
|
|
112
|
+
getCookie,
|
|
113
|
+
setCookie,
|
|
114
|
+
deleteCookie,
|
|
115
|
+
} from '@tanstack/react-start/server'
|
|
116
|
+
|
|
117
|
+
const serverFn = createServerFn({ method: 'POST' }).handler(async () => {
|
|
118
|
+
const allCookies = getCookies()
|
|
119
|
+
const token = getCookie('session-token')
|
|
120
|
+
|
|
121
|
+
setCookie('preference', 'dark', {
|
|
122
|
+
httpOnly: true,
|
|
123
|
+
secure: true,
|
|
124
|
+
maxAge: 60 * 60 * 24 * 30, // 30 days
|
|
125
|
+
path: '/',
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
deleteCookie('old-cookie')
|
|
129
|
+
})
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Session Management
|
|
133
|
+
|
|
134
|
+
Encrypted sessions stored in cookies. Requires a password for encryption.
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
// Use @tanstack/<framework>-start for your framework (react, solid, vue)
|
|
138
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
139
|
+
import {
|
|
140
|
+
useSession,
|
|
141
|
+
getSession,
|
|
142
|
+
updateSession,
|
|
143
|
+
clearSession,
|
|
144
|
+
} from '@tanstack/react-start/server'
|
|
145
|
+
|
|
146
|
+
const sessionConfig = {
|
|
147
|
+
password: process.env.SESSION_SECRET!,
|
|
148
|
+
name: 'my-app-session',
|
|
149
|
+
maxAge: 60 * 60 * 24 * 7, // 7 days
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Full session manager
|
|
153
|
+
const getUser = createServerFn({ method: 'GET' }).handler(async () => {
|
|
154
|
+
const session = await useSession<{ userId: string }>(sessionConfig)
|
|
155
|
+
return session.data
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
// Update session
|
|
159
|
+
const login = createServerFn({ method: 'POST' })
|
|
160
|
+
.inputValidator((data: { userId: string }) => data)
|
|
161
|
+
.handler(async ({ data }) => {
|
|
162
|
+
await updateSession(sessionConfig, { userId: data.userId })
|
|
163
|
+
return { success: true }
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
// Clear session
|
|
167
|
+
const logout = createServerFn({ method: 'POST' }).handler(async () => {
|
|
168
|
+
await clearSession(sessionConfig)
|
|
169
|
+
return { success: true }
|
|
170
|
+
})
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Session Config
|
|
174
|
+
|
|
175
|
+
| Option | Type | Default | Description |
|
|
176
|
+
| ---------- | ------------------------ | ----------- | ----------------- |
|
|
177
|
+
| `password` | `string` | required | Encryption key |
|
|
178
|
+
| `name` | `string` | `'start'` | Cookie name |
|
|
179
|
+
| `maxAge` | `number` | `undefined` | Expiry in seconds |
|
|
180
|
+
| `cookie` | `false \| CookieOptions` | `undefined` | Cookie settings |
|
|
181
|
+
|
|
182
|
+
### Session Manager Methods
|
|
183
|
+
|
|
184
|
+
```ts
|
|
185
|
+
const session = await useSession<{ userId: string }>(config)
|
|
186
|
+
|
|
187
|
+
session.id // Session ID (string | undefined)
|
|
188
|
+
session.data // Session data (typed)
|
|
189
|
+
await session.update({ userId: '123' }) // Persist session data
|
|
190
|
+
await session.clear() // Clear session data
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Query Validation
|
|
194
|
+
|
|
195
|
+
Validate query string parameters using a Standard Schema:
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
// Use @tanstack/<framework>-start for your framework (react, solid, vue)
|
|
199
|
+
import { getValidatedQuery } from '@tanstack/react-start/server'
|
|
200
|
+
import { z } from 'zod'
|
|
201
|
+
|
|
202
|
+
const serverFn = createServerFn({ method: 'GET' }).handler(async () => {
|
|
203
|
+
const query = await getValidatedQuery(
|
|
204
|
+
z.object({
|
|
205
|
+
page: z.coerce.number().default(1),
|
|
206
|
+
limit: z.coerce.number().default(20),
|
|
207
|
+
}),
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
return { page: query.page }
|
|
211
|
+
})
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
> Note: `getValidatedQuery` accepts a Standard Schema validator, not a callback function.
|
|
215
|
+
|
|
216
|
+
## How Request Handling Works
|
|
217
|
+
|
|
218
|
+
`createStartHandler` processes requests in three phases:
|
|
219
|
+
|
|
220
|
+
1. **Server Function Dispatch** — If URL matches the server function prefix (`/_serverFn`), deserializes the payload, runs global request middleware, executes the server function, and returns the serialized result.
|
|
221
|
+
|
|
222
|
+
2. **Server Route Handler** — For non-server-function requests, matches the URL against routes with `server.handlers`. Runs route middleware, then the matched HTTP method handler. Handlers can return a `Response` or call `next()` to fall through to SSR.
|
|
223
|
+
|
|
224
|
+
3. **App Router SSR** — Loads all route loaders, dehydrates state for client hydration, and calls the handler callback (e.g., `defaultStreamHandler`) to render HTML.
|
|
225
|
+
|
|
226
|
+
## Common Mistakes
|
|
227
|
+
|
|
228
|
+
### 1. CRITICAL: Importing server utilities in client code
|
|
229
|
+
|
|
230
|
+
Server utilities use AsyncLocalStorage and only work during server request handling. Importing them in client code causes build errors or runtime crashes.
|
|
231
|
+
|
|
232
|
+
```ts
|
|
233
|
+
// WRONG — importing in a component file that runs on client
|
|
234
|
+
import { getCookie } from '@tanstack/react-start/server'
|
|
235
|
+
|
|
236
|
+
function MyComponent() {
|
|
237
|
+
const token = getCookie('auth') // crashes on client
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// CORRECT — use inside server functions only
|
|
241
|
+
// Use @tanstack/<framework>-start for your framework (react, solid, vue)
|
|
242
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
243
|
+
import { getCookie } from '@tanstack/react-start/server'
|
|
244
|
+
|
|
245
|
+
const getAuth = createServerFn({ method: 'GET' }).handler(async () => {
|
|
246
|
+
return getCookie('auth')
|
|
247
|
+
})
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### 2. HIGH: Forgetting session password for most session operations
|
|
251
|
+
|
|
252
|
+
`useSession`, `getSession`, `updateSession`, and `sealSession` all require a `password` field for encryption. Missing it throws at runtime. `clearSession` accepts `Partial<SessionConfig>`, so password is optional for clearing.
|
|
253
|
+
|
|
254
|
+
### 3. MEDIUM: Using session without HTTPS in production
|
|
255
|
+
|
|
256
|
+
Session cookies should use `secure: true` in production. The default cookie options may not enforce this.
|
|
257
|
+
|
|
258
|
+
## Cross-References
|
|
259
|
+
|
|
260
|
+
- [start-core/server-functions](../../../start-client-core/skills/start-core/server-functions/SKILL.md) — creating server functions that use these utilities
|
|
261
|
+
- [start-core/middleware](../../../start-client-core/skills/start-core/middleware/SKILL.md) — request middleware
|
|
262
|
+
- [start-core/server-routes](../../../start-client-core/skills/start-core/server-routes/SKILL.md) — server route handlers
|