@tanstack/start-plugin-core 1.167.17 → 1.167.19
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/config-context.d.ts +26 -0
- package/dist/esm/config-context.js +81 -0
- package/dist/esm/config-context.js.map +1 -0
- package/dist/esm/constants.d.ts +6 -1
- package/dist/esm/constants.js +3 -2
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/import-protection-plugin/extensionlessAbsoluteIdResolver.js +1 -1
- package/dist/esm/import-protection-plugin/plugin.js +1 -1
- package/dist/esm/import-protection-plugin/virtualModules.js +1 -1
- package/dist/esm/index.d.ts +5 -3
- package/dist/esm/index.js +3 -4
- package/dist/esm/planning.d.ts +40 -0
- package/dist/esm/planning.js +107 -0
- package/dist/esm/planning.js.map +1 -0
- package/dist/esm/schema.d.ts +3093 -44
- package/dist/esm/schema.js +5 -5
- package/dist/esm/schema.js.map +1 -1
- package/dist/esm/serialization-adapters-module.d.ts +17 -0
- package/dist/esm/serialization-adapters-module.js +39 -0
- package/dist/esm/serialization-adapters-module.js.map +1 -0
- package/dist/esm/{start-compiler-plugin → start-compiler}/compiler.d.ts +2 -3
- package/dist/esm/{start-compiler-plugin → start-compiler}/compiler.js +17 -16
- package/dist/esm/start-compiler/compiler.js.map +1 -0
- package/dist/esm/start-compiler/config.d.ts +4 -0
- package/dist/esm/start-compiler/config.js +54 -0
- package/dist/esm/start-compiler/config.js.map +1 -0
- package/dist/esm/{start-compiler-plugin → start-compiler}/handleClientOnlyJSX.js +1 -1
- package/dist/esm/start-compiler/handleClientOnlyJSX.js.map +1 -0
- package/dist/esm/{start-compiler-plugin → start-compiler}/handleCreateIsomorphicFn.js +1 -1
- package/dist/esm/start-compiler/handleCreateIsomorphicFn.js.map +1 -0
- package/dist/esm/{start-compiler-plugin → start-compiler}/handleCreateMiddleware.js +1 -1
- package/dist/esm/start-compiler/handleCreateMiddleware.js.map +1 -0
- package/dist/esm/{start-compiler-plugin → start-compiler}/handleCreateServerFn.js +6 -17
- package/dist/esm/start-compiler/handleCreateServerFn.js.map +1 -0
- package/dist/esm/{start-compiler-plugin → start-compiler}/handleEnvOnly.js +1 -1
- package/dist/esm/start-compiler/handleEnvOnly.js.map +1 -0
- package/dist/esm/start-compiler/host.d.ts +20 -0
- package/dist/esm/start-compiler/host.js +38 -0
- package/dist/esm/start-compiler/host.js.map +1 -0
- package/dist/esm/start-compiler/load-module.d.ts +14 -0
- package/dist/esm/start-compiler/load-module.js +18 -0
- package/dist/esm/start-compiler/load-module.js.map +1 -0
- package/dist/esm/start-compiler/server-fn-resolver-module.d.ts +8 -0
- package/dist/esm/start-compiler/server-fn-resolver-module.js +77 -0
- package/dist/esm/start-compiler/server-fn-resolver-module.js.map +1 -0
- package/dist/esm/{start-compiler-plugin → start-compiler}/types.d.ts +4 -0
- package/dist/esm/{start-compiler-plugin → start-compiler}/utils.js +1 -1
- package/dist/esm/start-compiler/utils.js.map +1 -0
- package/dist/esm/start-manifest-plugin/manifestBuilder.d.ts +16 -16
- package/dist/esm/start-manifest-plugin/manifestBuilder.js +14 -45
- package/dist/esm/start-manifest-plugin/manifestBuilder.js.map +1 -1
- package/dist/esm/start-router-plugin/route-tree-footer.d.ts +6 -0
- package/dist/esm/start-router-plugin/route-tree-footer.js +44 -0
- package/dist/esm/start-router-plugin/route-tree-footer.js.map +1 -0
- package/dist/esm/types.d.ts +44 -10
- package/dist/esm/{dev-server-plugin → vite/dev-server-plugin}/dev-styles.js +1 -1
- package/dist/esm/vite/dev-server-plugin/dev-styles.js.map +1 -0
- package/dist/esm/{dev-server-plugin → vite/dev-server-plugin}/extract-html-scripts.js +1 -1
- package/dist/esm/vite/dev-server-plugin/extract-html-scripts.js.map +1 -0
- package/dist/esm/vite/dev-server-plugin/plugin.d.ts +7 -0
- package/dist/esm/{dev-server-plugin → vite/dev-server-plugin}/plugin.js +5 -6
- package/dist/esm/vite/dev-server-plugin/plugin.js.map +1 -0
- package/dist/esm/{load-env-plugin → vite/load-env-plugin}/plugin.js +1 -1
- package/dist/esm/vite/load-env-plugin/plugin.js.map +1 -0
- package/dist/esm/{output-directory.js → vite/output-directory.js} +2 -2
- package/dist/esm/vite/output-directory.js.map +1 -0
- package/dist/esm/vite/planning.d.ts +105 -0
- package/dist/esm/vite/planning.js +116 -0
- package/dist/esm/vite/planning.js.map +1 -0
- package/dist/esm/vite/plugin.d.ts +4 -0
- package/dist/esm/vite/plugin.js +169 -0
- package/dist/esm/vite/plugin.js.map +1 -0
- package/dist/esm/vite/plugins.d.ts +17 -0
- package/dist/esm/vite/plugins.js +50 -0
- package/dist/esm/vite/plugins.js.map +1 -0
- package/dist/esm/{post-server-build.d.ts → vite/post-server-build.d.ts} +1 -1
- package/dist/esm/{post-server-build.js → vite/post-server-build.js} +4 -4
- package/dist/esm/vite/post-server-build.js.map +1 -0
- package/dist/esm/{prerender.d.ts → vite/prerender.d.ts} +1 -1
- package/dist/esm/{prerender.js → vite/prerender.js} +5 -10
- package/dist/esm/vite/prerender.js.map +1 -0
- package/dist/esm/{preview-server-plugin → vite/preview-server-plugin}/plugin.js +4 -4
- package/dist/esm/vite/preview-server-plugin/plugin.js.map +1 -0
- package/dist/esm/vite/schema.d.ts +3373 -0
- package/dist/esm/vite/schema.js +12 -0
- package/dist/esm/vite/schema.js.map +1 -0
- package/dist/esm/vite/serialization-adapters-plugin.d.ts +5 -0
- package/dist/esm/vite/serialization-adapters-plugin.js +42 -0
- package/dist/esm/vite/serialization-adapters-plugin.js.map +1 -0
- package/dist/esm/vite/start-compiler-plugin/module-specifier.d.ts +3 -0
- package/dist/esm/vite/start-compiler-plugin/module-specifier.js +19 -0
- package/dist/esm/vite/start-compiler-plugin/module-specifier.js.map +1 -0
- package/dist/esm/{start-compiler-plugin → vite/start-compiler-plugin}/plugin.d.ts +4 -3
- package/dist/esm/vite/start-compiler-plugin/plugin.js +202 -0
- package/dist/esm/vite/start-compiler-plugin/plugin.js.map +1 -0
- package/dist/esm/vite/start-manifest-plugin/normalized-client-build.d.ts +6 -0
- package/dist/esm/vite/start-manifest-plugin/normalized-client-build.js +81 -0
- package/dist/esm/vite/start-manifest-plugin/normalized-client-build.js.map +1 -0
- package/dist/esm/vite/start-manifest-plugin/plugin.d.ts +6 -0
- package/dist/esm/{start-manifest-plugin → vite/start-manifest-plugin}/plugin.js +14 -9
- package/dist/esm/vite/start-manifest-plugin/plugin.js.map +1 -0
- package/dist/esm/{start-router-plugin → vite/start-router-plugin}/plugin.d.ts +3 -2
- package/dist/esm/{start-router-plugin → vite/start-router-plugin}/plugin.js +14 -37
- package/dist/esm/vite/start-router-plugin/plugin.js.map +1 -0
- package/dist/esm/vite/types.d.ts +15 -0
- package/package.json +14 -3
- package/src/config-context.ts +138 -0
- package/src/constants.ts +7 -3
- package/src/index.ts +5 -5
- package/src/planning.ts +151 -0
- package/src/schema.ts +93 -93
- package/src/serialization-adapters-module.ts +82 -0
- package/src/{start-compiler-plugin → start-compiler}/compiler.ts +67 -61
- package/src/start-compiler/config.ts +73 -0
- package/src/{start-compiler-plugin → start-compiler}/handleCreateServerFn.ts +14 -41
- package/src/start-compiler/host.ts +80 -0
- package/src/start-compiler/load-module.ts +31 -0
- package/src/start-compiler/server-fn-resolver-module.ts +129 -0
- package/src/{start-compiler-plugin → start-compiler}/types.ts +5 -0
- package/src/start-manifest-plugin/manifestBuilder.ts +65 -107
- package/src/start-router-plugin/route-tree-footer.ts +99 -0
- package/src/types.ts +53 -10
- package/src/{dev-server-plugin → vite/dev-server-plugin}/plugin.ts +7 -6
- package/src/{output-directory.ts → vite/output-directory.ts} +2 -2
- package/src/vite/planning.ts +234 -0
- package/src/vite/plugin.ts +276 -0
- package/src/vite/plugins.ts +81 -0
- package/src/{post-server-build.ts → vite/post-server-build.ts} +4 -6
- package/src/{prerender.ts → vite/prerender.ts} +21 -46
- package/src/{preview-server-plugin → vite/preview-server-plugin}/plugin.ts +2 -2
- package/src/vite/schema.ts +30 -0
- package/src/vite/serialization-adapters-plugin.ts +69 -0
- package/src/vite/start-compiler-plugin/module-specifier.ts +31 -0
- package/src/vite/start-compiler-plugin/plugin.ts +345 -0
- package/src/vite/start-manifest-plugin/normalized-client-build.ts +131 -0
- package/src/{start-manifest-plugin → vite/start-manifest-plugin}/plugin.ts +21 -13
- package/src/{start-router-plugin → vite/start-router-plugin}/plugin.ts +14 -80
- package/src/vite/types.ts +18 -0
- package/dist/esm/dev-server-plugin/dev-styles.js.map +0 -1
- package/dist/esm/dev-server-plugin/extract-html-scripts.js.map +0 -1
- package/dist/esm/dev-server-plugin/plugin.d.ts +0 -6
- package/dist/esm/dev-server-plugin/plugin.js.map +0 -1
- package/dist/esm/load-env-plugin/plugin.js.map +0 -1
- package/dist/esm/output-directory.js.map +0 -1
- package/dist/esm/plugin.d.ts +0 -4
- package/dist/esm/plugin.js +0 -301
- package/dist/esm/plugin.js.map +0 -1
- package/dist/esm/post-server-build.js.map +0 -1
- package/dist/esm/prerender.js.map +0 -1
- package/dist/esm/preview-server-plugin/plugin.js.map +0 -1
- package/dist/esm/start-compiler-plugin/compiler.js.map +0 -1
- package/dist/esm/start-compiler-plugin/handleClientOnlyJSX.js.map +0 -1
- package/dist/esm/start-compiler-plugin/handleCreateIsomorphicFn.js.map +0 -1
- package/dist/esm/start-compiler-plugin/handleCreateMiddleware.js.map +0 -1
- package/dist/esm/start-compiler-plugin/handleCreateServerFn.js.map +0 -1
- package/dist/esm/start-compiler-plugin/handleEnvOnly.js.map +0 -1
- package/dist/esm/start-compiler-plugin/plugin.js +0 -297
- package/dist/esm/start-compiler-plugin/plugin.js.map +0 -1
- package/dist/esm/start-compiler-plugin/utils.js.map +0 -1
- package/dist/esm/start-manifest-plugin/plugin.d.ts +0 -6
- package/dist/esm/start-manifest-plugin/plugin.js.map +0 -1
- package/dist/esm/start-router-plugin/plugin.js.map +0 -1
- package/src/plugin.ts +0 -471
- package/src/start-compiler-plugin/plugin.ts +0 -478
- /package/dist/esm/{start-compiler-plugin → start-compiler}/handleClientOnlyJSX.d.ts +0 -0
- /package/dist/esm/{start-compiler-plugin → start-compiler}/handleCreateIsomorphicFn.d.ts +0 -0
- /package/dist/esm/{start-compiler-plugin → start-compiler}/handleCreateMiddleware.d.ts +0 -0
- /package/dist/esm/{start-compiler-plugin → start-compiler}/handleCreateServerFn.d.ts +0 -0
- /package/dist/esm/{start-compiler-plugin → start-compiler}/handleEnvOnly.d.ts +0 -0
- /package/dist/esm/{start-compiler-plugin → start-compiler}/utils.d.ts +0 -0
- /package/dist/esm/{dev-server-plugin → vite/dev-server-plugin}/dev-styles.d.ts +0 -0
- /package/dist/esm/{dev-server-plugin → vite/dev-server-plugin}/extract-html-scripts.d.ts +0 -0
- /package/dist/esm/{load-env-plugin → vite/load-env-plugin}/plugin.d.ts +0 -0
- /package/dist/esm/{output-directory.d.ts → vite/output-directory.d.ts} +0 -0
- /package/dist/esm/{preview-server-plugin → vite/preview-server-plugin}/plugin.d.ts +0 -0
- /package/src/{start-compiler-plugin → start-compiler}/handleClientOnlyJSX.ts +0 -0
- /package/src/{start-compiler-plugin → start-compiler}/handleCreateIsomorphicFn.ts +0 -0
- /package/src/{start-compiler-plugin → start-compiler}/handleCreateMiddleware.ts +0 -0
- /package/src/{start-compiler-plugin → start-compiler}/handleEnvOnly.ts +0 -0
- /package/src/{start-compiler-plugin → start-compiler}/utils.ts +0 -0
- /package/src/{dev-server-plugin → vite/dev-server-plugin}/dev-styles.ts +0 -0
- /package/src/{dev-server-plugin → vite/dev-server-plugin}/extract-html-scripts.ts +0 -0
- /package/src/{load-env-plugin → vite/load-env-plugin}/plugin.ts +0 -0
|
@@ -2,11 +2,11 @@ import { promises as fsp } from 'node:fs'
|
|
|
2
2
|
import os from 'node:os'
|
|
3
3
|
import path from 'pathe'
|
|
4
4
|
import { joinURL, withBase, withTrailingSlash, withoutBase } from 'ufo'
|
|
5
|
-
import { VITE_ENVIRONMENT_NAMES } from '
|
|
6
|
-
import { createLogger } from '
|
|
7
|
-
import { Queue } from '
|
|
5
|
+
import { VITE_ENVIRONMENT_NAMES } from '../constants'
|
|
6
|
+
import { createLogger } from '../utils'
|
|
7
|
+
import { Queue } from '../queue'
|
|
8
8
|
import type { PreviewServer, ResolvedConfig, ViteBuilder } from 'vite'
|
|
9
|
-
import type { Page, TanStackStartOutputConfig } from '
|
|
9
|
+
import type { Page, TanStackStartOutputConfig } from '../schema'
|
|
10
10
|
|
|
11
11
|
export async function prerender({
|
|
12
12
|
startConfig,
|
|
@@ -18,13 +18,10 @@ export async function prerender({
|
|
|
18
18
|
const logger = createLogger('prerender')
|
|
19
19
|
logger.info('Prerendering pages...')
|
|
20
20
|
|
|
21
|
-
// If prerender is enabled
|
|
22
21
|
if (startConfig.prerender?.enabled) {
|
|
23
|
-
// default to root page if no pages are defined
|
|
24
22
|
let pages = startConfig.pages.length ? startConfig.pages : [{ path: '/' }]
|
|
25
23
|
|
|
26
24
|
if (startConfig.prerender.autoStaticPathsDiscovery ?? true) {
|
|
27
|
-
// merge discovered static pages with user-defined pages
|
|
28
25
|
const pagesMap = new Map(pages.map((item) => [item.path, item]))
|
|
29
26
|
const discoveredPages = globalThis.TSS_PRERENDABLE_PATHS || []
|
|
30
27
|
|
|
@@ -43,7 +40,6 @@ export async function prerender({
|
|
|
43
40
|
const routerBasePath = joinURL('/', startConfig.router.basepath ?? '')
|
|
44
41
|
const routerBaseUrl = new URL(routerBasePath, 'http://localhost')
|
|
45
42
|
|
|
46
|
-
// Enforce that prerender page paths are relative/path-based (no protocol/host)
|
|
47
43
|
startConfig.pages = validateAndNormalizePrerenderPages(
|
|
48
44
|
startConfig.pages,
|
|
49
45
|
routerBaseUrl,
|
|
@@ -69,13 +65,13 @@ export async function prerender({
|
|
|
69
65
|
process.env.TSS_PRERENDERING = 'true'
|
|
70
66
|
process.env.TSS_CLIENT_OUTPUT_DIR = outputDir
|
|
71
67
|
|
|
72
|
-
// Start Vite preview server instead of importing module
|
|
73
68
|
const previewServer = await startPreviewServer(serverEnv.config)
|
|
74
69
|
const baseUrl = getResolvedUrl(previewServer)
|
|
75
70
|
|
|
76
71
|
const isRedirectResponse = (res: Response) => {
|
|
77
72
|
return res.status >= 300 && res.status < 400 && res.headers.get('location')
|
|
78
73
|
}
|
|
74
|
+
|
|
79
75
|
async function localFetch(
|
|
80
76
|
path: string,
|
|
81
77
|
options?: RequestInit,
|
|
@@ -90,16 +86,15 @@ export async function prerender({
|
|
|
90
86
|
if (location.startsWith('http://localhost') || location.startsWith('/')) {
|
|
91
87
|
const newUrl = location.replace('http://localhost', '')
|
|
92
88
|
return localFetch(newUrl, options, maxRedirects - 1)
|
|
93
|
-
} else {
|
|
94
|
-
logger.warn(`Skipping redirect to external location: ${location}`)
|
|
95
89
|
}
|
|
90
|
+
|
|
91
|
+
logger.warn(`Skipping redirect to external location: ${location}`)
|
|
96
92
|
}
|
|
97
93
|
|
|
98
94
|
return response
|
|
99
95
|
}
|
|
100
96
|
|
|
101
97
|
try {
|
|
102
|
-
// Crawl all pages
|
|
103
98
|
const pages = await prerenderPages({ outputDir })
|
|
104
99
|
|
|
105
100
|
logger.info(`Prerendered ${pages.length} pages:`)
|
|
@@ -115,7 +110,7 @@ export async function prerender({
|
|
|
115
110
|
function extractLinks(html: string): Array<string> {
|
|
116
111
|
const linkRegex = /<a[^>]+href=["']([^"']+)["'][^>]*>/g
|
|
117
112
|
const links: Array<string> = []
|
|
118
|
-
let match
|
|
113
|
+
let match: RegExpExecArray | null
|
|
119
114
|
|
|
120
115
|
while ((match = linkRegex.exec(html)) !== null) {
|
|
121
116
|
const href = match[1]
|
|
@@ -136,7 +131,6 @@ export async function prerender({
|
|
|
136
131
|
const queue = new Queue({ concurrency })
|
|
137
132
|
const routerBasePath = joinURL('/', startConfig.router.basepath ?? '')
|
|
138
133
|
|
|
139
|
-
// Normalize discovered pages and enforce path-only entries
|
|
140
134
|
const routerBaseUrl = new URL(routerBasePath, 'http://localhost')
|
|
141
135
|
startConfig.pages = validateAndNormalizePrerenderPages(
|
|
142
136
|
startConfig.pages,
|
|
@@ -155,36 +149,32 @@ export async function prerender({
|
|
|
155
149
|
return Array.from(prerendered)
|
|
156
150
|
|
|
157
151
|
function addCrawlPageTask(page: Page) {
|
|
158
|
-
// Was the page already seen?
|
|
159
152
|
if (seen.has(page.path)) return
|
|
160
153
|
|
|
161
|
-
// Add the page to the seen set
|
|
162
154
|
seen.add(page.path)
|
|
163
155
|
|
|
164
156
|
if (page.fromCrawl) {
|
|
165
157
|
startConfig.pages.push(page)
|
|
166
158
|
}
|
|
167
159
|
|
|
168
|
-
// If not enabled, skip
|
|
169
160
|
if (!(page.prerender?.enabled ?? true)) return
|
|
170
161
|
|
|
171
|
-
|
|
172
|
-
|
|
162
|
+
if (
|
|
163
|
+
startConfig.prerender?.filter &&
|
|
164
|
+
!startConfig.prerender.filter(page)
|
|
165
|
+
) {
|
|
173
166
|
return
|
|
167
|
+
}
|
|
174
168
|
|
|
175
|
-
// Resolve the merged default and page-specific prerender options
|
|
176
169
|
const prerenderOptions = {
|
|
177
170
|
...startConfig.prerender,
|
|
178
171
|
...page.prerender,
|
|
179
172
|
}
|
|
180
173
|
|
|
181
|
-
// Add the task
|
|
182
174
|
queue.add(async () => {
|
|
183
175
|
logger.info(`Crawling: ${page.path}`)
|
|
184
176
|
const retries = retriesByPath.get(page.path) || 0
|
|
185
177
|
try {
|
|
186
|
-
// Fetch the route
|
|
187
|
-
|
|
188
178
|
const res = await localFetch(
|
|
189
179
|
withTrailingSlash(withBase(page.path, routerBasePath)),
|
|
190
180
|
{
|
|
@@ -208,7 +198,6 @@ export async function prerender({
|
|
|
208
198
|
prerenderOptions.outputPath || page.path
|
|
209
199
|
).split(/[?#]/)[0]!
|
|
210
200
|
|
|
211
|
-
// Guess route type and populate fileName
|
|
212
201
|
const contentType = res.headers.get('content-type') || ''
|
|
213
202
|
const isImplicitHTML =
|
|
214
203
|
!cleanPagePath.endsWith('.html') && contentType.includes('html')
|
|
@@ -222,17 +211,14 @@ export async function prerender({
|
|
|
222
211
|
|
|
223
212
|
let htmlPath: string
|
|
224
213
|
if (isSpaShell) {
|
|
225
|
-
// For SPA shell, ignore autoSubfolderIndex option
|
|
226
214
|
htmlPath = cleanPagePath + '.html'
|
|
215
|
+
} else if (
|
|
216
|
+
cleanPagePath.endsWith('/') ||
|
|
217
|
+
(prerenderOptions.autoSubfolderIndex ?? true)
|
|
218
|
+
) {
|
|
219
|
+
htmlPath = joinURL(cleanPagePath, 'index.html')
|
|
227
220
|
} else {
|
|
228
|
-
|
|
229
|
-
cleanPagePath.endsWith('/') ||
|
|
230
|
-
(prerenderOptions.autoSubfolderIndex ?? true)
|
|
231
|
-
) {
|
|
232
|
-
htmlPath = joinURL(cleanPagePath, 'index.html')
|
|
233
|
-
} else {
|
|
234
|
-
htmlPath = cleanPagePath + '.html'
|
|
235
|
-
}
|
|
221
|
+
htmlPath = cleanPagePath + '.html'
|
|
236
222
|
}
|
|
237
223
|
|
|
238
224
|
const filename = withoutBase(
|
|
@@ -258,7 +244,6 @@ export async function prerender({
|
|
|
258
244
|
Object.assign(page, newPage)
|
|
259
245
|
}
|
|
260
246
|
|
|
261
|
-
// Find new links
|
|
262
247
|
if (prerenderOptions.crawlLinks ?? true) {
|
|
263
248
|
const links = extractLinks(html)
|
|
264
249
|
for (const link of links) {
|
|
@@ -273,10 +258,8 @@ export async function prerender({
|
|
|
273
258
|
)
|
|
274
259
|
retriesByPath.set(page.path, retries + 1)
|
|
275
260
|
addCrawlPageTask(page)
|
|
276
|
-
} else {
|
|
277
|
-
|
|
278
|
-
throw error
|
|
279
|
-
}
|
|
261
|
+
} else if (prerenderOptions.failOnError ?? true) {
|
|
262
|
+
throw error
|
|
280
263
|
}
|
|
281
264
|
}
|
|
282
265
|
})
|
|
@@ -317,11 +300,6 @@ function getResolvedUrl(previewServer: PreviewServer): URL {
|
|
|
317
300
|
return new URL(baseUrl)
|
|
318
301
|
}
|
|
319
302
|
|
|
320
|
-
/**
|
|
321
|
-
* Validates and normalizes prerender page paths to ensure they are relative
|
|
322
|
-
* (no protocol/host) and returns normalized Page objects with cleaned paths.
|
|
323
|
-
* Preserves unicode characters by decoding the pathname after URL validation.
|
|
324
|
-
*/
|
|
325
303
|
function validateAndNormalizePrerenderPages(
|
|
326
304
|
pages: Array<Page>,
|
|
327
305
|
routerBaseUrl: URL,
|
|
@@ -340,9 +318,6 @@ function validateAndNormalizePrerenderPages(
|
|
|
340
318
|
throw new Error(`prerender page path must be relative: ${page.path}`)
|
|
341
319
|
}
|
|
342
320
|
|
|
343
|
-
// Decode the pathname to preserve unicode characters (e.g., /대한민국)
|
|
344
|
-
// The URL constructor encodes non-ASCII characters, but we want to keep
|
|
345
|
-
// the original unicode form for filesystem paths
|
|
346
321
|
const decodedPathname = decodeURIComponent(url.pathname)
|
|
347
322
|
|
|
348
323
|
return {
|
|
@@ -2,9 +2,9 @@ import { pathToFileURL } from 'node:url'
|
|
|
2
2
|
import { basename, extname, join } from 'pathe'
|
|
3
3
|
import { NodeRequest, sendNodeResponse } from 'srvx/node'
|
|
4
4
|
import { joinURL } from 'ufo'
|
|
5
|
-
import { VITE_ENVIRONMENT_NAMES } from '
|
|
5
|
+
import { VITE_ENVIRONMENT_NAMES } from '../../constants'
|
|
6
6
|
import { getServerOutputDirectory } from '../output-directory'
|
|
7
|
-
import { getBundlerOptions } from '
|
|
7
|
+
import { getBundlerOptions } from '../../utils'
|
|
8
8
|
import type { Plugin } from 'vite'
|
|
9
9
|
|
|
10
10
|
export function previewServerPlugin(): Plugin {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import {
|
|
3
|
+
parseStartConfig as parseCoreStartConfig,
|
|
4
|
+
tanstackStartOptionsObjectSchema,
|
|
5
|
+
} from '../schema'
|
|
6
|
+
import type { CompileStartFrameworkOptions } from '../types'
|
|
7
|
+
|
|
8
|
+
export const tanstackStartViteOptionsSchema = tanstackStartOptionsObjectSchema
|
|
9
|
+
.extend({
|
|
10
|
+
vite: z
|
|
11
|
+
.object({ installDevServerMiddleware: z.boolean().optional() })
|
|
12
|
+
.optional(),
|
|
13
|
+
})
|
|
14
|
+
.optional()
|
|
15
|
+
.default({})
|
|
16
|
+
|
|
17
|
+
export function parseStartConfig(
|
|
18
|
+
opts: z.input<typeof tanstackStartViteOptionsSchema>,
|
|
19
|
+
corePluginOpts: { framework: CompileStartFrameworkOptions },
|
|
20
|
+
root: string,
|
|
21
|
+
) {
|
|
22
|
+
const { vite: _vite, ...coreOptions } =
|
|
23
|
+
tanstackStartViteOptionsSchema.parse(opts)
|
|
24
|
+
|
|
25
|
+
return parseCoreStartConfig(coreOptions, corePluginOpts, root)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type TanStackStartViteInputConfig = z.input<
|
|
29
|
+
typeof tanstackStartViteOptionsSchema
|
|
30
|
+
>
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { VIRTUAL_MODULES } from '@tanstack/start-server-core'
|
|
2
|
+
import {
|
|
3
|
+
EMPTY_SERIALIZATION_ADAPTERS_MODULE,
|
|
4
|
+
generateSerializationAdaptersModule,
|
|
5
|
+
} from '../serialization-adapters-module'
|
|
6
|
+
import { START_ENVIRONMENT_NAMES } from '../constants'
|
|
7
|
+
import { resolveViteId } from '../utils'
|
|
8
|
+
import type { SerializationAdapterConfig } from '../types'
|
|
9
|
+
import type { PluginOption } from 'vite'
|
|
10
|
+
|
|
11
|
+
// Encode '#' as '%23' in the resolved ID to avoid browser treating it as URL fragment.
|
|
12
|
+
// The browser requests /@id/__x00__%23tanstack-start-plugin-adapters instead of
|
|
13
|
+
// /@id/__x00__#tanstack-start-plugin-adapters (which would truncate at #).
|
|
14
|
+
const resolvedModuleId = resolveViteId(
|
|
15
|
+
VIRTUAL_MODULES.pluginAdapters.replace('#', '%23'),
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
function escapeRegex(str: string): string {
|
|
19
|
+
return str.replace(/[.*+?^${}()|[\]\\#]/g, '\\$&')
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function serializationAdaptersPlugin(opts: {
|
|
23
|
+
adapters: Array<SerializationAdapterConfig> | undefined
|
|
24
|
+
}): PluginOption {
|
|
25
|
+
return {
|
|
26
|
+
name: 'tanstack-start:plugin-adapters',
|
|
27
|
+
enforce: 'pre',
|
|
28
|
+
resolveId: {
|
|
29
|
+
filter: { id: new RegExp(escapeRegex(VIRTUAL_MODULES.pluginAdapters)) },
|
|
30
|
+
handler(id: string) {
|
|
31
|
+
if (id === VIRTUAL_MODULES.pluginAdapters) {
|
|
32
|
+
return resolvedModuleId
|
|
33
|
+
}
|
|
34
|
+
return undefined
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
load: {
|
|
38
|
+
filter: {
|
|
39
|
+
id: new RegExp(escapeRegex(resolvedModuleId)),
|
|
40
|
+
},
|
|
41
|
+
handler(this: { environment: { name: string } }, id: string) {
|
|
42
|
+
if (id !== resolvedModuleId) {
|
|
43
|
+
return undefined
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const adapters = opts.adapters
|
|
47
|
+
if (!adapters || adapters.length === 0) {
|
|
48
|
+
return EMPTY_SERIALIZATION_ADAPTERS_MODULE
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (this.environment.name === START_ENVIRONMENT_NAMES.client) {
|
|
52
|
+
return generateSerializationAdaptersModule({
|
|
53
|
+
adapters,
|
|
54
|
+
runtime: 'client',
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (this.environment.name === START_ENVIRONMENT_NAMES.server) {
|
|
59
|
+
return generateSerializationAdaptersModule({
|
|
60
|
+
adapters,
|
|
61
|
+
runtime: 'server',
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return EMPTY_SERIALIZATION_ADAPTERS_MODULE
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { DevServerFnModuleSpecifierEncoder } from '../../start-compiler/types'
|
|
2
|
+
|
|
3
|
+
export function createViteDevServerFnModuleSpecifierEncoder(
|
|
4
|
+
root: string,
|
|
5
|
+
): DevServerFnModuleSpecifierEncoder {
|
|
6
|
+
const rootWithTrailingSlash = root.endsWith('/') ? root : `${root}/`
|
|
7
|
+
|
|
8
|
+
return ({ extractedFilename }) => {
|
|
9
|
+
let file = extractedFilename
|
|
10
|
+
|
|
11
|
+
if (file.startsWith(rootWithTrailingSlash)) {
|
|
12
|
+
file = file.slice(rootWithTrailingSlash.length)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return `/@id/${file}`
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function decodeViteDevServerModuleSpecifier(
|
|
20
|
+
moduleSpecifier: string,
|
|
21
|
+
): string {
|
|
22
|
+
let sourceFile = moduleSpecifier
|
|
23
|
+
|
|
24
|
+
if (sourceFile.startsWith('/@id/')) {
|
|
25
|
+
sourceFile = sourceFile.slice('/@id/'.length)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const queryIndex = sourceFile.indexOf('?')
|
|
29
|
+
|
|
30
|
+
return queryIndex === -1 ? sourceFile : sourceFile.slice(0, queryIndex)
|
|
31
|
+
}
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import assert from 'node:assert'
|
|
2
|
+
import { VIRTUAL_MODULES } from '@tanstack/start-server-core'
|
|
3
|
+
import { resolve as resolvePath } from 'pathe'
|
|
4
|
+
import {
|
|
5
|
+
SERVER_FN_LOOKUP,
|
|
6
|
+
TRANSFORM_ID_REGEX,
|
|
7
|
+
VITE_ENVIRONMENT_NAMES,
|
|
8
|
+
} from '../../constants'
|
|
9
|
+
import { detectKindsInCode } from '../../start-compiler/compiler'
|
|
10
|
+
import { getTransformCodeFilterForEnv } from '../../start-compiler/config'
|
|
11
|
+
import {
|
|
12
|
+
createStartCompiler,
|
|
13
|
+
mergeServerFnsById,
|
|
14
|
+
} from '../../start-compiler/host'
|
|
15
|
+
import { loadModuleForViteCompiler } from '../../start-compiler/load-module'
|
|
16
|
+
import { generateServerFnResolverModule } from '../../start-compiler/server-fn-resolver-module'
|
|
17
|
+
import { cleanId } from '../../start-compiler/utils'
|
|
18
|
+
import {
|
|
19
|
+
createViteDevServerFnModuleSpecifierEncoder,
|
|
20
|
+
decodeViteDevServerModuleSpecifier,
|
|
21
|
+
} from './module-specifier'
|
|
22
|
+
import type { CompileStartFrameworkOptions } from '../../types'
|
|
23
|
+
import type {
|
|
24
|
+
GenerateFunctionIdFnOptional,
|
|
25
|
+
ServerFn,
|
|
26
|
+
} from '../../start-compiler/types'
|
|
27
|
+
import type { PluginOption } from 'vite'
|
|
28
|
+
|
|
29
|
+
// Re-export from shared constants for backwards compatibility
|
|
30
|
+
export { SERVER_FN_LOOKUP }
|
|
31
|
+
|
|
32
|
+
function resolveViteId(id: string) {
|
|
33
|
+
return `\0${id}`
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const validateServerFnIdVirtualModule = `virtual:tanstack-start-validate-server-fn-id`
|
|
37
|
+
|
|
38
|
+
function getDevServerFnValidatorModule(): string {
|
|
39
|
+
return `
|
|
40
|
+
export async function getServerFnById(id, _access) {
|
|
41
|
+
const validateIdImport = ${JSON.stringify(validateServerFnIdVirtualModule)} + '?id=' + id
|
|
42
|
+
await import(/* @vite-ignore */ '/@id/__x00__' + validateIdImport)
|
|
43
|
+
const decoded = Buffer.from(id, 'base64url').toString('utf8')
|
|
44
|
+
const devServerFn = JSON.parse(decoded)
|
|
45
|
+
const mod = await import(/* @vite-ignore */ devServerFn.file)
|
|
46
|
+
return mod[devServerFn.export]
|
|
47
|
+
}
|
|
48
|
+
`
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function parseIdQuery(id: string): {
|
|
52
|
+
filename: string
|
|
53
|
+
query: {
|
|
54
|
+
[k: string]: string
|
|
55
|
+
}
|
|
56
|
+
} {
|
|
57
|
+
if (!id.includes('?')) return { filename: id, query: {} }
|
|
58
|
+
const [filename, rawQuery] = id.split(`?`, 2) as [string, string]
|
|
59
|
+
const query = Object.fromEntries(new URLSearchParams(rawQuery))
|
|
60
|
+
return { filename, query }
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface StartCompilerPluginOptions {
|
|
64
|
+
framework: CompileStartFrameworkOptions
|
|
65
|
+
environments: Array<{
|
|
66
|
+
name: string
|
|
67
|
+
type: 'client' | 'server'
|
|
68
|
+
getServerFnById?: string
|
|
69
|
+
}>
|
|
70
|
+
/**
|
|
71
|
+
* Custom function ID generator (optional).
|
|
72
|
+
*/
|
|
73
|
+
generateFunctionId?: GenerateFunctionIdFnOptional
|
|
74
|
+
/**
|
|
75
|
+
* The Vite environment name for the server function provider.
|
|
76
|
+
*/
|
|
77
|
+
providerEnvName: string
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function startCompilerPlugin(
|
|
81
|
+
opts: StartCompilerPluginOptions,
|
|
82
|
+
): PluginOption {
|
|
83
|
+
const compilers = new Map<string, ReturnType<typeof createStartCompiler>>()
|
|
84
|
+
|
|
85
|
+
// Shared registry of server functions across all environments
|
|
86
|
+
const serverFnsById: Record<string, ServerFn> = {}
|
|
87
|
+
|
|
88
|
+
const onServerFnsById = (d: Record<string, ServerFn>) => {
|
|
89
|
+
mergeServerFnsById(serverFnsById, d)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
let root = process.cwd()
|
|
93
|
+
const resolvedResolverVirtualImportId = resolveViteId(
|
|
94
|
+
VIRTUAL_MODULES.serverFnResolver,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
// Determine which environments need the resolver (getServerFnById)
|
|
98
|
+
// SSR environment always needs the resolver for server-side calls
|
|
99
|
+
// Provider environment needs it for the actual implementation
|
|
100
|
+
const ssrEnvName = VITE_ENVIRONMENT_NAMES.server
|
|
101
|
+
|
|
102
|
+
// SSR is the provider when the provider environment is the default server environment
|
|
103
|
+
const ssrIsProvider = opts.providerEnvName === ssrEnvName
|
|
104
|
+
|
|
105
|
+
// Environments that need the resolver: SSR (for server calls) and provider (for implementation)
|
|
106
|
+
const appliedResolverEnvironments = new Set(
|
|
107
|
+
ssrIsProvider ? [opts.providerEnvName] : [ssrEnvName, opts.providerEnvName],
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
function perEnvServerFnPlugin(environment: {
|
|
111
|
+
name: string
|
|
112
|
+
type: 'client' | 'server'
|
|
113
|
+
}): PluginOption {
|
|
114
|
+
// Derive transform code filter from KindDetectionPatterns (single source of truth)
|
|
115
|
+
const transformCodeFilter = getTransformCodeFilterForEnv(environment.type)
|
|
116
|
+
return {
|
|
117
|
+
name: `tanstack-start-core::server-fn:${environment.name}`,
|
|
118
|
+
enforce: 'pre',
|
|
119
|
+
applyToEnvironment(env) {
|
|
120
|
+
return env.name === environment.name
|
|
121
|
+
},
|
|
122
|
+
configResolved(config) {
|
|
123
|
+
root = config.root
|
|
124
|
+
},
|
|
125
|
+
transform: {
|
|
126
|
+
filter: {
|
|
127
|
+
id: {
|
|
128
|
+
exclude: new RegExp(`${SERVER_FN_LOOKUP}$`),
|
|
129
|
+
include: TRANSFORM_ID_REGEX,
|
|
130
|
+
},
|
|
131
|
+
code: {
|
|
132
|
+
include: transformCodeFilter,
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
async handler(code, id) {
|
|
136
|
+
let compiler = compilers.get(this.environment.name)
|
|
137
|
+
|
|
138
|
+
if (!compiler) {
|
|
139
|
+
// Default to 'dev' mode for unknown environments (conservative: no caching)
|
|
140
|
+
const mode = this.environment.mode === 'build' ? 'build' : 'dev'
|
|
141
|
+
|
|
142
|
+
compiler = createStartCompiler({
|
|
143
|
+
env: environment.type,
|
|
144
|
+
envName: environment.name,
|
|
145
|
+
root,
|
|
146
|
+
mode,
|
|
147
|
+
framework: opts.framework,
|
|
148
|
+
providerEnvName: opts.providerEnvName,
|
|
149
|
+
generateFunctionId: opts.generateFunctionId,
|
|
150
|
+
onServerFnsById,
|
|
151
|
+
getKnownServerFns: () => serverFnsById,
|
|
152
|
+
encodeModuleSpecifierInDev:
|
|
153
|
+
mode === 'dev'
|
|
154
|
+
? createViteDevServerFnModuleSpecifierEncoder(root)
|
|
155
|
+
: undefined,
|
|
156
|
+
loadModule: async (id: string) => {
|
|
157
|
+
await loadModuleForViteCompiler({
|
|
158
|
+
compiler: compiler!,
|
|
159
|
+
mode: this.environment.mode,
|
|
160
|
+
fetchModule:
|
|
161
|
+
this.environment.mode === 'dev'
|
|
162
|
+
? this.environment.fetchModule.bind(this.environment)
|
|
163
|
+
: undefined,
|
|
164
|
+
loadModule: this.load.bind(this),
|
|
165
|
+
id,
|
|
166
|
+
})
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
resolveId: async (source: string, importer?: string) => {
|
|
170
|
+
const r = await this.resolve(source, importer)
|
|
171
|
+
|
|
172
|
+
if (r) {
|
|
173
|
+
if (!r.external) {
|
|
174
|
+
return cleanId(r.id)
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return null
|
|
179
|
+
},
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
compilers.set(this.environment.name, compiler)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Detect which kinds are present in this file before parsing
|
|
186
|
+
const detectedKinds = detectKindsInCode(code, environment.type)
|
|
187
|
+
|
|
188
|
+
const result = await compiler.compile({
|
|
189
|
+
id,
|
|
190
|
+
code,
|
|
191
|
+
detectedKinds,
|
|
192
|
+
})
|
|
193
|
+
return result
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
|
|
197
|
+
hotUpdate(ctx) {
|
|
198
|
+
const compiler = compilers.get(this.environment.name)
|
|
199
|
+
|
|
200
|
+
ctx.modules.forEach((m) => {
|
|
201
|
+
if (m.id) {
|
|
202
|
+
const deleted = compiler?.invalidateModule(m.id)
|
|
203
|
+
if (deleted) {
|
|
204
|
+
m.importers.forEach((importer) => {
|
|
205
|
+
if (importer.id) {
|
|
206
|
+
compiler?.invalidateModule(importer.id)
|
|
207
|
+
}
|
|
208
|
+
})
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
})
|
|
212
|
+
},
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return [
|
|
217
|
+
...opts.environments.map(perEnvServerFnPlugin),
|
|
218
|
+
{
|
|
219
|
+
name: 'tanstack-start-core:capture-server-fn-module-lookup',
|
|
220
|
+
// we only need this plugin in dev mode
|
|
221
|
+
apply: 'serve',
|
|
222
|
+
applyToEnvironment(env) {
|
|
223
|
+
return !!opts.environments.find((e) => e.name === env.name)
|
|
224
|
+
},
|
|
225
|
+
transform: {
|
|
226
|
+
filter: {
|
|
227
|
+
id: new RegExp(`${SERVER_FN_LOOKUP}$`),
|
|
228
|
+
},
|
|
229
|
+
handler(code, id) {
|
|
230
|
+
const compiler = compilers.get(this.environment.name)
|
|
231
|
+
compiler?.ingestModule({ code, id: cleanId(id) })
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
// Validate server function ID in dev mode
|
|
236
|
+
{
|
|
237
|
+
name: 'tanstack-start-core:validate-server-fn-id',
|
|
238
|
+
apply: 'serve',
|
|
239
|
+
load: {
|
|
240
|
+
filter: {
|
|
241
|
+
id: new RegExp(resolveViteId(validateServerFnIdVirtualModule)),
|
|
242
|
+
},
|
|
243
|
+
async handler(id) {
|
|
244
|
+
const parsed = parseIdQuery(id)
|
|
245
|
+
const fnId = parsed.query.id
|
|
246
|
+
if (fnId && serverFnsById[fnId]) {
|
|
247
|
+
return `export {}`
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// ID not yet registered — the source file may not have been
|
|
251
|
+
// transformed in this dev session yet (e.g. cold restart with
|
|
252
|
+
// cached client). Try to decode the ID, discover the source
|
|
253
|
+
// file, trigger its compilation, and re-check.
|
|
254
|
+
if (fnId) {
|
|
255
|
+
try {
|
|
256
|
+
const decoded = JSON.parse(
|
|
257
|
+
Buffer.from(fnId, 'base64url').toString('utf8'),
|
|
258
|
+
)
|
|
259
|
+
if (
|
|
260
|
+
typeof decoded.file === 'string' &&
|
|
261
|
+
typeof decoded.export === 'string'
|
|
262
|
+
) {
|
|
263
|
+
// Use the Vite strategy to decode the module specifier
|
|
264
|
+
// back to the original source file path.
|
|
265
|
+
const sourceFile = decodeViteDevServerModuleSpecifier(
|
|
266
|
+
decoded.file,
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
if (sourceFile) {
|
|
270
|
+
// Resolve to absolute path
|
|
271
|
+
const absPath = resolvePath(root, sourceFile)
|
|
272
|
+
|
|
273
|
+
// Trigger transform of the source file in this environment,
|
|
274
|
+
// which will compile createServerFn calls and populate
|
|
275
|
+
// serverFnsById as a side effect.
|
|
276
|
+
// This plugin only runs in dev (apply: 'serve'), so mode
|
|
277
|
+
// must be 'dev' — assert to narrow to DevEnvironment.
|
|
278
|
+
assert(this.environment.mode === 'dev')
|
|
279
|
+
await this.environment.fetchModule(absPath)
|
|
280
|
+
|
|
281
|
+
// Re-check after lazy compilation
|
|
282
|
+
if (serverFnsById[fnId]) {
|
|
283
|
+
return `export {}`
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
} catch {
|
|
288
|
+
// Decoding or fetching failed — fall through to error
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
this.error(`Invalid server function ID: ${fnId}`)
|
|
293
|
+
},
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
// Manifest plugin for server environments
|
|
297
|
+
{
|
|
298
|
+
name: 'tanstack-start-core:server-fn-resolver',
|
|
299
|
+
enforce: 'pre',
|
|
300
|
+
applyToEnvironment: (env) => {
|
|
301
|
+
return appliedResolverEnvironments.has(env.name)
|
|
302
|
+
},
|
|
303
|
+
configResolved(config) {
|
|
304
|
+
root = config.root
|
|
305
|
+
},
|
|
306
|
+
resolveId: {
|
|
307
|
+
filter: { id: new RegExp(VIRTUAL_MODULES.serverFnResolver) },
|
|
308
|
+
handler() {
|
|
309
|
+
return resolvedResolverVirtualImportId
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
load: {
|
|
313
|
+
filter: { id: new RegExp(resolvedResolverVirtualImportId) },
|
|
314
|
+
handler() {
|
|
315
|
+
if (this.environment.name !== opts.providerEnvName) {
|
|
316
|
+
const mod = opts.environments.find(
|
|
317
|
+
(e) => e.name === this.environment.name,
|
|
318
|
+
)?.getServerFnById
|
|
319
|
+
if (mod) {
|
|
320
|
+
return mod
|
|
321
|
+
} else {
|
|
322
|
+
this.error(
|
|
323
|
+
`No getServerFnById implementation found for caller environment: ${this.environment.name}`,
|
|
324
|
+
)
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (this.environment.mode !== 'build') {
|
|
329
|
+
return getDevServerFnValidatorModule()
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// When SSR is the provider, server-only-referenced functions aren't in the manifest,
|
|
333
|
+
// so no isClientReferenced check is needed.
|
|
334
|
+
// When SSR is NOT the provider (custom provider env), server-only-referenced
|
|
335
|
+
// functions ARE in the manifest and need the isClientReferenced check to
|
|
336
|
+
// block direct client HTTP requests to server-only-referenced functions.
|
|
337
|
+
return generateServerFnResolverModule({
|
|
338
|
+
serverFnsById,
|
|
339
|
+
includeClientReferencedCheck: !ssrIsProvider,
|
|
340
|
+
})
|
|
341
|
+
},
|
|
342
|
+
},
|
|
343
|
+
},
|
|
344
|
+
]
|
|
345
|
+
}
|