@tanstack/start-plugin-core 1.132.0-alpha.2 → 1.132.0-alpha.20
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/create-server-fn-plugin/compiler.d.ts +61 -0
- package/dist/esm/create-server-fn-plugin/compiler.js +336 -0
- package/dist/esm/create-server-fn-plugin/compiler.js.map +1 -0
- package/dist/esm/create-server-fn-plugin/handleCreateServerFn.d.ts +6 -0
- package/dist/esm/create-server-fn-plugin/handleCreateServerFn.js +85 -0
- package/dist/esm/create-server-fn-plugin/handleCreateServerFn.js.map +1 -0
- package/dist/esm/create-server-fn-plugin/plugin.d.ts +3 -0
- package/dist/esm/create-server-fn-plugin/plugin.js +113 -0
- package/dist/esm/create-server-fn-plugin/plugin.js.map +1 -0
- package/dist/esm/output-directory.js +5 -2
- package/dist/esm/output-directory.js.map +1 -1
- package/dist/esm/plugin.d.ts +1 -6
- package/dist/esm/plugin.js +14 -61
- package/dist/esm/plugin.js.map +1 -1
- package/dist/esm/schema.d.ts +20 -28
- package/dist/esm/schema.js +10 -14
- package/dist/esm/schema.js.map +1 -1
- package/dist/esm/start-compiler-plugin/compilers.d.ts +15 -0
- package/dist/esm/start-compiler-plugin/compilers.js +131 -0
- package/dist/esm/start-compiler-plugin/compilers.js.map +1 -0
- package/dist/esm/start-compiler-plugin/constants.d.ts +1 -0
- package/dist/esm/start-compiler-plugin/constants.js +13 -0
- package/dist/esm/start-compiler-plugin/constants.js.map +1 -0
- package/dist/esm/start-compiler-plugin/envOnly.d.ts +5 -0
- package/dist/esm/start-compiler-plugin/envOnly.js +41 -0
- package/dist/esm/start-compiler-plugin/envOnly.js.map +1 -0
- package/dist/esm/start-compiler-plugin/isomorphicFn.d.ts +4 -0
- package/dist/esm/start-compiler-plugin/isomorphicFn.js +49 -0
- package/dist/esm/start-compiler-plugin/isomorphicFn.js.map +1 -0
- package/dist/esm/start-compiler-plugin/middleware.d.ts +4 -0
- package/dist/esm/start-compiler-plugin/middleware.js +51 -0
- package/dist/esm/start-compiler-plugin/middleware.js.map +1 -0
- package/dist/esm/{start-compiler-plugin.d.ts → start-compiler-plugin/plugin.d.ts} +1 -8
- package/dist/esm/start-compiler-plugin/plugin.js +96 -0
- package/dist/esm/start-compiler-plugin/plugin.js.map +1 -0
- package/dist/esm/start-compiler-plugin/serverFileRoute.d.ts +4 -0
- package/dist/esm/start-compiler-plugin/serverFileRoute.js +38 -0
- package/dist/esm/start-compiler-plugin/serverFileRoute.js.map +1 -0
- package/dist/esm/start-compiler-plugin/utils.d.ts +13 -0
- package/dist/esm/start-compiler-plugin/utils.js +30 -0
- package/dist/esm/start-compiler-plugin/utils.js.map +1 -0
- package/package.json +8 -8
- package/src/create-server-fn-plugin/compiler.ts +456 -0
- package/src/create-server-fn-plugin/handleCreateServerFn.ts +153 -0
- package/src/create-server-fn-plugin/plugin.ts +138 -0
- package/src/output-directory.ts +13 -6
- package/src/plugin.ts +18 -79
- package/src/schema.ts +10 -16
- package/src/start-compiler-plugin/compilers.ts +195 -0
- package/src/start-compiler-plugin/constants.ts +9 -0
- package/src/start-compiler-plugin/envOnly.ts +58 -0
- package/src/start-compiler-plugin/isomorphicFn.ts +78 -0
- package/src/start-compiler-plugin/middleware.ts +79 -0
- package/src/start-compiler-plugin/plugin.ts +122 -0
- package/src/start-compiler-plugin/serverFileRoute.ts +59 -0
- package/src/start-compiler-plugin/utils.ts +41 -0
- package/dist/esm/compilers.d.ts +0 -21
- package/dist/esm/compilers.js +0 -395
- package/dist/esm/compilers.js.map +0 -1
- package/dist/esm/start-compiler-plugin.js +0 -78
- package/dist/esm/start-compiler-plugin.js.map +0 -1
- package/src/compilers.ts +0 -659
- package/src/start-compiler-plugin.ts +0 -115
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { VITE_ENVIRONMENT_NAMES } from '../constants'
|
|
2
|
+
import { ServerFnCompiler } from './compiler'
|
|
3
|
+
import type { ViteEnvironmentNames } from '../constants'
|
|
4
|
+
import type { PluginOption } from 'vite'
|
|
5
|
+
import type { CompileStartFrameworkOptions } from '../start-compiler-plugin/compilers'
|
|
6
|
+
|
|
7
|
+
function cleanId(id: string): string {
|
|
8
|
+
return id.split('?')[0]!
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function createServerFnPlugin(
|
|
12
|
+
framework: CompileStartFrameworkOptions,
|
|
13
|
+
): PluginOption {
|
|
14
|
+
const libName = `@tanstack/${framework}-start`
|
|
15
|
+
const rootExport = 'createServerFn'
|
|
16
|
+
|
|
17
|
+
const SERVER_FN_LOOKUP = 'server-fn-module-lookup'
|
|
18
|
+
|
|
19
|
+
const compilers: Partial<Record<ViteEnvironmentNames, ServerFnCompiler>> = {}
|
|
20
|
+
return [
|
|
21
|
+
{
|
|
22
|
+
name: 'tanstack-start-core:capture-server-fn-module-lookup',
|
|
23
|
+
// we only need this plugin in dev mode
|
|
24
|
+
apply: 'serve',
|
|
25
|
+
applyToEnvironment(env) {
|
|
26
|
+
return [
|
|
27
|
+
VITE_ENVIRONMENT_NAMES.client,
|
|
28
|
+
VITE_ENVIRONMENT_NAMES.server,
|
|
29
|
+
].includes(env.name as ViteEnvironmentNames)
|
|
30
|
+
},
|
|
31
|
+
transform: {
|
|
32
|
+
filter: {
|
|
33
|
+
id: new RegExp(`${SERVER_FN_LOOKUP}$`),
|
|
34
|
+
},
|
|
35
|
+
handler(code, id) {
|
|
36
|
+
const compiler =
|
|
37
|
+
compilers[this.environment.name as ViteEnvironmentNames]
|
|
38
|
+
compiler?.ingestModule({ code, id: cleanId(id) })
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'tanstack-start-core::server-fn',
|
|
44
|
+
enforce: 'pre',
|
|
45
|
+
|
|
46
|
+
applyToEnvironment(env) {
|
|
47
|
+
return [
|
|
48
|
+
VITE_ENVIRONMENT_NAMES.client,
|
|
49
|
+
VITE_ENVIRONMENT_NAMES.server,
|
|
50
|
+
].includes(env.name as ViteEnvironmentNames)
|
|
51
|
+
},
|
|
52
|
+
transform: {
|
|
53
|
+
filter: {
|
|
54
|
+
id: {
|
|
55
|
+
exclude: new RegExp(`${SERVER_FN_LOOKUP}$`),
|
|
56
|
+
},
|
|
57
|
+
code: {
|
|
58
|
+
// only scan files that mention `.handler(`
|
|
59
|
+
include: [/\.handler\(/],
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
async handler(code, id) {
|
|
63
|
+
let compiler =
|
|
64
|
+
compilers[this.environment.name as ViteEnvironmentNames]
|
|
65
|
+
if (!compiler) {
|
|
66
|
+
const env =
|
|
67
|
+
this.environment.name === VITE_ENVIRONMENT_NAMES.client
|
|
68
|
+
? 'client'
|
|
69
|
+
: this.environment.name === VITE_ENVIRONMENT_NAMES.server
|
|
70
|
+
? 'server'
|
|
71
|
+
: (() => {
|
|
72
|
+
throw new Error(
|
|
73
|
+
`Environment ${this.environment.name} not configured`,
|
|
74
|
+
)
|
|
75
|
+
})()
|
|
76
|
+
|
|
77
|
+
compiler = new ServerFnCompiler({
|
|
78
|
+
env,
|
|
79
|
+
libName,
|
|
80
|
+
rootExport,
|
|
81
|
+
loadModule: async (id: string) => {
|
|
82
|
+
if (this.environment.mode === 'build') {
|
|
83
|
+
const loaded = await this.load({ id })
|
|
84
|
+
if (!loaded.code) {
|
|
85
|
+
throw new Error(`could not load module ${id}`)
|
|
86
|
+
}
|
|
87
|
+
compiler!.ingestModule({ code: loaded.code, id })
|
|
88
|
+
} else if (this.environment.mode === 'dev') {
|
|
89
|
+
/**
|
|
90
|
+
* in dev, vite does not return code from `ctx.load()`
|
|
91
|
+
* so instead, we need to take a different approach
|
|
92
|
+
* we must force vite to load the module and run it through the vite plugin pipeline
|
|
93
|
+
* we can do this by using the `fetchModule` method
|
|
94
|
+
* the `captureServerFnModuleLookupPlugin` captures the module code via its transform hook and invokes analyzeModuleAST
|
|
95
|
+
*/
|
|
96
|
+
await this.environment.fetchModule(
|
|
97
|
+
id + '?' + SERVER_FN_LOOKUP,
|
|
98
|
+
)
|
|
99
|
+
} else {
|
|
100
|
+
throw new Error(
|
|
101
|
+
`could not load module ${id}: unknown environment mode ${this.environment.mode}`,
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
resolveId: async (source: string, importer?: string) => {
|
|
106
|
+
const r = await this.resolve(source, importer)
|
|
107
|
+
return r ? cleanId(r.id) : null
|
|
108
|
+
},
|
|
109
|
+
})
|
|
110
|
+
compilers[this.environment.name as ViteEnvironmentNames] = compiler
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
id = cleanId(id)
|
|
114
|
+
const result = await compiler.compile({ id, code })
|
|
115
|
+
return result
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
hotUpdate(ctx) {
|
|
120
|
+
const compiler =
|
|
121
|
+
compilers[this.environment.name as ViteEnvironmentNames]
|
|
122
|
+
|
|
123
|
+
ctx.modules.forEach((m) => {
|
|
124
|
+
if (m.id) {
|
|
125
|
+
const deleted = compiler?.invalidateModule(m.id)
|
|
126
|
+
if (deleted) {
|
|
127
|
+
m.importers.forEach((importer) => {
|
|
128
|
+
if (importer.id) {
|
|
129
|
+
compiler?.invalidateModule(importer.id)
|
|
130
|
+
}
|
|
131
|
+
})
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
})
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
]
|
|
138
|
+
}
|
package/src/output-directory.ts
CHANGED
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
import { join } from 'pathe'
|
|
2
2
|
import { VITE_ENVIRONMENT_NAMES } from './constants'
|
|
3
|
+
import type { ViteEnvironmentNames } from './constants'
|
|
3
4
|
import type * as vite from 'vite'
|
|
4
5
|
|
|
5
6
|
export function getClientOutputDirectory(userConfig: vite.UserConfig) {
|
|
6
|
-
return (
|
|
7
|
-
userConfig.environments?.[VITE_ENVIRONMENT_NAMES.client]?.build?.outDir ??
|
|
8
|
-
join(getServerOutputDirectory(userConfig), 'public')
|
|
9
|
-
)
|
|
7
|
+
return getOutputDirectory(userConfig, VITE_ENVIRONMENT_NAMES.client, 'client')
|
|
10
8
|
}
|
|
11
9
|
|
|
12
10
|
export function getServerOutputDirectory(userConfig: vite.UserConfig) {
|
|
11
|
+
return getOutputDirectory(userConfig, VITE_ENVIRONMENT_NAMES.server, 'server')
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function getOutputDirectory(
|
|
15
|
+
userConfig: vite.UserConfig,
|
|
16
|
+
environmentName: ViteEnvironmentNames,
|
|
17
|
+
directoryName: string,
|
|
18
|
+
) {
|
|
13
19
|
const rootOutputDirectory = userConfig.build?.outDir ?? 'dist'
|
|
20
|
+
|
|
14
21
|
return (
|
|
15
|
-
userConfig.environments?.[
|
|
16
|
-
rootOutputDirectory
|
|
22
|
+
userConfig.environments?.[environmentName]?.build?.outDir ??
|
|
23
|
+
join(rootOutputDirectory, directoryName)
|
|
17
24
|
)
|
|
18
25
|
}
|
package/src/plugin.ts
CHANGED
|
@@ -6,7 +6,7 @@ import * as vite from 'vite'
|
|
|
6
6
|
import { crawlFrameworkPkgs } from 'vitefu'
|
|
7
7
|
import { join } from 'pathe'
|
|
8
8
|
import { startManifestPlugin } from './start-manifest-plugin/plugin'
|
|
9
|
-
import { startCompilerPlugin } from './start-compiler-plugin'
|
|
9
|
+
import { startCompilerPlugin } from './start-compiler-plugin/plugin'
|
|
10
10
|
import { ENTRY_POINTS, VITE_ENVIRONMENT_NAMES } from './constants'
|
|
11
11
|
import { tanStackStartRouter } from './start-router-plugin/plugin'
|
|
12
12
|
import { loadEnvPlugin } from './load-env-plugin/plugin'
|
|
@@ -18,10 +18,11 @@ import {
|
|
|
18
18
|
getServerOutputDirectory,
|
|
19
19
|
} from './output-directory'
|
|
20
20
|
import { postServerBuild } from './post-server-build'
|
|
21
|
+
import { createServerFnPlugin } from './create-server-fn-plugin/plugin'
|
|
21
22
|
import type { ViteEnvironmentNames } from './constants'
|
|
22
23
|
import type { TanStackStartInputConfig } from './schema'
|
|
23
24
|
import type { PluginOption } from 'vite'
|
|
24
|
-
import type { CompileStartFrameworkOptions } from './compilers'
|
|
25
|
+
import type { CompileStartFrameworkOptions } from './start-compiler-plugin/compilers'
|
|
25
26
|
|
|
26
27
|
export interface TanStackStartVitePluginCoreOptions {
|
|
27
28
|
framework: CompileStartFrameworkOptions
|
|
@@ -29,11 +30,6 @@ export interface TanStackStartVitePluginCoreOptions {
|
|
|
29
30
|
client: string
|
|
30
31
|
server: string
|
|
31
32
|
}
|
|
32
|
-
crawlPackages?: (opts: {
|
|
33
|
-
name: string
|
|
34
|
-
peerDependencies: Record<string, any>
|
|
35
|
-
exports?: Record<string, any> | string
|
|
36
|
-
}) => 'include' | 'exclude' | undefined
|
|
37
33
|
}
|
|
38
34
|
|
|
39
35
|
export function TanStackStartVitePluginCore(
|
|
@@ -56,7 +52,7 @@ export function TanStackStartVitePluginCore(
|
|
|
56
52
|
|
|
57
53
|
return [
|
|
58
54
|
tanStackStartRouter({
|
|
59
|
-
...startConfig.
|
|
55
|
+
...startConfig.router,
|
|
60
56
|
target: corePluginOpts.framework,
|
|
61
57
|
autoCodeSplitting: true,
|
|
62
58
|
}),
|
|
@@ -67,7 +63,7 @@ export function TanStackStartVitePluginCore(
|
|
|
67
63
|
globalThis.TSS_APP_BASE = viteAppBase
|
|
68
64
|
|
|
69
65
|
const root = viteConfig.root || process.cwd()
|
|
70
|
-
const resolvedSrcDirectory = join(root, startConfig.
|
|
66
|
+
const resolvedSrcDirectory = join(root, startConfig.srcDirectory)
|
|
71
67
|
|
|
72
68
|
const routerFilePath = resolveEntry({
|
|
73
69
|
type: 'router entry',
|
|
@@ -132,13 +128,8 @@ export function TanStackStartVitePluginCore(
|
|
|
132
128
|
return nitroOutputPublicDir
|
|
133
129
|
})()*/
|
|
134
130
|
|
|
135
|
-
const startPackageName =
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
const additionalOptimizeDeps = {
|
|
139
|
-
include: new Set<string>(),
|
|
140
|
-
exclude: new Set<string>(),
|
|
141
|
-
}
|
|
131
|
+
const startPackageName =
|
|
132
|
+
`@tanstack/${corePluginOpts.framework}-start` as const
|
|
142
133
|
|
|
143
134
|
// crawl packages that have start in "peerDependencies"
|
|
144
135
|
// see https://github.com/svitejs/vitefu/blob/d8d82fa121e3b2215ba437107093c77bde51b63b/src/index.js#L95-L101
|
|
@@ -146,34 +137,16 @@ export function TanStackStartVitePluginCore(
|
|
|
146
137
|
// this is currently uncached; could be implemented similarly as vite handles lock file changes
|
|
147
138
|
// see https://github.com/vitejs/vite/blob/557f797d29422027e8c451ca50dd84bf8c41b5f0/packages/vite/src/node/optimizer/index.ts#L1282
|
|
148
139
|
|
|
149
|
-
const
|
|
140
|
+
const crawlFrameworkPkgsResult = await crawlFrameworkPkgs({
|
|
150
141
|
root: process.cwd(),
|
|
151
142
|
isBuild: command === 'build',
|
|
152
143
|
isFrameworkPkgByJson(pkgJson) {
|
|
153
|
-
if ([routerPackageName, startPackageName].includes(pkgJson.name)) {
|
|
154
|
-
return false
|
|
155
|
-
}
|
|
156
|
-
|
|
157
144
|
const peerDependencies = pkgJson['peerDependencies']
|
|
158
145
|
|
|
159
146
|
if (peerDependencies) {
|
|
160
|
-
|
|
161
|
-
name: pkgJson.name,
|
|
162
|
-
peerDependencies,
|
|
163
|
-
exports: pkgJson.exports,
|
|
164
|
-
})
|
|
165
|
-
if (internalResult) {
|
|
166
|
-
if (internalResult === 'exclude') {
|
|
167
|
-
additionalOptimizeDeps.exclude.add(pkgJson.name)
|
|
168
|
-
} else {
|
|
169
|
-
additionalOptimizeDeps.include.add(pkgJson.name)
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
return (
|
|
173
|
-
startPackageName in peerDependencies ||
|
|
174
|
-
routerPackageName in peerDependencies
|
|
175
|
-
)
|
|
147
|
+
return startPackageName in peerDependencies
|
|
176
148
|
}
|
|
149
|
+
|
|
177
150
|
return false
|
|
178
151
|
},
|
|
179
152
|
})
|
|
@@ -187,9 +160,6 @@ export function TanStackStartVitePluginCore(
|
|
|
187
160
|
[VITE_ENVIRONMENT_NAMES.client]: {
|
|
188
161
|
consumer: 'client',
|
|
189
162
|
build: {
|
|
190
|
-
emptyOutDir:
|
|
191
|
-
viteConfig.environments?.[VITE_ENVIRONMENT_NAMES.client]
|
|
192
|
-
?.build?.emptyOutDir ?? true,
|
|
193
163
|
rollupOptions: {
|
|
194
164
|
input: {
|
|
195
165
|
main: ENTRY_POINTS.client,
|
|
@@ -201,9 +171,6 @@ export function TanStackStartVitePluginCore(
|
|
|
201
171
|
[VITE_ENVIRONMENT_NAMES.server]: {
|
|
202
172
|
consumer: 'server',
|
|
203
173
|
build: {
|
|
204
|
-
emptyOutDir:
|
|
205
|
-
viteConfig.environments?.[VITE_ENVIRONMENT_NAMES.server]
|
|
206
|
-
?.build?.emptyOutDir ?? false,
|
|
207
174
|
ssr: true,
|
|
208
175
|
rollupOptions: {
|
|
209
176
|
input:
|
|
@@ -218,42 +185,18 @@ export function TanStackStartVitePluginCore(
|
|
|
218
185
|
viteConfig.environments?.[VITE_ENVIRONMENT_NAMES.server]
|
|
219
186
|
?.build?.copyPublicDir ?? false,
|
|
220
187
|
},
|
|
221
|
-
optimizeDeps: {
|
|
222
|
-
exclude: [
|
|
223
|
-
...Object.values(VIRTUAL_MODULES),
|
|
224
|
-
...result.optimizeDeps.exclude.sort(),
|
|
225
|
-
...additionalOptimizeDeps.exclude,
|
|
226
|
-
`@tanstack/${corePluginOpts.framework}-start/server-functions-server`,
|
|
227
|
-
],
|
|
228
|
-
include: [
|
|
229
|
-
...additionalOptimizeDeps.include,
|
|
230
|
-
...result.optimizeDeps.include.sort(),
|
|
231
|
-
],
|
|
232
|
-
},
|
|
233
188
|
},
|
|
234
189
|
},
|
|
235
190
|
resolve: {
|
|
236
191
|
noExternal: [
|
|
237
192
|
'@tanstack/start**',
|
|
238
193
|
`@tanstack/${corePluginOpts.framework}-start**`,
|
|
239
|
-
...
|
|
240
|
-
startPackageName,
|
|
241
|
-
...result.ssr.noExternal.sort(),
|
|
194
|
+
...crawlFrameworkPkgsResult.ssr.noExternal.sort(),
|
|
242
195
|
],
|
|
243
|
-
dedupe: [startPackageName],
|
|
244
196
|
alias: {
|
|
245
197
|
...entryAliasConfiguration,
|
|
246
198
|
},
|
|
247
199
|
},
|
|
248
|
-
optimizeDeps: {
|
|
249
|
-
exclude: [
|
|
250
|
-
...Object.values(VIRTUAL_MODULES),
|
|
251
|
-
startPackageName,
|
|
252
|
-
...result.optimizeDeps.exclude.sort(),
|
|
253
|
-
...additionalOptimizeDeps.exclude,
|
|
254
|
-
],
|
|
255
|
-
include: [...additionalOptimizeDeps.include],
|
|
256
|
-
},
|
|
257
200
|
/* prettier-ignore */
|
|
258
201
|
define: {
|
|
259
202
|
// define is an esbuild function that replaces the any instances of given keys with the given values
|
|
@@ -261,7 +204,7 @@ export function TanStackStartVitePluginCore(
|
|
|
261
204
|
// This is not the same as injecting environment variables.
|
|
262
205
|
|
|
263
206
|
...defineReplaceEnv('TSS_SERVER_FN_BASE', startConfig.serverFns.base),
|
|
264
|
-
...defineReplaceEnv('
|
|
207
|
+
...defineReplaceEnv('TSS_CLIENT_OUTPUT_DIR', getClientOutputDirectory(viteConfig)),
|
|
265
208
|
...defineReplaceEnv('TSS_APP_BASE', viteAppBase),
|
|
266
209
|
...(command === 'serve' ? defineReplaceEnv('TSS_SHELL', startConfig.spa?.enabled ? 'true' : 'false') : {}),
|
|
267
210
|
...defineReplaceEnv('TSS_DEV_SERVER', command === 'serve' ? 'true' : 'false'),
|
|
@@ -295,27 +238,23 @@ export function TanStackStartVitePluginCore(
|
|
|
295
238
|
}
|
|
296
239
|
},
|
|
297
240
|
},
|
|
241
|
+
createServerFnPlugin(corePluginOpts.framework),
|
|
298
242
|
// N.B. TanStackStartCompilerPlugin must be before the TanStackServerFnPluginEnv
|
|
299
|
-
startCompilerPlugin(corePluginOpts.framework,
|
|
300
|
-
client: { envName: VITE_ENVIRONMENT_NAMES.client },
|
|
301
|
-
server: { envName: VITE_ENVIRONMENT_NAMES.server },
|
|
302
|
-
}),
|
|
243
|
+
startCompilerPlugin(corePluginOpts.framework),
|
|
303
244
|
TanStackServerFnPluginEnv({
|
|
304
245
|
// This is the ID that will be available to look up and import
|
|
305
246
|
// our server function manifest and resolve its module
|
|
306
247
|
manifestVirtualImportId: VIRTUAL_MODULES.serverFnManifest,
|
|
307
248
|
client: {
|
|
308
249
|
getRuntimeCode: () =>
|
|
309
|
-
`import { createClientRpc } from '@tanstack/${corePluginOpts.framework}-start/
|
|
310
|
-
replacer: (d) =>
|
|
311
|
-
`createClientRpc('${d.functionId}', '${startConfig.serverFns.base}')`,
|
|
250
|
+
`import { createClientRpc } from '@tanstack/${corePluginOpts.framework}-start/client'`,
|
|
251
|
+
replacer: (d) => `createClientRpc('${d.functionId}')`,
|
|
312
252
|
envName: VITE_ENVIRONMENT_NAMES.client,
|
|
313
253
|
},
|
|
314
254
|
server: {
|
|
315
255
|
getRuntimeCode: () =>
|
|
316
|
-
`import { createServerRpc } from '@tanstack/${corePluginOpts.framework}-start/server
|
|
317
|
-
replacer: (d) =>
|
|
318
|
-
`createServerRpc('${d.functionId}', '${startConfig.serverFns.base}', ${d.fn})`,
|
|
256
|
+
`import { createServerRpc } from '@tanstack/${corePluginOpts.framework}-start/server'`,
|
|
257
|
+
replacer: (d) => `createServerRpc('${d.functionId}', ${d.fn})`,
|
|
319
258
|
envName: VITE_ENVIRONMENT_NAMES.server,
|
|
320
259
|
},
|
|
321
260
|
}),
|
package/src/schema.ts
CHANGED
|
@@ -2,35 +2,28 @@ import path from 'node:path'
|
|
|
2
2
|
import { z } from 'zod'
|
|
3
3
|
import { configSchema, getConfig } from '@tanstack/router-generator'
|
|
4
4
|
|
|
5
|
-
const tsrConfig = configSchema
|
|
6
|
-
.omit({ autoCodeSplitting: true })
|
|
7
|
-
.partial()
|
|
8
|
-
.extend({
|
|
9
|
-
// this is relative to vite root
|
|
10
|
-
// TODO why is this nested under tsr?
|
|
11
|
-
srcDirectory: z.string().optional().default('src'),
|
|
12
|
-
})
|
|
5
|
+
const tsrConfig = configSchema.omit({ autoCodeSplitting: true }).partial()
|
|
13
6
|
|
|
14
7
|
export function parseStartConfig(
|
|
15
8
|
opts?: z.input<typeof tanstackStartOptionsSchema>,
|
|
16
9
|
) {
|
|
17
10
|
const options = tanstackStartOptionsSchema.parse(opts)
|
|
18
11
|
|
|
19
|
-
const srcDirectory = options.
|
|
12
|
+
const srcDirectory = options.srcDirectory
|
|
20
13
|
|
|
21
14
|
const routesDirectory =
|
|
22
|
-
options.
|
|
15
|
+
options.router.routesDirectory ?? path.join(srcDirectory, 'routes')
|
|
23
16
|
|
|
24
17
|
const generatedRouteTree =
|
|
25
|
-
options.
|
|
18
|
+
options.router.generatedRouteTree ??
|
|
26
19
|
path.join(srcDirectory, 'routeTree.gen.ts')
|
|
27
20
|
|
|
28
21
|
return {
|
|
29
22
|
...options,
|
|
30
|
-
|
|
31
|
-
...options.
|
|
23
|
+
router: {
|
|
24
|
+
...options.router,
|
|
32
25
|
...getConfig({
|
|
33
|
-
...options.
|
|
26
|
+
...options.router,
|
|
34
27
|
routesDirectory,
|
|
35
28
|
generatedRouteTree,
|
|
36
29
|
}),
|
|
@@ -121,12 +114,13 @@ const pageSchema = pageBaseSchema.extend({
|
|
|
121
114
|
|
|
122
115
|
const tanstackStartOptionsSchema = z
|
|
123
116
|
.object({
|
|
124
|
-
|
|
117
|
+
srcDirectory: z.string().optional().default('src'),
|
|
125
118
|
router: z
|
|
126
119
|
.object({
|
|
127
|
-
// TODO
|
|
120
|
+
// TODO this will move to 'start' once we have `createStart`
|
|
128
121
|
entry: z.string().optional(),
|
|
129
122
|
})
|
|
123
|
+
.and(tsrConfig.optional().default({}))
|
|
130
124
|
.optional()
|
|
131
125
|
.default({}),
|
|
132
126
|
client: z
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import * as babel from '@babel/core'
|
|
2
|
+
import * as t from '@babel/types'
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
deadCodeElimination,
|
|
6
|
+
findReferencedIdentifiers,
|
|
7
|
+
} from 'babel-dead-code-elimination'
|
|
8
|
+
import { generateFromAst, parseAst } from '@tanstack/router-utils'
|
|
9
|
+
import { transformFuncs } from './constants'
|
|
10
|
+
import { handleCreateServerFileRouteCallExpressionFactory } from './serverFileRoute'
|
|
11
|
+
import { handleCreateIsomorphicFnCallExpression } from './isomorphicFn'
|
|
12
|
+
import { handleCreateMiddlewareCallExpression } from './middleware'
|
|
13
|
+
import {
|
|
14
|
+
handleCreateClientOnlyFnCallExpression,
|
|
15
|
+
handleCreateServerOnlyFnCallExpression,
|
|
16
|
+
} from './envOnly'
|
|
17
|
+
import type { GeneratorResult, ParseAstOptions } from '@tanstack/router-utils'
|
|
18
|
+
|
|
19
|
+
export type CompileStartFrameworkOptions = 'react' | 'solid'
|
|
20
|
+
|
|
21
|
+
type Identifiers = { [K in (typeof transformFuncs)[number]]: IdentifierConfig }
|
|
22
|
+
const getIdentifiers = (
|
|
23
|
+
framework: CompileStartFrameworkOptions,
|
|
24
|
+
): Identifiers => ({
|
|
25
|
+
createServerRootRoute: {
|
|
26
|
+
name: 'createServerRootRoute',
|
|
27
|
+
handleCallExpression: handleCreateServerFileRouteCallExpressionFactory(
|
|
28
|
+
framework,
|
|
29
|
+
'createServerRootRoute',
|
|
30
|
+
),
|
|
31
|
+
paths: [],
|
|
32
|
+
},
|
|
33
|
+
createServerRoute: {
|
|
34
|
+
name: 'createServerRoute',
|
|
35
|
+
handleCallExpression: handleCreateServerFileRouteCallExpressionFactory(
|
|
36
|
+
framework,
|
|
37
|
+
'createServerRoute',
|
|
38
|
+
),
|
|
39
|
+
paths: [],
|
|
40
|
+
},
|
|
41
|
+
createServerFileRoute: {
|
|
42
|
+
name: 'createServerFileRoute',
|
|
43
|
+
handleCallExpression: handleCreateServerFileRouteCallExpressionFactory(
|
|
44
|
+
framework,
|
|
45
|
+
'createServerFileRoute',
|
|
46
|
+
),
|
|
47
|
+
paths: [],
|
|
48
|
+
},
|
|
49
|
+
createMiddleware: {
|
|
50
|
+
name: 'createMiddleware',
|
|
51
|
+
handleCallExpression: handleCreateMiddlewareCallExpression,
|
|
52
|
+
paths: [],
|
|
53
|
+
},
|
|
54
|
+
createServerOnlyFn: {
|
|
55
|
+
name: 'createServerOnlyFn',
|
|
56
|
+
handleCallExpression: handleCreateServerOnlyFnCallExpression,
|
|
57
|
+
paths: [],
|
|
58
|
+
},
|
|
59
|
+
createClientOnlyFn: {
|
|
60
|
+
name: 'createClientOnlyFn',
|
|
61
|
+
handleCallExpression: handleCreateClientOnlyFnCallExpression,
|
|
62
|
+
paths: [],
|
|
63
|
+
},
|
|
64
|
+
createIsomorphicFn: {
|
|
65
|
+
name: 'createIsomorphicFn',
|
|
66
|
+
handleCallExpression: handleCreateIsomorphicFnCallExpression,
|
|
67
|
+
paths: [],
|
|
68
|
+
},
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
export function compileStartOutputFactory(
|
|
72
|
+
framework: CompileStartFrameworkOptions,
|
|
73
|
+
) {
|
|
74
|
+
return function compileStartOutput(opts: CompileOptions): GeneratorResult {
|
|
75
|
+
const ast = parseAst(opts)
|
|
76
|
+
|
|
77
|
+
const doDce = opts.dce ?? true
|
|
78
|
+
// find referenced identifiers *before* we transform anything
|
|
79
|
+
const refIdents = doDce ? findReferencedIdentifiers(ast) : undefined
|
|
80
|
+
|
|
81
|
+
babel.traverse(ast, {
|
|
82
|
+
Program: {
|
|
83
|
+
enter(programPath) {
|
|
84
|
+
const identifiers = getIdentifiers(framework)
|
|
85
|
+
programPath.traverse({
|
|
86
|
+
ImportDeclaration: (path) => {
|
|
87
|
+
if (path.node.source.value !== `@tanstack/${framework}-start`) {
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// handle a destructured imports being renamed like "import { createServerFn as myCreateServerFn } from '@tanstack/react-start';"
|
|
92
|
+
path.node.specifiers.forEach((specifier) => {
|
|
93
|
+
transformFuncs.forEach((identifierKey) => {
|
|
94
|
+
const identifier = identifiers[identifierKey]
|
|
95
|
+
|
|
96
|
+
if (
|
|
97
|
+
specifier.type === 'ImportSpecifier' &&
|
|
98
|
+
specifier.imported.type === 'Identifier'
|
|
99
|
+
) {
|
|
100
|
+
if (specifier.imported.name === identifierKey) {
|
|
101
|
+
identifier.name = specifier.local.name
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// handle namespace imports like "import * as TanStackStart from '@tanstack/react-start';"
|
|
106
|
+
if (specifier.type === 'ImportNamespaceSpecifier') {
|
|
107
|
+
identifier.name = `${specifier.local.name}.${identifierKey}`
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
})
|
|
111
|
+
},
|
|
112
|
+
CallExpression: (path) => {
|
|
113
|
+
transformFuncs.forEach((identifierKey) => {
|
|
114
|
+
// Check to see if the call expression is a call to the
|
|
115
|
+
// identifiers[identifierKey].name
|
|
116
|
+
if (
|
|
117
|
+
t.isIdentifier(path.node.callee) &&
|
|
118
|
+
path.node.callee.name === identifiers[identifierKey].name
|
|
119
|
+
) {
|
|
120
|
+
// The identifier could be a call to the original function
|
|
121
|
+
// in the source code. If this is case, we need to ignore it.
|
|
122
|
+
// Check the scope to see if the identifier is a function declaration.
|
|
123
|
+
// if it is, then we can ignore it.
|
|
124
|
+
|
|
125
|
+
if (
|
|
126
|
+
path.scope.getBinding(identifiers[identifierKey].name)?.path
|
|
127
|
+
.node.type === 'FunctionDeclaration'
|
|
128
|
+
) {
|
|
129
|
+
return
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return identifiers[identifierKey].paths.push(path)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// handle namespace imports like "import * as TanStackStart from '@tanstack/react-start';"
|
|
136
|
+
// which are then called like "TanStackStart.createServerFn()"
|
|
137
|
+
if (t.isMemberExpression(path.node.callee)) {
|
|
138
|
+
if (
|
|
139
|
+
t.isIdentifier(path.node.callee.object) &&
|
|
140
|
+
t.isIdentifier(path.node.callee.property)
|
|
141
|
+
) {
|
|
142
|
+
const callname = [
|
|
143
|
+
path.node.callee.object.name,
|
|
144
|
+
path.node.callee.property.name,
|
|
145
|
+
].join('.')
|
|
146
|
+
|
|
147
|
+
if (callname === identifiers[identifierKey].name) {
|
|
148
|
+
identifiers[identifierKey].paths.push(path)
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return
|
|
154
|
+
})
|
|
155
|
+
},
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
transformFuncs.forEach((identifierKey) => {
|
|
159
|
+
identifiers[identifierKey].paths.forEach((path) => {
|
|
160
|
+
identifiers[identifierKey].handleCallExpression(
|
|
161
|
+
path as babel.NodePath<t.CallExpression>,
|
|
162
|
+
opts,
|
|
163
|
+
)
|
|
164
|
+
})
|
|
165
|
+
})
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
if (doDce) {
|
|
171
|
+
deadCodeElimination(ast, refIdents)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return generateFromAst(ast, {
|
|
175
|
+
sourceMaps: true,
|
|
176
|
+
sourceFileName: opts.filename,
|
|
177
|
+
filename: opts.filename,
|
|
178
|
+
})
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export type CompileOptions = ParseAstOptions & {
|
|
183
|
+
env: 'server' | 'client'
|
|
184
|
+
dce?: boolean
|
|
185
|
+
filename: string
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export type IdentifierConfig = {
|
|
189
|
+
name: string
|
|
190
|
+
handleCallExpression: (
|
|
191
|
+
path: babel.NodePath<t.CallExpression>,
|
|
192
|
+
opts: CompileOptions,
|
|
193
|
+
) => void
|
|
194
|
+
paths: Array<babel.NodePath>
|
|
195
|
+
}
|