@tanstack/start-plugin-core 1.166.12 → 1.166.14

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 (87) hide show
  1. package/dist/esm/build-sitemap.js +94 -123
  2. package/dist/esm/build-sitemap.js.map +1 -1
  3. package/dist/esm/constants.js +15 -20
  4. package/dist/esm/constants.js.map +1 -1
  5. package/dist/esm/dev-server-plugin/dev-styles.js +137 -150
  6. package/dist/esm/dev-server-plugin/dev-styles.js.map +1 -1
  7. package/dist/esm/dev-server-plugin/extract-html-scripts.js +16 -15
  8. package/dist/esm/dev-server-plugin/extract-html-scripts.js.map +1 -1
  9. package/dist/esm/dev-server-plugin/plugin.js +125 -195
  10. package/dist/esm/dev-server-plugin/plugin.js.map +1 -1
  11. package/dist/esm/import-protection-plugin/ast.js +6 -5
  12. package/dist/esm/import-protection-plugin/ast.js.map +1 -1
  13. package/dist/esm/import-protection-plugin/constants.js +20 -22
  14. package/dist/esm/import-protection-plugin/constants.js.map +1 -1
  15. package/dist/esm/import-protection-plugin/defaults.js +35 -25
  16. package/dist/esm/import-protection-plugin/defaults.js.map +1 -1
  17. package/dist/esm/import-protection-plugin/extensionlessAbsoluteIdResolver.js +93 -92
  18. package/dist/esm/import-protection-plugin/extensionlessAbsoluteIdResolver.js.map +1 -1
  19. package/dist/esm/import-protection-plugin/matchers.js +23 -24
  20. package/dist/esm/import-protection-plugin/matchers.js.map +1 -1
  21. package/dist/esm/import-protection-plugin/plugin.js +1045 -1361
  22. package/dist/esm/import-protection-plugin/plugin.js.map +1 -1
  23. package/dist/esm/import-protection-plugin/postCompileUsage.js +58 -55
  24. package/dist/esm/import-protection-plugin/postCompileUsage.js.map +1 -1
  25. package/dist/esm/import-protection-plugin/rewriteDeniedImports.js +187 -259
  26. package/dist/esm/import-protection-plugin/rewriteDeniedImports.js.map +1 -1
  27. package/dist/esm/import-protection-plugin/sourceLocation.js +238 -248
  28. package/dist/esm/import-protection-plugin/sourceLocation.js.map +1 -1
  29. package/dist/esm/import-protection-plugin/trace.js +173 -184
  30. package/dist/esm/import-protection-plugin/trace.js.map +1 -1
  31. package/dist/esm/import-protection-plugin/utils.js +132 -111
  32. package/dist/esm/import-protection-plugin/utils.js.map +1 -1
  33. package/dist/esm/import-protection-plugin/virtualModules.js +216 -196
  34. package/dist/esm/import-protection-plugin/virtualModules.js.map +1 -1
  35. package/dist/esm/index.js +2 -7
  36. package/dist/esm/load-env-plugin/plugin.js +12 -11
  37. package/dist/esm/load-env-plugin/plugin.js.map +1 -1
  38. package/dist/esm/output-directory.js +10 -10
  39. package/dist/esm/output-directory.js.map +1 -1
  40. package/dist/esm/plugin.js +275 -355
  41. package/dist/esm/plugin.js.map +1 -1
  42. package/dist/esm/post-server-build.js +39 -53
  43. package/dist/esm/post-server-build.js.map +1 -1
  44. package/dist/esm/prerender.js +177 -239
  45. package/dist/esm/prerender.js.map +1 -1
  46. package/dist/esm/preview-server-plugin/plugin.js +41 -44
  47. package/dist/esm/preview-server-plugin/plugin.js.map +1 -1
  48. package/dist/esm/queue.js +115 -126
  49. package/dist/esm/queue.js.map +1 -1
  50. package/dist/esm/resolve-entries.js +31 -32
  51. package/dist/esm/resolve-entries.js.map +1 -1
  52. package/dist/esm/schema.js +156 -179
  53. package/dist/esm/schema.js.map +1 -1
  54. package/dist/esm/start-compiler-plugin/compiler.js +655 -812
  55. package/dist/esm/start-compiler-plugin/compiler.js.map +1 -1
  56. package/dist/esm/start-compiler-plugin/handleClientOnlyJSX.js +25 -8
  57. package/dist/esm/start-compiler-plugin/handleClientOnlyJSX.js.map +1 -1
  58. package/dist/esm/start-compiler-plugin/handleCreateIsomorphicFn.js +22 -19
  59. package/dist/esm/start-compiler-plugin/handleCreateIsomorphicFn.js.map +1 -1
  60. package/dist/esm/start-compiler-plugin/handleCreateMiddleware.js +20 -22
  61. package/dist/esm/start-compiler-plugin/handleCreateMiddleware.js.map +1 -1
  62. package/dist/esm/start-compiler-plugin/handleCreateServerFn.js +187 -255
  63. package/dist/esm/start-compiler-plugin/handleCreateServerFn.js.map +1 -1
  64. package/dist/esm/start-compiler-plugin/handleEnvOnly.js +23 -33
  65. package/dist/esm/start-compiler-plugin/handleEnvOnly.js.map +1 -1
  66. package/dist/esm/start-compiler-plugin/plugin.js +247 -291
  67. package/dist/esm/start-compiler-plugin/plugin.js.map +1 -1
  68. package/dist/esm/start-compiler-plugin/utils.js +27 -27
  69. package/dist/esm/start-compiler-plugin/utils.js.map +1 -1
  70. package/dist/esm/start-manifest-plugin/manifestBuilder.js +272 -378
  71. package/dist/esm/start-manifest-plugin/manifestBuilder.js.map +1 -1
  72. package/dist/esm/start-manifest-plugin/plugin.js +35 -44
  73. package/dist/esm/start-manifest-plugin/plugin.js.map +1 -1
  74. package/dist/esm/start-router-plugin/constants.js +6 -5
  75. package/dist/esm/start-router-plugin/constants.js.map +1 -1
  76. package/dist/esm/start-router-plugin/generator-plugins/prerender-routes-plugin.js +24 -19
  77. package/dist/esm/start-router-plugin/generator-plugins/prerender-routes-plugin.js.map +1 -1
  78. package/dist/esm/start-router-plugin/generator-plugins/routes-manifest-plugin.js +28 -29
  79. package/dist/esm/start-router-plugin/generator-plugins/routes-manifest-plugin.js.map +1 -1
  80. package/dist/esm/start-router-plugin/plugin.js +146 -199
  81. package/dist/esm/start-router-plugin/plugin.js.map +1 -1
  82. package/dist/esm/start-router-plugin/pruneServerOnlySubtrees.js +32 -31
  83. package/dist/esm/start-router-plugin/pruneServerOnlySubtrees.js.map +1 -1
  84. package/dist/esm/utils.js +14 -14
  85. package/dist/esm/utils.js.map +1 -1
  86. package/package.json +7 -7
  87. package/dist/esm/index.js.map +0 -1
@@ -1,38 +1,28 @@
1
1
  import * as t from "@babel/types";
2
+ //#region src/start-compiler-plugin/handleEnvOnly.ts
2
3
  function capitalize(str) {
3
- return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
4
+ if (!str) return "";
5
+ return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
4
6
  }
7
+ /**
8
+ * Handles serverOnly/clientOnly function transformations for a batch of candidates.
9
+ *
10
+ * @param candidates - All EnvOnly candidates to process (all same kind)
11
+ * @param context - The compilation context
12
+ * @param kind - The specific kind (ServerOnlyFn or ClientOnlyFn)
13
+ */
5
14
  function handleEnvOnlyFn(candidates, context, kind) {
6
- const targetEnv = kind === "ClientOnlyFn" ? "client" : "server";
7
- for (const candidate of candidates) {
8
- const { path } = candidate;
9
- if (context.env === targetEnv) {
10
- const innerFn = path.node.arguments[0];
11
- if (!t.isExpression(innerFn)) {
12
- throw new Error(
13
- `create${capitalize(targetEnv)}OnlyFn() must be called with a function!`
14
- );
15
- }
16
- path.replaceWith(innerFn);
17
- } else {
18
- path.replaceWith(
19
- t.arrowFunctionExpression(
20
- [],
21
- t.blockStatement([
22
- t.throwStatement(
23
- t.newExpression(t.identifier("Error"), [
24
- t.stringLiteral(
25
- `create${capitalize(targetEnv)}OnlyFn() functions can only be called on the ${targetEnv}!`
26
- )
27
- ])
28
- )
29
- ])
30
- )
31
- );
32
- }
33
- }
15
+ const targetEnv = kind === "ClientOnlyFn" ? "client" : "server";
16
+ for (const candidate of candidates) {
17
+ const { path } = candidate;
18
+ if (context.env === targetEnv) {
19
+ const innerFn = path.node.arguments[0];
20
+ if (!t.isExpression(innerFn)) throw new Error(`create${capitalize(targetEnv)}OnlyFn() must be called with a function!`);
21
+ path.replaceWith(innerFn);
22
+ } else path.replaceWith(t.arrowFunctionExpression([], t.blockStatement([t.throwStatement(t.newExpression(t.identifier("Error"), [t.stringLiteral(`create${capitalize(targetEnv)}OnlyFn() functions can only be called on the ${targetEnv}!`)]))])));
23
+ }
34
24
  }
35
- export {
36
- handleEnvOnlyFn
37
- };
38
- //# sourceMappingURL=handleEnvOnly.js.map
25
+ //#endregion
26
+ export { handleEnvOnlyFn };
27
+
28
+ //# sourceMappingURL=handleEnvOnly.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"handleEnvOnly.js","sources":["../../../src/start-compiler-plugin/handleEnvOnly.ts"],"sourcesContent":["import * as t from '@babel/types'\nimport type { CompilationContext, RewriteCandidate } from './types'\nimport type { LookupKind } from './compiler'\n\nfunction capitalize(str: string) {\n if (!str) return ''\n return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase()\n}\n\n/**\n * Handles serverOnly/clientOnly function transformations for a batch of candidates.\n *\n * @param candidates - All EnvOnly candidates to process (all same kind)\n * @param context - The compilation context\n * @param kind - The specific kind (ServerOnlyFn or ClientOnlyFn)\n */\nexport function handleEnvOnlyFn(\n candidates: Array<RewriteCandidate>,\n context: CompilationContext,\n kind: LookupKind,\n): void {\n const targetEnv = kind === 'ClientOnlyFn' ? 'client' : 'server'\n\n for (const candidate of candidates) {\n const { path } = candidate\n\n if (context.env === targetEnv) {\n // Matching environment - extract the inner function\n const innerFn = path.node.arguments[0]\n\n if (!t.isExpression(innerFn)) {\n throw new Error(\n `create${capitalize(targetEnv)}OnlyFn() must be called with a function!`,\n )\n }\n\n path.replaceWith(innerFn)\n } else {\n // Wrong environment - replace with a function that throws an error\n path.replaceWith(\n t.arrowFunctionExpression(\n [],\n t.blockStatement([\n t.throwStatement(\n t.newExpression(t.identifier('Error'), [\n t.stringLiteral(\n `create${capitalize(targetEnv)}OnlyFn() functions can only be called on the ${targetEnv}!`,\n ),\n ]),\n ),\n ]),\n ),\n )\n }\n }\n}\n"],"names":[],"mappings":";AAIA,SAAS,WAAW,KAAa;AAE/B,SAAO,IAAI,OAAO,CAAC,EAAE,gBAAgB,IAAI,MAAM,CAAC,EAAE,YAAA;AACpD;AASO,SAAS,gBACd,YACA,SACA,MACM;AACN,QAAM,YAAY,SAAS,iBAAiB,WAAW;AAEvD,aAAW,aAAa,YAAY;AAClC,UAAM,EAAE,SAAS;AAEjB,QAAI,QAAQ,QAAQ,WAAW;AAE7B,YAAM,UAAU,KAAK,KAAK,UAAU,CAAC;AAErC,UAAI,CAAC,EAAE,aAAa,OAAO,GAAG;AAC5B,cAAM,IAAI;AAAA,UACR,SAAS,WAAW,SAAS,CAAC;AAAA,QAAA;AAAA,MAElC;AAEA,WAAK,YAAY,OAAO;AAAA,IAC1B,OAAO;AAEL,WAAK;AAAA,QACH,EAAE;AAAA,UACA,CAAA;AAAA,UACA,EAAE,eAAe;AAAA,YACf,EAAE;AAAA,cACA,EAAE,cAAc,EAAE,WAAW,OAAO,GAAG;AAAA,gBACrC,EAAE;AAAA,kBACA,SAAS,WAAW,SAAS,CAAC,gDAAgD,SAAS;AAAA,gBAAA;AAAA,cACzF,CACD;AAAA,YAAA;AAAA,UACH,CACD;AAAA,QAAA;AAAA,MACH;AAAA,IAEJ;AAAA,EACF;AACF;"}
1
+ {"version":3,"file":"handleEnvOnly.js","names":[],"sources":["../../../src/start-compiler-plugin/handleEnvOnly.ts"],"sourcesContent":["import * as t from '@babel/types'\nimport type { CompilationContext, RewriteCandidate } from './types'\nimport type { LookupKind } from './compiler'\n\nfunction capitalize(str: string) {\n if (!str) return ''\n return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase()\n}\n\n/**\n * Handles serverOnly/clientOnly function transformations for a batch of candidates.\n *\n * @param candidates - All EnvOnly candidates to process (all same kind)\n * @param context - The compilation context\n * @param kind - The specific kind (ServerOnlyFn or ClientOnlyFn)\n */\nexport function handleEnvOnlyFn(\n candidates: Array<RewriteCandidate>,\n context: CompilationContext,\n kind: LookupKind,\n): void {\n const targetEnv = kind === 'ClientOnlyFn' ? 'client' : 'server'\n\n for (const candidate of candidates) {\n const { path } = candidate\n\n if (context.env === targetEnv) {\n // Matching environment - extract the inner function\n const innerFn = path.node.arguments[0]\n\n if (!t.isExpression(innerFn)) {\n throw new Error(\n `create${capitalize(targetEnv)}OnlyFn() must be called with a function!`,\n )\n }\n\n path.replaceWith(innerFn)\n } else {\n // Wrong environment - replace with a function that throws an error\n path.replaceWith(\n t.arrowFunctionExpression(\n [],\n t.blockStatement([\n t.throwStatement(\n t.newExpression(t.identifier('Error'), [\n t.stringLiteral(\n `create${capitalize(targetEnv)}OnlyFn() functions can only be called on the ${targetEnv}!`,\n ),\n ]),\n ),\n ]),\n ),\n )\n }\n }\n}\n"],"mappings":";;AAIA,SAAS,WAAW,KAAa;AAC/B,KAAI,CAAC,IAAK,QAAO;AACjB,QAAO,IAAI,OAAO,EAAE,CAAC,aAAa,GAAG,IAAI,MAAM,EAAE,CAAC,aAAa;;;;;;;;;AAUjE,SAAgB,gBACd,YACA,SACA,MACM;CACN,MAAM,YAAY,SAAS,iBAAiB,WAAW;AAEvD,MAAK,MAAM,aAAa,YAAY;EAClC,MAAM,EAAE,SAAS;AAEjB,MAAI,QAAQ,QAAQ,WAAW;GAE7B,MAAM,UAAU,KAAK,KAAK,UAAU;AAEpC,OAAI,CAAC,EAAE,aAAa,QAAQ,CAC1B,OAAM,IAAI,MACR,SAAS,WAAW,UAAU,CAAC,0CAChC;AAGH,QAAK,YAAY,QAAQ;QAGzB,MAAK,YACH,EAAE,wBACA,EAAE,EACF,EAAE,eAAe,CACf,EAAE,eACA,EAAE,cAAc,EAAE,WAAW,QAAQ,EAAE,CACrC,EAAE,cACA,SAAS,WAAW,UAAU,CAAC,+CAA+C,UAAU,GACzF,CACF,CAAC,CACH,CACF,CAAC,CACH,CACF"}
@@ -1,102 +1,101 @@
1
- import assert from "node:assert";
2
- import { VIRTUAL_MODULES } from "@tanstack/start-server-core";
3
- import { resolve } from "pathe";
4
- import { VITE_ENVIRONMENT_NAMES, SERVER_FN_LOOKUP, TRANSFORM_ID_REGEX } from "../constants.js";
5
- import { StartCompiler, LookupKindsPerEnv, detectKindsInCode, KindDetectionPatterns } from "./compiler.js";
1
+ import { SERVER_FN_LOOKUP, TRANSFORM_ID_REGEX, VITE_ENVIRONMENT_NAMES } from "../constants.js";
6
2
  import { cleanId } from "./utils.js";
3
+ import { KindDetectionPatterns, LookupKindsPerEnv, StartCompiler, detectKindsInCode } from "./compiler.js";
4
+ import { resolve } from "pathe";
5
+ import { VIRTUAL_MODULES } from "@tanstack/start-server-core";
6
+ import assert from "node:assert";
7
+ //#region src/start-compiler-plugin/plugin.ts
7
8
  function getTransformCodeFilterForEnv(env) {
8
- const validKinds = LookupKindsPerEnv[env];
9
- const patterns = [];
10
- for (const [kind, pattern] of Object.entries(KindDetectionPatterns)) {
11
- if (validKinds.has(kind)) {
12
- patterns.push(pattern);
13
- }
14
- }
15
- return patterns;
9
+ const validKinds = LookupKindsPerEnv[env];
10
+ const patterns = [];
11
+ for (const [kind, pattern] of Object.entries(KindDetectionPatterns)) if (validKinds.has(kind)) patterns.push(pattern);
12
+ return patterns;
16
13
  }
17
- const getLookupConfigurationsForEnv = (env, framework) => {
18
- const commonConfigs = [
19
- {
20
- libName: `@tanstack/${framework}-start`,
21
- rootExport: "createServerFn",
22
- kind: "Root"
23
- },
24
- {
25
- libName: `@tanstack/${framework}-start`,
26
- rootExport: "createIsomorphicFn",
27
- kind: "IsomorphicFn"
28
- },
29
- {
30
- libName: `@tanstack/${framework}-start`,
31
- rootExport: "createServerOnlyFn",
32
- kind: "ServerOnlyFn"
33
- },
34
- {
35
- libName: `@tanstack/${framework}-start`,
36
- rootExport: "createClientOnlyFn",
37
- kind: "ClientOnlyFn"
38
- }
39
- ];
40
- if (env === "client") {
41
- return [
42
- {
43
- libName: `@tanstack/${framework}-start`,
44
- rootExport: "createMiddleware",
45
- kind: "Root"
46
- },
47
- {
48
- libName: `@tanstack/${framework}-start`,
49
- rootExport: "createStart",
50
- kind: "Root"
51
- },
52
- ...commonConfigs
53
- ];
54
- } else {
55
- return [
56
- ...commonConfigs,
57
- {
58
- libName: `@tanstack/${framework}-router`,
59
- rootExport: "ClientOnly",
60
- kind: "ClientOnlyJSX"
61
- }
62
- ];
63
- }
14
+ var getLookupConfigurationsForEnv = (env, framework) => {
15
+ const commonConfigs = [
16
+ {
17
+ libName: `@tanstack/${framework}-start`,
18
+ rootExport: "createServerFn",
19
+ kind: "Root"
20
+ },
21
+ {
22
+ libName: `@tanstack/${framework}-start`,
23
+ rootExport: "createIsomorphicFn",
24
+ kind: "IsomorphicFn"
25
+ },
26
+ {
27
+ libName: `@tanstack/${framework}-start`,
28
+ rootExport: "createServerOnlyFn",
29
+ kind: "ServerOnlyFn"
30
+ },
31
+ {
32
+ libName: `@tanstack/${framework}-start`,
33
+ rootExport: "createClientOnlyFn",
34
+ kind: "ClientOnlyFn"
35
+ }
36
+ ];
37
+ if (env === "client") return [
38
+ {
39
+ libName: `@tanstack/${framework}-start`,
40
+ rootExport: "createMiddleware",
41
+ kind: "Root"
42
+ },
43
+ {
44
+ libName: `@tanstack/${framework}-start`,
45
+ rootExport: "createStart",
46
+ kind: "Root"
47
+ },
48
+ ...commonConfigs
49
+ ];
50
+ else return [...commonConfigs, {
51
+ libName: `@tanstack/${framework}-router`,
52
+ rootExport: "ClientOnly",
53
+ kind: "ClientOnlyJSX"
54
+ }];
64
55
  };
65
56
  function resolveViteId(id) {
66
- return `\0${id}`;
57
+ return `\0${id}`;
67
58
  }
68
- const validateServerFnIdVirtualModule = `virtual:tanstack-start-validate-server-fn-id`;
59
+ var validateServerFnIdVirtualModule = `virtual:tanstack-start-validate-server-fn-id`;
69
60
  function parseIdQuery(id) {
70
- if (!id.includes("?")) return { filename: id, query: {} };
71
- const [filename, rawQuery] = id.split(`?`, 2);
72
- const query = Object.fromEntries(new URLSearchParams(rawQuery));
73
- return { filename, query };
61
+ if (!id.includes("?")) return {
62
+ filename: id,
63
+ query: {}
64
+ };
65
+ const [filename, rawQuery] = id.split(`?`, 2);
66
+ return {
67
+ filename,
68
+ query: Object.fromEntries(new URLSearchParams(rawQuery))
69
+ };
74
70
  }
71
+ /**
72
+ * Generates the manifest module code for server functions.
73
+ * @param serverFnsById - Map of function IDs to their server function info
74
+ * @param includeClientReferencedCheck - Whether to include isClientReferenced flag and runtime check.
75
+ * This is needed when SSR is NOT the provider, so server-only-referenced functions in the manifest
76
+ * can be blocked from client HTTP requests.
77
+ */
75
78
  function generateManifestModule(serverFnsById, includeClientReferencedCheck) {
76
- const manifestEntries = Object.entries(serverFnsById).map(([id, fn]) => {
77
- const baseEntry = `'${id}': {
79
+ return `
80
+ const manifest = {${Object.entries(serverFnsById).map(([id, fn]) => {
81
+ return `'${id}': {
78
82
  functionName: '${fn.functionName}',
79
83
  importer: () => import(${JSON.stringify(fn.extractedFilename)})${includeClientReferencedCheck ? `,
80
84
  isClientReferenced: ${fn.isClientReferenced ?? true}` : ""}
81
85
  }`;
82
- return baseEntry;
83
- }).join(",");
84
- const getServerFnByIdParams = includeClientReferencedCheck ? "id, opts" : "id";
85
- const clientReferencedCheck = includeClientReferencedCheck ? `
86
- // If called from client, only allow client-referenced functions
87
- if (opts?.fromClient && !serverFnInfo.isClientReferenced) {
88
- throw new Error('Server function not accessible from client: ' + id)
89
- }
90
- ` : "";
91
- return `
92
- const manifest = {${manifestEntries}}
86
+ }).join(",")}}
93
87
 
94
- export async function getServerFnById(${getServerFnByIdParams}) {
88
+ export async function getServerFnById(${includeClientReferencedCheck ? "id, opts" : "id"}) {
95
89
  const serverFnInfo = manifest[id]
96
90
  if (!serverFnInfo) {
97
91
  throw new Error('Server function info not found for ' + id)
98
92
  }
99
- ${clientReferencedCheck}
93
+ ${includeClientReferencedCheck ? `
94
+ // If called from client, only allow client-referenced functions
95
+ if (opts?.fromClient && !serverFnInfo.isClientReferenced) {
96
+ throw new Error('Server function not accessible from client: ' + id)
97
+ }
98
+ ` : ""}
100
99
  const fnModule = await serverFnInfo.importer()
101
100
 
102
101
  if (!fnModule) {
@@ -119,200 +118,164 @@ ${clientReferencedCheck}
119
118
  `;
120
119
  }
121
120
  function startCompilerPlugin(opts) {
122
- const compilers = {};
123
- const serverFnsById = {};
124
- const onServerFnsById = (d) => {
125
- Object.assign(serverFnsById, d);
126
- };
127
- let root = process.cwd();
128
- const resolvedResolverVirtualImportId = resolveViteId(
129
- VIRTUAL_MODULES.serverFnResolver
130
- );
131
- const ssrEnvName = VITE_ENVIRONMENT_NAMES.server;
132
- const ssrIsProvider = opts.providerEnvName === ssrEnvName;
133
- const appliedResolverEnvironments = new Set(
134
- ssrIsProvider ? [opts.providerEnvName] : [ssrEnvName, opts.providerEnvName]
135
- );
136
- function perEnvServerFnPlugin(environment) {
137
- const transformCodeFilter = getTransformCodeFilterForEnv(environment.type);
138
- return {
139
- name: `tanstack-start-core::server-fn:${environment.name}`,
140
- enforce: "pre",
141
- applyToEnvironment(env) {
142
- return env.name === environment.name;
143
- },
144
- configResolved(config) {
145
- root = config.root;
146
- config.command;
147
- },
148
- transform: {
149
- filter: {
150
- id: {
151
- exclude: new RegExp(`${SERVER_FN_LOOKUP}$`),
152
- include: TRANSFORM_ID_REGEX
153
- },
154
- code: {
155
- include: transformCodeFilter
156
- }
157
- },
158
- async handler(code, id) {
159
- let compiler = compilers[this.environment.name];
160
- if (!compiler) {
161
- const mode = this.environment.mode === "build" ? "build" : "dev";
162
- compiler = new StartCompiler({
163
- env: environment.type,
164
- envName: environment.name,
165
- root,
166
- lookupKinds: LookupKindsPerEnv[environment.type],
167
- lookupConfigurations: getLookupConfigurationsForEnv(
168
- environment.type,
169
- opts.framework
170
- ),
171
- mode,
172
- framework: opts.framework,
173
- providerEnvName: opts.providerEnvName,
174
- generateFunctionId: opts.generateFunctionId,
175
- onServerFnsById,
176
- getKnownServerFns: () => serverFnsById,
177
- loadModule: async (id2) => {
178
- if (this.environment.mode === "build") {
179
- const loaded = await this.load({ id: id2 });
180
- const code2 = loaded.code ?? "";
181
- compiler.ingestModule({ code: code2, id: id2 });
182
- } else if (this.environment.mode === "dev") {
183
- await this.environment.fetchModule(
184
- id2 + "?" + SERVER_FN_LOOKUP
185
- );
186
- } else {
187
- throw new Error(
188
- `could not load module ${id2}: unknown environment mode ${this.environment.mode}`
189
- );
190
- }
191
- },
192
- resolveId: async (source, importer) => {
193
- const r = await this.resolve(source, importer);
194
- if (r) {
195
- if (!r.external) {
196
- return cleanId(r.id);
197
- }
198
- }
199
- return null;
200
- }
201
- });
202
- compilers[this.environment.name] = compiler;
203
- }
204
- const detectedKinds = detectKindsInCode(code, environment.type);
205
- const result = await compiler.compile({
206
- id,
207
- code,
208
- detectedKinds
209
- });
210
- return result;
211
- }
212
- },
213
- hotUpdate(ctx) {
214
- const compiler = compilers[this.environment.name];
215
- ctx.modules.forEach((m) => {
216
- if (m.id) {
217
- const deleted = compiler?.invalidateModule(m.id);
218
- if (deleted) {
219
- m.importers.forEach((importer) => {
220
- if (importer.id) {
221
- compiler?.invalidateModule(importer.id);
222
- }
223
- });
224
- }
225
- }
226
- });
227
- }
228
- };
229
- }
230
- return [
231
- ...opts.environments.map(perEnvServerFnPlugin),
232
- {
233
- name: "tanstack-start-core:capture-server-fn-module-lookup",
234
- // we only need this plugin in dev mode
235
- apply: "serve",
236
- applyToEnvironment(env) {
237
- return !!opts.environments.find((e) => e.name === env.name);
238
- },
239
- transform: {
240
- filter: {
241
- id: new RegExp(`${SERVER_FN_LOOKUP}$`)
242
- },
243
- handler(code, id) {
244
- const compiler = compilers[this.environment.name];
245
- compiler?.ingestModule({ code, id: cleanId(id) });
246
- }
247
- }
248
- },
249
- // Validate server function ID in dev mode
250
- {
251
- name: "tanstack-start-core:validate-server-fn-id",
252
- apply: "serve",
253
- load: {
254
- filter: {
255
- id: new RegExp(resolveViteId(validateServerFnIdVirtualModule))
256
- },
257
- async handler(id) {
258
- const parsed = parseIdQuery(id);
259
- const fnId = parsed.query.id;
260
- if (fnId && serverFnsById[fnId]) {
261
- return `export {}`;
262
- }
263
- if (fnId) {
264
- try {
265
- const decoded = JSON.parse(
266
- Buffer.from(fnId, "base64url").toString("utf8")
267
- );
268
- if (typeof decoded.file === "string" && typeof decoded.export === "string") {
269
- let sourceFile = decoded.file;
270
- if (sourceFile.startsWith("/@id/")) {
271
- sourceFile = sourceFile.slice("/@id/".length);
272
- }
273
- const qIdx = sourceFile.indexOf("?");
274
- if (qIdx !== -1) {
275
- sourceFile = sourceFile.slice(0, qIdx);
276
- }
277
- const absPath = resolve(root, sourceFile);
278
- assert(this.environment.mode === "dev");
279
- await this.environment.fetchModule(absPath);
280
- if (serverFnsById[fnId]) {
281
- return `export {}`;
282
- }
283
- }
284
- } catch {
285
- }
286
- }
287
- this.error(`Invalid server function ID: ${fnId}`);
288
- }
289
- }
290
- },
291
- // Manifest plugin for server environments
292
- {
293
- name: "tanstack-start-core:server-fn-resolver",
294
- enforce: "pre",
295
- applyToEnvironment: (env) => {
296
- return appliedResolverEnvironments.has(env.name);
297
- },
298
- configResolved(config) {
299
- root = config.root;
300
- config.command;
301
- },
302
- resolveId: {
303
- filter: { id: new RegExp(VIRTUAL_MODULES.serverFnResolver) },
304
- handler() {
305
- return resolvedResolverVirtualImportId;
306
- }
307
- },
308
- load: {
309
- filter: { id: new RegExp(resolvedResolverVirtualImportId) },
310
- handler() {
311
- if (this.environment.name !== opts.providerEnvName) {
312
- return `export { getServerFnById } from '@tanstack/start-server-core/server-fn-ssr-caller'`;
313
- }
314
- if (this.environment.mode !== "build") {
315
- const mod = `
121
+ const compilers = {};
122
+ const serverFnsById = {};
123
+ const onServerFnsById = (d) => {
124
+ Object.assign(serverFnsById, d);
125
+ };
126
+ let root = process.cwd();
127
+ const resolvedResolverVirtualImportId = resolveViteId(VIRTUAL_MODULES.serverFnResolver);
128
+ const ssrEnvName = VITE_ENVIRONMENT_NAMES.server;
129
+ const ssrIsProvider = opts.providerEnvName === ssrEnvName;
130
+ const appliedResolverEnvironments = new Set(ssrIsProvider ? [opts.providerEnvName] : [ssrEnvName, opts.providerEnvName]);
131
+ function perEnvServerFnPlugin(environment) {
132
+ const transformCodeFilter = getTransformCodeFilterForEnv(environment.type);
133
+ return {
134
+ name: `tanstack-start-core::server-fn:${environment.name}`,
135
+ enforce: "pre",
136
+ applyToEnvironment(env) {
137
+ return env.name === environment.name;
138
+ },
139
+ configResolved(config) {
140
+ root = config.root;
141
+ config.command;
142
+ },
143
+ transform: {
144
+ filter: {
145
+ id: {
146
+ exclude: new RegExp(`${SERVER_FN_LOOKUP}$`),
147
+ include: TRANSFORM_ID_REGEX
148
+ },
149
+ code: { include: transformCodeFilter }
150
+ },
151
+ async handler(code, id) {
152
+ let compiler = compilers[this.environment.name];
153
+ if (!compiler) {
154
+ const mode = this.environment.mode === "build" ? "build" : "dev";
155
+ compiler = new StartCompiler({
156
+ env: environment.type,
157
+ envName: environment.name,
158
+ root,
159
+ lookupKinds: LookupKindsPerEnv[environment.type],
160
+ lookupConfigurations: getLookupConfigurationsForEnv(environment.type, opts.framework),
161
+ mode,
162
+ framework: opts.framework,
163
+ providerEnvName: opts.providerEnvName,
164
+ generateFunctionId: opts.generateFunctionId,
165
+ onServerFnsById,
166
+ getKnownServerFns: () => serverFnsById,
167
+ loadModule: async (id) => {
168
+ if (this.environment.mode === "build") {
169
+ const code = (await this.load({ id })).code ?? "";
170
+ compiler.ingestModule({
171
+ code,
172
+ id
173
+ });
174
+ } else if (this.environment.mode === "dev")
175
+ /**
176
+ * in dev, vite does not return code from `ctx.load()`
177
+ * so instead, we need to take a different approach
178
+ * we must force vite to load the module and run it through the vite plugin pipeline
179
+ * we can do this by using the `fetchModule` method
180
+ * the `captureServerFnModuleLookupPlugin` captures the module code via its transform hook and invokes analyzeModuleAST
181
+ */
182
+ await this.environment.fetchModule(id + "?" + SERVER_FN_LOOKUP);
183
+ else throw new Error(`could not load module ${id}: unknown environment mode ${this.environment.mode}`);
184
+ },
185
+ resolveId: async (source, importer) => {
186
+ const r = await this.resolve(source, importer);
187
+ if (r) {
188
+ if (!r.external) return cleanId(r.id);
189
+ }
190
+ return null;
191
+ }
192
+ });
193
+ compilers[this.environment.name] = compiler;
194
+ }
195
+ const detectedKinds = detectKindsInCode(code, environment.type);
196
+ return await compiler.compile({
197
+ id,
198
+ code,
199
+ detectedKinds
200
+ });
201
+ }
202
+ },
203
+ hotUpdate(ctx) {
204
+ const compiler = compilers[this.environment.name];
205
+ ctx.modules.forEach((m) => {
206
+ if (m.id) {
207
+ if (compiler?.invalidateModule(m.id)) m.importers.forEach((importer) => {
208
+ if (importer.id) compiler?.invalidateModule(importer.id);
209
+ });
210
+ }
211
+ });
212
+ }
213
+ };
214
+ }
215
+ return [
216
+ ...opts.environments.map(perEnvServerFnPlugin),
217
+ {
218
+ name: "tanstack-start-core:capture-server-fn-module-lookup",
219
+ apply: "serve",
220
+ applyToEnvironment(env) {
221
+ return !!opts.environments.find((e) => e.name === env.name);
222
+ },
223
+ transform: {
224
+ filter: { id: new RegExp(`${SERVER_FN_LOOKUP}$`) },
225
+ handler(code, id) {
226
+ compilers[this.environment.name]?.ingestModule({
227
+ code,
228
+ id: cleanId(id)
229
+ });
230
+ }
231
+ }
232
+ },
233
+ {
234
+ name: "tanstack-start-core:validate-server-fn-id",
235
+ apply: "serve",
236
+ load: {
237
+ filter: { id: new RegExp(resolveViteId(validateServerFnIdVirtualModule)) },
238
+ async handler(id) {
239
+ const fnId = parseIdQuery(id).query.id;
240
+ if (fnId && serverFnsById[fnId]) return `export {}`;
241
+ if (fnId) try {
242
+ const decoded = JSON.parse(Buffer.from(fnId, "base64url").toString("utf8"));
243
+ if (typeof decoded.file === "string" && typeof decoded.export === "string") {
244
+ let sourceFile = decoded.file;
245
+ if (sourceFile.startsWith("/@id/")) sourceFile = sourceFile.slice(5);
246
+ const qIdx = sourceFile.indexOf("?");
247
+ if (qIdx !== -1) sourceFile = sourceFile.slice(0, qIdx);
248
+ const absPath = resolve(root, sourceFile);
249
+ assert(this.environment.mode === "dev");
250
+ await this.environment.fetchModule(absPath);
251
+ if (serverFnsById[fnId]) return `export {}`;
252
+ }
253
+ } catch {}
254
+ this.error(`Invalid server function ID: ${fnId}`);
255
+ }
256
+ }
257
+ },
258
+ {
259
+ name: "tanstack-start-core:server-fn-resolver",
260
+ enforce: "pre",
261
+ applyToEnvironment: (env) => {
262
+ return appliedResolverEnvironments.has(env.name);
263
+ },
264
+ configResolved(config) {
265
+ root = config.root;
266
+ config.command;
267
+ },
268
+ resolveId: {
269
+ filter: { id: new RegExp(VIRTUAL_MODULES.serverFnResolver) },
270
+ handler() {
271
+ return resolvedResolverVirtualImportId;
272
+ }
273
+ },
274
+ load: {
275
+ filter: { id: new RegExp(resolvedResolverVirtualImportId) },
276
+ handler() {
277
+ if (this.environment.name !== opts.providerEnvName) return `export { getServerFnById } from '@tanstack/start-server-core/server-fn-ssr-caller'`;
278
+ if (this.environment.mode !== "build") return `
316
279
  export async function getServerFnById(id) {
317
280
  const validateIdImport = ${JSON.stringify(validateServerFnIdVirtualModule)} + '?id=' + id
318
281
  await import(/* @vite-ignore */ '/@id/__x00__' + validateIdImport)
@@ -322,20 +285,13 @@ function startCompilerPlugin(opts) {
322
285
  return mod[devServerFn.export]
323
286
  }
324
287
  `;
325
- return mod;
326
- }
327
- const includeClientReferencedCheck = !ssrIsProvider;
328
- return generateManifestModule(
329
- serverFnsById,
330
- includeClientReferencedCheck
331
- );
332
- }
333
- }
334
- }
335
- ];
288
+ return generateManifestModule(serverFnsById, !ssrIsProvider);
289
+ }
290
+ }
291
+ }
292
+ ];
336
293
  }
337
- export {
338
- SERVER_FN_LOOKUP,
339
- startCompilerPlugin
340
- };
341
- //# sourceMappingURL=plugin.js.map
294
+ //#endregion
295
+ export { startCompilerPlugin };
296
+
297
+ //# sourceMappingURL=plugin.js.map