@tanstack/start-plugin-core 1.142.7 → 1.142.10
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 +8 -5
- package/dist/esm/create-server-fn-plugin/compiler.js +108 -43
- package/dist/esm/create-server-fn-plugin/compiler.js.map +1 -1
- package/dist/esm/create-server-fn-plugin/handleCreateIsomorphicFn.d.ts +4 -0
- package/dist/esm/create-server-fn-plugin/handleCreateIsomorphicFn.js +31 -0
- package/dist/esm/create-server-fn-plugin/handleCreateIsomorphicFn.js.map +1 -0
- package/dist/esm/create-server-fn-plugin/handleCreateServerFn.js +1 -1
- package/dist/esm/create-server-fn-plugin/handleCreateServerFn.js.map +1 -1
- package/dist/esm/create-server-fn-plugin/handleEnvOnly.d.ts +6 -0
- package/dist/esm/create-server-fn-plugin/handleEnvOnly.js +36 -0
- package/dist/esm/create-server-fn-plugin/handleEnvOnly.js.map +1 -0
- package/dist/esm/create-server-fn-plugin/plugin.d.ts +1 -1
- package/dist/esm/create-server-fn-plugin/plugin.js +50 -12
- package/dist/esm/create-server-fn-plugin/plugin.js.map +1 -1
- package/dist/esm/create-server-fn-plugin/types.d.ts +0 -1
- package/dist/esm/{start-compiler-plugin → create-server-fn-plugin}/utils.d.ts +0 -3
- package/dist/esm/create-server-fn-plugin/utils.js +19 -0
- package/dist/esm/create-server-fn-plugin/utils.js.map +1 -0
- package/dist/esm/plugin.d.ts +2 -30
- package/dist/esm/plugin.js +2 -2
- package/dist/esm/plugin.js.map +1 -1
- package/dist/esm/schema.d.ts +288 -288
- package/dist/esm/schema.js.map +1 -1
- package/dist/esm/start-manifest-plugin/plugin.d.ts +1 -1
- package/dist/esm/start-manifest-plugin/plugin.js.map +1 -1
- package/dist/esm/start-router-plugin/plugin.d.ts +1 -1
- package/dist/esm/start-router-plugin/plugin.js.map +1 -1
- package/dist/esm/types.d.ts +30 -0
- package/package.json +6 -6
- package/src/create-server-fn-plugin/compiler.ts +164 -58
- package/src/create-server-fn-plugin/handleCreateIsomorphicFn.ts +46 -0
- package/src/create-server-fn-plugin/handleCreateServerFn.ts +1 -1
- package/src/create-server-fn-plugin/handleEnvOnly.ts +45 -0
- package/src/create-server-fn-plugin/plugin.ts +58 -14
- package/src/create-server-fn-plugin/types.ts +0 -8
- package/src/create-server-fn-plugin/utils.ts +24 -0
- package/src/plugin.ts +7 -34
- package/src/schema.ts +1 -1
- package/src/start-manifest-plugin/plugin.ts +1 -1
- package/src/start-router-plugin/plugin.ts +1 -1
- package/src/types.ts +34 -0
- package/dist/esm/start-compiler-plugin/compilers.d.ts +0 -15
- package/dist/esm/start-compiler-plugin/compilers.js +0 -114
- package/dist/esm/start-compiler-plugin/compilers.js.map +0 -1
- package/dist/esm/start-compiler-plugin/constants.d.ts +0 -1
- package/dist/esm/start-compiler-plugin/constants.js +0 -9
- package/dist/esm/start-compiler-plugin/constants.js.map +0 -1
- package/dist/esm/start-compiler-plugin/envOnly.d.ts +0 -5
- package/dist/esm/start-compiler-plugin/envOnly.js +0 -41
- package/dist/esm/start-compiler-plugin/envOnly.js.map +0 -1
- package/dist/esm/start-compiler-plugin/isomorphicFn.d.ts +0 -4
- package/dist/esm/start-compiler-plugin/isomorphicFn.js +0 -49
- package/dist/esm/start-compiler-plugin/isomorphicFn.js.map +0 -1
- package/dist/esm/start-compiler-plugin/plugin.d.ts +0 -12
- package/dist/esm/start-compiler-plugin/plugin.js +0 -88
- package/dist/esm/start-compiler-plugin/plugin.js.map +0 -1
- package/dist/esm/start-compiler-plugin/utils.js +0 -30
- package/dist/esm/start-compiler-plugin/utils.js.map +0 -1
- package/src/start-compiler-plugin/compilers.ts +0 -176
- package/src/start-compiler-plugin/constants.ts +0 -5
- package/src/start-compiler-plugin/envOnly.ts +0 -58
- package/src/start-compiler-plugin/isomorphicFn.ts +0 -78
- package/src/start-compiler-plugin/plugin.ts +0 -111
- package/src/start-compiler-plugin/utils.ts +0 -41
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { pathToFileURL, fileURLToPath } from "node:url";
|
|
2
|
-
import { createRequire } from "node:module";
|
|
3
|
-
import { logDiff } from "@tanstack/router-utils";
|
|
4
|
-
import { VIRTUAL_MODULES } from "@tanstack/start-server-core";
|
|
5
|
-
import { normalizePath } from "vite";
|
|
6
|
-
import path from "pathe";
|
|
7
|
-
import { makeIdFiltersToMatchWithQuery } from "@rolldown/pluginutils";
|
|
8
|
-
import { TRANSFORM_ID_REGEX } from "../constants.js";
|
|
9
|
-
import { compileStartOutputFactory } from "./compilers.js";
|
|
10
|
-
import { transformFuncs } from "./constants.js";
|
|
11
|
-
const debug = process.env.TSR_VITE_DEBUG && ["true", "start-plugin"].includes(process.env.TSR_VITE_DEBUG);
|
|
12
|
-
const tokenRegex = new RegExp(transformFuncs.join("|"));
|
|
13
|
-
const require2 = createRequire(import.meta.url);
|
|
14
|
-
function resolveRuntimeFiles(opts) {
|
|
15
|
-
const pkgRoot = resolvePackage(opts.package);
|
|
16
|
-
const basePath = path.join(pkgRoot, "dist", "esm");
|
|
17
|
-
return opts.files.map((file) => normalizePath(path.join(basePath, file)));
|
|
18
|
-
}
|
|
19
|
-
function resolvePackage(packageName) {
|
|
20
|
-
const pkgRoot = path.dirname(require2.resolve(packageName + "/package.json"));
|
|
21
|
-
return pkgRoot;
|
|
22
|
-
}
|
|
23
|
-
const transformFilter = {
|
|
24
|
-
code: tokenRegex,
|
|
25
|
-
id: {
|
|
26
|
-
include: TRANSFORM_ID_REGEX,
|
|
27
|
-
exclude: [
|
|
28
|
-
VIRTUAL_MODULES.serverFnManifest,
|
|
29
|
-
// N.B. the following files either just re-export or provide the runtime implementation of those functions
|
|
30
|
-
// we do not want to include them in the transformation
|
|
31
|
-
// however, those packages (especially start-client-core ATM) also USE these functions
|
|
32
|
-
// (namely `createIsomorphicFn` in `packages/start-client-core/src/getRouterInstance.ts`) and thus need to be transformed
|
|
33
|
-
...makeIdFiltersToMatchWithQuery([
|
|
34
|
-
...resolveRuntimeFiles({
|
|
35
|
-
package: "@tanstack/start-client-core",
|
|
36
|
-
files: [
|
|
37
|
-
"index.js",
|
|
38
|
-
"createIsomorphicFn.js",
|
|
39
|
-
"envOnly.js",
|
|
40
|
-
"serverFnFetcher.js",
|
|
41
|
-
"createStart.js",
|
|
42
|
-
"createMiddleware.js"
|
|
43
|
-
]
|
|
44
|
-
}),
|
|
45
|
-
...resolveRuntimeFiles({
|
|
46
|
-
package: "@tanstack/start-server-core",
|
|
47
|
-
files: ["index.js", "server-functions-handler.js"]
|
|
48
|
-
})
|
|
49
|
-
])
|
|
50
|
-
]
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
function startCompilerPlugin(opts) {
|
|
54
|
-
const compileStartOutput = compileStartOutputFactory(opts.framework);
|
|
55
|
-
function perEnvCompilerPlugin(environment) {
|
|
56
|
-
return {
|
|
57
|
-
name: `tanstack-start-core:compiler:${environment.name}`,
|
|
58
|
-
enforce: "pre",
|
|
59
|
-
applyToEnvironment(env) {
|
|
60
|
-
return env.name === environment.name;
|
|
61
|
-
},
|
|
62
|
-
transform: {
|
|
63
|
-
filter: transformFilter,
|
|
64
|
-
handler(code, id) {
|
|
65
|
-
const url = pathToFileURL(id);
|
|
66
|
-
url.searchParams.delete("v");
|
|
67
|
-
id = fileURLToPath(url).replace(/\\/g, "/");
|
|
68
|
-
if (debug) console.info(`${environment.name} Compiling Start: `, id);
|
|
69
|
-
const compiled = compileStartOutput({
|
|
70
|
-
code,
|
|
71
|
-
filename: id,
|
|
72
|
-
env: environment.type
|
|
73
|
-
});
|
|
74
|
-
if (debug) {
|
|
75
|
-
logDiff(code, compiled.code);
|
|
76
|
-
console.log("Output:\n", compiled.code + "\n\n");
|
|
77
|
-
}
|
|
78
|
-
return compiled;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
return opts.environments.map(perEnvCompilerPlugin);
|
|
84
|
-
}
|
|
85
|
-
export {
|
|
86
|
-
startCompilerPlugin
|
|
87
|
-
};
|
|
88
|
-
//# sourceMappingURL=plugin.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sources":["../../../src/start-compiler-plugin/plugin.ts"],"sourcesContent":["import { fileURLToPath, pathToFileURL } from 'node:url'\nimport { createRequire } from 'node:module'\nimport { logDiff } from '@tanstack/router-utils'\n\nimport { VIRTUAL_MODULES } from '@tanstack/start-server-core'\nimport { normalizePath } from 'vite'\nimport path from 'pathe'\nimport { makeIdFiltersToMatchWithQuery } from '@rolldown/pluginutils'\nimport { TRANSFORM_ID_REGEX } from '../constants'\nimport { compileStartOutputFactory } from './compilers'\nimport { transformFuncs } from './constants'\nimport type { Plugin, PluginOption } from 'vite'\nimport type { CompileStartFrameworkOptions } from './compilers'\n\nconst debug =\n process.env.TSR_VITE_DEBUG &&\n ['true', 'start-plugin'].includes(process.env.TSR_VITE_DEBUG)\n\nexport type TanStackStartViteOptions = {\n globalMiddlewareEntry: string\n}\n\nconst tokenRegex = new RegExp(transformFuncs.join('|'))\n\nconst require = createRequire(import.meta.url)\n\nfunction resolveRuntimeFiles(opts: { package: string; files: Array<string> }) {\n const pkgRoot = resolvePackage(opts.package)\n const basePath = path.join(pkgRoot, 'dist', 'esm')\n return opts.files.map((file) => normalizePath(path.join(basePath, file)))\n}\n\nfunction resolvePackage(packageName: string): string {\n const pkgRoot = path.dirname(require.resolve(packageName + '/package.json'))\n return pkgRoot\n}\n\nconst transformFilter = {\n code: tokenRegex,\n id: {\n include: TRANSFORM_ID_REGEX,\n exclude: [\n VIRTUAL_MODULES.serverFnManifest,\n // N.B. the following files either just re-export or provide the runtime implementation of those functions\n // we do not want to include them in the transformation\n // however, those packages (especially start-client-core ATM) also USE these functions\n // (namely `createIsomorphicFn` in `packages/start-client-core/src/getRouterInstance.ts`) and thus need to be transformed\n ...makeIdFiltersToMatchWithQuery([\n ...resolveRuntimeFiles({\n package: '@tanstack/start-client-core',\n files: [\n 'index.js',\n 'createIsomorphicFn.js',\n 'envOnly.js',\n 'serverFnFetcher.js',\n 'createStart.js',\n 'createMiddleware.js',\n ],\n }),\n ...resolveRuntimeFiles({\n package: '@tanstack/start-server-core',\n files: ['index.js', 'server-functions-handler.js'],\n }),\n ]),\n ],\n },\n}\n\nexport function startCompilerPlugin(opts: {\n framework: CompileStartFrameworkOptions\n environments: Array<{ name: string; type: 'client' | 'server' }>\n}): PluginOption {\n const compileStartOutput = compileStartOutputFactory(opts.framework)\n\n function perEnvCompilerPlugin(environment: {\n name: string\n type: 'client' | 'server'\n }): Plugin {\n return {\n name: `tanstack-start-core:compiler:${environment.name}`,\n enforce: 'pre',\n applyToEnvironment(env) {\n return env.name === environment.name\n },\n transform: {\n filter: transformFilter,\n handler(code, id) {\n const url = pathToFileURL(id)\n url.searchParams.delete('v')\n id = fileURLToPath(url).replace(/\\\\/g, '/')\n\n if (debug) console.info(`${environment.name} Compiling Start: `, id)\n\n const compiled = compileStartOutput({\n code,\n filename: id,\n env: environment.type,\n })\n\n if (debug) {\n logDiff(code, compiled.code)\n console.log('Output:\\n', compiled.code + '\\n\\n')\n }\n\n return compiled\n },\n },\n }\n }\n return opts.environments.map(perEnvCompilerPlugin)\n}\n"],"names":["require"],"mappings":";;;;;;;;;;AAcA,MAAM,QACJ,QAAQ,IAAI,kBACZ,CAAC,QAAQ,cAAc,EAAE,SAAS,QAAQ,IAAI,cAAc;AAM9D,MAAM,aAAa,IAAI,OAAO,eAAe,KAAK,GAAG,CAAC;AAEtD,MAAMA,WAAU,cAAc,YAAY,GAAG;AAE7C,SAAS,oBAAoB,MAAiD;AAC5E,QAAM,UAAU,eAAe,KAAK,OAAO;AAC3C,QAAM,WAAW,KAAK,KAAK,SAAS,QAAQ,KAAK;AACjD,SAAO,KAAK,MAAM,IAAI,CAAC,SAAS,cAAc,KAAK,KAAK,UAAU,IAAI,CAAC,CAAC;AAC1E;AAEA,SAAS,eAAe,aAA6B;AACnD,QAAM,UAAU,KAAK,QAAQA,SAAQ,QAAQ,cAAc,eAAe,CAAC;AAC3E,SAAO;AACT;AAEA,MAAM,kBAAkB;AAAA,EACtB,MAAM;AAAA,EACN,IAAI;AAAA,IACF,SAAS;AAAA,IACT,SAAS;AAAA,MACP,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA,MAKhB,GAAG,8BAA8B;AAAA,QAC/B,GAAG,oBAAoB;AAAA,UACrB,SAAS;AAAA,UACT,OAAO;AAAA,YACL;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UAAA;AAAA,QACF,CACD;AAAA,QACD,GAAG,oBAAoB;AAAA,UACrB,SAAS;AAAA,UACT,OAAO,CAAC,YAAY,6BAA6B;AAAA,QAAA,CAClD;AAAA,MAAA,CACF;AAAA,IAAA;AAAA,EACH;AAEJ;AAEO,SAAS,oBAAoB,MAGnB;AACf,QAAM,qBAAqB,0BAA0B,KAAK,SAAS;AAEnE,WAAS,qBAAqB,aAGnB;AACT,WAAO;AAAA,MACL,MAAM,gCAAgC,YAAY,IAAI;AAAA,MACtD,SAAS;AAAA,MACT,mBAAmB,KAAK;AACtB,eAAO,IAAI,SAAS,YAAY;AAAA,MAClC;AAAA,MACA,WAAW;AAAA,QACT,QAAQ;AAAA,QACR,QAAQ,MAAM,IAAI;AAChB,gBAAM,MAAM,cAAc,EAAE;AAC5B,cAAI,aAAa,OAAO,GAAG;AAC3B,eAAK,cAAc,GAAG,EAAE,QAAQ,OAAO,GAAG;AAE1C,cAAI,MAAO,SAAQ,KAAK,GAAG,YAAY,IAAI,sBAAsB,EAAE;AAEnE,gBAAM,WAAW,mBAAmB;AAAA,YAClC;AAAA,YACA,UAAU;AAAA,YACV,KAAK,YAAY;AAAA,UAAA,CAClB;AAED,cAAI,OAAO;AACT,oBAAQ,MAAM,SAAS,IAAI;AAC3B,oBAAQ,IAAI,aAAa,SAAS,OAAO,MAAM;AAAA,UACjD;AAEA,iBAAO;AAAA,QACT;AAAA,MAAA;AAAA,IACF;AAAA,EAEJ;AACA,SAAO,KAAK,aAAa,IAAI,oBAAoB;AACnD;"}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { codeFrameColumns } from "@babel/code-frame";
|
|
2
|
-
function getRootCallExpression(path) {
|
|
3
|
-
let rootCallExpression = path;
|
|
4
|
-
while (rootCallExpression.parentPath.isMemberExpression()) {
|
|
5
|
-
const parent = rootCallExpression.parentPath;
|
|
6
|
-
if (parent.parentPath.isCallExpression()) {
|
|
7
|
-
rootCallExpression = parent.parentPath;
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
return rootCallExpression;
|
|
11
|
-
}
|
|
12
|
-
function codeFrameError(code, loc, message) {
|
|
13
|
-
const frame = codeFrameColumns(
|
|
14
|
-
code,
|
|
15
|
-
{
|
|
16
|
-
start: loc.start,
|
|
17
|
-
end: loc.end
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
highlightCode: true,
|
|
21
|
-
message
|
|
22
|
-
}
|
|
23
|
-
);
|
|
24
|
-
return new Error(frame);
|
|
25
|
-
}
|
|
26
|
-
export {
|
|
27
|
-
codeFrameError,
|
|
28
|
-
getRootCallExpression
|
|
29
|
-
};
|
|
30
|
-
//# sourceMappingURL=utils.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["../../../src/start-compiler-plugin/utils.ts"],"sourcesContent":["import { codeFrameColumns } from '@babel/code-frame'\nimport type * as t from '@babel/types'\nimport type * as babel from '@babel/core'\n\nexport function getRootCallExpression(path: babel.NodePath<t.CallExpression>) {\n // Find the highest callExpression parent\n let rootCallExpression: babel.NodePath<t.CallExpression> = path\n\n // Traverse up the chain of CallExpressions\n while (rootCallExpression.parentPath.isMemberExpression()) {\n const parent = rootCallExpression.parentPath\n if (parent.parentPath.isCallExpression()) {\n rootCallExpression = parent.parentPath\n }\n }\n\n return rootCallExpression\n}\n\nexport function codeFrameError(\n code: string,\n loc: {\n start: { line: number; column: number }\n end: { line: number; column: number }\n },\n message: string,\n) {\n const frame = codeFrameColumns(\n code,\n {\n start: loc.start,\n end: loc.end,\n },\n {\n highlightCode: true,\n message,\n },\n )\n\n return new Error(frame)\n}\n"],"names":[],"mappings":";AAIO,SAAS,sBAAsB,MAAwC;AAE5E,MAAI,qBAAuD;AAG3D,SAAO,mBAAmB,WAAW,sBAAsB;AACzD,UAAM,SAAS,mBAAmB;AAClC,QAAI,OAAO,WAAW,oBAAoB;AACxC,2BAAqB,OAAO;AAAA,IAC9B;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,eACd,MACA,KAIA,SACA;AACA,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA;AAAA,MACE,OAAO,IAAI;AAAA,MACX,KAAK,IAAI;AAAA,IAAA;AAAA,IAEX;AAAA,MACE,eAAe;AAAA,MACf;AAAA,IAAA;AAAA,EACF;AAGF,SAAO,IAAI,MAAM,KAAK;AACxB;"}
|
|
@@ -1,176 +0,0 @@
|
|
|
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 { handleCreateIsomorphicFnCallExpression } from './isomorphicFn'
|
|
11
|
-
import {
|
|
12
|
-
handleCreateClientOnlyFnCallExpression,
|
|
13
|
-
handleCreateServerOnlyFnCallExpression,
|
|
14
|
-
} from './envOnly'
|
|
15
|
-
import type { GeneratorResult, ParseAstOptions } from '@tanstack/router-utils'
|
|
16
|
-
|
|
17
|
-
export type CompileStartFrameworkOptions = 'react' | 'solid' | 'vue'
|
|
18
|
-
|
|
19
|
-
type Identifiers = { [K in (typeof transformFuncs)[number]]: IdentifierConfig }
|
|
20
|
-
|
|
21
|
-
export function compileStartOutputFactory(
|
|
22
|
-
framework: CompileStartFrameworkOptions,
|
|
23
|
-
) {
|
|
24
|
-
return function compileStartOutput(opts: CompileOptions): GeneratorResult {
|
|
25
|
-
const identifiers: Partial<Identifiers> = {
|
|
26
|
-
createServerOnlyFn: {
|
|
27
|
-
name: 'createServerOnlyFn',
|
|
28
|
-
handleCallExpression: handleCreateServerOnlyFnCallExpression,
|
|
29
|
-
paths: [],
|
|
30
|
-
},
|
|
31
|
-
createClientOnlyFn: {
|
|
32
|
-
name: 'createClientOnlyFn',
|
|
33
|
-
handleCallExpression: handleCreateClientOnlyFnCallExpression,
|
|
34
|
-
paths: [],
|
|
35
|
-
},
|
|
36
|
-
createIsomorphicFn: {
|
|
37
|
-
name: 'createIsomorphicFn',
|
|
38
|
-
handleCallExpression: handleCreateIsomorphicFnCallExpression,
|
|
39
|
-
paths: [],
|
|
40
|
-
},
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const ast = parseAst(opts)
|
|
44
|
-
|
|
45
|
-
const doDce = opts.dce ?? true
|
|
46
|
-
// find referenced identifiers *before* we transform anything
|
|
47
|
-
const refIdents = doDce ? findReferencedIdentifiers(ast) : undefined
|
|
48
|
-
|
|
49
|
-
const validImportSources = [
|
|
50
|
-
`@tanstack/${framework}-start`,
|
|
51
|
-
'@tanstack/start-client-core',
|
|
52
|
-
]
|
|
53
|
-
babel.traverse(ast, {
|
|
54
|
-
Program: {
|
|
55
|
-
enter(programPath) {
|
|
56
|
-
programPath.traverse({
|
|
57
|
-
ImportDeclaration: (path) => {
|
|
58
|
-
if (!validImportSources.includes(path.node.source.value)) {
|
|
59
|
-
return
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// handle a destructured imports being renamed like "import { createServerFn as myCreateServerFn } from '@tanstack/react-start';"
|
|
63
|
-
path.node.specifiers.forEach((specifier) => {
|
|
64
|
-
transformFuncs.forEach((identifierKey) => {
|
|
65
|
-
const identifier = identifiers[identifierKey]
|
|
66
|
-
if (!identifier) {
|
|
67
|
-
return
|
|
68
|
-
}
|
|
69
|
-
if (
|
|
70
|
-
specifier.type === 'ImportSpecifier' &&
|
|
71
|
-
specifier.imported.type === 'Identifier'
|
|
72
|
-
) {
|
|
73
|
-
if (specifier.imported.name === identifierKey) {
|
|
74
|
-
identifier.name = specifier.local.name
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// handle namespace imports like "import * as TanStackStart from '@tanstack/react-start';"
|
|
79
|
-
if (specifier.type === 'ImportNamespaceSpecifier') {
|
|
80
|
-
identifier.name = `${specifier.local.name}.${identifierKey}`
|
|
81
|
-
}
|
|
82
|
-
})
|
|
83
|
-
})
|
|
84
|
-
},
|
|
85
|
-
CallExpression: (path) => {
|
|
86
|
-
transformFuncs.forEach((identifierKey) => {
|
|
87
|
-
const identifier = identifiers[identifierKey]
|
|
88
|
-
if (!identifier) {
|
|
89
|
-
return
|
|
90
|
-
}
|
|
91
|
-
// Check to see if the call expression is a call to the
|
|
92
|
-
// identifiers[identifierKey].name
|
|
93
|
-
if (
|
|
94
|
-
t.isIdentifier(path.node.callee) &&
|
|
95
|
-
path.node.callee.name === identifier.name
|
|
96
|
-
) {
|
|
97
|
-
// The identifier could be a call to the original function
|
|
98
|
-
// in the source code. If this is case, we need to ignore it.
|
|
99
|
-
// Check the scope to see if the identifier is a function declaration.
|
|
100
|
-
// if it is, then we can ignore it.
|
|
101
|
-
|
|
102
|
-
if (
|
|
103
|
-
path.scope.getBinding(identifier.name)?.path.node.type ===
|
|
104
|
-
'FunctionDeclaration'
|
|
105
|
-
) {
|
|
106
|
-
return
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
return identifier.paths.push(path)
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// handle namespace imports like "import * as TanStackStart from '@tanstack/react-start';"
|
|
113
|
-
// which are then called like "TanStackStart.createServerFn()"
|
|
114
|
-
if (t.isMemberExpression(path.node.callee)) {
|
|
115
|
-
if (
|
|
116
|
-
t.isIdentifier(path.node.callee.object) &&
|
|
117
|
-
t.isIdentifier(path.node.callee.property)
|
|
118
|
-
) {
|
|
119
|
-
const callname = [
|
|
120
|
-
path.node.callee.object.name,
|
|
121
|
-
path.node.callee.property.name,
|
|
122
|
-
].join('.')
|
|
123
|
-
|
|
124
|
-
if (callname === identifier.name) {
|
|
125
|
-
identifier.paths.push(path)
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return
|
|
131
|
-
})
|
|
132
|
-
},
|
|
133
|
-
})
|
|
134
|
-
|
|
135
|
-
transformFuncs.forEach((identifierKey) => {
|
|
136
|
-
const identifier = identifiers[identifierKey]
|
|
137
|
-
if (!identifier) {
|
|
138
|
-
return
|
|
139
|
-
}
|
|
140
|
-
identifier.paths.forEach((path) => {
|
|
141
|
-
identifier.handleCallExpression(
|
|
142
|
-
path as babel.NodePath<t.CallExpression>,
|
|
143
|
-
opts,
|
|
144
|
-
)
|
|
145
|
-
})
|
|
146
|
-
})
|
|
147
|
-
},
|
|
148
|
-
},
|
|
149
|
-
})
|
|
150
|
-
|
|
151
|
-
if (doDce) {
|
|
152
|
-
deadCodeElimination(ast, refIdents)
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return generateFromAst(ast, {
|
|
156
|
-
sourceMaps: true,
|
|
157
|
-
sourceFileName: opts.filename,
|
|
158
|
-
filename: opts.filename,
|
|
159
|
-
})
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
export type CompileOptions = ParseAstOptions & {
|
|
164
|
-
env: 'server' | 'client'
|
|
165
|
-
dce?: boolean
|
|
166
|
-
filename: string
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
export type IdentifierConfig = {
|
|
170
|
-
name: string
|
|
171
|
-
handleCallExpression: (
|
|
172
|
-
path: babel.NodePath<t.CallExpression>,
|
|
173
|
-
opts: CompileOptions,
|
|
174
|
-
) => void
|
|
175
|
-
paths: Array<babel.NodePath>
|
|
176
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import * as t from '@babel/types'
|
|
2
|
-
import type * as babel from '@babel/core'
|
|
3
|
-
|
|
4
|
-
import type { CompileOptions } from './compilers'
|
|
5
|
-
|
|
6
|
-
function capitalize(str: string) {
|
|
7
|
-
if (!str) return ''
|
|
8
|
-
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase()
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function buildEnvOnlyCallExpressionHandler(env: 'client' | 'server') {
|
|
12
|
-
return function envOnlyCallExpressionHandler(
|
|
13
|
-
path: babel.NodePath<t.CallExpression>,
|
|
14
|
-
opts: CompileOptions,
|
|
15
|
-
) {
|
|
16
|
-
// if (debug)
|
|
17
|
-
// console.info(`Handling ${env}Only call expression:`, path.toString())
|
|
18
|
-
|
|
19
|
-
const isEnvMatch =
|
|
20
|
-
env === 'client' ? opts.env === 'client' : opts.env === 'server'
|
|
21
|
-
|
|
22
|
-
if (isEnvMatch) {
|
|
23
|
-
// extract the inner function from the call expression
|
|
24
|
-
const innerInputExpression = path.node.arguments[0]
|
|
25
|
-
|
|
26
|
-
if (!t.isExpression(innerInputExpression)) {
|
|
27
|
-
throw new Error(
|
|
28
|
-
`${env}Only() functions must be called with a function!`,
|
|
29
|
-
)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
path.replaceWith(innerInputExpression)
|
|
33
|
-
return
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// If we're on the wrong environment, replace the call expression
|
|
37
|
-
// with a function that always throws an error.
|
|
38
|
-
path.replaceWith(
|
|
39
|
-
t.arrowFunctionExpression(
|
|
40
|
-
[],
|
|
41
|
-
t.blockStatement([
|
|
42
|
-
t.throwStatement(
|
|
43
|
-
t.newExpression(t.identifier('Error'), [
|
|
44
|
-
t.stringLiteral(
|
|
45
|
-
`create${capitalize(env)}OnlyFn() functions can only be called on the ${env}!`,
|
|
46
|
-
),
|
|
47
|
-
]),
|
|
48
|
-
),
|
|
49
|
-
]),
|
|
50
|
-
),
|
|
51
|
-
)
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export const handleCreateServerOnlyFnCallExpression =
|
|
56
|
-
buildEnvOnlyCallExpressionHandler('server')
|
|
57
|
-
export const handleCreateClientOnlyFnCallExpression =
|
|
58
|
-
buildEnvOnlyCallExpressionHandler('client')
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import * as t from '@babel/types'
|
|
2
|
-
import { getRootCallExpression } from './utils'
|
|
3
|
-
import type * as babel from '@babel/core'
|
|
4
|
-
|
|
5
|
-
import type { CompileOptions } from './compilers'
|
|
6
|
-
|
|
7
|
-
export function handleCreateIsomorphicFnCallExpression(
|
|
8
|
-
path: babel.NodePath<t.CallExpression>,
|
|
9
|
-
opts: CompileOptions,
|
|
10
|
-
) {
|
|
11
|
-
const rootCallExpression = getRootCallExpression(path)
|
|
12
|
-
|
|
13
|
-
// if (debug)
|
|
14
|
-
// console.info(
|
|
15
|
-
// 'Handling createIsomorphicFn call expression:',
|
|
16
|
-
// rootCallExpression.toString(),
|
|
17
|
-
// )
|
|
18
|
-
|
|
19
|
-
const callExpressionPaths = {
|
|
20
|
-
client: null as babel.NodePath<t.CallExpression> | null,
|
|
21
|
-
server: null as babel.NodePath<t.CallExpression> | null,
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const validMethods = Object.keys(callExpressionPaths)
|
|
25
|
-
|
|
26
|
-
rootCallExpression.traverse({
|
|
27
|
-
MemberExpression(memberExpressionPath) {
|
|
28
|
-
if (t.isIdentifier(memberExpressionPath.node.property)) {
|
|
29
|
-
const name = memberExpressionPath.node.property
|
|
30
|
-
.name as keyof typeof callExpressionPaths
|
|
31
|
-
|
|
32
|
-
if (
|
|
33
|
-
validMethods.includes(name) &&
|
|
34
|
-
memberExpressionPath.parentPath.isCallExpression()
|
|
35
|
-
) {
|
|
36
|
-
callExpressionPaths[name] = memberExpressionPath.parentPath
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
},
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
if (
|
|
43
|
-
validMethods.every(
|
|
44
|
-
(method) =>
|
|
45
|
-
!callExpressionPaths[method as keyof typeof callExpressionPaths],
|
|
46
|
-
)
|
|
47
|
-
) {
|
|
48
|
-
const variableId = rootCallExpression.parentPath.isVariableDeclarator()
|
|
49
|
-
? rootCallExpression.parentPath.node.id
|
|
50
|
-
: null
|
|
51
|
-
console.warn(
|
|
52
|
-
'createIsomorphicFn called without a client or server implementation!',
|
|
53
|
-
'This will result in a no-op function.',
|
|
54
|
-
'Variable name:',
|
|
55
|
-
t.isIdentifier(variableId) ? variableId.name : 'unknown',
|
|
56
|
-
)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const envCallExpression = callExpressionPaths[opts.env]
|
|
60
|
-
|
|
61
|
-
if (!envCallExpression) {
|
|
62
|
-
// if we don't have an implementation for this environment, default to a no-op
|
|
63
|
-
rootCallExpression.replaceWith(
|
|
64
|
-
t.arrowFunctionExpression([], t.blockStatement([])),
|
|
65
|
-
)
|
|
66
|
-
return
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const innerInputExpression = envCallExpression.node.arguments[0]
|
|
70
|
-
|
|
71
|
-
if (!t.isExpression(innerInputExpression)) {
|
|
72
|
-
throw new Error(
|
|
73
|
-
`createIsomorphicFn().${opts.env}(func) must be called with a function!`,
|
|
74
|
-
)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
rootCallExpression.replaceWith(innerInputExpression)
|
|
78
|
-
}
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
2
|
-
import { createRequire } from 'node:module'
|
|
3
|
-
import { logDiff } from '@tanstack/router-utils'
|
|
4
|
-
|
|
5
|
-
import { VIRTUAL_MODULES } from '@tanstack/start-server-core'
|
|
6
|
-
import { normalizePath } from 'vite'
|
|
7
|
-
import path from 'pathe'
|
|
8
|
-
import { makeIdFiltersToMatchWithQuery } from '@rolldown/pluginutils'
|
|
9
|
-
import { TRANSFORM_ID_REGEX } from '../constants'
|
|
10
|
-
import { compileStartOutputFactory } from './compilers'
|
|
11
|
-
import { transformFuncs } from './constants'
|
|
12
|
-
import type { Plugin, PluginOption } from 'vite'
|
|
13
|
-
import type { CompileStartFrameworkOptions } from './compilers'
|
|
14
|
-
|
|
15
|
-
const debug =
|
|
16
|
-
process.env.TSR_VITE_DEBUG &&
|
|
17
|
-
['true', 'start-plugin'].includes(process.env.TSR_VITE_DEBUG)
|
|
18
|
-
|
|
19
|
-
export type TanStackStartViteOptions = {
|
|
20
|
-
globalMiddlewareEntry: string
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const tokenRegex = new RegExp(transformFuncs.join('|'))
|
|
24
|
-
|
|
25
|
-
const require = createRequire(import.meta.url)
|
|
26
|
-
|
|
27
|
-
function resolveRuntimeFiles(opts: { package: string; files: Array<string> }) {
|
|
28
|
-
const pkgRoot = resolvePackage(opts.package)
|
|
29
|
-
const basePath = path.join(pkgRoot, 'dist', 'esm')
|
|
30
|
-
return opts.files.map((file) => normalizePath(path.join(basePath, file)))
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function resolvePackage(packageName: string): string {
|
|
34
|
-
const pkgRoot = path.dirname(require.resolve(packageName + '/package.json'))
|
|
35
|
-
return pkgRoot
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const transformFilter = {
|
|
39
|
-
code: tokenRegex,
|
|
40
|
-
id: {
|
|
41
|
-
include: TRANSFORM_ID_REGEX,
|
|
42
|
-
exclude: [
|
|
43
|
-
VIRTUAL_MODULES.serverFnManifest,
|
|
44
|
-
// N.B. the following files either just re-export or provide the runtime implementation of those functions
|
|
45
|
-
// we do not want to include them in the transformation
|
|
46
|
-
// however, those packages (especially start-client-core ATM) also USE these functions
|
|
47
|
-
// (namely `createIsomorphicFn` in `packages/start-client-core/src/getRouterInstance.ts`) and thus need to be transformed
|
|
48
|
-
...makeIdFiltersToMatchWithQuery([
|
|
49
|
-
...resolveRuntimeFiles({
|
|
50
|
-
package: '@tanstack/start-client-core',
|
|
51
|
-
files: [
|
|
52
|
-
'index.js',
|
|
53
|
-
'createIsomorphicFn.js',
|
|
54
|
-
'envOnly.js',
|
|
55
|
-
'serverFnFetcher.js',
|
|
56
|
-
'createStart.js',
|
|
57
|
-
'createMiddleware.js',
|
|
58
|
-
],
|
|
59
|
-
}),
|
|
60
|
-
...resolveRuntimeFiles({
|
|
61
|
-
package: '@tanstack/start-server-core',
|
|
62
|
-
files: ['index.js', 'server-functions-handler.js'],
|
|
63
|
-
}),
|
|
64
|
-
]),
|
|
65
|
-
],
|
|
66
|
-
},
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export function startCompilerPlugin(opts: {
|
|
70
|
-
framework: CompileStartFrameworkOptions
|
|
71
|
-
environments: Array<{ name: string; type: 'client' | 'server' }>
|
|
72
|
-
}): PluginOption {
|
|
73
|
-
const compileStartOutput = compileStartOutputFactory(opts.framework)
|
|
74
|
-
|
|
75
|
-
function perEnvCompilerPlugin(environment: {
|
|
76
|
-
name: string
|
|
77
|
-
type: 'client' | 'server'
|
|
78
|
-
}): Plugin {
|
|
79
|
-
return {
|
|
80
|
-
name: `tanstack-start-core:compiler:${environment.name}`,
|
|
81
|
-
enforce: 'pre',
|
|
82
|
-
applyToEnvironment(env) {
|
|
83
|
-
return env.name === environment.name
|
|
84
|
-
},
|
|
85
|
-
transform: {
|
|
86
|
-
filter: transformFilter,
|
|
87
|
-
handler(code, id) {
|
|
88
|
-
const url = pathToFileURL(id)
|
|
89
|
-
url.searchParams.delete('v')
|
|
90
|
-
id = fileURLToPath(url).replace(/\\/g, '/')
|
|
91
|
-
|
|
92
|
-
if (debug) console.info(`${environment.name} Compiling Start: `, id)
|
|
93
|
-
|
|
94
|
-
const compiled = compileStartOutput({
|
|
95
|
-
code,
|
|
96
|
-
filename: id,
|
|
97
|
-
env: environment.type,
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
if (debug) {
|
|
101
|
-
logDiff(code, compiled.code)
|
|
102
|
-
console.log('Output:\n', compiled.code + '\n\n')
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
return compiled
|
|
106
|
-
},
|
|
107
|
-
},
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
return opts.environments.map(perEnvCompilerPlugin)
|
|
111
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { codeFrameColumns } from '@babel/code-frame'
|
|
2
|
-
import type * as t from '@babel/types'
|
|
3
|
-
import type * as babel from '@babel/core'
|
|
4
|
-
|
|
5
|
-
export function getRootCallExpression(path: babel.NodePath<t.CallExpression>) {
|
|
6
|
-
// Find the highest callExpression parent
|
|
7
|
-
let rootCallExpression: babel.NodePath<t.CallExpression> = path
|
|
8
|
-
|
|
9
|
-
// Traverse up the chain of CallExpressions
|
|
10
|
-
while (rootCallExpression.parentPath.isMemberExpression()) {
|
|
11
|
-
const parent = rootCallExpression.parentPath
|
|
12
|
-
if (parent.parentPath.isCallExpression()) {
|
|
13
|
-
rootCallExpression = parent.parentPath
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
return rootCallExpression
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function codeFrameError(
|
|
21
|
-
code: string,
|
|
22
|
-
loc: {
|
|
23
|
-
start: { line: number; column: number }
|
|
24
|
-
end: { line: number; column: number }
|
|
25
|
-
},
|
|
26
|
-
message: string,
|
|
27
|
-
) {
|
|
28
|
-
const frame = codeFrameColumns(
|
|
29
|
-
code,
|
|
30
|
-
{
|
|
31
|
-
start: loc.start,
|
|
32
|
-
end: loc.end,
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
highlightCode: true,
|
|
36
|
-
message,
|
|
37
|
-
},
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
return new Error(frame)
|
|
41
|
-
}
|