@tanstack/start-plugin-core 1.132.0-alpha.6 → 1.132.0-alpha.8

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.
Files changed (36) hide show
  1. package/dist/esm/start-compiler-plugin/compilers.d.ts +0 -6
  2. package/dist/esm/start-compiler-plugin/compilers.js +12 -271
  3. package/dist/esm/start-compiler-plugin/compilers.js.map +1 -1
  4. package/dist/esm/start-compiler-plugin/constants.d.ts +1 -1
  5. package/dist/esm/start-compiler-plugin/constants.js +2 -2
  6. package/dist/esm/start-compiler-plugin/constants.js.map +1 -1
  7. package/dist/esm/start-compiler-plugin/envOnly.d.ts +5 -0
  8. package/dist/esm/start-compiler-plugin/envOnly.js +41 -0
  9. package/dist/esm/start-compiler-plugin/envOnly.js.map +1 -0
  10. package/dist/esm/start-compiler-plugin/isomorphicFn.d.ts +4 -0
  11. package/dist/esm/start-compiler-plugin/isomorphicFn.js +49 -0
  12. package/dist/esm/start-compiler-plugin/isomorphicFn.js.map +1 -0
  13. package/dist/esm/start-compiler-plugin/middleware.d.ts +4 -0
  14. package/dist/esm/start-compiler-plugin/middleware.js +51 -0
  15. package/dist/esm/start-compiler-plugin/middleware.js.map +1 -0
  16. package/dist/esm/start-compiler-plugin/plugin.js +59 -26
  17. package/dist/esm/start-compiler-plugin/plugin.js.map +1 -1
  18. package/dist/esm/start-compiler-plugin/serverFileRoute.d.ts +4 -0
  19. package/dist/esm/start-compiler-plugin/serverFileRoute.js +38 -0
  20. package/dist/esm/start-compiler-plugin/serverFileRoute.js.map +1 -0
  21. package/dist/esm/start-compiler-plugin/serverFn.d.ts +4 -0
  22. package/dist/esm/start-compiler-plugin/serverFn.js +87 -0
  23. package/dist/esm/start-compiler-plugin/serverFn.js.map +1 -0
  24. package/dist/esm/start-compiler-plugin/utils.d.ts +13 -0
  25. package/dist/esm/start-compiler-plugin/utils.js +30 -0
  26. package/dist/esm/start-compiler-plugin/utils.js.map +1 -0
  27. package/package.json +5 -5
  28. package/src/start-compiler-plugin/compilers.ts +16 -462
  29. package/src/start-compiler-plugin/constants.ts +2 -2
  30. package/src/start-compiler-plugin/envOnly.ts +58 -0
  31. package/src/start-compiler-plugin/isomorphicFn.ts +78 -0
  32. package/src/start-compiler-plugin/middleware.ts +79 -0
  33. package/src/start-compiler-plugin/plugin.ts +67 -36
  34. package/src/start-compiler-plugin/serverFileRoute.ts +59 -0
  35. package/src/start-compiler-plugin/serverFn.ts +163 -0
  36. package/src/start-compiler-plugin/utils.ts +41 -0
@@ -1,21 +1,36 @@
1
1
  import { pathToFileURL, fileURLToPath } from "node:url";
2
+ import { createRequire } from "node:module";
2
3
  import { logDiff } from "@tanstack/router-utils";
3
4
  import { VIRTUAL_MODULES } from "@tanstack/start-server-core";
5
+ import { normalizePath } from "vite";
6
+ import path from "pathe";
7
+ import { VITE_ENVIRONMENT_NAMES } from "../constants.js";
4
8
  import { compileStartOutputFactory } from "./compilers.js";
5
9
  import { transformFuncs } from "./constants.js";
6
10
  const debug = process.env.TSR_VITE_DEBUG && ["true", "start-plugin"].includes(process.env.TSR_VITE_DEBUG);
7
11
  const tokenRegex = new RegExp(transformFuncs.join("|"));
12
+ const require2 = createRequire(import.meta.url);
13
+ function resolveRuntimeFiles(opts) {
14
+ const pkgRoot = resolvePackage(opts.package);
15
+ const basePath = path.join(pkgRoot, "dist", "esm");
16
+ return opts.files.map((file) => normalizePath(path.join(basePath, file)));
17
+ }
18
+ function resolvePackage(packageName) {
19
+ const pkgRoot = path.dirname(require2.resolve(packageName + "/package.json"));
20
+ return pkgRoot;
21
+ }
8
22
  function startCompilerPlugin(framework, inputOpts) {
9
23
  const opts = {
10
24
  client: {
11
- envName: "client",
25
+ envName: VITE_ENVIRONMENT_NAMES.client,
12
26
  ...inputOpts?.client
13
27
  },
14
28
  server: {
15
- envName: "server",
29
+ envName: VITE_ENVIRONMENT_NAMES.server,
16
30
  ...inputOpts?.server
17
31
  }
18
32
  };
33
+ const compileStartOutput = compileStartOutputFactory(framework);
19
34
  return {
20
35
  name: "tanstack-start-core:compiler",
21
36
  enforce: "pre",
@@ -26,7 +41,36 @@ function startCompilerPlugin(framework, inputOpts) {
26
41
  filter: {
27
42
  code: tokenRegex,
28
43
  id: {
29
- exclude: VIRTUAL_MODULES.serverFnManifest
44
+ exclude: [
45
+ VIRTUAL_MODULES.serverFnManifest,
46
+ // N.B. the following files either just re-export or provide the runtime implementation of those functions
47
+ // we do not want to include them in the transformation
48
+ // however, those packages (especially start-client-core ATM) also USE these functions
49
+ // (namely `createIsomorphicFn` in `packages/start-client-core/src/getRouterInstance.ts`) and thus need to be transformed
50
+ ...resolveRuntimeFiles({
51
+ package: "@tanstack/start-client-core",
52
+ files: [
53
+ "index.js",
54
+ "createIsomorphicFn.js",
55
+ "envOnly.js",
56
+ "createServerFn.js",
57
+ "createMiddleware.js",
58
+ "serverFnFetcher.js"
59
+ ]
60
+ }),
61
+ ...resolveRuntimeFiles({
62
+ package: "@tanstack/start-server-core",
63
+ files: [
64
+ "index.js",
65
+ "server-functions-handler.js",
66
+ "serverRoute.js"
67
+ ]
68
+ }),
69
+ ...resolveRuntimeFiles({
70
+ package: `@tanstack/${framework}-start-client`,
71
+ files: ["index.js"]
72
+ })
73
+ ]
30
74
  }
31
75
  },
32
76
  handler(code, id) {
@@ -35,35 +79,24 @@ function startCompilerPlugin(framework, inputOpts) {
35
79
  `Environment ${this.environment.name} not configured`
36
80
  );
37
81
  })();
38
- return transformCode({
82
+ const url = pathToFileURL(id);
83
+ url.searchParams.delete("v");
84
+ id = fileURLToPath(url).replace(/\\/g, "/");
85
+ if (debug) console.info(`${env} Compiling Start: `, id);
86
+ const compiled = compileStartOutput({
39
87
  code,
40
- id,
41
- env,
42
- framework
88
+ filename: id,
89
+ env
43
90
  });
91
+ if (debug) {
92
+ logDiff(code, compiled.code);
93
+ console.log("Output:\n", compiled.code + "\n\n");
94
+ }
95
+ return compiled;
44
96
  }
45
97
  }
46
98
  };
47
99
  }
48
- function transformCode(opts) {
49
- const { code, env, framework } = opts;
50
- let { id } = opts;
51
- const url = pathToFileURL(id);
52
- url.searchParams.delete("v");
53
- id = fileURLToPath(url).replace(/\\/g, "/");
54
- if (debug) console.info(`${env} Compiling Start: `, id);
55
- const compileStartOutput = compileStartOutputFactory(framework);
56
- const compiled = compileStartOutput({
57
- code,
58
- filename: id,
59
- env
60
- });
61
- if (debug) {
62
- logDiff(code, compiled.code);
63
- console.log("Output:\n", compiled.code + "\n\n");
64
- }
65
- return compiled;
66
- }
67
100
  export {
68
101
  startCompilerPlugin
69
102
  };
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sources":["../../../src/start-compiler-plugin/plugin.ts"],"sourcesContent":["import { fileURLToPath, pathToFileURL } from 'node:url'\nimport { logDiff } from '@tanstack/router-utils'\n\nimport { VIRTUAL_MODULES } from '@tanstack/start-server-core'\nimport { compileStartOutputFactory } from './compilers'\nimport { transformFuncs } from './constants'\nimport type { Plugin } 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\nexport function startCompilerPlugin(\n framework: CompileStartFrameworkOptions,\n inputOpts?: {\n client?: {\n envName?: string\n }\n server?: {\n envName?: string\n }\n },\n): Plugin {\n const opts = {\n client: {\n envName: 'client',\n ...inputOpts?.client,\n },\n server: {\n envName: 'server',\n ...inputOpts?.server,\n },\n }\n\n return {\n name: 'tanstack-start-core:compiler',\n enforce: 'pre',\n applyToEnvironment(env) {\n return [opts.client.envName, opts.server.envName].includes(env.name)\n },\n transform: {\n filter: {\n code: tokenRegex,\n id: {\n exclude: VIRTUAL_MODULES.serverFnManifest,\n },\n },\n handler(code, id) {\n const env =\n this.environment.name === opts.client.envName\n ? 'client'\n : this.environment.name === opts.server.envName\n ? 'server'\n : (() => {\n throw new Error(\n `Environment ${this.environment.name} not configured`,\n )\n })()\n\n return transformCode({\n code,\n id,\n env,\n framework,\n })\n },\n },\n }\n}\n\nfunction transformCode(opts: {\n code: string\n id: string\n env: 'server' | 'client'\n framework: CompileStartFrameworkOptions\n}) {\n const { code, env, framework } = opts\n let { id } = opts\n\n const url = pathToFileURL(id)\n url.searchParams.delete('v')\n id = fileURLToPath(url).replace(/\\\\/g, '/')\n\n if (debug) console.info(`${env} Compiling Start: `, id)\n\n const compileStartOutput = compileStartOutputFactory(framework)\n const compiled = compileStartOutput({\n code,\n filename: id,\n env,\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"],"names":[],"mappings":";;;;;AASA,MAAM,QACJ,QAAQ,IAAI,kBACZ,CAAC,QAAQ,cAAc,EAAE,SAAS,QAAQ,IAAI,cAAc;AAM9D,MAAM,aAAa,IAAI,OAAO,eAAe,KAAK,GAAG,CAAC;AAE/C,SAAS,oBACd,WACA,WAQQ;AACR,QAAM,OAAO;AAAA,IACX,QAAQ;AAAA,MACN,SAAS;AAAA,MACT,GAAG,WAAW;AAAA,IAAA;AAAA,IAEhB,QAAQ;AAAA,MACN,SAAS;AAAA,MACT,GAAG,WAAW;AAAA,IAAA;AAAA,EAChB;AAGF,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,mBAAmB,KAAK;AACtB,aAAO,CAAC,KAAK,OAAO,SAAS,KAAK,OAAO,OAAO,EAAE,SAAS,IAAI,IAAI;AAAA,IACrE;AAAA,IACA,WAAW;AAAA,MACT,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,IAAI;AAAA,UACF,SAAS,gBAAgB;AAAA,QAAA;AAAA,MAC3B;AAAA,MAEF,QAAQ,MAAM,IAAI;AAChB,cAAM,MACJ,KAAK,YAAY,SAAS,KAAK,OAAO,UAClC,WACA,KAAK,YAAY,SAAS,KAAK,OAAO,UACpC,YACC,MAAM;AACL,gBAAM,IAAI;AAAA,YACR,eAAe,KAAK,YAAY,IAAI;AAAA,UAAA;AAAA,QAExC,GAAA;AAER,eAAO,cAAc;AAAA,UACnB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QAAA,CACD;AAAA,MACH;AAAA,IAAA;AAAA,EACF;AAEJ;AAEA,SAAS,cAAc,MAKpB;AACD,QAAM,EAAE,MAAM,KAAK,UAAA,IAAc;AACjC,MAAI,EAAE,OAAO;AAEb,QAAM,MAAM,cAAc,EAAE;AAC5B,MAAI,aAAa,OAAO,GAAG;AAC3B,OAAK,cAAc,GAAG,EAAE,QAAQ,OAAO,GAAG;AAE1C,MAAI,MAAO,SAAQ,KAAK,GAAG,GAAG,sBAAsB,EAAE;AAEtD,QAAM,qBAAqB,0BAA0B,SAAS;AAC9D,QAAM,WAAW,mBAAmB;AAAA,IAClC;AAAA,IACA,UAAU;AAAA,IACV;AAAA,EAAA,CACD;AAED,MAAI,OAAO;AACT,YAAQ,MAAM,SAAS,IAAI;AAC3B,YAAQ,IAAI,aAAa,SAAS,OAAO,MAAM;AAAA,EACjD;AAEA,SAAO;AACT;"}
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 { VITE_ENVIRONMENT_NAMES } from '../constants'\nimport { compileStartOutputFactory } from './compilers'\nimport { transformFuncs } from './constants'\nimport type { Plugin } 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\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\nexport function startCompilerPlugin(\n framework: CompileStartFrameworkOptions,\n inputOpts?: {\n client?: {\n envName?: string\n }\n server?: {\n envName?: string\n }\n },\n): Plugin {\n const opts = {\n client: {\n envName: VITE_ENVIRONMENT_NAMES.client,\n ...inputOpts?.client,\n },\n server: {\n envName: VITE_ENVIRONMENT_NAMES.server,\n ...inputOpts?.server,\n },\n }\n\n const compileStartOutput = compileStartOutputFactory(framework)\n\n return {\n name: 'tanstack-start-core:compiler',\n enforce: 'pre',\n applyToEnvironment(env) {\n return [opts.client.envName, opts.server.envName].includes(env.name)\n },\n transform: {\n filter: {\n code: tokenRegex,\n id: {\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 ...resolveRuntimeFiles({\n package: '@tanstack/start-client-core',\n files: [\n 'index.js',\n 'createIsomorphicFn.js',\n 'envOnly.js',\n 'createServerFn.js',\n 'createMiddleware.js',\n 'serverFnFetcher.js',\n ],\n }),\n ...resolveRuntimeFiles({\n package: '@tanstack/start-server-core',\n files: [\n 'index.js',\n 'server-functions-handler.js',\n 'serverRoute.js',\n ],\n }),\n ...resolveRuntimeFiles({\n package: `@tanstack/${framework}-start-client`,\n files: ['index.js'],\n }),\n ],\n },\n },\n handler(code, id) {\n const env =\n this.environment.name === opts.client.envName\n ? 'client'\n : this.environment.name === opts.server.envName\n ? 'server'\n : (() => {\n throw new Error(\n `Environment ${this.environment.name} not configured`,\n )\n })()\n\n const url = pathToFileURL(id)\n url.searchParams.delete('v')\n id = fileURLToPath(url).replace(/\\\\/g, '/')\n\n if (debug) console.info(`${env} Compiling Start: `, id)\n\n const compiled = compileStartOutput({\n code,\n filename: id,\n env,\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"],"names":["require"],"mappings":";;;;;;;;;AAaA,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;AAEjD,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;AAEO,SAAS,oBACd,WACA,WAQQ;AACR,QAAM,OAAO;AAAA,IACX,QAAQ;AAAA,MACN,SAAS,uBAAuB;AAAA,MAChC,GAAG,WAAW;AAAA,IAAA;AAAA,IAEhB,QAAQ;AAAA,MACN,SAAS,uBAAuB;AAAA,MAChC,GAAG,WAAW;AAAA,IAAA;AAAA,EAChB;AAGF,QAAM,qBAAqB,0BAA0B,SAAS;AAE9D,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,mBAAmB,KAAK;AACtB,aAAO,CAAC,KAAK,OAAO,SAAS,KAAK,OAAO,OAAO,EAAE,SAAS,IAAI,IAAI;AAAA,IACrE;AAAA,IACA,WAAW;AAAA,MACT,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,IAAI;AAAA,UACF,SAAS;AAAA,YACP,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA,YAKhB,GAAG,oBAAoB;AAAA,cACrB,SAAS;AAAA,cACT,OAAO;AAAA,gBACL;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,cAAA;AAAA,YACF,CACD;AAAA,YACD,GAAG,oBAAoB;AAAA,cACrB,SAAS;AAAA,cACT,OAAO;AAAA,gBACL;AAAA,gBACA;AAAA,gBACA;AAAA,cAAA;AAAA,YACF,CACD;AAAA,YACD,GAAG,oBAAoB;AAAA,cACrB,SAAS,aAAa,SAAS;AAAA,cAC/B,OAAO,CAAC,UAAU;AAAA,YAAA,CACnB;AAAA,UAAA;AAAA,QACH;AAAA,MACF;AAAA,MAEF,QAAQ,MAAM,IAAI;AAChB,cAAM,MACJ,KAAK,YAAY,SAAS,KAAK,OAAO,UAClC,WACA,KAAK,YAAY,SAAS,KAAK,OAAO,UACpC,YACC,MAAM;AACL,gBAAM,IAAI;AAAA,YACR,eAAe,KAAK,YAAY,IAAI;AAAA,UAAA;AAAA,QAExC,GAAA;AAER,cAAM,MAAM,cAAc,EAAE;AAC5B,YAAI,aAAa,OAAO,GAAG;AAC3B,aAAK,cAAc,GAAG,EAAE,QAAQ,OAAO,GAAG;AAE1C,YAAI,MAAO,SAAQ,KAAK,GAAG,GAAG,sBAAsB,EAAE;AAEtD,cAAM,WAAW,mBAAmB;AAAA,UAClC;AAAA,UACA,UAAU;AAAA,UACV;AAAA,QAAA,CACD;AAED,YAAI,OAAO;AACT,kBAAQ,MAAM,SAAS,IAAI;AAC3B,kBAAQ,IAAI,aAAa,SAAS,OAAO,MAAM;AAAA,QACjD;AAEA,eAAO;AAAA,MACT;AAAA,IAAA;AAAA,EACF;AAEJ;"}
@@ -0,0 +1,4 @@
1
+ import { CompileOptions, CompileStartFrameworkOptions } from './compilers.js';
2
+ import * as t from '@babel/types';
3
+ import type * as babel from '@babel/core';
4
+ export declare function handleCreateServerFileRouteCallExpressionFactory(framework: CompileStartFrameworkOptions, method: 'createServerFileRoute' | 'createServerRoute' | 'createServerRootRoute'): (path: babel.NodePath<t.CallExpression>, opts: CompileOptions) => void;
@@ -0,0 +1,38 @@
1
+ import * as t from "@babel/types";
2
+ function handleCreateServerFileRouteCallExpressionFactory(framework, method) {
3
+ return function handleCreateServerFileRouteCallExpression(path, opts) {
4
+ const PACKAGES = { start: `@tanstack/${framework}-start/server` };
5
+ let highestParent = path;
6
+ while (highestParent.parentPath && !highestParent.parentPath.isProgram()) {
7
+ highestParent = highestParent.parentPath;
8
+ }
9
+ const programPath = highestParent.parentPath;
10
+ if (opts.env === "client") {
11
+ highestParent.remove();
12
+ return;
13
+ }
14
+ let isCreateServerFileRouteImported = false;
15
+ programPath.traverse({
16
+ ImportDeclaration(importPath) {
17
+ const importSource = importPath.node.source.value;
18
+ if (importSource === PACKAGES.start) {
19
+ const specifiers = importPath.node.specifiers;
20
+ isCreateServerFileRouteImported ||= specifiers.some((specifier) => {
21
+ return t.isImportSpecifier(specifier) && t.isIdentifier(specifier.imported) && specifier.imported.name === method;
22
+ });
23
+ }
24
+ }
25
+ });
26
+ if (!isCreateServerFileRouteImported) {
27
+ const importDeclaration = t.importDeclaration(
28
+ [t.importSpecifier(t.identifier(method), t.identifier(method))],
29
+ t.stringLiteral(PACKAGES.start)
30
+ );
31
+ programPath.node.body.unshift(importDeclaration);
32
+ }
33
+ };
34
+ }
35
+ export {
36
+ handleCreateServerFileRouteCallExpressionFactory
37
+ };
38
+ //# sourceMappingURL=serverFileRoute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serverFileRoute.js","sources":["../../../src/start-compiler-plugin/serverFileRoute.ts"],"sourcesContent":["import * as t from '@babel/types'\nimport type * as babel from '@babel/core'\n\nimport type { CompileOptions, CompileStartFrameworkOptions } from './compilers'\n\nexport function handleCreateServerFileRouteCallExpressionFactory(\n framework: CompileStartFrameworkOptions,\n method:\n | 'createServerFileRoute'\n | 'createServerRoute'\n | 'createServerRootRoute',\n) {\n return function handleCreateServerFileRouteCallExpression(\n path: babel.NodePath<t.CallExpression>,\n opts: CompileOptions,\n ) {\n const PACKAGES = { start: `@tanstack/${framework}-start/server` }\n\n let highestParent: babel.NodePath<any> = path\n\n while (highestParent.parentPath && !highestParent.parentPath.isProgram()) {\n highestParent = highestParent.parentPath\n }\n\n const programPath = highestParent.parentPath as babel.NodePath<t.Program>\n\n // If we're on the client, remove the entire variable\n if (opts.env === 'client') {\n highestParent.remove()\n return\n }\n\n let isCreateServerFileRouteImported = false as boolean\n\n programPath.traverse({\n ImportDeclaration(importPath) {\n const importSource = importPath.node.source.value\n if (importSource === PACKAGES.start) {\n const specifiers = importPath.node.specifiers\n isCreateServerFileRouteImported ||= specifiers.some((specifier) => {\n return (\n t.isImportSpecifier(specifier) &&\n t.isIdentifier(specifier.imported) &&\n specifier.imported.name === method\n )\n })\n }\n },\n })\n\n if (!isCreateServerFileRouteImported) {\n const importDeclaration = t.importDeclaration(\n [t.importSpecifier(t.identifier(method), t.identifier(method))],\n t.stringLiteral(PACKAGES.start),\n )\n programPath.node.body.unshift(importDeclaration)\n }\n }\n}\n"],"names":[],"mappings":";AAKO,SAAS,iDACd,WACA,QAIA;AACA,SAAO,SAAS,0CACd,MACA,MACA;AACA,UAAM,WAAW,EAAE,OAAO,aAAa,SAAS,gBAAA;AAEhD,QAAI,gBAAqC;AAEzC,WAAO,cAAc,cAAc,CAAC,cAAc,WAAW,aAAa;AACxE,sBAAgB,cAAc;AAAA,IAChC;AAEA,UAAM,cAAc,cAAc;AAGlC,QAAI,KAAK,QAAQ,UAAU;AACzB,oBAAc,OAAA;AACd;AAAA,IACF;AAEA,QAAI,kCAAkC;AAEtC,gBAAY,SAAS;AAAA,MACnB,kBAAkB,YAAY;AAC5B,cAAM,eAAe,WAAW,KAAK,OAAO;AAC5C,YAAI,iBAAiB,SAAS,OAAO;AACnC,gBAAM,aAAa,WAAW,KAAK;AACnC,8CAAoC,WAAW,KAAK,CAAC,cAAc;AACjE,mBACE,EAAE,kBAAkB,SAAS,KAC7B,EAAE,aAAa,UAAU,QAAQ,KACjC,UAAU,SAAS,SAAS;AAAA,UAEhC,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IAAA,CACD;AAED,QAAI,CAAC,iCAAiC;AACpC,YAAM,oBAAoB,EAAE;AAAA,QAC1B,CAAC,EAAE,gBAAgB,EAAE,WAAW,MAAM,GAAG,EAAE,WAAW,MAAM,CAAC,CAAC;AAAA,QAC9D,EAAE,cAAc,SAAS,KAAK;AAAA,MAAA;AAEhC,kBAAY,KAAK,KAAK,QAAQ,iBAAiB;AAAA,IACjD;AAAA,EACF;AACF;"}
@@ -0,0 +1,4 @@
1
+ import { CompileOptions } from './compilers.js';
2
+ import * as t from '@babel/types';
3
+ import type * as babel from '@babel/core';
4
+ export declare function handleCreateServerFnCallExpression(path: babel.NodePath<t.CallExpression>, opts: CompileOptions): void;
@@ -0,0 +1,87 @@
1
+ import * as t from "@babel/types";
2
+ import { getRootCallExpression, codeFrameError } from "./utils.js";
3
+ function handleCreateServerFnCallExpression(path, opts) {
4
+ const calledOptions = path.node.arguments[0] ? path.get("arguments.0") : null;
5
+ const shouldValidateClient = !!calledOptions?.node.properties.find((prop) => {
6
+ return t.isObjectProperty(prop) && t.isIdentifier(prop.key) && prop.key.name === "validateClient" && t.isBooleanLiteral(prop.value) && prop.value.value === true;
7
+ });
8
+ const callExpressionPaths = {
9
+ middleware: null,
10
+ validator: null,
11
+ handler: null
12
+ };
13
+ const validMethods = Object.keys(callExpressionPaths);
14
+ const rootCallExpression = getRootCallExpression(path);
15
+ if (!rootCallExpression.parentPath.isVariableDeclarator()) {
16
+ throw new Error("createServerFn must be assigned to a variable!");
17
+ }
18
+ const variableDeclarator = rootCallExpression.parentPath.node;
19
+ const existingVariableName = variableDeclarator.id.name;
20
+ rootCallExpression.traverse({
21
+ MemberExpression(memberExpressionPath) {
22
+ if (t.isIdentifier(memberExpressionPath.node.property)) {
23
+ const name = memberExpressionPath.node.property.name;
24
+ if (validMethods.includes(name) && memberExpressionPath.parentPath.isCallExpression()) {
25
+ callExpressionPaths[name] = memberExpressionPath.parentPath;
26
+ }
27
+ }
28
+ }
29
+ });
30
+ if (callExpressionPaths.validator) {
31
+ const innerInputExpression = callExpressionPaths.validator.node.arguments[0];
32
+ if (!innerInputExpression) {
33
+ throw new Error(
34
+ "createServerFn().validator() must be called with a validator!"
35
+ );
36
+ }
37
+ if (opts.env === "client" && !shouldValidateClient && t.isMemberExpression(callExpressionPaths.validator.node.callee)) {
38
+ callExpressionPaths.validator.replaceWith(
39
+ callExpressionPaths.validator.node.callee.object
40
+ );
41
+ }
42
+ }
43
+ const handlerFnPath = callExpressionPaths.handler?.get(
44
+ "arguments.0"
45
+ );
46
+ if (!callExpressionPaths.handler || !handlerFnPath.node) {
47
+ throw codeFrameError(
48
+ opts.code,
49
+ path.node.callee.loc,
50
+ `createServerFn must be called with a "handler" property!`
51
+ );
52
+ }
53
+ const handlerFn = handlerFnPath.node;
54
+ if (t.isIdentifier(handlerFn)) {
55
+ if (opts.env === "client") {
56
+ const binding = handlerFnPath.scope.getBinding(handlerFn.name);
57
+ if (binding) {
58
+ binding.path.remove();
59
+ }
60
+ }
61
+ }
62
+ handlerFnPath.replaceWith(
63
+ t.arrowFunctionExpression(
64
+ [t.identifier("opts"), t.identifier("signal")],
65
+ t.blockStatement(
66
+ // Everything in here is server-only, since the client
67
+ // will strip out anything in the 'use server' directive.
68
+ [
69
+ t.returnStatement(
70
+ t.callExpression(
71
+ t.identifier(`${existingVariableName}.__executeServer`),
72
+ [t.identifier("opts"), t.identifier("signal")]
73
+ )
74
+ )
75
+ ],
76
+ [t.directive(t.directiveLiteral("use server"))]
77
+ )
78
+ )
79
+ );
80
+ if (opts.env === "server") {
81
+ callExpressionPaths.handler.node.arguments.push(handlerFn);
82
+ }
83
+ }
84
+ export {
85
+ handleCreateServerFnCallExpression
86
+ };
87
+ //# sourceMappingURL=serverFn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serverFn.js","sources":["../../../src/start-compiler-plugin/serverFn.ts"],"sourcesContent":["import * as t from '@babel/types'\nimport { codeFrameError, getRootCallExpression } from './utils'\nimport type * as babel from '@babel/core'\n\nimport type { CompileOptions } from './compilers'\n\nexport function handleCreateServerFnCallExpression(\n path: babel.NodePath<t.CallExpression>,\n opts: CompileOptions,\n) {\n // Traverse the member expression and find the call expressions for\n // the validator, handler, and middleware methods. Check to make sure they\n // are children of the createServerFn call expression.\n\n const calledOptions = path.node.arguments[0]\n ? (path.get('arguments.0') as babel.NodePath<t.ObjectExpression>)\n : null\n\n const shouldValidateClient = !!calledOptions?.node.properties.find((prop) => {\n return (\n t.isObjectProperty(prop) &&\n t.isIdentifier(prop.key) &&\n prop.key.name === 'validateClient' &&\n t.isBooleanLiteral(prop.value) &&\n prop.value.value === true\n )\n })\n\n const callExpressionPaths = {\n middleware: null as babel.NodePath<t.CallExpression> | null,\n validator: null as babel.NodePath<t.CallExpression> | null,\n handler: null as babel.NodePath<t.CallExpression> | null,\n }\n\n const validMethods = Object.keys(callExpressionPaths)\n\n const rootCallExpression = getRootCallExpression(path)\n\n // if (debug)\n // console.info(\n // 'Handling createServerFn call expression:',\n // rootCallExpression.toString(),\n // )\n\n // Check if the call is assigned to a variable\n if (!rootCallExpression.parentPath.isVariableDeclarator()) {\n throw new Error('createServerFn must be assigned to a variable!')\n }\n\n // Get the identifier name of the variable\n const variableDeclarator = rootCallExpression.parentPath.node\n const existingVariableName = (variableDeclarator.id as t.Identifier).name\n\n rootCallExpression.traverse({\n MemberExpression(memberExpressionPath) {\n if (t.isIdentifier(memberExpressionPath.node.property)) {\n const name = memberExpressionPath.node.property\n .name as keyof typeof callExpressionPaths\n\n if (\n validMethods.includes(name) &&\n memberExpressionPath.parentPath.isCallExpression()\n ) {\n callExpressionPaths[name] = memberExpressionPath.parentPath\n }\n }\n },\n })\n\n if (callExpressionPaths.validator) {\n const innerInputExpression = callExpressionPaths.validator.node.arguments[0]\n\n if (!innerInputExpression) {\n throw new Error(\n 'createServerFn().validator() must be called with a validator!',\n )\n }\n\n // If we're on the client, and we're not validating the client, remove the validator call expression\n if (\n opts.env === 'client' &&\n !shouldValidateClient &&\n t.isMemberExpression(callExpressionPaths.validator.node.callee)\n ) {\n callExpressionPaths.validator.replaceWith(\n callExpressionPaths.validator.node.callee.object,\n )\n }\n }\n\n // First, we need to move the handler function to a nested function call\n // that is applied to the arguments passed to the server function.\n\n const handlerFnPath = callExpressionPaths.handler?.get(\n 'arguments.0',\n ) as babel.NodePath<any>\n\n if (!callExpressionPaths.handler || !handlerFnPath.node) {\n throw codeFrameError(\n opts.code,\n path.node.callee.loc!,\n `createServerFn must be called with a \"handler\" property!`,\n )\n }\n\n const handlerFn = handlerFnPath.node\n\n // So, the way we do this is we give the handler function a way\n // to access the serverFn ctx on the server via function scope.\n // The 'use server' extracted function will be called with the\n // payload from the client, then use the scoped serverFn ctx\n // to execute the handler function.\n // This way, we can do things like data and middleware validation\n // in the __execute function without having to AST transform the\n // handler function too much itself.\n\n // .handler((optsOut, ctx) => {\n // return ((optsIn) => {\n // 'use server'\n // ctx.__execute(handlerFn, optsIn)\n // })(optsOut)\n // })\n\n // If the handler function is an identifier and we're on the client, we need to\n // remove the bound function from the file.\n // If we're on the server, you can leave it, since it will get referenced\n // as a second argument.\n\n if (t.isIdentifier(handlerFn)) {\n if (opts.env === 'client') {\n // Find the binding for the handler function\n const binding = handlerFnPath.scope.getBinding(handlerFn.name)\n // Remove it\n if (binding) {\n binding.path.remove()\n }\n }\n // If the env is server, just leave it alone\n }\n\n handlerFnPath.replaceWith(\n t.arrowFunctionExpression(\n [t.identifier('opts'), t.identifier('signal')],\n t.blockStatement(\n // Everything in here is server-only, since the client\n // will strip out anything in the 'use server' directive.\n [\n t.returnStatement(\n t.callExpression(\n t.identifier(`${existingVariableName}.__executeServer`),\n [t.identifier('opts'), t.identifier('signal')],\n ),\n ),\n ],\n [t.directive(t.directiveLiteral('use server'))],\n ),\n ),\n )\n\n if (opts.env === 'server') {\n callExpressionPaths.handler.node.arguments.push(handlerFn)\n }\n}\n"],"names":[],"mappings":";;AAMO,SAAS,mCACd,MACA,MACA;AAKA,QAAM,gBAAgB,KAAK,KAAK,UAAU,CAAC,IACtC,KAAK,IAAI,aAAa,IACvB;AAEJ,QAAM,uBAAuB,CAAC,CAAC,eAAe,KAAK,WAAW,KAAK,CAAC,SAAS;AAC3E,WACE,EAAE,iBAAiB,IAAI,KACvB,EAAE,aAAa,KAAK,GAAG,KACvB,KAAK,IAAI,SAAS,oBAClB,EAAE,iBAAiB,KAAK,KAAK,KAC7B,KAAK,MAAM,UAAU;AAAA,EAEzB,CAAC;AAED,QAAM,sBAAsB;AAAA,IAC1B,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,SAAS;AAAA,EAAA;AAGX,QAAM,eAAe,OAAO,KAAK,mBAAmB;AAEpD,QAAM,qBAAqB,sBAAsB,IAAI;AASrD,MAAI,CAAC,mBAAmB,WAAW,wBAAwB;AACzD,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AAGA,QAAM,qBAAqB,mBAAmB,WAAW;AACzD,QAAM,uBAAwB,mBAAmB,GAAoB;AAErE,qBAAmB,SAAS;AAAA,IAC1B,iBAAiB,sBAAsB;AACrC,UAAI,EAAE,aAAa,qBAAqB,KAAK,QAAQ,GAAG;AACtD,cAAM,OAAO,qBAAqB,KAAK,SACpC;AAEH,YACE,aAAa,SAAS,IAAI,KAC1B,qBAAqB,WAAW,oBAChC;AACA,8BAAoB,IAAI,IAAI,qBAAqB;AAAA,QACnD;AAAA,MACF;AAAA,IACF;AAAA,EAAA,CACD;AAED,MAAI,oBAAoB,WAAW;AACjC,UAAM,uBAAuB,oBAAoB,UAAU,KAAK,UAAU,CAAC;AAE3E,QAAI,CAAC,sBAAsB;AACzB,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,IAEJ;AAGA,QACE,KAAK,QAAQ,YACb,CAAC,wBACD,EAAE,mBAAmB,oBAAoB,UAAU,KAAK,MAAM,GAC9D;AACA,0BAAoB,UAAU;AAAA,QAC5B,oBAAoB,UAAU,KAAK,OAAO;AAAA,MAAA;AAAA,IAE9C;AAAA,EACF;AAKA,QAAM,gBAAgB,oBAAoB,SAAS;AAAA,IACjD;AAAA,EAAA;AAGF,MAAI,CAAC,oBAAoB,WAAW,CAAC,cAAc,MAAM;AACvD,UAAM;AAAA,MACJ,KAAK;AAAA,MACL,KAAK,KAAK,OAAO;AAAA,MACjB;AAAA,IAAA;AAAA,EAEJ;AAEA,QAAM,YAAY,cAAc;AAuBhC,MAAI,EAAE,aAAa,SAAS,GAAG;AAC7B,QAAI,KAAK,QAAQ,UAAU;AAEzB,YAAM,UAAU,cAAc,MAAM,WAAW,UAAU,IAAI;AAE7D,UAAI,SAAS;AACX,gBAAQ,KAAK,OAAA;AAAA,MACf;AAAA,IACF;AAAA,EAEF;AAEA,gBAAc;AAAA,IACZ,EAAE;AAAA,MACA,CAAC,EAAE,WAAW,MAAM,GAAG,EAAE,WAAW,QAAQ,CAAC;AAAA,MAC7C,EAAE;AAAA;AAAA;AAAA,QAGA;AAAA,UACE,EAAE;AAAA,YACA,EAAE;AAAA,cACA,EAAE,WAAW,GAAG,oBAAoB,kBAAkB;AAAA,cACtD,CAAC,EAAE,WAAW,MAAM,GAAG,EAAE,WAAW,QAAQ,CAAC;AAAA,YAAA;AAAA,UAC/C;AAAA,QACF;AAAA,QAEF,CAAC,EAAE,UAAU,EAAE,iBAAiB,YAAY,CAAC,CAAC;AAAA,MAAA;AAAA,IAChD;AAAA,EACF;AAGF,MAAI,KAAK,QAAQ,UAAU;AACzB,wBAAoB,QAAQ,KAAK,UAAU,KAAK,SAAS;AAAA,EAC3D;AACF;"}
@@ -0,0 +1,13 @@
1
+ import type * as t from '@babel/types';
2
+ import type * as babel from '@babel/core';
3
+ export declare function getRootCallExpression(path: babel.NodePath<t.CallExpression>): babel.NodePath<t.CallExpression>;
4
+ export declare function codeFrameError(code: string, loc: {
5
+ start: {
6
+ line: number;
7
+ column: number;
8
+ };
9
+ end: {
10
+ line: number;
11
+ column: number;
12
+ };
13
+ }, message: string): Error;
@@ -0,0 +1,30 @@
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
@@ -0,0 +1 @@
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;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/start-plugin-core",
3
- "version": "1.132.0-alpha.6",
3
+ "version": "1.132.0-alpha.8",
4
4
  "description": "Modern and scalable routing for React applications",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -57,12 +57,12 @@
57
57
  "vitefu": "^1.1.1",
58
58
  "xmlbuilder2": "^3.1.1",
59
59
  "zod": "^3.24.2",
60
- "@tanstack/router-core": "1.132.0-alpha.4",
61
- "@tanstack/router-generator": "1.132.0-alpha.4",
62
- "@tanstack/router-plugin": "1.132.0-alpha.4",
60
+ "@tanstack/router-core": "1.132.0-alpha.8",
61
+ "@tanstack/router-generator": "1.132.0-alpha.8",
63
62
  "@tanstack/router-utils": "1.132.0-alpha.1",
63
+ "@tanstack/router-plugin": "1.132.0-alpha.8",
64
64
  "@tanstack/server-functions-plugin": "1.132.0-alpha.3",
65
- "@tanstack/start-server-core": "1.132.0-alpha.5"
65
+ "@tanstack/start-server-core": "1.132.0-alpha.8"
66
66
  },
67
67
  "devDependencies": {
68
68
  "@types/babel__code-frame": "^7.0.6",