@tanstack/start-plugin-core 1.142.4 → 1.142.6
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 +6 -0
- package/dist/esm/create-server-fn-plugin/compiler.js +146 -80
- package/dist/esm/create-server-fn-plugin/compiler.js.map +1 -1
- package/dist/esm/create-server-fn-plugin/handleCreateMiddleware.d.ts +8 -3
- package/dist/esm/create-server-fn-plugin/handleCreateMiddleware.js +10 -33
- package/dist/esm/create-server-fn-plugin/handleCreateMiddleware.js.map +1 -1
- package/dist/esm/create-server-fn-plugin/handleCreateServerFn.d.ts +8 -3
- package/dist/esm/create-server-fn-plugin/handleCreateServerFn.js +28 -31
- package/dist/esm/create-server-fn-plugin/handleCreateServerFn.js.map +1 -1
- package/dist/esm/create-server-fn-plugin/types.d.ts +31 -0
- package/package.json +6 -6
- package/src/create-server-fn-plugin/compiler.ts +215 -94
- package/src/create-server-fn-plugin/handleCreateMiddleware.ts +18 -44
- package/src/create-server-fn-plugin/handleCreateServerFn.ts +39 -60
- package/src/create-server-fn-plugin/types.ts +42 -0
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import * as t from '@babel/types'
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import type { RewriteCandidate } from './types'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Handles createMiddleware transformations.
|
|
6
|
+
*
|
|
7
|
+
* @param candidate - The rewrite candidate containing path and method chain
|
|
8
|
+
* @param opts - Options including the environment
|
|
9
|
+
*/
|
|
5
10
|
export function handleCreateMiddleware(
|
|
6
|
-
|
|
11
|
+
candidate: RewriteCandidate,
|
|
7
12
|
opts: {
|
|
8
13
|
env: 'client' | 'server'
|
|
9
14
|
},
|
|
@@ -11,36 +16,11 @@ export function handleCreateMiddleware(
|
|
|
11
16
|
if (opts.env === 'server') {
|
|
12
17
|
throw new Error('handleCreateMiddleware should not be called on the server')
|
|
13
18
|
}
|
|
14
|
-
const rootCallExpression = getRootCallExpression(path)
|
|
15
|
-
|
|
16
|
-
const callExpressionPaths = {
|
|
17
|
-
middleware: null as babel.NodePath<t.CallExpression> | null,
|
|
18
|
-
inputValidator: null as babel.NodePath<t.CallExpression> | null,
|
|
19
|
-
client: null as babel.NodePath<t.CallExpression> | null,
|
|
20
|
-
server: null as babel.NodePath<t.CallExpression> | null,
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const validMethods = Object.keys(callExpressionPaths)
|
|
24
19
|
|
|
25
|
-
|
|
26
|
-
MemberExpression(memberExpressionPath) {
|
|
27
|
-
if (t.isIdentifier(memberExpressionPath.node.property)) {
|
|
28
|
-
const name = memberExpressionPath.node.property
|
|
29
|
-
.name as keyof typeof callExpressionPaths
|
|
20
|
+
const { inputValidator, server } = candidate.methodChain
|
|
30
21
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
memberExpressionPath.parentPath.isCallExpression()
|
|
34
|
-
) {
|
|
35
|
-
callExpressionPaths[name] = memberExpressionPath.parentPath
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
},
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
if (callExpressionPaths.inputValidator) {
|
|
42
|
-
const innerInputExpression =
|
|
43
|
-
callExpressionPaths.inputValidator.node.arguments[0]
|
|
22
|
+
if (inputValidator) {
|
|
23
|
+
const innerInputExpression = inputValidator.callPath.node.arguments[0]
|
|
44
24
|
|
|
45
25
|
if (!innerInputExpression) {
|
|
46
26
|
throw new Error(
|
|
@@ -49,23 +29,17 @@ export function handleCreateMiddleware(
|
|
|
49
29
|
}
|
|
50
30
|
|
|
51
31
|
// remove the validator call expression
|
|
52
|
-
if (t.isMemberExpression(
|
|
53
|
-
|
|
54
|
-
|
|
32
|
+
if (t.isMemberExpression(inputValidator.callPath.node.callee)) {
|
|
33
|
+
inputValidator.callPath.replaceWith(
|
|
34
|
+
inputValidator.callPath.node.callee.object,
|
|
55
35
|
)
|
|
56
36
|
}
|
|
57
37
|
}
|
|
58
38
|
|
|
59
|
-
|
|
60
|
-
'arguments.0',
|
|
61
|
-
) as babel.NodePath<any>
|
|
62
|
-
|
|
63
|
-
if (callExpressionPaths.server && serverFnPath.node) {
|
|
39
|
+
if (server) {
|
|
64
40
|
// remove the server call expression
|
|
65
|
-
if (t.isMemberExpression(
|
|
66
|
-
|
|
67
|
-
callExpressionPaths.server.node.callee.object,
|
|
68
|
-
)
|
|
41
|
+
if (t.isMemberExpression(server.callPath.node.callee)) {
|
|
42
|
+
server.callPath.replaceWith(server.callPath.node.callee.object)
|
|
69
43
|
}
|
|
70
44
|
}
|
|
71
45
|
}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import * as t from '@babel/types'
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
import { codeFrameError } from '../start-compiler-plugin/utils'
|
|
3
|
+
import type { RewriteCandidate } from './types'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Handles createServerFn transformations.
|
|
7
|
+
*
|
|
8
|
+
* @param candidate - The rewrite candidate containing path and method chain
|
|
9
|
+
* @param opts - Options including the environment, code, directive, and provider file flag
|
|
10
|
+
*/
|
|
8
11
|
export function handleCreateServerFn(
|
|
9
|
-
|
|
12
|
+
candidate: RewriteCandidate,
|
|
10
13
|
opts: {
|
|
11
14
|
env: 'client' | 'server'
|
|
12
15
|
code: string
|
|
@@ -18,56 +21,27 @@ export function handleCreateServerFn(
|
|
|
18
21
|
isProviderFile: boolean
|
|
19
22
|
},
|
|
20
23
|
) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
// are children of the createServerFn call expression.
|
|
24
|
-
|
|
25
|
-
const validMethods = ['middleware', 'inputValidator', 'handler'] as const
|
|
26
|
-
type ValidMethods = (typeof validMethods)[number]
|
|
27
|
-
const callExpressionPaths: Record<
|
|
28
|
-
ValidMethods,
|
|
29
|
-
babel.NodePath<t.CallExpression> | null
|
|
30
|
-
> = {
|
|
31
|
-
middleware: null,
|
|
32
|
-
inputValidator: null,
|
|
33
|
-
handler: null,
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const rootCallExpression = getRootCallExpression(path)
|
|
37
|
-
|
|
38
|
-
// if (debug)
|
|
39
|
-
// console.info(
|
|
40
|
-
// 'Handling createServerFn call expression:',
|
|
41
|
-
// rootCallExpression.toString(),
|
|
42
|
-
// )
|
|
24
|
+
const { path, methodChain } = candidate
|
|
25
|
+
const { inputValidator, handler } = methodChain
|
|
43
26
|
|
|
44
27
|
// Check if the call is assigned to a variable
|
|
45
|
-
if (!
|
|
28
|
+
if (!path.parentPath.isVariableDeclarator()) {
|
|
46
29
|
throw new Error('createServerFn must be assigned to a variable!')
|
|
47
30
|
}
|
|
48
31
|
|
|
49
32
|
// Get the identifier name of the variable
|
|
50
|
-
const variableDeclarator =
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
validMethods.includes(name) &&
|
|
60
|
-
memberExpressionPath.parentPath.isCallExpression()
|
|
61
|
-
) {
|
|
62
|
-
callExpressionPaths[name] = memberExpressionPath.parentPath
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
},
|
|
66
|
-
})
|
|
33
|
+
const variableDeclarator = path.parentPath.node
|
|
34
|
+
if (!t.isIdentifier(variableDeclarator.id)) {
|
|
35
|
+
throw codeFrameError(
|
|
36
|
+
opts.code,
|
|
37
|
+
variableDeclarator.id.loc!,
|
|
38
|
+
'createServerFn must be assigned to a simple identifier, not a destructuring pattern',
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
const existingVariableName = variableDeclarator.id.name
|
|
67
42
|
|
|
68
|
-
if (
|
|
69
|
-
const innerInputExpression =
|
|
70
|
-
callExpressionPaths.inputValidator.node.arguments[0]
|
|
43
|
+
if (inputValidator) {
|
|
44
|
+
const innerInputExpression = inputValidator.callPath.node.arguments[0]
|
|
71
45
|
|
|
72
46
|
if (!innerInputExpression) {
|
|
73
47
|
throw new Error(
|
|
@@ -77,11 +51,9 @@ export function handleCreateServerFn(
|
|
|
77
51
|
|
|
78
52
|
// If we're on the client, remove the validator call expression
|
|
79
53
|
if (opts.env === 'client') {
|
|
80
|
-
if (
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
callExpressionPaths.inputValidator.replaceWith(
|
|
84
|
-
callExpressionPaths.inputValidator.node.callee.object,
|
|
54
|
+
if (t.isMemberExpression(inputValidator.callPath.node.callee)) {
|
|
55
|
+
inputValidator.callPath.replaceWith(
|
|
56
|
+
inputValidator.callPath.node.callee.object,
|
|
85
57
|
)
|
|
86
58
|
}
|
|
87
59
|
}
|
|
@@ -90,11 +62,9 @@ export function handleCreateServerFn(
|
|
|
90
62
|
// First, we need to move the handler function to a nested function call
|
|
91
63
|
// that is applied to the arguments passed to the server function.
|
|
92
64
|
|
|
93
|
-
const handlerFnPath =
|
|
94
|
-
'arguments.0',
|
|
95
|
-
) as babel.NodePath<any>
|
|
65
|
+
const handlerFnPath = handler?.firstArgPath
|
|
96
66
|
|
|
97
|
-
if (!
|
|
67
|
+
if (!handler || !handlerFnPath?.node) {
|
|
98
68
|
throw codeFrameError(
|
|
99
69
|
opts.code,
|
|
100
70
|
path.node.callee.loc!,
|
|
@@ -102,6 +72,15 @@ export function handleCreateServerFn(
|
|
|
102
72
|
)
|
|
103
73
|
}
|
|
104
74
|
|
|
75
|
+
// Validate the handler argument is an expression (not a SpreadElement, etc.)
|
|
76
|
+
if (!t.isExpression(handlerFnPath.node)) {
|
|
77
|
+
throw codeFrameError(
|
|
78
|
+
opts.code,
|
|
79
|
+
handlerFnPath.node.loc!,
|
|
80
|
+
`handler() must be called with an expression, not a ${handlerFnPath.node.type}`,
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
105
84
|
const handlerFn = handlerFnPath.node
|
|
106
85
|
|
|
107
86
|
// So, the way we do this is we give the handler function a way
|
|
@@ -161,6 +140,6 @@ export function handleCreateServerFn(
|
|
|
161
140
|
// Caller files must NOT have the second argument because the implementation is already available in the extracted chunk
|
|
162
141
|
// and including it would duplicate code
|
|
163
142
|
if (opts.env === 'server' && opts.isProviderFile) {
|
|
164
|
-
|
|
143
|
+
handler.callPath.node.arguments.push(handlerFn)
|
|
165
144
|
}
|
|
166
145
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type * as babel from '@babel/core'
|
|
2
|
+
import type * as t from '@babel/types'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Info about a method call in the chain, including the call expression path
|
|
6
|
+
* and the path to its first argument (if any).
|
|
7
|
+
*/
|
|
8
|
+
export interface MethodCallInfo {
|
|
9
|
+
callPath: babel.NodePath<t.CallExpression>
|
|
10
|
+
/** Path to the first argument, or null if no arguments */
|
|
11
|
+
firstArgPath: babel.NodePath | null
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Pre-collected method chain paths for a root call expression.
|
|
16
|
+
* This avoids needing to traverse the AST again in handlers.
|
|
17
|
+
*/
|
|
18
|
+
export interface MethodChainPaths {
|
|
19
|
+
middleware: MethodCallInfo | null
|
|
20
|
+
inputValidator: MethodCallInfo | null
|
|
21
|
+
handler: MethodCallInfo | null
|
|
22
|
+
server: MethodCallInfo | null
|
|
23
|
+
client: MethodCallInfo | null
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type MethodChainKey = keyof MethodChainPaths
|
|
27
|
+
|
|
28
|
+
export const METHOD_CHAIN_KEYS: ReadonlyArray<MethodChainKey> = [
|
|
29
|
+
'middleware',
|
|
30
|
+
'inputValidator',
|
|
31
|
+
'handler',
|
|
32
|
+
'server',
|
|
33
|
+
'client',
|
|
34
|
+
] as const
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Information about a candidate that needs to be rewritten.
|
|
38
|
+
*/
|
|
39
|
+
export interface RewriteCandidate {
|
|
40
|
+
path: babel.NodePath<t.CallExpression>
|
|
41
|
+
methodChain: MethodChainPaths
|
|
42
|
+
}
|