@tanstack/start-server-core 1.167.2 → 1.167.3
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/esm/createStartHandler.d.ts +85 -5
- package/dist/esm/createStartHandler.js +16 -10
- package/dist/esm/createStartHandler.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/router-manifest.js.map +1 -1
- package/dist/esm/transformAssetUrls.d.ts +67 -20
- package/dist/esm/transformAssetUrls.js +98 -38
- package/dist/esm/transformAssetUrls.js.map +1 -1
- package/package.json +4 -4
- package/src/createStartHandler.ts +128 -21
- package/src/index.tsx +8 -0
- package/src/router-manifest.ts +7 -3
- package/src/transformAssetUrls.ts +277 -72
|
@@ -1,12 +1,39 @@
|
|
|
1
|
-
import { rootRouteId } from '@tanstack/router-core'
|
|
1
|
+
import { resolveManifestAssetLink, rootRouteId } from '@tanstack/router-core'
|
|
2
2
|
|
|
3
3
|
import type {
|
|
4
|
+
AssetCrossOrigin,
|
|
4
5
|
Awaitable,
|
|
5
6
|
Manifest,
|
|
7
|
+
ManifestAssetLink,
|
|
6
8
|
RouterManagedTag,
|
|
7
9
|
} from '@tanstack/router-core'
|
|
8
10
|
|
|
9
|
-
export type
|
|
11
|
+
export type { AssetCrossOrigin }
|
|
12
|
+
|
|
13
|
+
export type TransformAssetKind = 'modulepreload' | 'stylesheet' | 'clientEntry'
|
|
14
|
+
|
|
15
|
+
type TransformAssetsShorthandCrossOriginKind = Exclude<
|
|
16
|
+
TransformAssetKind,
|
|
17
|
+
'clientEntry'
|
|
18
|
+
>
|
|
19
|
+
|
|
20
|
+
export type AssetUrlType = TransformAssetKind
|
|
21
|
+
|
|
22
|
+
export interface TransformAssetsContext {
|
|
23
|
+
url: string
|
|
24
|
+
kind: TransformAssetKind
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type TransformAssetResult =
|
|
28
|
+
| string
|
|
29
|
+
| {
|
|
30
|
+
href: string
|
|
31
|
+
crossOrigin?: AssetCrossOrigin
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type TransformAssetsFn = (
|
|
35
|
+
context: TransformAssetsContext,
|
|
36
|
+
) => Awaitable<TransformAssetResult>
|
|
10
37
|
|
|
11
38
|
export interface TransformAssetUrlsContext {
|
|
12
39
|
url: string
|
|
@@ -41,6 +68,10 @@ export type CreateTransformAssetUrlsFn = (
|
|
|
41
68
|
ctx: CreateTransformAssetUrlsContext,
|
|
42
69
|
) => Awaitable<TransformAssetUrlsFn>
|
|
43
70
|
|
|
71
|
+
export type CreateTransformAssetsFn = (
|
|
72
|
+
ctx: CreateTransformAssetUrlsContext,
|
|
73
|
+
) => Awaitable<TransformAssetsFn>
|
|
74
|
+
|
|
44
75
|
type TransformAssetUrlsOptionsBase = {
|
|
45
76
|
/**
|
|
46
77
|
* Whether to cache the transformed manifest after the first request.
|
|
@@ -91,41 +122,132 @@ export type TransformAssetUrlsOptions =
|
|
|
91
122
|
transform?: never
|
|
92
123
|
})
|
|
93
124
|
|
|
125
|
+
export type TransformAssetsOptions =
|
|
126
|
+
| (TransformAssetUrlsOptionsBase & {
|
|
127
|
+
transform: string | TransformAssetsFn
|
|
128
|
+
createTransform?: never
|
|
129
|
+
})
|
|
130
|
+
| (TransformAssetUrlsOptionsBase & {
|
|
131
|
+
createTransform: CreateTransformAssetsFn
|
|
132
|
+
transform?: never
|
|
133
|
+
})
|
|
134
|
+
|
|
94
135
|
export type TransformAssetUrls =
|
|
95
136
|
| string
|
|
96
137
|
| TransformAssetUrlsFn
|
|
97
138
|
| TransformAssetUrlsOptions
|
|
98
139
|
|
|
99
|
-
|
|
140
|
+
/**
|
|
141
|
+
* Per-kind crossOrigin configuration for the object shorthand.
|
|
142
|
+
*
|
|
143
|
+
* Accepts either a single value applied to all asset kinds, or a per-kind
|
|
144
|
+
* record (matching `HeadContent`'s `assetCrossOrigin` shape):
|
|
145
|
+
*
|
|
146
|
+
* ```ts
|
|
147
|
+
* // All assets get the same value
|
|
148
|
+
* crossOrigin: 'anonymous'
|
|
149
|
+
*
|
|
150
|
+
* // Different values per kind
|
|
151
|
+
* crossOrigin: { modulepreload: 'anonymous', stylesheet: 'use-credentials' }
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
export type TransformAssetsCrossOriginConfig =
|
|
155
|
+
| AssetCrossOrigin
|
|
156
|
+
| Partial<Record<TransformAssetsShorthandCrossOriginKind, AssetCrossOrigin>>
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Object shorthand for `transformAssets`. Combines a URL prefix with optional
|
|
160
|
+
* per-asset `crossOrigin` without needing a callback:
|
|
161
|
+
*
|
|
162
|
+
* ```ts
|
|
163
|
+
* transformAssets: {
|
|
164
|
+
* prefix: 'https://cdn.example.com',
|
|
165
|
+
* crossOrigin: 'anonymous',
|
|
166
|
+
* }
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
export interface TransformAssetsObjectShorthand {
|
|
170
|
+
/** URL prefix prepended to every asset URL. */
|
|
171
|
+
prefix: string
|
|
172
|
+
/**
|
|
173
|
+
* Optional crossOrigin attribute applied to manifest-managed `<link>` assets.
|
|
174
|
+
*
|
|
175
|
+
* Accepts a single value or a per-kind record.
|
|
176
|
+
*/
|
|
177
|
+
crossOrigin?: TransformAssetsCrossOriginConfig
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export type TransformAssets =
|
|
181
|
+
| string
|
|
182
|
+
| TransformAssetsFn
|
|
183
|
+
| TransformAssetsObjectShorthand
|
|
184
|
+
| TransformAssetsOptions
|
|
185
|
+
|
|
186
|
+
export type ResolvedTransformAssetsConfig =
|
|
100
187
|
| {
|
|
101
188
|
type: 'transform'
|
|
102
|
-
transformFn:
|
|
189
|
+
transformFn: TransformAssetsFn
|
|
103
190
|
cache: boolean
|
|
104
191
|
}
|
|
105
192
|
| {
|
|
106
193
|
type: 'createTransform'
|
|
107
|
-
createTransform:
|
|
194
|
+
createTransform: CreateTransformAssetsFn
|
|
108
195
|
cache: boolean
|
|
109
196
|
}
|
|
110
197
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
198
|
+
let hasWarnedAboutDeprecatedTransformAssetUrls = false
|
|
199
|
+
|
|
200
|
+
export function warnDeprecatedTransformAssetUrls() {
|
|
201
|
+
if (
|
|
202
|
+
(process.env.NODE_ENV === 'development' ||
|
|
203
|
+
process.env.TSS_DEV_SERVER === 'true') &&
|
|
204
|
+
!hasWarnedAboutDeprecatedTransformAssetUrls
|
|
205
|
+
) {
|
|
206
|
+
hasWarnedAboutDeprecatedTransformAssetUrls = true
|
|
207
|
+
console.warn(
|
|
208
|
+
'[TanStack Start] `transformAssetUrls` is deprecated. Use `transformAssets` instead.',
|
|
209
|
+
)
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function normalizeTransformAssetResult(
|
|
214
|
+
result: TransformAssetResult,
|
|
215
|
+
): Exclude<TransformAssetResult, string> {
|
|
216
|
+
if (typeof result === 'string') {
|
|
217
|
+
return { href: result }
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return result
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function resolveTransformAssetsCrossOrigin(
|
|
224
|
+
config: TransformAssetsCrossOriginConfig | undefined,
|
|
225
|
+
kind: TransformAssetsShorthandCrossOriginKind,
|
|
226
|
+
): AssetCrossOrigin | undefined {
|
|
227
|
+
if (!config) return undefined
|
|
228
|
+
if (typeof config === 'string') return config
|
|
229
|
+
|
|
230
|
+
return config[kind]
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function isObjectShorthand(
|
|
234
|
+
transform: TransformAssetsObjectShorthand | TransformAssetsOptions,
|
|
235
|
+
): transform is TransformAssetsObjectShorthand {
|
|
236
|
+
return 'prefix' in transform
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export function resolveTransformAssetsConfig(
|
|
240
|
+
transform: TransformAssets,
|
|
241
|
+
): ResolvedTransformAssetsConfig {
|
|
119
242
|
if (typeof transform === 'string') {
|
|
120
243
|
const prefix = transform
|
|
121
244
|
return {
|
|
122
245
|
type: 'transform',
|
|
123
|
-
transformFn: ({ url }) => `${prefix}${url}
|
|
246
|
+
transformFn: ({ url }) => ({ href: `${prefix}${url}` }),
|
|
124
247
|
cache: true,
|
|
125
248
|
}
|
|
126
249
|
}
|
|
127
250
|
|
|
128
|
-
// Callback shorthand
|
|
129
251
|
if (typeof transform === 'function') {
|
|
130
252
|
return {
|
|
131
253
|
type: 'transform',
|
|
@@ -134,7 +256,26 @@ export function resolveTransformConfig(
|
|
|
134
256
|
}
|
|
135
257
|
}
|
|
136
258
|
|
|
137
|
-
//
|
|
259
|
+
// Object shorthand: { prefix, crossOrigin? }
|
|
260
|
+
if (isObjectShorthand(transform)) {
|
|
261
|
+
const { prefix, crossOrigin } = transform
|
|
262
|
+
|
|
263
|
+
return {
|
|
264
|
+
type: 'transform',
|
|
265
|
+
transformFn: ({ url, kind }) => {
|
|
266
|
+
const href = `${prefix}${url}`
|
|
267
|
+
|
|
268
|
+
if (kind === 'clientEntry') {
|
|
269
|
+
return { href }
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const co = resolveTransformAssetsCrossOrigin(crossOrigin, kind)
|
|
273
|
+
return co ? { href, crossOrigin: co } : { href }
|
|
274
|
+
},
|
|
275
|
+
cache: true,
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
138
279
|
if ('createTransform' in transform && transform.createTransform) {
|
|
139
280
|
return {
|
|
140
281
|
type: 'createTransform',
|
|
@@ -145,8 +286,9 @@ export function resolveTransformConfig(
|
|
|
145
286
|
|
|
146
287
|
const transformFn =
|
|
147
288
|
typeof transform.transform === 'string'
|
|
148
|
-
? ((({ url }:
|
|
149
|
-
`${transform.transform}${url}
|
|
289
|
+
? ((({ url }: TransformAssetsContext) => ({
|
|
290
|
+
href: `${transform.transform}${url}`,
|
|
291
|
+
})) as TransformAssetsFn)
|
|
150
292
|
: transform.transform
|
|
151
293
|
|
|
152
294
|
return {
|
|
@@ -156,6 +298,48 @@ export function resolveTransformConfig(
|
|
|
156
298
|
}
|
|
157
299
|
}
|
|
158
300
|
|
|
301
|
+
export function adaptTransformAssetUrlsToTransformAssets(
|
|
302
|
+
transformFn: TransformAssetUrlsFn,
|
|
303
|
+
): TransformAssetsFn {
|
|
304
|
+
return async ({ url, kind }) => ({
|
|
305
|
+
href: await transformFn({ url, type: kind }),
|
|
306
|
+
})
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export function adaptTransformAssetUrlsConfigToTransformAssets(
|
|
310
|
+
transform: TransformAssetUrls,
|
|
311
|
+
): TransformAssets {
|
|
312
|
+
warnDeprecatedTransformAssetUrls()
|
|
313
|
+
|
|
314
|
+
if (typeof transform === 'string') {
|
|
315
|
+
return transform
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (typeof transform === 'function') {
|
|
319
|
+
return adaptTransformAssetUrlsToTransformAssets(transform)
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if ('createTransform' in transform && transform.createTransform) {
|
|
323
|
+
return {
|
|
324
|
+
createTransform: async (ctx: CreateTransformAssetUrlsContext) =>
|
|
325
|
+
adaptTransformAssetUrlsToTransformAssets(
|
|
326
|
+
await transform.createTransform(ctx),
|
|
327
|
+
),
|
|
328
|
+
cache: transform.cache,
|
|
329
|
+
warmup: transform.warmup,
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
return {
|
|
334
|
+
transform:
|
|
335
|
+
typeof transform.transform === 'string'
|
|
336
|
+
? transform.transform
|
|
337
|
+
: adaptTransformAssetUrlsToTransformAssets(transform.transform),
|
|
338
|
+
cache: transform.cache,
|
|
339
|
+
warmup: transform.warmup,
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
159
343
|
export interface StartManifestWithClientEntry {
|
|
160
344
|
manifest: Manifest
|
|
161
345
|
clientEntry: string
|
|
@@ -186,72 +370,93 @@ export function buildClientEntryScriptTag(
|
|
|
186
370
|
}
|
|
187
371
|
}
|
|
188
372
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
373
|
+
function assignManifestAssetLink(
|
|
374
|
+
link: ManifestAssetLink,
|
|
375
|
+
next: { href: string; crossOrigin?: AssetCrossOrigin },
|
|
376
|
+
): ManifestAssetLink {
|
|
377
|
+
if (typeof link === 'string') {
|
|
378
|
+
return next.crossOrigin ? next : next.href
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
return next.crossOrigin ? next : { href: next.href }
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
export async function transformManifestAssets(
|
|
197
385
|
source: StartManifestWithClientEntry,
|
|
198
|
-
transformFn:
|
|
199
|
-
|
|
200
|
-
/** When true, clone the source manifest before mutating it. */
|
|
386
|
+
transformFn: TransformAssetsFn,
|
|
387
|
+
_opts?: {
|
|
201
388
|
clone?: boolean
|
|
202
389
|
},
|
|
203
390
|
): Promise<Manifest> {
|
|
204
|
-
|
|
205
|
-
const manifest = opts?.clone
|
|
206
|
-
? structuredClone(source.manifest)
|
|
207
|
-
: source.manifest
|
|
208
|
-
|
|
209
|
-
for (const route of Object.values(manifest.routes)) {
|
|
210
|
-
// Transform preload URLs (modulepreload)
|
|
211
|
-
if (route.preloads) {
|
|
212
|
-
route.preloads = await Promise.all(
|
|
213
|
-
route.preloads.map((url) =>
|
|
214
|
-
Promise.resolve(transformFn({ url, type: 'modulepreload' })),
|
|
215
|
-
),
|
|
216
|
-
)
|
|
217
|
-
}
|
|
391
|
+
const manifest = structuredClone(source.manifest)
|
|
218
392
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
)
|
|
393
|
+
for (const route of Object.values(manifest.routes)) {
|
|
394
|
+
if (route.preloads) {
|
|
395
|
+
route.preloads = await Promise.all(
|
|
396
|
+
route.preloads.map(async (link) => {
|
|
397
|
+
const resolved = resolveManifestAssetLink(link)
|
|
398
|
+
const result = normalizeTransformAssetResult(
|
|
399
|
+
await transformFn({
|
|
400
|
+
url: resolved.href,
|
|
401
|
+
kind: 'modulepreload',
|
|
402
|
+
}),
|
|
403
|
+
)
|
|
404
|
+
|
|
405
|
+
return assignManifestAssetLink(link, {
|
|
406
|
+
href: result.href,
|
|
407
|
+
crossOrigin: result.crossOrigin,
|
|
408
|
+
})
|
|
409
|
+
}),
|
|
410
|
+
)
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
if (route.assets) {
|
|
414
|
+
for (const asset of route.assets) {
|
|
415
|
+
if (asset.tag === 'link' && asset.attrs?.href) {
|
|
416
|
+
const rel = asset.attrs.rel
|
|
417
|
+
const relTokens = typeof rel === 'string' ? rel.split(/\s+/) : []
|
|
418
|
+
|
|
419
|
+
if (!relTokens.includes('stylesheet')) {
|
|
420
|
+
continue
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
const result = normalizeTransformAssetResult(
|
|
424
|
+
await transformFn({
|
|
425
|
+
url: asset.attrs.href,
|
|
426
|
+
kind: 'stylesheet',
|
|
427
|
+
}),
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
asset.attrs.href = result.href
|
|
431
|
+
if (result.crossOrigin) {
|
|
432
|
+
asset.attrs.crossOrigin = result.crossOrigin
|
|
433
|
+
} else {
|
|
434
|
+
delete asset.attrs.crossOrigin
|
|
229
435
|
}
|
|
230
436
|
}
|
|
231
437
|
}
|
|
232
438
|
}
|
|
439
|
+
}
|
|
233
440
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
)
|
|
441
|
+
const transformedClientEntry = normalizeTransformAssetResult(
|
|
442
|
+
await transformFn({
|
|
443
|
+
url: source.clientEntry,
|
|
444
|
+
kind: 'clientEntry',
|
|
445
|
+
}),
|
|
446
|
+
)
|
|
241
447
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
448
|
+
const rootRoute = manifest.routes[rootRouteId]
|
|
449
|
+
if (rootRoute) {
|
|
450
|
+
rootRoute.assets = rootRoute.assets || []
|
|
451
|
+
rootRoute.assets.push(
|
|
452
|
+
buildClientEntryScriptTag(
|
|
453
|
+
transformedClientEntry.href,
|
|
454
|
+
source.injectedHeadScripts,
|
|
455
|
+
),
|
|
456
|
+
)
|
|
457
|
+
}
|
|
252
458
|
|
|
253
|
-
|
|
254
|
-
})()
|
|
459
|
+
return manifest
|
|
255
460
|
}
|
|
256
461
|
|
|
257
462
|
/**
|