@tanstack/start-plugin-core 1.132.0-alpha.9 → 1.132.1

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 (78) hide show
  1. package/dist/esm/constants.d.ts +2 -1
  2. package/dist/esm/constants.js +3 -2
  3. package/dist/esm/constants.js.map +1 -1
  4. package/dist/esm/create-server-fn-plugin/compiler.d.ts +8 -5
  5. package/dist/esm/create-server-fn-plugin/compiler.js +74 -46
  6. package/dist/esm/create-server-fn-plugin/compiler.js.map +1 -1
  7. package/dist/esm/create-server-fn-plugin/handleCreateMiddleware.d.ts +5 -0
  8. package/dist/esm/{start-compiler-plugin/middleware.js → create-server-fn-plugin/handleCreateMiddleware.js} +11 -11
  9. package/dist/esm/create-server-fn-plugin/handleCreateMiddleware.js.map +1 -0
  10. package/dist/esm/create-server-fn-plugin/handleCreateServerFn.js +8 -8
  11. package/dist/esm/create-server-fn-plugin/handleCreateServerFn.js.map +1 -1
  12. package/dist/esm/create-server-fn-plugin/plugin.d.ts +1 -1
  13. package/dist/esm/create-server-fn-plugin/plugin.js +22 -7
  14. package/dist/esm/create-server-fn-plugin/plugin.js.map +1 -1
  15. package/dist/esm/dev-server-plugin/plugin.d.ts +4 -2
  16. package/dist/esm/dev-server-plugin/plugin.js +6 -2
  17. package/dist/esm/dev-server-plugin/plugin.js.map +1 -1
  18. package/dist/esm/plugin.d.ts +12 -6
  19. package/dist/esm/plugin.js +54 -65
  20. package/dist/esm/plugin.js.map +1 -1
  21. package/dist/esm/resolve-entries.d.ts +0 -1
  22. package/dist/esm/resolve-entries.js +1 -1
  23. package/dist/esm/resolve-entries.js.map +1 -1
  24. package/dist/esm/schema.d.ts +375 -308
  25. package/dist/esm/schema.js +23 -11
  26. package/dist/esm/schema.js.map +1 -1
  27. package/dist/esm/start-compiler-plugin/compilers.js +17 -49
  28. package/dist/esm/start-compiler-plugin/compilers.js.map +1 -1
  29. package/dist/esm/start-compiler-plugin/constants.d.ts +1 -1
  30. package/dist/esm/start-compiler-plugin/constants.js +1 -5
  31. package/dist/esm/start-compiler-plugin/constants.js.map +1 -1
  32. package/dist/esm/start-router-plugin/constants.d.ts +1 -0
  33. package/dist/esm/start-router-plugin/constants.js +5 -0
  34. package/dist/esm/start-router-plugin/constants.js.map +1 -0
  35. package/dist/esm/start-router-plugin/generator-plugins/routes-manifest-plugin.js +3 -9
  36. package/dist/esm/start-router-plugin/generator-plugins/routes-manifest-plugin.js.map +1 -1
  37. package/dist/esm/start-router-plugin/plugin.d.ts +3 -2
  38. package/dist/esm/start-router-plugin/plugin.js +191 -31
  39. package/dist/esm/start-router-plugin/plugin.js.map +1 -1
  40. package/dist/esm/start-router-plugin/pruneServerOnlySubtrees.d.ts +8 -0
  41. package/dist/esm/start-router-plugin/pruneServerOnlySubtrees.js +34 -0
  42. package/dist/esm/start-router-plugin/pruneServerOnlySubtrees.js.map +1 -0
  43. package/package.json +8 -8
  44. package/src/constants.ts +3 -2
  45. package/src/create-server-fn-plugin/compiler.ts +99 -57
  46. package/src/{start-compiler-plugin/middleware.ts → create-server-fn-plugin/handleCreateMiddleware.ts} +15 -12
  47. package/src/create-server-fn-plugin/handleCreateServerFn.ts +11 -8
  48. package/src/create-server-fn-plugin/plugin.ts +24 -9
  49. package/src/dev-server-plugin/plugin.ts +6 -3
  50. package/src/plugin.ts +76 -84
  51. package/src/resolve-entries.ts +1 -2
  52. package/src/schema.ts +31 -14
  53. package/src/start-compiler-plugin/compilers.ts +18 -51
  54. package/src/start-compiler-plugin/constants.ts +0 -4
  55. package/src/start-router-plugin/constants.ts +1 -0
  56. package/src/start-router-plugin/generator-plugins/routes-manifest-plugin.ts +3 -9
  57. package/src/start-router-plugin/plugin.ts +233 -45
  58. package/src/start-router-plugin/pruneServerOnlySubtrees.ts +51 -0
  59. package/dist/esm/debug.js +0 -5
  60. package/dist/esm/debug.js.map +0 -1
  61. package/dist/esm/start-compiler-plugin/middleware.d.ts +0 -4
  62. package/dist/esm/start-compiler-plugin/middleware.js.map +0 -1
  63. package/dist/esm/start-compiler-plugin/serverFileRoute.d.ts +0 -4
  64. package/dist/esm/start-compiler-plugin/serverFileRoute.js +0 -38
  65. package/dist/esm/start-compiler-plugin/serverFileRoute.js.map +0 -1
  66. package/dist/esm/start-router-plugin/generator-plugins/server-routes-plugin.d.ts +0 -2
  67. package/dist/esm/start-router-plugin/generator-plugins/server-routes-plugin.js +0 -119
  68. package/dist/esm/start-router-plugin/generator-plugins/server-routes-plugin.js.map +0 -1
  69. package/dist/esm/start-router-plugin/route-tree-client-plugin.d.ts +0 -6
  70. package/dist/esm/start-router-plugin/route-tree-client-plugin.js +0 -56
  71. package/dist/esm/start-router-plugin/route-tree-client-plugin.js.map +0 -1
  72. package/dist/esm/start-router-plugin/virtual-route-tree-plugin.d.ts +0 -3
  73. package/dist/esm/start-router-plugin/virtual-route-tree-plugin.js +0 -29
  74. package/dist/esm/start-router-plugin/virtual-route-tree-plugin.js.map +0 -1
  75. package/src/start-compiler-plugin/serverFileRoute.ts +0 -59
  76. package/src/start-router-plugin/generator-plugins/server-routes-plugin.ts +0 -138
  77. package/src/start-router-plugin/route-tree-client-plugin.ts +0 -77
  78. package/src/start-router-plugin/virtual-route-tree-plugin.ts +0 -29
@@ -6,5 +6,6 @@ export type ViteEnvironmentNames = (typeof VITE_ENVIRONMENT_NAMES)[keyof typeof
6
6
  export declare const ENTRY_POINTS: {
7
7
  readonly client: "virtual:tanstack-start-client-entry";
8
8
  readonly server: "virtual:tanstack-start-server-request-entry";
9
- readonly router: "#tanstack-start-router-entry";
9
+ readonly start: "#tanstack-start-entry";
10
+ readonly router: "#tanstack-router-entry";
10
11
  };
@@ -7,8 +7,9 @@ const VITE_ENVIRONMENT_NAMES = {
7
7
  const ENTRY_POINTS = {
8
8
  client: "virtual:tanstack-start-client-entry",
9
9
  server: "virtual:tanstack-start-server-request-entry",
10
- // the router entry point must always be provided by the user
11
- router: "#tanstack-start-router-entry"
10
+ // the start entry point must always be provided by the user
11
+ start: "#tanstack-start-entry",
12
+ router: "#tanstack-router-entry"
12
13
  };
13
14
  export {
14
15
  ENTRY_POINTS,
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sources":["../../src/constants.ts"],"sourcesContent":["export const VITE_ENVIRONMENT_NAMES = {\n // 'ssr' is chosen as the name for the server environment to ensure backwards compatibility\n // with vite plugins that are not compatible with the new vite environment API (e.g. tailwindcss)\n server: 'ssr',\n client: 'client',\n} as const\n\nexport type ViteEnvironmentNames =\n (typeof VITE_ENVIRONMENT_NAMES)[keyof typeof VITE_ENVIRONMENT_NAMES]\n\n// for client and router:\n// if a user has a custom server/client entry point file, resolve.alias will point to this\n// otherwise it will be aliased to the default entry point in the respective framework plugin\nexport const ENTRY_POINTS = {\n client: 'virtual:tanstack-start-client-entry',\n server: 'virtual:tanstack-start-server-request-entry',\n // the router entry point must always be provided by the user\n router: '#tanstack-start-router-entry',\n} as const\n"],"names":[],"mappings":"AAAO,MAAM,yBAAyB;AAAA;AAAA;AAAA,EAGpC,QAAQ;AAAA,EACR,QAAQ;AACV;AAQO,MAAM,eAAe;AAAA,EAC1B,QAAQ;AAAA,EACR,QAAQ;AAAA;AAAA,EAER,QAAQ;AACV;"}
1
+ {"version":3,"file":"constants.js","sources":["../../src/constants.ts"],"sourcesContent":["export const VITE_ENVIRONMENT_NAMES = {\n // 'ssr' is chosen as the name for the server environment to ensure backwards compatibility\n // with vite plugins that are not compatible with the new vite environment API (e.g. tailwindcss)\n server: 'ssr',\n client: 'client',\n} as const\n\nexport type ViteEnvironmentNames =\n (typeof VITE_ENVIRONMENT_NAMES)[keyof typeof VITE_ENVIRONMENT_NAMES]\n\n// for client and router:\n// if a user has a custom server/client entry point file, resolve.alias will point to this\n// otherwise it will be aliased to the default entry point in the respective framework plugin\nexport const ENTRY_POINTS = {\n client: 'virtual:tanstack-start-client-entry',\n server: 'virtual:tanstack-start-server-request-entry',\n // the start entry point must always be provided by the user\n start: '#tanstack-start-entry',\n router: '#tanstack-router-entry',\n} as const\n"],"names":[],"mappings":"AAAO,MAAM,yBAAyB;AAAA;AAAA;AAAA,EAGpC,QAAQ;AAAA,EACR,QAAQ;AACV;AAQO,MAAM,eAAe;AAAA,EAC1B,QAAQ;AAAA,EACR,QAAQ;AAAA;AAAA,EAER,OAAO;AAAA,EACP,QAAQ;AACV;"}
@@ -21,7 +21,12 @@ type ExportEntry = {
21
21
  name: string;
22
22
  targetId: string;
23
23
  };
24
- type Kind = 'None' | 'Root' | 'Builder' | 'ServerFn';
24
+ type Kind = 'None' | `Root` | `Builder` | LookupKind;
25
+ type LookupKind = 'ServerFn' | 'Middleware';
26
+ export type LookupConfig = {
27
+ libName: string;
28
+ rootExport: string;
29
+ };
25
30
  interface ModuleInfo {
26
31
  id: string;
27
32
  code: string;
@@ -32,12 +37,10 @@ interface ModuleInfo {
32
37
  export declare class ServerFnCompiler {
33
38
  private options;
34
39
  private moduleCache;
35
- private resolvedLibId;
36
40
  private initialized;
37
41
  constructor(options: {
38
42
  env: 'client' | 'server';
39
- libName: string;
40
- rootExport: string;
43
+ lookupConfigurations: Array<LookupConfig>;
41
44
  loadModule: (id: string) => Promise<void>;
42
45
  resolveId: (id: string, importer?: string) => Promise<string | null>;
43
46
  });
@@ -51,7 +54,7 @@ export declare class ServerFnCompiler {
51
54
  code: string;
52
55
  id: string;
53
56
  }): Promise<import('@tanstack/router-utils').GeneratorResult | null>;
54
- private collectHandlerCandidates;
57
+ private collectCandidates;
55
58
  private resolveIdentifierKind;
56
59
  private resolveBindingKind;
57
60
  private resolveExprKind;
@@ -3,37 +3,51 @@ import { parseAst, generateFromAst } from "@tanstack/router-utils";
3
3
  import babel__default from "@babel/core";
4
4
  import { findReferencedIdentifiers, deadCodeElimination } from "babel-dead-code-elimination";
5
5
  import { handleCreateServerFn } from "./handleCreateServerFn.js";
6
+ import { handleCreateMiddleware } from "./handleCreateMiddleware.js";
7
+ const validLookupKinds = ["ServerFn", "Middleware"];
8
+ const candidateCallIdentifier = ["handler", "server", "client"];
6
9
  class ServerFnCompiler {
7
10
  constructor(options) {
8
11
  this.options = options;
9
12
  }
10
13
  moduleCache = /* @__PURE__ */ new Map();
11
- resolvedLibId;
12
14
  initialized = false;
13
15
  async init(id) {
14
- const libId = await this.options.resolveId(this.options.libName, id);
15
- if (!libId) {
16
- throw new Error(`could not resolve "${this.options.libName}"`);
17
- }
18
- const rootModule = {
19
- ast: null,
20
- bindings: /* @__PURE__ */ new Map(),
21
- exports: /* @__PURE__ */ new Map(),
22
- code: "",
23
- id: libId
24
- };
25
- rootModule.exports.set(this.options.rootExport, {
26
- tag: "Normal",
27
- name: this.options.rootExport
28
- });
29
- rootModule.bindings.set(this.options.rootExport, {
30
- type: "var",
31
- init: t.identifier(this.options.rootExport),
32
- resolvedKind: "Root"
33
- });
34
- this.moduleCache.set(libId, rootModule);
16
+ await Promise.all(
17
+ this.options.lookupConfigurations.map(async (config) => {
18
+ const libId = await this.options.resolveId(config.libName, id);
19
+ if (!libId) {
20
+ throw new Error(`could not resolve "${config.libName}"`);
21
+ }
22
+ let rootModule = this.moduleCache.get(libId);
23
+ if (!rootModule) {
24
+ rootModule = {
25
+ ast: null,
26
+ bindings: /* @__PURE__ */ new Map(),
27
+ exports: /* @__PURE__ */ new Map(),
28
+ code: "",
29
+ id: libId
30
+ };
31
+ this.moduleCache.set(libId, rootModule);
32
+ }
33
+ rootModule.exports.set(config.rootExport, {
34
+ tag: "Normal",
35
+ name: config.rootExport
36
+ });
37
+ rootModule.exports.set("*", {
38
+ tag: "Namespace",
39
+ name: config.rootExport,
40
+ targetId: libId
41
+ });
42
+ rootModule.bindings.set(config.rootExport, {
43
+ type: "var",
44
+ init: t.identifier(config.rootExport),
45
+ resolvedKind: `Root`
46
+ });
47
+ this.moduleCache.set(libId, rootModule);
48
+ })
49
+ );
35
50
  this.initialized = true;
36
- this.resolvedLibId = libId;
37
51
  }
38
52
  ingestModule({ code, id }) {
39
53
  const ast = parseAst({ code });
@@ -116,15 +130,15 @@ class ServerFnCompiler {
116
130
  await this.init(id);
117
131
  }
118
132
  const { bindings, ast } = this.ingestModule({ code, id });
119
- const candidates = this.collectHandlerCandidates(bindings);
133
+ const candidates = this.collectCandidates(bindings);
120
134
  if (candidates.length === 0) {
121
135
  return null;
122
136
  }
123
137
  const toRewrite = [];
124
138
  for (const handler of candidates) {
125
139
  const kind = await this.resolveExprKind(handler, id);
126
- if (kind === "ServerFn") {
127
- toRewrite.push(handler);
140
+ if (validLookupKinds.includes(kind)) {
141
+ toRewrite.push({ callExpression: handler, kind });
128
142
  }
129
143
  }
130
144
  if (toRewrite.length === 0) {
@@ -133,9 +147,9 @@ class ServerFnCompiler {
133
147
  const pathsToRewrite = [];
134
148
  babel__default.traverse(ast, {
135
149
  CallExpression(path) {
136
- const found = toRewrite.findIndex((h) => path.node === h);
150
+ const found = toRewrite.findIndex((h) => path.node === h.callExpression);
137
151
  if (found !== -1) {
138
- pathsToRewrite.push(path);
152
+ pathsToRewrite.push({ nodePath: path, kind: toRewrite[found].kind });
139
153
  toRewrite.splice(found, 1);
140
154
  }
141
155
  }
@@ -146,9 +160,13 @@ class ServerFnCompiler {
146
160
  );
147
161
  }
148
162
  const refIdents = findReferencedIdentifiers(ast);
149
- pathsToRewrite.map(
150
- (p) => handleCreateServerFn(p, { env: this.options.env, code })
151
- );
163
+ pathsToRewrite.map((p) => {
164
+ if (p.kind === "ServerFn") {
165
+ handleCreateServerFn(p.nodePath, { env: this.options.env, code });
166
+ } else {
167
+ handleCreateMiddleware(p.nodePath, { env: this.options.env });
168
+ }
169
+ });
152
170
  deadCodeElimination(ast, refIdents);
153
171
  return generateFromAst(ast, {
154
172
  sourceMaps: true,
@@ -156,12 +174,12 @@ class ServerFnCompiler {
156
174
  filename: id
157
175
  });
158
176
  }
159
- // collects all `.handler(...)` CallExpressions at top-level
160
- collectHandlerCandidates(bindings) {
177
+ // collects all candidate CallExpressions at top-level
178
+ collectCandidates(bindings) {
161
179
  const candidates = [];
162
180
  for (const binding of bindings.values()) {
163
181
  if (binding.type === "var") {
164
- const handler = isHandlerCall(binding.init);
182
+ const handler = isCandidateCallExpression(binding.init);
165
183
  if (handler) {
166
184
  candidates.push(handler);
167
185
  }
@@ -196,11 +214,6 @@ class ServerFnCompiler {
196
214
  if (!target) {
197
215
  return "None";
198
216
  }
199
- if (binding.importedName === "*") {
200
- throw new Error(
201
- `should never get here, namespace imports are handled in resolveCalleeKind`
202
- );
203
- }
204
217
  const importedModule = await this.getModuleInfo(target);
205
218
  const moduleExport = importedModule.exports.get(binding.importedName);
206
219
  if (!moduleExport) {
@@ -243,11 +256,15 @@ class ServerFnCompiler {
243
256
  fileId,
244
257
  visited
245
258
  );
246
- if (calleeKind === "Root" || calleeKind === "Builder") {
247
- return "Builder";
248
- }
249
- if (calleeKind === "ServerFn") {
250
- return "ServerFn";
259
+ if (calleeKind !== "None") {
260
+ if (calleeKind === `Root` || calleeKind === `Builder`) {
261
+ return `Builder`;
262
+ }
263
+ for (const kind of validLookupKinds) {
264
+ if (calleeKind === kind) {
265
+ return kind;
266
+ }
267
+ }
251
268
  }
252
269
  } else if (t.isMemberExpression(expr) && t.isIdentifier(expr.property)) {
253
270
  result = await this.resolveCalleeKind(expr.object, fileId, visited);
@@ -278,6 +295,12 @@ class ServerFnCompiler {
278
295
  return "ServerFn";
279
296
  }
280
297
  return "None";
298
+ } else if (prop === "client" || prop === "server" || prop === "createMiddleware") {
299
+ const base = await this.resolveExprKind(callee.object, fileId, visited);
300
+ if (base === "Root" || base === "Builder" || base === "Middleware") {
301
+ return "Middleware";
302
+ }
303
+ return "None";
281
304
  }
282
305
  if (t.isIdentifier(callee.object)) {
283
306
  const info = await this.getModuleInfo(fileId);
@@ -302,6 +325,8 @@ class ServerFnCompiler {
302
325
  );
303
326
  }
304
327
  }
328
+ } else {
329
+ return "None";
305
330
  }
306
331
  }
307
332
  }
@@ -322,10 +347,13 @@ class ServerFnCompiler {
322
347
  return cached;
323
348
  }
324
349
  }
325
- function isHandlerCall(node) {
350
+ function isCandidateCallExpression(node) {
326
351
  if (!t.isCallExpression(node)) return void 0;
327
352
  const callee = node.callee;
328
- if (!t.isMemberExpression(callee) || !t.isIdentifier(callee.property, { name: "handler" })) {
353
+ if (!t.isMemberExpression(callee) || !t.isIdentifier(callee.property)) {
354
+ return void 0;
355
+ }
356
+ if (!candidateCallIdentifier.includes(callee.property.name)) {
329
357
  return void 0;
330
358
  }
331
359
  return node;
@@ -1 +1 @@
1
- {"version":3,"file":"compiler.js","sources":["../../../src/create-server-fn-plugin/compiler.ts"],"sourcesContent":["/* eslint-disable import/no-commonjs */\nimport * as t from '@babel/types'\nimport { generateFromAst, parseAst } from '@tanstack/router-utils'\nimport babel from '@babel/core'\nimport {\n deadCodeElimination,\n findReferencedIdentifiers,\n} from 'babel-dead-code-elimination'\nimport { handleCreateServerFn } from './handleCreateServerFn'\n\ntype Binding =\n | {\n type: 'import'\n source: string\n importedName: string\n resolvedKind?: Kind\n }\n | {\n type: 'var'\n init: t.Expression | null\n resolvedKind?: Kind\n }\n\ntype ExportEntry =\n | { tag: 'Normal'; name: string }\n | { tag: 'Default'; name: string }\n | { tag: 'Namespace'; name: string; targetId: string } // for `export * as ns from './x'`\n\ntype Kind = 'None' | 'Root' | 'Builder' | 'ServerFn'\n\ninterface ModuleInfo {\n id: string\n code: string\n ast: ReturnType<typeof parseAst>\n bindings: Map<string, Binding>\n exports: Map<string, ExportEntry>\n}\n\nexport class ServerFnCompiler {\n private moduleCache = new Map<string, ModuleInfo>()\n private resolvedLibId!: string\n private initialized = false\n constructor(\n private options: {\n env: 'client' | 'server'\n libName: string\n rootExport: string\n loadModule: (id: string) => Promise<void>\n resolveId: (id: string, importer?: string) => Promise<string | null>\n },\n ) {}\n\n private async init(id: string) {\n const libId = await this.options.resolveId(this.options.libName, id)\n if (!libId) {\n throw new Error(`could not resolve \"${this.options.libName}\"`)\n }\n // insert root binding\n const rootModule = {\n ast: null as any,\n bindings: new Map(),\n exports: new Map(),\n code: '',\n id: libId,\n }\n rootModule.exports.set(this.options.rootExport, {\n tag: 'Normal',\n name: this.options.rootExport,\n })\n rootModule.bindings.set(this.options.rootExport, {\n type: 'var',\n init: t.identifier(this.options.rootExport),\n resolvedKind: 'Root',\n })\n this.moduleCache.set(libId, rootModule)\n this.initialized = true\n this.resolvedLibId = libId\n }\n\n public ingestModule({ code, id }: { code: string; id: string }) {\n const ast = parseAst({ code })\n\n const bindings = new Map<string, Binding>()\n const exports = new Map<string, ExportEntry>()\n\n // we are only interested in top-level bindings, hence we don't traverse the AST\n // instead we only iterate over the program body\n for (const node of ast.program.body) {\n if (t.isImportDeclaration(node)) {\n const source = node.source.value\n for (const s of node.specifiers) {\n if (t.isImportSpecifier(s)) {\n const importedName = t.isIdentifier(s.imported)\n ? s.imported.name\n : s.imported.value\n bindings.set(s.local.name, { type: 'import', source, importedName })\n } else if (t.isImportDefaultSpecifier(s)) {\n bindings.set(s.local.name, {\n type: 'import',\n source,\n importedName: 'default',\n })\n } else if (t.isImportNamespaceSpecifier(s)) {\n bindings.set(s.local.name, {\n type: 'import',\n source,\n importedName: '*',\n })\n }\n }\n } else if (t.isVariableDeclaration(node)) {\n for (const decl of node.declarations) {\n if (t.isIdentifier(decl.id)) {\n bindings.set(decl.id.name, {\n type: 'var',\n init: decl.init ?? null,\n })\n }\n }\n } else if (t.isExportNamedDeclaration(node)) {\n // export const foo = ...\n if (node.declaration) {\n if (t.isVariableDeclaration(node.declaration)) {\n for (const d of node.declaration.declarations) {\n if (t.isIdentifier(d.id)) {\n exports.set(d.id.name, { tag: 'Normal', name: d.id.name })\n bindings.set(d.id.name, { type: 'var', init: d.init ?? null })\n }\n }\n }\n }\n for (const sp of node.specifiers) {\n if (t.isExportNamespaceSpecifier(sp)) {\n exports.set(sp.exported.name, {\n tag: 'Namespace',\n name: sp.exported.name,\n targetId: node.source?.value || '',\n })\n }\n // export { local as exported }\n else if (t.isExportSpecifier(sp)) {\n const local = sp.local.name\n const exported = t.isIdentifier(sp.exported)\n ? sp.exported.name\n : sp.exported.value\n exports.set(exported, { tag: 'Normal', name: local })\n }\n }\n } else if (t.isExportDefaultDeclaration(node)) {\n const d = node.declaration\n if (t.isIdentifier(d)) {\n exports.set('default', { tag: 'Default', name: d.name })\n } else {\n const synth = '__default_export__'\n bindings.set(synth, { type: 'var', init: d as t.Expression })\n exports.set('default', { tag: 'Default', name: synth })\n }\n }\n }\n\n const info: ModuleInfo = { code, id, ast, bindings, exports }\n this.moduleCache.set(id, info)\n return info\n }\n\n public invalidateModule(id: string) {\n return this.moduleCache.delete(id)\n }\n\n public async compile({ code, id }: { code: string; id: string }) {\n if (!this.initialized) {\n await this.init(id)\n }\n const { bindings, ast } = this.ingestModule({ code, id })\n const candidates = this.collectHandlerCandidates(bindings)\n if (candidates.length === 0) {\n // this hook will only be invoked if there is `.handler(` in the code,\n // so not discovering a handler candidate is rather unlikely, but maybe possible?\n return null\n }\n\n // let's find out which of the candidates are actually server functions\n const toRewrite: Array<t.CallExpression> = []\n for (const handler of candidates) {\n const kind = await this.resolveExprKind(handler, id)\n if (kind === 'ServerFn') {\n toRewrite.push(handler)\n }\n }\n if (toRewrite.length === 0) {\n return null\n }\n const pathsToRewrite: Array<babel.NodePath<t.CallExpression>> = []\n babel.traverse(ast, {\n CallExpression(path) {\n const found = toRewrite.findIndex((h) => path.node === h)\n if (found !== -1) {\n pathsToRewrite.push(path)\n // delete from toRewrite\n toRewrite.splice(found, 1)\n }\n },\n })\n\n if (toRewrite.length > 0) {\n throw new Error(\n `Internal error: could not find all paths to rewrite. please file an issue`,\n )\n }\n\n const refIdents = findReferencedIdentifiers(ast)\n\n pathsToRewrite.map((p) =>\n handleCreateServerFn(p, { env: this.options.env, code }),\n )\n\n deadCodeElimination(ast, refIdents)\n\n return generateFromAst(ast, {\n sourceMaps: true,\n sourceFileName: id,\n filename: id,\n })\n }\n\n // collects all `.handler(...)` CallExpressions at top-level\n private collectHandlerCandidates(bindings: Map<string, Binding>) {\n const candidates: Array<t.CallExpression> = []\n\n for (const binding of bindings.values()) {\n if (binding.type === 'var') {\n const handler = isHandlerCall(binding.init)\n if (handler) {\n candidates.push(handler)\n }\n }\n }\n return candidates\n }\n\n private async resolveIdentifierKind(\n ident: string,\n id: string,\n visited = new Set<string>(),\n ): Promise<Kind> {\n const info = await this.getModuleInfo(id)\n\n const binding = info.bindings.get(ident)\n if (!binding) {\n return 'None'\n }\n if (binding.resolvedKind) {\n return binding.resolvedKind\n }\n\n // TODO improve cycle detection? should we throw here instead of returning 'None'?\n // prevent cycles\n const vKey = `${id}:${ident}`\n if (visited.has(vKey)) {\n return 'None'\n }\n visited.add(vKey)\n\n const resolvedKind = await this.resolveBindingKind(binding, id, visited)\n binding.resolvedKind = resolvedKind\n return resolvedKind\n }\n\n private async resolveBindingKind(\n binding: Binding,\n fileId: string,\n visited = new Set<string>(),\n ): Promise<Kind> {\n if (binding.resolvedKind) {\n return binding.resolvedKind\n }\n if (binding.type === 'import') {\n const target = await this.options.resolveId(binding.source, fileId)\n if (!target) {\n return 'None'\n }\n\n if (binding.importedName === '*') {\n throw new Error(\n `should never get here, namespace imports are handled in resolveCalleeKind`,\n )\n }\n\n const importedModule = await this.getModuleInfo(target)\n\n const moduleExport = importedModule.exports.get(binding.importedName)\n if (!moduleExport) {\n return 'None'\n }\n const importedBinding = importedModule.bindings.get(moduleExport.name)\n if (!importedBinding) {\n return 'None'\n }\n if (importedBinding.resolvedKind) {\n return importedBinding.resolvedKind\n }\n\n const resolvedKind = await this.resolveBindingKind(\n importedBinding,\n importedModule.id,\n visited,\n )\n importedBinding.resolvedKind = resolvedKind\n return resolvedKind\n }\n\n const resolvedKind = await this.resolveExprKind(\n binding.init,\n fileId,\n visited,\n )\n binding.resolvedKind = resolvedKind\n return resolvedKind\n }\n\n private async resolveExprKind(\n expr: t.Expression | null,\n fileId: string,\n visited = new Set<string>(),\n ): Promise<Kind> {\n if (!expr) {\n return 'None'\n }\n\n let result: Kind = 'None'\n\n if (t.isCallExpression(expr)) {\n if (!t.isExpression(expr.callee)) {\n return 'None'\n }\n const calleeKind = await this.resolveCalleeKind(\n expr.callee,\n fileId,\n visited,\n )\n if (calleeKind === 'Root' || calleeKind === 'Builder') {\n return 'Builder'\n }\n if (calleeKind === 'ServerFn') {\n return 'ServerFn'\n }\n } else if (t.isMemberExpression(expr) && t.isIdentifier(expr.property)) {\n result = await this.resolveCalleeKind(expr.object, fileId, visited)\n }\n\n if (result === 'None' && t.isIdentifier(expr)) {\n result = await this.resolveIdentifierKind(expr.name, fileId, visited)\n }\n\n if (result === 'None' && t.isTSAsExpression(expr)) {\n result = await this.resolveExprKind(expr.expression, fileId, visited)\n }\n if (result === 'None' && t.isTSNonNullExpression(expr)) {\n result = await this.resolveExprKind(expr.expression, fileId, visited)\n }\n if (result === 'None' && t.isParenthesizedExpression(expr)) {\n result = await this.resolveExprKind(expr.expression, fileId, visited)\n }\n\n return result\n }\n\n private async resolveCalleeKind(\n callee: t.Expression,\n fileId: string,\n visited = new Set<string>(),\n ): Promise<Kind> {\n if (t.isIdentifier(callee)) {\n return this.resolveIdentifierKind(callee.name, fileId, visited)\n }\n\n if (t.isMemberExpression(callee) && t.isIdentifier(callee.property)) {\n const prop = callee.property.name\n\n if (prop === 'handler') {\n const base = await this.resolveExprKind(callee.object, fileId, visited)\n if (base === 'Root' || base === 'Builder') {\n return 'ServerFn'\n }\n return 'None'\n }\n // Check if the object is a namespace import\n if (t.isIdentifier(callee.object)) {\n const info = await this.getModuleInfo(fileId)\n const binding = info.bindings.get(callee.object.name)\n if (\n binding &&\n binding.type === 'import' &&\n binding.importedName === '*'\n ) {\n // resolve the property from the target module\n const targetModuleId = await this.options.resolveId(\n binding.source,\n fileId,\n )\n if (targetModuleId) {\n const targetModule = await this.getModuleInfo(targetModuleId)\n const exportEntry = targetModule.exports.get(callee.property.name)\n if (exportEntry) {\n const exportedBinding = targetModule.bindings.get(\n exportEntry.name,\n )\n if (exportedBinding) {\n return await this.resolveBindingKind(\n exportedBinding,\n targetModule.id,\n visited,\n )\n }\n }\n }\n }\n }\n return this.resolveExprKind(callee.object, fileId, visited)\n }\n\n // handle nested expressions\n return this.resolveExprKind(callee, fileId, visited)\n }\n\n private async getModuleInfo(id: string) {\n let cached = this.moduleCache.get(id)\n if (cached) {\n return cached\n }\n\n await this.options.loadModule(id)\n\n cached = this.moduleCache.get(id)\n if (!cached) {\n throw new Error(`could not load module info for ${id}`)\n }\n return cached\n }\n}\n\nfunction isHandlerCall(\n node: t.Node | null | undefined,\n): undefined | t.CallExpression {\n if (!t.isCallExpression(node)) return undefined\n\n const callee = node.callee\n if (\n !t.isMemberExpression(callee) ||\n !t.isIdentifier(callee.property, { name: 'handler' })\n ) {\n return undefined\n }\n\n return node\n}\n"],"names":["babel","resolvedKind"],"mappings":"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"}
1
+ {"version":3,"file":"compiler.js","sources":["../../../src/create-server-fn-plugin/compiler.ts"],"sourcesContent":["/* eslint-disable import/no-commonjs */\nimport * as t from '@babel/types'\nimport { generateFromAst, parseAst } from '@tanstack/router-utils'\nimport babel from '@babel/core'\nimport {\n deadCodeElimination,\n findReferencedIdentifiers,\n} from 'babel-dead-code-elimination'\nimport { handleCreateServerFn } from './handleCreateServerFn'\nimport { handleCreateMiddleware } from './handleCreateMiddleware'\n\ntype Binding =\n | {\n type: 'import'\n source: string\n importedName: string\n resolvedKind?: Kind\n }\n | {\n type: 'var'\n init: t.Expression | null\n resolvedKind?: Kind\n }\n\ntype ExportEntry =\n | { tag: 'Normal'; name: string }\n | { tag: 'Default'; name: string }\n | { tag: 'Namespace'; name: string; targetId: string } // for `export * as ns from './x'`\n\ntype Kind = 'None' | `Root` | `Builder` | LookupKind\n\ntype LookupKind = 'ServerFn' | 'Middleware'\n\nconst validLookupKinds: Array<LookupKind> = ['ServerFn', 'Middleware']\nconst candidateCallIdentifier = ['handler', 'server', 'client']\nexport type LookupConfig = {\n libName: string\n rootExport: string\n}\ninterface ModuleInfo {\n id: string\n code: string\n ast: ReturnType<typeof parseAst>\n bindings: Map<string, Binding>\n exports: Map<string, ExportEntry>\n}\n\nexport class ServerFnCompiler {\n private moduleCache = new Map<string, ModuleInfo>()\n private initialized = false\n constructor(\n private options: {\n env: 'client' | 'server'\n lookupConfigurations: Array<LookupConfig>\n loadModule: (id: string) => Promise<void>\n resolveId: (id: string, importer?: string) => Promise<string | null>\n },\n ) {}\n\n private async init(id: string) {\n await Promise.all(\n this.options.lookupConfigurations.map(async (config) => {\n const libId = await this.options.resolveId(config.libName, id)\n if (!libId) {\n throw new Error(`could not resolve \"${config.libName}\"`)\n }\n let rootModule = this.moduleCache.get(libId)\n if (!rootModule) {\n // insert root binding\n rootModule = {\n ast: null as any,\n bindings: new Map(),\n exports: new Map(),\n code: '',\n id: libId,\n }\n this.moduleCache.set(libId, rootModule)\n }\n\n rootModule.exports.set(config.rootExport, {\n tag: 'Normal',\n name: config.rootExport,\n })\n rootModule.exports.set('*', {\n tag: 'Namespace',\n name: config.rootExport,\n targetId: libId,\n })\n rootModule.bindings.set(config.rootExport, {\n type: 'var',\n init: t.identifier(config.rootExport),\n resolvedKind: `Root` satisfies Kind,\n })\n this.moduleCache.set(libId, rootModule)\n }),\n )\n\n this.initialized = true\n }\n\n public ingestModule({ code, id }: { code: string; id: string }) {\n const ast = parseAst({ code })\n\n const bindings = new Map<string, Binding>()\n const exports = new Map<string, ExportEntry>()\n\n // we are only interested in top-level bindings, hence we don't traverse the AST\n // instead we only iterate over the program body\n for (const node of ast.program.body) {\n if (t.isImportDeclaration(node)) {\n const source = node.source.value\n for (const s of node.specifiers) {\n if (t.isImportSpecifier(s)) {\n const importedName = t.isIdentifier(s.imported)\n ? s.imported.name\n : s.imported.value\n bindings.set(s.local.name, { type: 'import', source, importedName })\n } else if (t.isImportDefaultSpecifier(s)) {\n bindings.set(s.local.name, {\n type: 'import',\n source,\n importedName: 'default',\n })\n } else if (t.isImportNamespaceSpecifier(s)) {\n bindings.set(s.local.name, {\n type: 'import',\n source,\n importedName: '*',\n })\n }\n }\n } else if (t.isVariableDeclaration(node)) {\n for (const decl of node.declarations) {\n if (t.isIdentifier(decl.id)) {\n bindings.set(decl.id.name, {\n type: 'var',\n init: decl.init ?? null,\n })\n }\n }\n } else if (t.isExportNamedDeclaration(node)) {\n // export const foo = ...\n if (node.declaration) {\n if (t.isVariableDeclaration(node.declaration)) {\n for (const d of node.declaration.declarations) {\n if (t.isIdentifier(d.id)) {\n exports.set(d.id.name, { tag: 'Normal', name: d.id.name })\n bindings.set(d.id.name, { type: 'var', init: d.init ?? null })\n }\n }\n }\n }\n for (const sp of node.specifiers) {\n if (t.isExportNamespaceSpecifier(sp)) {\n exports.set(sp.exported.name, {\n tag: 'Namespace',\n name: sp.exported.name,\n targetId: node.source?.value || '',\n })\n }\n // export { local as exported }\n else if (t.isExportSpecifier(sp)) {\n const local = sp.local.name\n const exported = t.isIdentifier(sp.exported)\n ? sp.exported.name\n : sp.exported.value\n exports.set(exported, { tag: 'Normal', name: local })\n }\n }\n } else if (t.isExportDefaultDeclaration(node)) {\n const d = node.declaration\n if (t.isIdentifier(d)) {\n exports.set('default', { tag: 'Default', name: d.name })\n } else {\n const synth = '__default_export__'\n bindings.set(synth, { type: 'var', init: d as t.Expression })\n exports.set('default', { tag: 'Default', name: synth })\n }\n }\n }\n\n const info: ModuleInfo = { code, id, ast, bindings, exports }\n this.moduleCache.set(id, info)\n return info\n }\n\n public invalidateModule(id: string) {\n return this.moduleCache.delete(id)\n }\n\n public async compile({ code, id }: { code: string; id: string }) {\n if (!this.initialized) {\n await this.init(id)\n }\n const { bindings, ast } = this.ingestModule({ code, id })\n const candidates = this.collectCandidates(bindings)\n if (candidates.length === 0) {\n // this hook will only be invoked if there is `.handler(` | `.server(` | `.client(` in the code,\n // so not discovering a handler candidate is rather unlikely, but maybe possible?\n return null\n }\n\n // let's find out which of the candidates are actually server functions\n const toRewrite: Array<{\n callExpression: t.CallExpression\n kind: LookupKind\n }> = []\n for (const handler of candidates) {\n const kind = await this.resolveExprKind(handler, id)\n if (validLookupKinds.includes(kind as LookupKind)) {\n toRewrite.push({ callExpression: handler, kind: kind as LookupKind })\n }\n }\n if (toRewrite.length === 0) {\n return null\n }\n\n const pathsToRewrite: Array<{\n nodePath: babel.NodePath<t.CallExpression>\n kind: LookupKind\n }> = []\n babel.traverse(ast, {\n CallExpression(path) {\n const found = toRewrite.findIndex((h) => path.node === h.callExpression)\n if (found !== -1) {\n pathsToRewrite.push({ nodePath: path, kind: toRewrite[found]!.kind })\n // delete from toRewrite\n toRewrite.splice(found, 1)\n }\n },\n })\n\n if (toRewrite.length > 0) {\n throw new Error(\n `Internal error: could not find all paths to rewrite. please file an issue`,\n )\n }\n\n const refIdents = findReferencedIdentifiers(ast)\n\n pathsToRewrite.map((p) => {\n if (p.kind === 'ServerFn') {\n handleCreateServerFn(p.nodePath, { env: this.options.env, code })\n } else {\n handleCreateMiddleware(p.nodePath, { env: this.options.env })\n }\n })\n\n deadCodeElimination(ast, refIdents)\n\n return generateFromAst(ast, {\n sourceMaps: true,\n sourceFileName: id,\n filename: id,\n })\n }\n\n // collects all candidate CallExpressions at top-level\n private collectCandidates(bindings: Map<string, Binding>) {\n const candidates: Array<t.CallExpression> = []\n\n for (const binding of bindings.values()) {\n if (binding.type === 'var') {\n const handler = isCandidateCallExpression(binding.init)\n if (handler) {\n candidates.push(handler)\n }\n }\n }\n return candidates\n }\n\n private async resolveIdentifierKind(\n ident: string,\n id: string,\n visited = new Set<string>(),\n ): Promise<Kind> {\n const info = await this.getModuleInfo(id)\n\n const binding = info.bindings.get(ident)\n if (!binding) {\n return 'None'\n }\n if (binding.resolvedKind) {\n return binding.resolvedKind\n }\n\n // TODO improve cycle detection? should we throw here instead of returning 'None'?\n // prevent cycles\n const vKey = `${id}:${ident}`\n if (visited.has(vKey)) {\n return 'None'\n }\n visited.add(vKey)\n\n const resolvedKind = await this.resolveBindingKind(binding, id, visited)\n binding.resolvedKind = resolvedKind\n return resolvedKind\n }\n\n private async resolveBindingKind(\n binding: Binding,\n fileId: string,\n visited = new Set<string>(),\n ): Promise<Kind> {\n if (binding.resolvedKind) {\n return binding.resolvedKind\n }\n if (binding.type === 'import') {\n const target = await this.options.resolveId(binding.source, fileId)\n if (!target) {\n return 'None'\n }\n\n const importedModule = await this.getModuleInfo(target)\n\n const moduleExport = importedModule.exports.get(binding.importedName)\n if (!moduleExport) {\n return 'None'\n }\n const importedBinding = importedModule.bindings.get(moduleExport.name)\n if (!importedBinding) {\n return 'None'\n }\n if (importedBinding.resolvedKind) {\n return importedBinding.resolvedKind\n }\n\n const resolvedKind = await this.resolveBindingKind(\n importedBinding,\n importedModule.id,\n visited,\n )\n importedBinding.resolvedKind = resolvedKind\n return resolvedKind\n }\n\n const resolvedKind = await this.resolveExprKind(\n binding.init,\n fileId,\n visited,\n )\n binding.resolvedKind = resolvedKind\n return resolvedKind\n }\n\n private async resolveExprKind(\n expr: t.Expression | null,\n fileId: string,\n visited = new Set<string>(),\n ): Promise<Kind> {\n if (!expr) {\n return 'None'\n }\n\n let result: Kind = 'None'\n\n if (t.isCallExpression(expr)) {\n if (!t.isExpression(expr.callee)) {\n return 'None'\n }\n const calleeKind = await this.resolveCalleeKind(\n expr.callee,\n fileId,\n visited,\n )\n if (calleeKind !== 'None') {\n if (calleeKind === `Root` || calleeKind === `Builder`) {\n return `Builder`\n }\n for (const kind of validLookupKinds) {\n if (calleeKind === kind) {\n return kind\n }\n }\n }\n } else if (t.isMemberExpression(expr) && t.isIdentifier(expr.property)) {\n result = await this.resolveCalleeKind(expr.object, fileId, visited)\n }\n\n if (result === 'None' && t.isIdentifier(expr)) {\n result = await this.resolveIdentifierKind(expr.name, fileId, visited)\n }\n\n if (result === 'None' && t.isTSAsExpression(expr)) {\n result = await this.resolveExprKind(expr.expression, fileId, visited)\n }\n if (result === 'None' && t.isTSNonNullExpression(expr)) {\n result = await this.resolveExprKind(expr.expression, fileId, visited)\n }\n if (result === 'None' && t.isParenthesizedExpression(expr)) {\n result = await this.resolveExprKind(expr.expression, fileId, visited)\n }\n\n return result\n }\n\n private async resolveCalleeKind(\n callee: t.Expression,\n fileId: string,\n visited = new Set<string>(),\n ): Promise<Kind> {\n if (t.isIdentifier(callee)) {\n return this.resolveIdentifierKind(callee.name, fileId, visited)\n }\n\n if (t.isMemberExpression(callee) && t.isIdentifier(callee.property)) {\n const prop = callee.property.name\n\n if (prop === 'handler') {\n const base = await this.resolveExprKind(callee.object, fileId, visited)\n if (base === 'Root' || base === 'Builder') {\n return 'ServerFn'\n }\n return 'None'\n } else if (\n prop === 'client' ||\n prop === 'server' ||\n prop === 'createMiddleware'\n ) {\n const base = await this.resolveExprKind(callee.object, fileId, visited)\n if (base === 'Root' || base === 'Builder' || base === 'Middleware') {\n return 'Middleware'\n }\n return 'None'\n }\n // Check if the object is a namespace import\n if (t.isIdentifier(callee.object)) {\n const info = await this.getModuleInfo(fileId)\n const binding = info.bindings.get(callee.object.name)\n if (\n binding &&\n binding.type === 'import' &&\n binding.importedName === '*'\n ) {\n // resolve the property from the target module\n const targetModuleId = await this.options.resolveId(\n binding.source,\n fileId,\n )\n if (targetModuleId) {\n const targetModule = await this.getModuleInfo(targetModuleId)\n const exportEntry = targetModule.exports.get(callee.property.name)\n if (exportEntry) {\n const exportedBinding = targetModule.bindings.get(\n exportEntry.name,\n )\n if (exportedBinding) {\n return await this.resolveBindingKind(\n exportedBinding,\n targetModule.id,\n visited,\n )\n }\n }\n } else {\n return 'None'\n }\n }\n }\n return this.resolveExprKind(callee.object, fileId, visited)\n }\n\n // handle nested expressions\n return this.resolveExprKind(callee, fileId, visited)\n }\n\n private async getModuleInfo(id: string) {\n let cached = this.moduleCache.get(id)\n if (cached) {\n return cached\n }\n\n await this.options.loadModule(id)\n\n cached = this.moduleCache.get(id)\n if (!cached) {\n throw new Error(`could not load module info for ${id}`)\n }\n return cached\n }\n}\n\nfunction isCandidateCallExpression(\n node: t.Node | null | undefined,\n): undefined | t.CallExpression {\n if (!t.isCallExpression(node)) return undefined\n\n const callee = node.callee\n if (!t.isMemberExpression(callee) || !t.isIdentifier(callee.property)) {\n return undefined\n }\n if (!candidateCallIdentifier.includes(callee.property.name)) {\n return undefined\n }\n\n return node\n}\n"],"names":["babel","resolvedKind"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import * as t from '@babel/types';
2
+ import type * as babel from '@babel/core';
3
+ export declare function handleCreateMiddleware(path: babel.NodePath<t.CallExpression>, opts: {
4
+ env: 'client' | 'server';
5
+ }): void;
@@ -1,10 +1,10 @@
1
1
  import * as t from "@babel/types";
2
- import { getRootCallExpression } from "./utils.js";
3
- function handleCreateMiddlewareCallExpression(path, opts) {
2
+ import { getRootCallExpression } from "../start-compiler-plugin/utils.js";
3
+ function handleCreateMiddleware(path, opts) {
4
4
  const rootCallExpression = getRootCallExpression(path);
5
5
  const callExpressionPaths = {
6
6
  middleware: null,
7
- validator: null,
7
+ inputValidator: null,
8
8
  client: null,
9
9
  server: null
10
10
  };
@@ -19,17 +19,17 @@ function handleCreateMiddlewareCallExpression(path, opts) {
19
19
  }
20
20
  }
21
21
  });
22
- if (callExpressionPaths.validator) {
23
- const innerInputExpression = callExpressionPaths.validator.node.arguments[0];
22
+ if (callExpressionPaths.inputValidator) {
23
+ const innerInputExpression = callExpressionPaths.inputValidator.node.arguments[0];
24
24
  if (!innerInputExpression) {
25
25
  throw new Error(
26
- "createMiddleware().validator() must be called with a validator!"
26
+ "createMiddleware().inputValidator() must be called with a validator!"
27
27
  );
28
28
  }
29
29
  if (opts.env === "client") {
30
- if (t.isMemberExpression(callExpressionPaths.validator.node.callee)) {
31
- callExpressionPaths.validator.replaceWith(
32
- callExpressionPaths.validator.node.callee.object
30
+ if (t.isMemberExpression(callExpressionPaths.inputValidator.node.callee)) {
31
+ callExpressionPaths.inputValidator.replaceWith(
32
+ callExpressionPaths.inputValidator.node.callee.object
33
33
  );
34
34
  }
35
35
  }
@@ -46,6 +46,6 @@ function handleCreateMiddlewareCallExpression(path, opts) {
46
46
  }
47
47
  }
48
48
  export {
49
- handleCreateMiddlewareCallExpression
49
+ handleCreateMiddleware
50
50
  };
51
- //# sourceMappingURL=middleware.js.map
51
+ //# sourceMappingURL=handleCreateMiddleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handleCreateMiddleware.js","sources":["../../../src/create-server-fn-plugin/handleCreateMiddleware.ts"],"sourcesContent":["import * as t from '@babel/types'\nimport { getRootCallExpression } from '../start-compiler-plugin/utils'\nimport type * as babel from '@babel/core'\n\nexport function handleCreateMiddleware(\n path: babel.NodePath<t.CallExpression>,\n opts: {\n env: 'client' | 'server'\n },\n) {\n const rootCallExpression = getRootCallExpression(path)\n\n // if (debug)\n // console.info(\n // 'Handling createMiddleware call expression:',\n // rootCallExpression.toString(),\n // )\n\n const callExpressionPaths = {\n middleware: null as babel.NodePath<t.CallExpression> | null,\n inputValidator: null as babel.NodePath<t.CallExpression> | null,\n client: null as babel.NodePath<t.CallExpression> | null,\n server: null as babel.NodePath<t.CallExpression> | null,\n }\n\n const validMethods = Object.keys(callExpressionPaths)\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.inputValidator) {\n const innerInputExpression =\n callExpressionPaths.inputValidator.node.arguments[0]\n\n if (!innerInputExpression) {\n throw new Error(\n 'createMiddleware().inputValidator() must be called with a validator!',\n )\n }\n\n // If we're on the client, remove the validator call expression\n if (opts.env === 'client') {\n if (\n t.isMemberExpression(callExpressionPaths.inputValidator.node.callee)\n ) {\n callExpressionPaths.inputValidator.replaceWith(\n callExpressionPaths.inputValidator.node.callee.object,\n )\n }\n }\n }\n\n const serverFnPath = callExpressionPaths.server?.get(\n 'arguments.0',\n ) as babel.NodePath<any>\n\n if (\n callExpressionPaths.server &&\n serverFnPath.node &&\n opts.env === 'client'\n ) {\n // If we're on the client, remove the server call expression\n if (t.isMemberExpression(callExpressionPaths.server.node.callee)) {\n callExpressionPaths.server.replaceWith(\n callExpressionPaths.server.node.callee.object,\n )\n }\n }\n}\n"],"names":[],"mappings":";;AAIO,SAAS,uBACd,MACA,MAGA;AACA,QAAM,qBAAqB,sBAAsB,IAAI;AAQrD,QAAM,sBAAsB;AAAA,IAC1B,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,QAAQ;AAAA,IACR,QAAQ;AAAA,EAAA;AAGV,QAAM,eAAe,OAAO,KAAK,mBAAmB;AAEpD,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,gBAAgB;AACtC,UAAM,uBACJ,oBAAoB,eAAe,KAAK,UAAU,CAAC;AAErD,QAAI,CAAC,sBAAsB;AACzB,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,IAEJ;AAGA,QAAI,KAAK,QAAQ,UAAU;AACzB,UACE,EAAE,mBAAmB,oBAAoB,eAAe,KAAK,MAAM,GACnE;AACA,4BAAoB,eAAe;AAAA,UACjC,oBAAoB,eAAe,KAAK,OAAO;AAAA,QAAA;AAAA,MAEnD;AAAA,IACF;AAAA,EACF;AAEA,QAAM,eAAe,oBAAoB,QAAQ;AAAA,IAC/C;AAAA,EAAA;AAGF,MACE,oBAAoB,UACpB,aAAa,QACb,KAAK,QAAQ,UACb;AAEA,QAAI,EAAE,mBAAmB,oBAAoB,OAAO,KAAK,MAAM,GAAG;AAChE,0BAAoB,OAAO;AAAA,QACzB,oBAAoB,OAAO,KAAK,OAAO;AAAA,MAAA;AAAA,IAE3C;AAAA,EACF;AACF;"}
@@ -1,10 +1,10 @@
1
1
  import * as t from "@babel/types";
2
2
  import { getRootCallExpression, codeFrameError } from "../start-compiler-plugin/utils.js";
3
3
  function handleCreateServerFn(path, opts) {
4
- const validMethods = ["middleware", "validator", "handler"];
4
+ const validMethods = ["middleware", "inputValidator", "handler"];
5
5
  const callExpressionPaths = {
6
6
  middleware: null,
7
- validator: null,
7
+ inputValidator: null,
8
8
  handler: null
9
9
  };
10
10
  const rootCallExpression = getRootCallExpression(path);
@@ -23,17 +23,17 @@ function handleCreateServerFn(path, opts) {
23
23
  }
24
24
  }
25
25
  });
26
- if (callExpressionPaths.validator) {
27
- const innerInputExpression = callExpressionPaths.validator.node.arguments[0];
26
+ if (callExpressionPaths.inputValidator) {
27
+ const innerInputExpression = callExpressionPaths.inputValidator.node.arguments[0];
28
28
  if (!innerInputExpression) {
29
29
  throw new Error(
30
- "createServerFn().validator() must be called with a validator!"
30
+ "createServerFn().inputValidator() must be called with a validator!"
31
31
  );
32
32
  }
33
33
  if (opts.env === "client") {
34
- if (t.isMemberExpression(callExpressionPaths.validator.node.callee)) {
35
- callExpressionPaths.validator.replaceWith(
36
- callExpressionPaths.validator.node.callee.object
34
+ if (t.isMemberExpression(callExpressionPaths.inputValidator.node.callee)) {
35
+ callExpressionPaths.inputValidator.replaceWith(
36
+ callExpressionPaths.inputValidator.node.callee.object
37
37
  );
38
38
  }
39
39
  }
@@ -1 +1 @@
1
- {"version":3,"file":"handleCreateServerFn.js","sources":["../../../src/create-server-fn-plugin/handleCreateServerFn.ts"],"sourcesContent":["import * as t from '@babel/types'\nimport {\n codeFrameError,\n getRootCallExpression,\n} from '../start-compiler-plugin/utils'\nimport type * as babel from '@babel/core'\n\nexport function handleCreateServerFn(\n path: babel.NodePath<t.CallExpression>,\n opts: {\n env: 'client' | 'server'\n code: string\n },\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 validMethods = ['middleware', 'validator', 'handler'] as const\n type ValidMethods = (typeof validMethods)[number]\n const callExpressionPaths: Record<\n ValidMethods,\n babel.NodePath<t.CallExpression> | null\n > = {\n middleware: null,\n validator: null,\n handler: null,\n }\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.name as ValidMethods\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, remove the validator call expression\n if (opts.env === 'client') {\n if (t.isMemberExpression(callExpressionPaths.validator.node.callee)) {\n callExpressionPaths.validator.replaceWith(\n callExpressionPaths.validator.node.callee.object,\n )\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":";;AAOO,SAAS,qBACd,MACA,MAIA;AAKA,QAAM,eAAe,CAAC,cAAc,aAAa,SAAS;AAE1D,QAAM,sBAGF;AAAA,IACF,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,SAAS;AAAA,EAAA;AAGX,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,SAAS;AAEhD,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,QAAI,KAAK,QAAQ,UAAU;AACzB,UAAI,EAAE,mBAAmB,oBAAoB,UAAU,KAAK,MAAM,GAAG;AACnE,4BAAoB,UAAU;AAAA,UAC5B,oBAAoB,UAAU,KAAK,OAAO;AAAA,QAAA;AAAA,MAE9C;AAAA,IACF;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;"}
1
+ {"version":3,"file":"handleCreateServerFn.js","sources":["../../../src/create-server-fn-plugin/handleCreateServerFn.ts"],"sourcesContent":["import * as t from '@babel/types'\nimport {\n codeFrameError,\n getRootCallExpression,\n} from '../start-compiler-plugin/utils'\nimport type * as babel from '@babel/core'\n\nexport function handleCreateServerFn(\n path: babel.NodePath<t.CallExpression>,\n opts: {\n env: 'client' | 'server'\n code: string\n },\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 validMethods = ['middleware', 'inputValidator', 'handler'] as const\n type ValidMethods = (typeof validMethods)[number]\n const callExpressionPaths: Record<\n ValidMethods,\n babel.NodePath<t.CallExpression> | null\n > = {\n middleware: null,\n inputValidator: null,\n handler: null,\n }\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.name as ValidMethods\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.inputValidator) {\n const innerInputExpression =\n callExpressionPaths.inputValidator.node.arguments[0]\n\n if (!innerInputExpression) {\n throw new Error(\n 'createServerFn().inputValidator() must be called with a validator!',\n )\n }\n\n // If we're on the client, remove the validator call expression\n if (opts.env === 'client') {\n if (\n t.isMemberExpression(callExpressionPaths.inputValidator.node.callee)\n ) {\n callExpressionPaths.inputValidator.replaceWith(\n callExpressionPaths.inputValidator.node.callee.object,\n )\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":";;AAOO,SAAS,qBACd,MACA,MAIA;AAKA,QAAM,eAAe,CAAC,cAAc,kBAAkB,SAAS;AAE/D,QAAM,sBAGF;AAAA,IACF,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,SAAS;AAAA,EAAA;AAGX,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,SAAS;AAEhD,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,gBAAgB;AACtC,UAAM,uBACJ,oBAAoB,eAAe,KAAK,UAAU,CAAC;AAErD,QAAI,CAAC,sBAAsB;AACzB,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,IAEJ;AAGA,QAAI,KAAK,QAAQ,UAAU;AACzB,UACE,EAAE,mBAAmB,oBAAoB,eAAe,KAAK,MAAM,GACnE;AACA,4BAAoB,eAAe;AAAA,UACjC,oBAAoB,eAAe,KAAK,OAAO;AAAA,QAAA;AAAA,MAEnD;AAAA,IACF;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;"}
@@ -1,3 +1,3 @@
1
- import { PluginOption } from 'vite';
2
1
  import { CompileStartFrameworkOptions } from '../start-compiler-plugin/compilers.js';
2
+ import { PluginOption } from 'vite';
3
3
  export declare function createServerFnPlugin(framework: CompileStartFrameworkOptions): PluginOption;
@@ -4,8 +4,6 @@ function cleanId(id) {
4
4
  return id.split("?")[0];
5
5
  }
6
6
  function createServerFnPlugin(framework) {
7
- const libName = `@tanstack/${framework}-start`;
8
- const rootExport = "createServerFn";
9
7
  const SERVER_FN_LOOKUP = "server-fn-module-lookup";
10
8
  const compilers = {};
11
9
  return [
@@ -44,8 +42,8 @@ function createServerFnPlugin(framework) {
44
42
  exclude: new RegExp(`${SERVER_FN_LOOKUP}$`)
45
43
  },
46
44
  code: {
47
- // only scan files that mention `.handler(`
48
- include: [/\.handler\(/]
45
+ // only scan files that mention `.handler(` | `.server(` | `.client(`
46
+ include: [/\.handler\(/, /\.server\(/, /\.client\(/]
49
47
  }
50
48
  },
51
49
  async handler(code, id) {
@@ -58,8 +56,20 @@ function createServerFnPlugin(framework) {
58
56
  })();
59
57
  compiler = new ServerFnCompiler({
60
58
  env,
61
- libName,
62
- rootExport,
59
+ lookupConfigurations: [
60
+ {
61
+ libName: `@tanstack/${framework}-start`,
62
+ rootExport: "createMiddleware"
63
+ },
64
+ {
65
+ libName: `@tanstack/${framework}-start`,
66
+ rootExport: "createServerFn"
67
+ },
68
+ {
69
+ libName: `@tanstack/${framework}-start`,
70
+ rootExport: "createStart"
71
+ }
72
+ ],
63
73
  loadModule: async (id2) => {
64
74
  if (this.environment.mode === "build") {
65
75
  const loaded = await this.load({ id: id2 });
@@ -79,7 +89,12 @@ function createServerFnPlugin(framework) {
79
89
  },
80
90
  resolveId: async (source, importer) => {
81
91
  const r = await this.resolve(source, importer);
82
- return r ? cleanId(r.id) : null;
92
+ if (r) {
93
+ if (!r.external) {
94
+ return cleanId(r.id);
95
+ }
96
+ }
97
+ return null;
83
98
  }
84
99
  });
85
100
  compilers[this.environment.name] = compiler;
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sources":["../../../src/create-server-fn-plugin/plugin.ts"],"sourcesContent":["import { VITE_ENVIRONMENT_NAMES } from '../constants'\nimport { ServerFnCompiler } from './compiler'\nimport type { ViteEnvironmentNames } from '../constants'\nimport type { PluginOption } from 'vite'\nimport type { CompileStartFrameworkOptions } from '../start-compiler-plugin/compilers'\n\nfunction cleanId(id: string): string {\n return id.split('?')[0]!\n}\n\nexport function createServerFnPlugin(\n framework: CompileStartFrameworkOptions,\n): PluginOption {\n const libName = `@tanstack/${framework}-start`\n const rootExport = 'createServerFn'\n\n const SERVER_FN_LOOKUP = 'server-fn-module-lookup'\n\n const compilers: Partial<Record<ViteEnvironmentNames, ServerFnCompiler>> = {}\n return [\n {\n name: 'tanstack-start-core:capture-server-fn-module-lookup',\n // we only need this plugin in dev mode\n apply: 'serve',\n applyToEnvironment(env) {\n return [\n VITE_ENVIRONMENT_NAMES.client,\n VITE_ENVIRONMENT_NAMES.server,\n ].includes(env.name as ViteEnvironmentNames)\n },\n transform: {\n filter: {\n id: new RegExp(`${SERVER_FN_LOOKUP}$`),\n },\n handler(code, id) {\n const compiler =\n compilers[this.environment.name as ViteEnvironmentNames]\n compiler?.ingestModule({ code, id: cleanId(id) })\n },\n },\n },\n {\n name: 'tanstack-start-core::server-fn',\n enforce: 'pre',\n\n applyToEnvironment(env) {\n return [\n VITE_ENVIRONMENT_NAMES.client,\n VITE_ENVIRONMENT_NAMES.server,\n ].includes(env.name as ViteEnvironmentNames)\n },\n transform: {\n filter: {\n id: {\n exclude: new RegExp(`${SERVER_FN_LOOKUP}$`),\n },\n code: {\n // only scan files that mention `.handler(`\n include: [/\\.handler\\(/],\n },\n },\n async handler(code, id) {\n let compiler =\n compilers[this.environment.name as ViteEnvironmentNames]\n if (!compiler) {\n const env =\n this.environment.name === VITE_ENVIRONMENT_NAMES.client\n ? 'client'\n : this.environment.name === VITE_ENVIRONMENT_NAMES.server\n ? 'server'\n : (() => {\n throw new Error(\n `Environment ${this.environment.name} not configured`,\n )\n })()\n\n compiler = new ServerFnCompiler({\n env,\n libName,\n rootExport,\n loadModule: async (id: string) => {\n if (this.environment.mode === 'build') {\n const loaded = await this.load({ id })\n if (!loaded.code) {\n throw new Error(`could not load module ${id}`)\n }\n compiler!.ingestModule({ code: loaded.code, id })\n } else if (this.environment.mode === 'dev') {\n /**\n * in dev, vite does not return code from `ctx.load()`\n * so instead, we need to take a different approach\n * we must force vite to load the module and run it through the vite plugin pipeline\n * we can do this by using the `fetchModule` method\n * the `captureServerFnModuleLookupPlugin` captures the module code via its transform hook and invokes analyzeModuleAST\n */\n await this.environment.fetchModule(\n id + '?' + SERVER_FN_LOOKUP,\n )\n } else {\n throw new Error(\n `could not load module ${id}: unknown environment mode ${this.environment.mode}`,\n )\n }\n },\n resolveId: async (source: string, importer?: string) => {\n const r = await this.resolve(source, importer)\n return r ? cleanId(r.id) : null\n },\n })\n compilers[this.environment.name as ViteEnvironmentNames] = compiler\n }\n\n id = cleanId(id)\n const result = await compiler.compile({ id, code })\n return result\n },\n },\n\n hotUpdate(ctx) {\n const compiler =\n compilers[this.environment.name as ViteEnvironmentNames]\n\n ctx.modules.forEach((m) => {\n if (m.id) {\n const deleted = compiler?.invalidateModule(m.id)\n if (deleted) {\n m.importers.forEach((importer) => {\n if (importer.id) {\n compiler?.invalidateModule(importer.id)\n }\n })\n }\n }\n })\n },\n },\n ]\n}\n"],"names":["id"],"mappings":"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"}
1
+ {"version":3,"file":"plugin.js","sources":["../../../src/create-server-fn-plugin/plugin.ts"],"sourcesContent":["import { VITE_ENVIRONMENT_NAMES } from '../constants'\nimport { ServerFnCompiler } from './compiler'\nimport type { CompileStartFrameworkOptions } from '../start-compiler-plugin/compilers'\nimport type { ViteEnvironmentNames } from '../constants'\nimport type { PluginOption } from 'vite'\n\nfunction cleanId(id: string): string {\n return id.split('?')[0]!\n}\n\nexport function createServerFnPlugin(\n framework: CompileStartFrameworkOptions,\n): PluginOption {\n const SERVER_FN_LOOKUP = 'server-fn-module-lookup'\n\n const compilers: Partial<Record<ViteEnvironmentNames, ServerFnCompiler>> = {}\n return [\n {\n name: 'tanstack-start-core:capture-server-fn-module-lookup',\n // we only need this plugin in dev mode\n apply: 'serve',\n applyToEnvironment(env) {\n return [\n VITE_ENVIRONMENT_NAMES.client,\n VITE_ENVIRONMENT_NAMES.server,\n ].includes(env.name as ViteEnvironmentNames)\n },\n transform: {\n filter: {\n id: new RegExp(`${SERVER_FN_LOOKUP}$`),\n },\n handler(code, id) {\n const compiler =\n compilers[this.environment.name as ViteEnvironmentNames]\n compiler?.ingestModule({ code, id: cleanId(id) })\n },\n },\n },\n {\n name: 'tanstack-start-core::server-fn',\n enforce: 'pre',\n\n applyToEnvironment(env) {\n return [\n VITE_ENVIRONMENT_NAMES.client,\n VITE_ENVIRONMENT_NAMES.server,\n ].includes(env.name as ViteEnvironmentNames)\n },\n transform: {\n filter: {\n id: {\n exclude: new RegExp(`${SERVER_FN_LOOKUP}$`),\n },\n code: {\n // only scan files that mention `.handler(` | `.server(` | `.client(`\n include: [/\\.handler\\(/, /\\.server\\(/, /\\.client\\(/],\n },\n },\n async handler(code, id) {\n let compiler =\n compilers[this.environment.name as ViteEnvironmentNames]\n if (!compiler) {\n const env =\n this.environment.name === VITE_ENVIRONMENT_NAMES.client\n ? 'client'\n : this.environment.name === VITE_ENVIRONMENT_NAMES.server\n ? 'server'\n : (() => {\n throw new Error(\n `Environment ${this.environment.name} not configured`,\n )\n })()\n\n compiler = new ServerFnCompiler({\n env,\n lookupConfigurations: [\n {\n libName: `@tanstack/${framework}-start`,\n rootExport: 'createMiddleware',\n },\n\n {\n libName: `@tanstack/${framework}-start`,\n rootExport: 'createServerFn',\n },\n {\n libName: `@tanstack/${framework}-start`,\n rootExport: 'createStart',\n },\n ],\n loadModule: async (id: string) => {\n if (this.environment.mode === 'build') {\n const loaded = await this.load({ id })\n if (!loaded.code) {\n throw new Error(`could not load module ${id}`)\n }\n compiler!.ingestModule({ code: loaded.code, id })\n } else if (this.environment.mode === 'dev') {\n /**\n * in dev, vite does not return code from `ctx.load()`\n * so instead, we need to take a different approach\n * we must force vite to load the module and run it through the vite plugin pipeline\n * we can do this by using the `fetchModule` method\n * the `captureServerFnModuleLookupPlugin` captures the module code via its transform hook and invokes analyzeModuleAST\n */\n await this.environment.fetchModule(\n id + '?' + SERVER_FN_LOOKUP,\n )\n } else {\n throw new Error(\n `could not load module ${id}: unknown environment mode ${this.environment.mode}`,\n )\n }\n },\n resolveId: async (source: string, importer?: string) => {\n const r = await this.resolve(source, importer)\n if (r) {\n if (!r.external) {\n return cleanId(r.id)\n }\n }\n return null\n },\n })\n compilers[this.environment.name as ViteEnvironmentNames] = compiler\n }\n\n id = cleanId(id)\n const result = await compiler.compile({ id, code })\n return result\n },\n },\n\n hotUpdate(ctx) {\n const compiler =\n compilers[this.environment.name as ViteEnvironmentNames]\n\n ctx.modules.forEach((m) => {\n if (m.id) {\n const deleted = compiler?.invalidateModule(m.id)\n if (deleted) {\n m.importers.forEach((importer) => {\n if (importer.id) {\n compiler?.invalidateModule(importer.id)\n }\n })\n }\n }\n })\n },\n },\n ]\n}\n"],"names":["id"],"mappings":"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"}