@tanstack/start-plugin-core 1.167.35 → 1.169.0

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 (187) hide show
  1. package/dist/esm/import-protection/adapterUtils.d.ts +27 -0
  2. package/dist/esm/import-protection/adapterUtils.js +31 -0
  3. package/dist/esm/import-protection/adapterUtils.js.map +1 -0
  4. package/dist/esm/import-protection/analysis.d.ts +36 -0
  5. package/dist/esm/import-protection/analysis.js +407 -0
  6. package/dist/esm/import-protection/analysis.js.map +1 -0
  7. package/dist/esm/{import-protection-plugin → import-protection}/ast.js +1 -1
  8. package/dist/esm/import-protection/ast.js.map +1 -0
  9. package/dist/esm/import-protection/constants.d.ts +11 -0
  10. package/dist/esm/{import-protection-plugin → import-protection}/constants.js +7 -2
  11. package/dist/esm/import-protection/constants.js.map +1 -0
  12. package/dist/esm/{import-protection-plugin → import-protection}/defaults.js +1 -1
  13. package/dist/esm/import-protection/defaults.js.map +1 -0
  14. package/dist/esm/{import-protection-plugin → import-protection}/extensionlessAbsoluteIdResolver.js +2 -2
  15. package/dist/esm/import-protection/extensionlessAbsoluteIdResolver.js.map +1 -0
  16. package/dist/esm/{import-protection-plugin → import-protection}/matchers.js +1 -1
  17. package/dist/esm/import-protection/matchers.js.map +1 -0
  18. package/dist/esm/{import-protection-plugin/rewriteDeniedImports.d.ts → import-protection/rewrite.d.ts} +0 -4
  19. package/dist/esm/import-protection/rewrite.js +121 -0
  20. package/dist/esm/import-protection/rewrite.js.map +1 -0
  21. package/dist/esm/{import-protection-plugin → import-protection}/sourceLocation.d.ts +32 -3
  22. package/dist/esm/{import-protection-plugin → import-protection}/sourceLocation.js +65 -10
  23. package/dist/esm/import-protection/sourceLocation.js.map +1 -0
  24. package/dist/esm/{import-protection-plugin → import-protection}/trace.d.ts +0 -1
  25. package/dist/esm/{import-protection-plugin → import-protection}/trace.js +1 -1
  26. package/dist/esm/import-protection/trace.js.map +1 -0
  27. package/dist/esm/{import-protection-plugin → import-protection}/utils.d.ts +18 -1
  28. package/dist/esm/{import-protection-plugin → import-protection}/utils.js +13 -20
  29. package/dist/esm/import-protection/utils.js.map +1 -0
  30. package/dist/esm/import-protection/virtualModules.d.ts +25 -0
  31. package/dist/esm/{import-protection-plugin → import-protection}/virtualModules.js +5 -117
  32. package/dist/esm/import-protection/virtualModules.js.map +1 -0
  33. package/dist/esm/index.d.ts +1 -5
  34. package/dist/esm/index.js +2 -4
  35. package/dist/esm/post-build.d.ts +9 -0
  36. package/dist/esm/post-build.js +37 -0
  37. package/dist/esm/post-build.js.map +1 -0
  38. package/dist/esm/prerender.d.ts +11 -0
  39. package/dist/esm/prerender.js +159 -0
  40. package/dist/esm/prerender.js.map +1 -0
  41. package/dist/esm/rsbuild/dev-server.d.ts +21 -0
  42. package/dist/esm/rsbuild/dev-server.js +76 -0
  43. package/dist/esm/rsbuild/dev-server.js.map +1 -0
  44. package/dist/esm/rsbuild/import-protection.d.ts +10 -0
  45. package/dist/esm/rsbuild/import-protection.js +775 -0
  46. package/dist/esm/rsbuild/import-protection.js.map +1 -0
  47. package/dist/esm/rsbuild/index.d.ts +4 -0
  48. package/dist/esm/rsbuild/index.js +3 -0
  49. package/dist/esm/rsbuild/normalized-client-build.d.ts +18 -0
  50. package/dist/esm/rsbuild/normalized-client-build.js +207 -0
  51. package/dist/esm/rsbuild/normalized-client-build.js.map +1 -0
  52. package/dist/esm/rsbuild/planning.d.ts +52 -0
  53. package/dist/esm/rsbuild/planning.js +108 -0
  54. package/dist/esm/rsbuild/planning.js.map +1 -0
  55. package/dist/esm/rsbuild/plugin.d.ts +4 -0
  56. package/dist/esm/rsbuild/plugin.js +344 -0
  57. package/dist/esm/rsbuild/plugin.js.map +1 -0
  58. package/dist/esm/rsbuild/post-build.d.ts +6 -0
  59. package/dist/esm/rsbuild/post-build.js +57 -0
  60. package/dist/esm/rsbuild/post-build.js.map +1 -0
  61. package/dist/esm/rsbuild/schema.d.ts +3372 -0
  62. package/dist/esm/rsbuild/schema.js +12 -0
  63. package/dist/esm/rsbuild/schema.js.map +1 -0
  64. package/dist/esm/rsbuild/start-compiler-host.d.ts +20 -0
  65. package/dist/esm/rsbuild/start-compiler-host.js +150 -0
  66. package/dist/esm/rsbuild/start-compiler-host.js.map +1 -0
  67. package/dist/esm/rsbuild/start-router-plugin.d.ts +18 -0
  68. package/dist/esm/rsbuild/start-router-plugin.js +63 -0
  69. package/dist/esm/rsbuild/start-router-plugin.js.map +1 -0
  70. package/dist/esm/rsbuild/swc-rsc.d.ts +14 -0
  71. package/dist/esm/rsbuild/swc-rsc.js +93 -0
  72. package/dist/esm/rsbuild/swc-rsc.js.map +1 -0
  73. package/dist/esm/rsbuild/types.d.ts +17 -0
  74. package/dist/esm/rsbuild/types.js +0 -0
  75. package/dist/esm/rsbuild/virtual-modules.d.ts +53 -0
  76. package/dist/esm/rsbuild/virtual-modules.js +287 -0
  77. package/dist/esm/rsbuild/virtual-modules.js.map +1 -0
  78. package/dist/esm/schema.d.ts +43 -43
  79. package/dist/esm/start-compiler/compiler.d.ts +1 -1
  80. package/dist/esm/start-compiler/compiler.js +80 -9
  81. package/dist/esm/start-compiler/compiler.js.map +1 -1
  82. package/dist/esm/start-compiler/handleCreateServerFn.js +9 -0
  83. package/dist/esm/start-compiler/handleCreateServerFn.js.map +1 -1
  84. package/dist/esm/start-compiler/host.js +5 -1
  85. package/dist/esm/start-compiler/host.js.map +1 -1
  86. package/dist/esm/start-compiler/types.d.ts +1 -0
  87. package/dist/esm/utils.d.ts +1 -0
  88. package/dist/esm/utils.js +10 -1
  89. package/dist/esm/utils.js.map +1 -1
  90. package/dist/esm/{import-protection-plugin → vite/import-protection-plugin}/plugin.js +41 -92
  91. package/dist/esm/vite/import-protection-plugin/plugin.js.map +1 -0
  92. package/dist/esm/{import-protection-plugin → vite/import-protection-plugin}/types.d.ts +5 -5
  93. package/dist/esm/vite/import-protection-plugin/virtualModules.d.ts +8 -0
  94. package/dist/esm/vite/import-protection-plugin/virtualModules.js +49 -0
  95. package/dist/esm/vite/import-protection-plugin/virtualModules.js.map +1 -0
  96. package/dist/esm/vite/index.d.ts +5 -0
  97. package/dist/esm/vite/index.js +4 -0
  98. package/dist/esm/vite/plugin.js +1 -1
  99. package/dist/esm/vite/plugin.js.map +1 -1
  100. package/dist/esm/vite/post-server-build.js +14 -32
  101. package/dist/esm/vite/post-server-build.js.map +1 -1
  102. package/dist/esm/vite/prerender.d.ts +2 -2
  103. package/dist/esm/vite/prerender.js +17 -147
  104. package/dist/esm/vite/prerender.js.map +1 -1
  105. package/dist/esm/vite/schema.d.ts +23 -23
  106. package/dist/esm/vite/start-compiler-plugin/hot-update.d.ts +2 -0
  107. package/dist/esm/vite/start-compiler-plugin/hot-update.js +16 -0
  108. package/dist/esm/vite/start-compiler-plugin/hot-update.js.map +1 -0
  109. package/dist/esm/vite/start-compiler-plugin/module-specifier.js +9 -4
  110. package/dist/esm/vite/start-compiler-plugin/module-specifier.js.map +1 -1
  111. package/dist/esm/vite/start-compiler-plugin/plugin.js +86 -13
  112. package/dist/esm/vite/start-compiler-plugin/plugin.js.map +1 -1
  113. package/package.json +32 -4
  114. package/src/import-protection/INTERNALS.md +266 -0
  115. package/src/import-protection/adapterUtils.ts +94 -0
  116. package/src/import-protection/analysis.ts +853 -0
  117. package/src/{import-protection-plugin → import-protection}/constants.ts +7 -0
  118. package/src/import-protection/rewrite.ts +229 -0
  119. package/src/{import-protection-plugin → import-protection}/sourceLocation.ts +125 -9
  120. package/src/{import-protection-plugin → import-protection}/trace.ts +0 -1
  121. package/src/{import-protection-plugin → import-protection}/utils.ts +36 -21
  122. package/src/{import-protection-plugin → import-protection}/virtualModules.ts +30 -177
  123. package/src/index.ts +1 -8
  124. package/src/post-build.ts +64 -0
  125. package/src/prerender.ts +292 -0
  126. package/src/rsbuild/INTERNALS-import-protection.md +169 -0
  127. package/src/rsbuild/dev-server.ts +129 -0
  128. package/src/rsbuild/import-protection.ts +1599 -0
  129. package/src/rsbuild/index.ts +4 -0
  130. package/src/rsbuild/normalized-client-build.ts +346 -0
  131. package/src/rsbuild/planning.ts +234 -0
  132. package/src/rsbuild/plugin.ts +754 -0
  133. package/src/rsbuild/post-build.ts +96 -0
  134. package/src/rsbuild/schema.ts +31 -0
  135. package/src/rsbuild/start-compiler-host.ts +250 -0
  136. package/src/rsbuild/start-router-plugin.ts +86 -0
  137. package/src/rsbuild/swc-rsc.ts +166 -0
  138. package/src/rsbuild/types.ts +20 -0
  139. package/src/rsbuild/virtual-modules.ts +565 -0
  140. package/src/start-compiler/compiler.ts +153 -19
  141. package/src/start-compiler/handleCreateServerFn.ts +18 -0
  142. package/src/start-compiler/types.ts +1 -0
  143. package/src/utils.ts +14 -0
  144. package/src/vite/import-protection-plugin/INTERNALS.md +187 -0
  145. package/src/{import-protection-plugin → vite/import-protection-plugin}/plugin.ts +73 -158
  146. package/src/{import-protection-plugin → vite/import-protection-plugin}/types.ts +5 -5
  147. package/src/vite/import-protection-plugin/virtualModules.ts +122 -0
  148. package/src/vite/index.ts +8 -0
  149. package/src/vite/plugin.ts +1 -1
  150. package/src/vite/post-server-build.ts +14 -57
  151. package/src/vite/prerender.ts +19 -260
  152. package/src/vite/start-compiler-plugin/hot-update.ts +24 -0
  153. package/src/vite/start-compiler-plugin/module-specifier.ts +15 -5
  154. package/src/vite/start-compiler-plugin/plugin.ts +193 -18
  155. package/dist/esm/import-protection-plugin/ast.js.map +0 -1
  156. package/dist/esm/import-protection-plugin/constants.d.ts +0 -6
  157. package/dist/esm/import-protection-plugin/constants.js.map +0 -1
  158. package/dist/esm/import-protection-plugin/defaults.js.map +0 -1
  159. package/dist/esm/import-protection-plugin/extensionlessAbsoluteIdResolver.js.map +0 -1
  160. package/dist/esm/import-protection-plugin/matchers.js.map +0 -1
  161. package/dist/esm/import-protection-plugin/plugin.js.map +0 -1
  162. package/dist/esm/import-protection-plugin/postCompileUsage.d.ts +0 -13
  163. package/dist/esm/import-protection-plugin/postCompileUsage.js +0 -63
  164. package/dist/esm/import-protection-plugin/postCompileUsage.js.map +0 -1
  165. package/dist/esm/import-protection-plugin/rewriteDeniedImports.js +0 -205
  166. package/dist/esm/import-protection-plugin/rewriteDeniedImports.js.map +0 -1
  167. package/dist/esm/import-protection-plugin/sourceLocation.js.map +0 -1
  168. package/dist/esm/import-protection-plugin/trace.js.map +0 -1
  169. package/dist/esm/import-protection-plugin/utils.js.map +0 -1
  170. package/dist/esm/import-protection-plugin/virtualModules.d.ts +0 -78
  171. package/dist/esm/import-protection-plugin/virtualModules.js.map +0 -1
  172. package/dist/esm/start-compiler/load-module.d.ts +0 -14
  173. package/dist/esm/start-compiler/load-module.js +0 -18
  174. package/dist/esm/start-compiler/load-module.js.map +0 -1
  175. package/src/import-protection-plugin/INTERNALS.md +0 -700
  176. package/src/import-protection-plugin/postCompileUsage.ts +0 -100
  177. package/src/import-protection-plugin/rewriteDeniedImports.ts +0 -379
  178. package/src/start-compiler/load-module.ts +0 -31
  179. /package/dist/esm/{import-protection-plugin → import-protection}/ast.d.ts +0 -0
  180. /package/dist/esm/{import-protection-plugin → import-protection}/defaults.d.ts +0 -0
  181. /package/dist/esm/{import-protection-plugin → import-protection}/extensionlessAbsoluteIdResolver.d.ts +0 -0
  182. /package/dist/esm/{import-protection-plugin → import-protection}/matchers.d.ts +0 -0
  183. /package/dist/esm/{import-protection-plugin → vite/import-protection-plugin}/plugin.d.ts +0 -0
  184. /package/src/{import-protection-plugin → import-protection}/ast.ts +0 -0
  185. /package/src/{import-protection-plugin → import-protection}/defaults.ts +0 -0
  186. /package/src/{import-protection-plugin → import-protection}/extensionlessAbsoluteIdResolver.ts +0 -0
  187. /package/src/{import-protection-plugin → import-protection}/matchers.ts +0 -0
@@ -0,0 +1,12 @@
1
+ import { parseStartConfig as parseStartConfig$1, tanstackStartOptionsObjectSchema } from "../schema.js";
2
+ import { z } from "zod";
3
+ //#region src/rsbuild/schema.ts
4
+ var tanstackStartRsbuildOptionsSchema = tanstackStartOptionsObjectSchema.extend({ rsbuild: z.object({ installDevServerMiddleware: z.boolean().optional() }).optional() }).optional().default({});
5
+ function parseStartConfig(opts, corePluginOpts, root) {
6
+ const { rsbuild: _rsbuild, ...coreOptions } = tanstackStartRsbuildOptionsSchema.parse(opts);
7
+ return parseStartConfig$1(coreOptions, corePluginOpts, root);
8
+ }
9
+ //#endregion
10
+ export { parseStartConfig };
11
+
12
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","names":[],"sources":["../../../src/rsbuild/schema.ts"],"sourcesContent":["import { z } from 'zod'\nimport {\n parseStartConfig as parseCoreStartConfig,\n tanstackStartOptionsObjectSchema,\n} from '../schema'\nimport type { CompileStartFrameworkOptions } from '../types'\n\nexport const tanstackStartRsbuildOptionsSchema =\n tanstackStartOptionsObjectSchema\n .extend({\n rsbuild: z\n .object({ installDevServerMiddleware: z.boolean().optional() })\n .optional(),\n })\n .optional()\n .default({})\n\nexport function parseStartConfig(\n opts: z.input<typeof tanstackStartRsbuildOptionsSchema>,\n corePluginOpts: { framework: CompileStartFrameworkOptions },\n root: string,\n) {\n const { rsbuild: _rsbuild, ...coreOptions } =\n tanstackStartRsbuildOptionsSchema.parse(opts)\n\n return parseCoreStartConfig(coreOptions, corePluginOpts, root)\n}\n\nexport type TanStackStartRsbuildInputConfig = z.input<\n typeof tanstackStartRsbuildOptionsSchema\n>\n"],"mappings":";;;AAOA,IAAa,oCACX,iCACG,OAAO,EACN,SAAS,EACN,OAAO,EAAE,4BAA4B,EAAE,SAAS,CAAC,UAAU,EAAE,CAAC,CAC9D,UAAU,EACd,CAAC,CACD,UAAU,CACV,QAAQ,EAAE,CAAC;AAEhB,SAAgB,iBACd,MACA,gBACA,MACA;CACA,MAAM,EAAE,SAAS,UAAU,GAAG,gBAC5B,kCAAkC,MAAM,KAAK;AAE/C,QAAO,mBAAqB,aAAa,gBAAgB,KAAK"}
@@ -0,0 +1,20 @@
1
+ import { RsbuildPluginAPI } from '@rsbuild/core';
2
+ import { CompileStartFrameworkOptions } from '../types.js';
3
+ import { GenerateFunctionIdFnOptional, ServerFn } from '../start-compiler/types.js';
4
+ export interface StartCompilerHostOptions {
5
+ framework: CompileStartFrameworkOptions;
6
+ root: string | (() => string);
7
+ providerEnvName: string;
8
+ generateFunctionId?: GenerateFunctionIdFnOptional;
9
+ serverFnsById?: Record<string, ServerFn>;
10
+ onServerFnsByIdChange?: () => void;
11
+ }
12
+ /**
13
+ * Registers the shared StartCompiler as rsbuild transforms for client + ssr environments.
14
+ *
15
+ * Uses `api.transform()` to hook into the rsbuild loader pipeline, and the
16
+ * transform context's native `resolve()` for module resolution.
17
+ */
18
+ export declare function registerStartCompilerTransforms(api: RsbuildPluginAPI, opts: StartCompilerHostOptions): {
19
+ serverFnsById: Record<string, ServerFn>;
20
+ };
@@ -0,0 +1,150 @@
1
+ import { TRANSFORM_ID_REGEX } from "../constants.js";
2
+ import { cleanId } from "../start-compiler/utils.js";
3
+ import { detectKindsInCode } from "../start-compiler/compiler.js";
4
+ import { getTransformCodeFilterForEnv } from "../start-compiler/config.js";
5
+ import { createStartCompiler, matchesCodeFilters, mergeServerFnsById } from "../start-compiler/host.js";
6
+ import { RSBUILD_ENVIRONMENT_NAMES } from "./planning.js";
7
+ import { pathToFileURL } from "node:url";
8
+ import { AsyncLocalStorage } from "node:async_hooks";
9
+ //#region src/rsbuild/start-compiler-host.ts
10
+ /**
11
+ * Rsbuild dev server fn ref strategy: uses file:// URLs for absolute paths.
12
+ * These are directly importable by Node's ESM VM runner without any bundler
13
+ * path conventions (unlike Vite's /@id/ prefix).
14
+ */
15
+ var rsbuildDevServerFnModuleSpecifierEncoder = ({ extractedFilename }) => pathToFileURL(extractedFilename).href;
16
+ /**
17
+ * Registers the shared StartCompiler as rsbuild transforms for client + ssr environments.
18
+ *
19
+ * Uses `api.transform()` to hook into the rsbuild loader pipeline, and the
20
+ * transform context's native `resolve()` for module resolution.
21
+ */
22
+ function registerStartCompilerTransforms(api, opts) {
23
+ const compilers = /* @__PURE__ */ new Map();
24
+ const inputFileSystems = /* @__PURE__ */ new Map();
25
+ const transformContextStorage = new AsyncLocalStorage();
26
+ const serverFnsById = opts.serverFnsById ?? {};
27
+ const getRoot = () => typeof opts.root === "function" ? opts.root() : opts.root;
28
+ const onServerFnsById = (d) => {
29
+ mergeServerFnsById(serverFnsById, d);
30
+ opts.onServerFnsByIdChange?.();
31
+ };
32
+ const isDev = api.context.action === "dev";
33
+ const mode = isDev ? "dev" : "build";
34
+ const environments = [{
35
+ name: RSBUILD_ENVIRONMENT_NAMES.client,
36
+ type: "client"
37
+ }, {
38
+ name: RSBUILD_ENVIRONMENT_NAMES.server,
39
+ type: "server"
40
+ }];
41
+ const codeFilters = {
42
+ client: getTransformCodeFilterForEnv("client"),
43
+ server: getTransformCodeFilterForEnv("server")
44
+ };
45
+ for (const env of environments) {
46
+ const envCodeFilters = codeFilters[env.type];
47
+ api.transform({
48
+ test: TRANSFORM_ID_REGEX[0],
49
+ environments: [env.name],
50
+ order: "pre"
51
+ }, async (ctx) => {
52
+ return transformContextStorage.run(ctx, async () => {
53
+ const code = ctx.code;
54
+ const id = ctx.resourcePath + (ctx.resourceQuery || "");
55
+ if (!matchesCodeFilters(code, envCodeFilters)) return code;
56
+ let compiler = compilers.get(env.name);
57
+ if (!compiler) {
58
+ const root = getRoot();
59
+ compiler = createStartCompiler({
60
+ env: env.type,
61
+ envName: env.name,
62
+ root,
63
+ mode,
64
+ framework: opts.framework,
65
+ providerEnvName: opts.providerEnvName,
66
+ generateFunctionId: opts.generateFunctionId,
67
+ onServerFnsById,
68
+ getKnownServerFns: () => serverFnsById,
69
+ encodeModuleSpecifierInDev: isDev ? rsbuildDevServerFnModuleSpecifierEncoder : void 0,
70
+ loadModule: async (moduleId) => {
71
+ const activeCtx = transformContextStorage.getStore();
72
+ if (!activeCtx) throw new Error(`could not load module ${moduleId}: missing active rsbuild transform context for ${env.name}`);
73
+ const inputFileSystem = inputFileSystems.get(env.name);
74
+ if (!inputFileSystem) throw new Error(`could not load module ${moduleId}: missing rspack input filesystem for ${env.name}`);
75
+ const cleanedId = cleanId(moduleId);
76
+ activeCtx.addDependency(cleanedId);
77
+ const loaded = await readFileFromInputFileSystem(inputFileSystem, cleanedId);
78
+ const moduleCode = Buffer.isBuffer(loaded) ? loaded.toString("utf8") : loaded;
79
+ compiler.ingestModule({
80
+ code: moduleCode,
81
+ id: cleanedId
82
+ });
83
+ },
84
+ resolveId: async (source, importer) => {
85
+ const activeCtx = transformContextStorage.getStore();
86
+ if (!activeCtx) throw new Error(`could not resolve ${source}: missing active rsbuild transform context for ${env.name}`);
87
+ const context = importer ? importer.replace(/[/\\][^/\\]*$/, "") : getRoot();
88
+ return await new Promise((resolve, reject) => {
89
+ activeCtx.resolve(context, source, (error, resolved) => {
90
+ if (error) {
91
+ reject(error);
92
+ return;
93
+ }
94
+ if (!resolved) {
95
+ resolve(null);
96
+ return;
97
+ }
98
+ resolve(cleanId(resolved));
99
+ });
100
+ });
101
+ }
102
+ });
103
+ compilers.set(env.name, compiler);
104
+ }
105
+ const detectedKinds = detectKindsInCode(code, env.type);
106
+ const result = await compiler.compile({
107
+ id,
108
+ code,
109
+ detectedKinds
110
+ });
111
+ if (!result) return code;
112
+ return {
113
+ code: result.code,
114
+ map: result.map ?? null
115
+ };
116
+ });
117
+ });
118
+ }
119
+ api.modifyRspackConfig((config, utils) => {
120
+ config.plugins.push({ apply(compiler) {
121
+ if (compiler.inputFileSystem) inputFileSystems.set(utils.environment.name, compiler.inputFileSystem);
122
+ compiler.hooks.watchRun.tap("TanStackStartCompilerModuleInvalidation", (watchCompiler) => {
123
+ const startCompiler = compilers.get(utils.environment.name);
124
+ if (!startCompiler) return;
125
+ for (const file of watchCompiler.modifiedFiles ?? []) startCompiler.invalidateModule(file);
126
+ for (const file of watchCompiler.removedFiles ?? []) startCompiler.invalidateModule(file);
127
+ });
128
+ } });
129
+ });
130
+ return { serverFnsById };
131
+ }
132
+ function readFileFromInputFileSystem(inputFileSystem, file) {
133
+ return new Promise((resolve, reject) => {
134
+ inputFileSystem.readFile(file, (error, data) => {
135
+ if (error) {
136
+ reject(error);
137
+ return;
138
+ }
139
+ if (data == null) {
140
+ reject(/* @__PURE__ */ new Error(`could not read module source for ${file}`));
141
+ return;
142
+ }
143
+ resolve(data);
144
+ });
145
+ });
146
+ }
147
+ //#endregion
148
+ export { registerStartCompilerTransforms };
149
+
150
+ //# sourceMappingURL=start-compiler-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start-compiler-host.js","names":[],"sources":["../../../src/rsbuild/start-compiler-host.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks'\nimport { pathToFileURL } from 'node:url'\nimport { TRANSFORM_ID_REGEX } from '../constants'\nimport { detectKindsInCode } from '../start-compiler/compiler'\nimport { getTransformCodeFilterForEnv } from '../start-compiler/config'\nimport {\n createStartCompiler,\n matchesCodeFilters,\n mergeServerFnsById,\n} from '../start-compiler/host'\nimport { cleanId } from '../start-compiler/utils'\nimport { RSBUILD_ENVIRONMENT_NAMES } from './planning'\nimport type { RsbuildPluginAPI, Rspack } from '@rsbuild/core'\nimport type { CompileStartFrameworkOptions } from '../types'\nimport type {\n DevServerFnModuleSpecifierEncoder,\n GenerateFunctionIdFnOptional,\n ServerFn,\n} from '../start-compiler/types'\n\ntype RsbuildTransformContext = Parameters<\n Parameters<RsbuildPluginAPI['transform']>[1]\n>[0]\ntype RsbuildInputFileSystem = NonNullable<Rspack.Compiler['inputFileSystem']>\n\n/**\n * Rsbuild dev server fn ref strategy: uses file:// URLs for absolute paths.\n * These are directly importable by Node's ESM VM runner without any bundler\n * path conventions (unlike Vite's /@id/ prefix).\n */\nconst rsbuildDevServerFnModuleSpecifierEncoder: DevServerFnModuleSpecifierEncoder =\n ({ extractedFilename }) => pathToFileURL(extractedFilename).href\n\nexport interface StartCompilerHostOptions {\n framework: CompileStartFrameworkOptions\n root: string | (() => string)\n providerEnvName: string\n generateFunctionId?: GenerateFunctionIdFnOptional\n serverFnsById?: Record<string, ServerFn>\n onServerFnsByIdChange?: () => void\n}\n\n/**\n * Registers the shared StartCompiler as rsbuild transforms for client + ssr environments.\n *\n * Uses `api.transform()` to hook into the rsbuild loader pipeline, and the\n * transform context's native `resolve()` for module resolution.\n */\nexport function registerStartCompilerTransforms(\n api: RsbuildPluginAPI,\n opts: StartCompilerHostOptions,\n): {\n serverFnsById: Record<string, ServerFn>\n} {\n const compilers = new Map<string, ReturnType<typeof createStartCompiler>>()\n const inputFileSystems = new Map<string, RsbuildInputFileSystem>()\n const transformContextStorage =\n new AsyncLocalStorage<RsbuildTransformContext>()\n const serverFnsById = opts.serverFnsById ?? {}\n const getRoot = () =>\n typeof opts.root === 'function' ? opts.root() : opts.root\n\n const onServerFnsById = (d: Record<string, ServerFn>) => {\n mergeServerFnsById(serverFnsById, d)\n opts.onServerFnsByIdChange?.()\n }\n\n const isDev = api.context.action === 'dev'\n const mode = isDev ? 'dev' : 'build'\n\n const environments: Array<{\n name: string\n type: 'client' | 'server'\n }> = [\n { name: RSBUILD_ENVIRONMENT_NAMES.client, type: 'client' },\n { name: RSBUILD_ENVIRONMENT_NAMES.server, type: 'server' },\n ]\n\n // Pre-compute code filter patterns per environment type\n const codeFilters: Record<'client' | 'server', Array<RegExp>> = {\n client: getTransformCodeFilterForEnv('client'),\n server: getTransformCodeFilterForEnv('server'),\n }\n\n for (const env of environments) {\n const envCodeFilters = codeFilters[env.type]\n\n api.transform(\n {\n test: TRANSFORM_ID_REGEX[0],\n environments: [env.name],\n order: 'pre',\n },\n async (ctx: RsbuildTransformContext) => {\n return transformContextStorage.run(ctx, async () => {\n const code = ctx.code\n const id = ctx.resourcePath + (ctx.resourceQuery || '')\n\n // Quick string-level check: does this file contain any patterns for this env?\n if (!matchesCodeFilters(code, envCodeFilters)) {\n return code\n }\n\n let compiler = compilers.get(env.name)\n if (!compiler) {\n const root = getRoot()\n\n compiler = createStartCompiler({\n env: env.type,\n envName: env.name,\n root,\n mode,\n framework: opts.framework,\n providerEnvName: opts.providerEnvName,\n generateFunctionId: opts.generateFunctionId,\n onServerFnsById,\n getKnownServerFns: () => serverFnsById,\n encodeModuleSpecifierInDev: isDev\n ? rsbuildDevServerFnModuleSpecifierEncoder\n : undefined,\n loadModule: async (moduleId: string) => {\n const activeCtx = transformContextStorage.getStore()\n if (!activeCtx) {\n throw new Error(\n `could not load module ${moduleId}: missing active rsbuild transform context for ${env.name}`,\n )\n }\n\n const inputFileSystem = inputFileSystems.get(env.name)\n if (!inputFileSystem) {\n throw new Error(\n `could not load module ${moduleId}: missing rspack input filesystem for ${env.name}`,\n )\n }\n\n const cleanedId = cleanId(moduleId)\n activeCtx.addDependency(cleanedId)\n const loaded = await readFileFromInputFileSystem(\n inputFileSystem,\n cleanedId,\n )\n const moduleCode = Buffer.isBuffer(loaded)\n ? loaded.toString('utf8')\n : loaded\n\n compiler!.ingestModule({ code: moduleCode, id: cleanedId })\n },\n resolveId: async (\n source: string,\n importer?: string,\n ): Promise<string | null> => {\n const activeCtx = transformContextStorage.getStore()\n if (!activeCtx) {\n throw new Error(\n `could not resolve ${source}: missing active rsbuild transform context for ${env.name}`,\n )\n }\n\n const context = importer\n ? importer.replace(/[/\\\\][^/\\\\]*$/, '')\n : getRoot()\n\n return await new Promise((resolve, reject) => {\n activeCtx.resolve(context, source, (error, resolved) => {\n if (error) {\n reject(error)\n return\n }\n\n if (!resolved) {\n resolve(null)\n return\n }\n\n resolve(cleanId(resolved))\n })\n })\n },\n })\n compilers.set(env.name, compiler)\n }\n\n const detectedKinds = detectKindsInCode(code, env.type)\n const result = await compiler.compile({ id, code, detectedKinds })\n\n if (!result) {\n return code\n }\n\n return {\n code: result.code,\n map: result.map ?? null,\n }\n })\n },\n )\n }\n\n api.modifyRspackConfig((config, utils) => {\n config.plugins.push({\n apply(compiler: Rspack.Compiler) {\n if (compiler.inputFileSystem) {\n inputFileSystems.set(utils.environment.name, compiler.inputFileSystem)\n }\n\n compiler.hooks.watchRun.tap(\n 'TanStackStartCompilerModuleInvalidation',\n (watchCompiler) => {\n const startCompiler = compilers.get(utils.environment.name)\n\n if (!startCompiler) {\n return\n }\n\n for (const file of watchCompiler.modifiedFiles ?? []) {\n startCompiler.invalidateModule(file)\n }\n\n for (const file of watchCompiler.removedFiles ?? []) {\n startCompiler.invalidateModule(file)\n }\n },\n )\n },\n })\n })\n\n return { serverFnsById }\n}\n\nfunction readFileFromInputFileSystem(\n inputFileSystem: RsbuildInputFileSystem,\n file: string,\n): Promise<string | Buffer> {\n return new Promise((resolve, reject) => {\n inputFileSystem.readFile(file, (error, data) => {\n if (error) {\n reject(error)\n return\n }\n\n if (data == null) {\n reject(new Error(`could not read module source for ${file}`))\n return\n }\n\n resolve(data)\n })\n })\n}\n"],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { RsbuildPluginAPI } from '@rsbuild/core';
2
+ import { GetConfigFn, TanStackStartCoreOptions } from '../types.js';
3
+ import { TanStackStartRsbuildInputConfig } from './schema.js';
4
+ /**
5
+ * Registers the TanStack Router generator and code-splitter plugins
6
+ * as rspack plugins via `modifyRspackConfig`.
7
+ *
8
+ * The router-plugin package exports rspack-compatible unplugin wrappers:
9
+ * - TanStackRouterGeneratorRspack: file-based route generation
10
+ * - TanStackRouterCodeSplitterRspack: route code splitting
11
+ *
12
+ * These are dynamically imported to avoid hard dependency on router-plugin/rspack.
13
+ */
14
+ export declare function registerRouterPlugins(api: RsbuildPluginAPI, opts: {
15
+ getConfig: GetConfigFn;
16
+ corePluginOpts: TanStackStartCoreOptions;
17
+ startPluginOpts: TanStackStartRsbuildInputConfig;
18
+ }): void;
@@ -0,0 +1,63 @@
1
+ import { routesManifestPlugin } from "../start-router-plugin/generator-plugins/routes-manifest-plugin.js";
2
+ import { prerenderRoutesPlugin } from "../start-router-plugin/generator-plugins/prerender-routes-plugin.js";
3
+ import { buildRouteTreeFileFooterFromConfig } from "../start-router-plugin/route-tree-footer.js";
4
+ import { RSBUILD_ENVIRONMENT_NAMES } from "./planning.js";
5
+ import path from "pathe";
6
+ //#region src/rsbuild/start-router-plugin.ts
7
+ /**
8
+ * Registers the TanStack Router generator and code-splitter plugins
9
+ * as rspack plugins via `modifyRspackConfig`.
10
+ *
11
+ * The router-plugin package exports rspack-compatible unplugin wrappers:
12
+ * - TanStackRouterGeneratorRspack: file-based route generation
13
+ * - TanStackRouterCodeSplitterRspack: route code splitting
14
+ *
15
+ * These are dynamically imported to avoid hard dependency on router-plugin/rspack.
16
+ */
17
+ function registerRouterPlugins(api, opts) {
18
+ api.modifyRspackConfig(async (config, utils) => {
19
+ const envName = utils.environment.name;
20
+ const { startConfig } = opts.getConfig();
21
+ const routerConfig = startConfig.router;
22
+ if (envName === RSBUILD_ENVIRONMENT_NAMES.client) try {
23
+ const { TanStackRouterGeneratorRspack } = await import("@tanstack/router-plugin/rspack");
24
+ const generatorPlugin = TanStackRouterGeneratorRspack({
25
+ ...routerConfig,
26
+ target: opts.corePluginOpts.framework,
27
+ routeTreeFileFooter: () => {
28
+ return buildRouteTreeFileFooterFromConfig({
29
+ generatedRouteTreePath: path.resolve(routerConfig.generatedRouteTree),
30
+ getConfig: opts.getConfig,
31
+ corePluginOpts: opts.corePluginOpts
32
+ });
33
+ },
34
+ plugins: [routesManifestPlugin(), ...opts.startPluginOpts?.prerender?.enabled === true ? [prerenderRoutesPlugin()] : []]
35
+ });
36
+ utils.appendPlugins(generatorPlugin);
37
+ } catch {}
38
+ if (envName === RSBUILD_ENVIRONMENT_NAMES.client || envName === RSBUILD_ENVIRONMENT_NAMES.server) {
39
+ const isClient = envName === RSBUILD_ENVIRONMENT_NAMES.client;
40
+ try {
41
+ const { TanStackRouterCodeSplitterRspack } = await import("@tanstack/router-plugin/rspack");
42
+ const splitterPlugin = TanStackRouterCodeSplitterRspack({
43
+ ...routerConfig,
44
+ target: opts.corePluginOpts.framework,
45
+ codeSplittingOptions: {
46
+ ...routerConfig.codeSplittingOptions,
47
+ deleteNodes: isClient ? [
48
+ "ssr",
49
+ "server",
50
+ "headers"
51
+ ] : void 0,
52
+ addHmr: isClient
53
+ }
54
+ });
55
+ utils.appendPlugins(splitterPlugin);
56
+ } catch {}
57
+ }
58
+ });
59
+ }
60
+ //#endregion
61
+ export { registerRouterPlugins };
62
+
63
+ //# sourceMappingURL=start-router-plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start-router-plugin.js","names":[],"sources":["../../../src/rsbuild/start-router-plugin.ts"],"sourcesContent":["import path from 'pathe'\nimport { routesManifestPlugin } from '../start-router-plugin/generator-plugins/routes-manifest-plugin'\nimport { prerenderRoutesPlugin } from '../start-router-plugin/generator-plugins/prerender-routes-plugin'\nimport { buildRouteTreeFileFooterFromConfig } from '../start-router-plugin/route-tree-footer'\nimport { RSBUILD_ENVIRONMENT_NAMES } from './planning'\nimport type { RsbuildPluginAPI } from '@rsbuild/core'\nimport type { GetConfigFn, TanStackStartCoreOptions } from '../types'\nimport type { TanStackStartRsbuildInputConfig } from './schema'\n\n/**\n * Registers the TanStack Router generator and code-splitter plugins\n * as rspack plugins via `modifyRspackConfig`.\n *\n * The router-plugin package exports rspack-compatible unplugin wrappers:\n * - TanStackRouterGeneratorRspack: file-based route generation\n * - TanStackRouterCodeSplitterRspack: route code splitting\n *\n * These are dynamically imported to avoid hard dependency on router-plugin/rspack.\n */\nexport function registerRouterPlugins(\n api: RsbuildPluginAPI,\n opts: {\n getConfig: GetConfigFn\n corePluginOpts: TanStackStartCoreOptions\n startPluginOpts: TanStackStartRsbuildInputConfig\n },\n): void {\n api.modifyRspackConfig(async (config, utils) => {\n const envName = utils.environment.name\n const { startConfig } = opts.getConfig()\n const routerConfig = startConfig.router\n\n // Generator only runs once — register for the client environment\n if (envName === RSBUILD_ENVIRONMENT_NAMES.client) {\n try {\n const { TanStackRouterGeneratorRspack } =\n await import('@tanstack/router-plugin/rspack')\n const generatorPlugin = TanStackRouterGeneratorRspack({\n ...routerConfig,\n target: opts.corePluginOpts.framework,\n routeTreeFileFooter: () => {\n return buildRouteTreeFileFooterFromConfig({\n generatedRouteTreePath: path.resolve(\n routerConfig.generatedRouteTree,\n ),\n getConfig: opts.getConfig,\n corePluginOpts: opts.corePluginOpts,\n })\n },\n plugins: [\n routesManifestPlugin(),\n ...(opts.startPluginOpts?.prerender?.enabled === true\n ? [prerenderRoutesPlugin()]\n : []),\n ],\n })\n utils.appendPlugins(generatorPlugin as any)\n } catch {\n // router-plugin/rspack not available — skip\n }\n }\n\n if (\n envName === RSBUILD_ENVIRONMENT_NAMES.client ||\n envName === RSBUILD_ENVIRONMENT_NAMES.server\n ) {\n const isClient = envName === RSBUILD_ENVIRONMENT_NAMES.client\n try {\n const { TanStackRouterCodeSplitterRspack } =\n await import('@tanstack/router-plugin/rspack')\n const splitterPlugin = TanStackRouterCodeSplitterRspack({\n ...routerConfig,\n target: opts.corePluginOpts.framework,\n codeSplittingOptions: {\n ...routerConfig.codeSplittingOptions,\n deleteNodes: isClient ? ['ssr', 'server', 'headers'] : undefined,\n addHmr: isClient,\n },\n })\n utils.appendPlugins(splitterPlugin as any)\n } catch {\n // router-plugin/rspack not available — skip\n }\n }\n })\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAmBA,SAAgB,sBACd,KACA,MAKM;AACN,KAAI,mBAAmB,OAAO,QAAQ,UAAU;EAC9C,MAAM,UAAU,MAAM,YAAY;EAClC,MAAM,EAAE,gBAAgB,KAAK,WAAW;EACxC,MAAM,eAAe,YAAY;AAGjC,MAAI,YAAY,0BAA0B,OACxC,KAAI;GACF,MAAM,EAAE,kCACN,MAAM,OAAO;GACf,MAAM,kBAAkB,8BAA8B;IACpD,GAAG;IACH,QAAQ,KAAK,eAAe;IAC5B,2BAA2B;AACzB,YAAO,mCAAmC;MACxC,wBAAwB,KAAK,QAC3B,aAAa,mBACd;MACD,WAAW,KAAK;MAChB,gBAAgB,KAAK;MACtB,CAAC;;IAEJ,SAAS,CACP,sBAAsB,EACtB,GAAI,KAAK,iBAAiB,WAAW,YAAY,OAC7C,CAAC,uBAAuB,CAAC,GACzB,EAAE,CACP;IACF,CAAC;AACF,SAAM,cAAc,gBAAuB;UACrC;AAKV,MACE,YAAY,0BAA0B,UACtC,YAAY,0BAA0B,QACtC;GACA,MAAM,WAAW,YAAY,0BAA0B;AACvD,OAAI;IACF,MAAM,EAAE,qCACN,MAAM,OAAO;IACf,MAAM,iBAAiB,iCAAiC;KACtD,GAAG;KACH,QAAQ,KAAK,eAAe;KAC5B,sBAAsB;MACpB,GAAG,aAAa;MAChB,aAAa,WAAW;OAAC;OAAO;OAAU;OAAU,GAAG,KAAA;MACvD,QAAQ;MACT;KACF,CAAC;AACF,UAAM,cAAc,eAAsB;WACpC;;GAIV"}
@@ -0,0 +1,14 @@
1
+ import { ModifyRspackConfigFn } from '@rsbuild/core';
2
+ type RspackConfig = Parameters<ModifyRspackConfigFn>[0];
3
+ /**
4
+ * Walk the rspack config's module.rules and inject
5
+ * `rspackExperiments.reactServerComponents: true` into SWC loaders.
6
+ *
7
+ * Recurses into `oneOf` arrays because rsbuild nests the main SWC loader
8
+ * inside a `oneOf` rule (e.g. separate branches for asset/source vs
9
+ * javascript/auto). Without recursion, only the mimetype-based fallback
10
+ * SWC rule gets the flag, leaving most .js/.ts files without RSC
11
+ * directive detection.
12
+ */
13
+ export declare function enableSwcReactServerComponents(config: RspackConfig, scope: 'all' | 'rsc-subtree'): void;
14
+ export {};
@@ -0,0 +1,93 @@
1
+ import { RSBUILD_RSC_LAYERS } from "./planning.js";
2
+ //#region src/rsbuild/swc-rsc.ts
3
+ /**
4
+ * Walk the rspack config's module.rules and inject
5
+ * `rspackExperiments.reactServerComponents: true` into SWC loaders.
6
+ *
7
+ * Recurses into `oneOf` arrays because rsbuild nests the main SWC loader
8
+ * inside a `oneOf` rule (e.g. separate branches for asset/source vs
9
+ * javascript/auto). Without recursion, only the mimetype-based fallback
10
+ * SWC rule gets the flag, leaving most .js/.ts files without RSC
11
+ * directive detection.
12
+ */
13
+ function enableSwcReactServerComponents(config, scope) {
14
+ const isRspackRule = (rule) => !!rule && rule !== "...";
15
+ const getRuleLoaders = (rule) => {
16
+ const { use } = rule;
17
+ if (!use) return [];
18
+ return typeof use === "function" ? [] : Array.isArray(use) ? use : [use];
19
+ };
20
+ const getLoaderPath = (loader) => typeof loader === "string" ? loader : loader.loader;
21
+ const cloneLoader = (loader) => {
22
+ if (typeof loader === "string") return loader;
23
+ const options = loader.options;
24
+ return {
25
+ ...loader,
26
+ ...options && typeof options === "object" && !Array.isArray(options) ? { options: {
27
+ ...options,
28
+ ...options.rspackExperiments && typeof options.rspackExperiments === "object" && !Array.isArray(options.rspackExperiments) ? { rspackExperiments: { ...options.rspackExperiments } } : {}
29
+ } } : {}
30
+ };
31
+ };
32
+ const cloneRuleUse = (use) => {
33
+ if (!use || typeof use === "function") return use;
34
+ if (Array.isArray(use)) return use.map((loader) => cloneLoader(loader));
35
+ return cloneLoader(use);
36
+ };
37
+ const cloneRspackRule = (rule) => {
38
+ return {
39
+ ...rule,
40
+ use: cloneRuleUse(rule.use),
41
+ resolve: rule.resolve ? { ...rule.resolve } : rule.resolve,
42
+ oneOf: Array.isArray(rule.oneOf) ? rule.oneOf.map((childRule) => isRspackRule(childRule) ? cloneRspackRule(childRule) : childRule) : rule.oneOf
43
+ };
44
+ };
45
+ const rootRules = (config.module.rules ??= []).filter(isRspackRule);
46
+ function processRules(rules = rootRules) {
47
+ for (const rule of rules) {
48
+ processRules(Array.isArray(rule.oneOf) ? rule.oneOf.filter(isRspackRule) : []);
49
+ if (!getRuleLoaders(rule).some((loader) => Boolean(getLoaderPath(loader)?.includes("swc-loader")))) continue;
50
+ const enableReactServerComponentsOnRule = (nextRule) => {
51
+ for (const loader of getRuleLoaders(nextRule)) {
52
+ if (typeof loader === "string") continue;
53
+ const loaderPath = getLoaderPath(loader);
54
+ if (!loaderPath || !loaderPath.includes("swc-loader")) continue;
55
+ const options = loader.options && typeof loader.options === "object" ? loader.options : loader.options = {};
56
+ const experiments = options.rspackExperiments && typeof options.rspackExperiments === "object" ? options.rspackExperiments : options.rspackExperiments = {};
57
+ const current = experiments.reactServerComponents;
58
+ experiments.reactServerComponents = current === true || current == null ? {} : typeof current === "object" && current !== null && !Array.isArray(current) ? { ...current } : {};
59
+ }
60
+ };
61
+ if (scope === "all") {
62
+ enableReactServerComponentsOnRule(rule);
63
+ continue;
64
+ }
65
+ const originalRule = cloneRspackRule(rule);
66
+ const providerRule = cloneRspackRule(originalRule);
67
+ providerRule.resourceQuery = /(?:^|[?&])tss-serverfn-split(?:&|$)/;
68
+ enableReactServerComponentsOnRule(providerRule);
69
+ const routeSplitRule = cloneRspackRule(originalRule);
70
+ routeSplitRule.resourceQuery = /(?:^|[?&])tsr-split(?:=|&|$)/;
71
+ const routeSplitConditionNames = originalRule.resolve?.conditionNames;
72
+ routeSplitRule.resolve = {
73
+ ...originalRule.resolve,
74
+ conditionNames: Array.isArray(routeSplitConditionNames) ? routeSplitConditionNames.includes("...") ? [...routeSplitConditionNames] : ["...", ...routeSplitConditionNames] : ["..."]
75
+ };
76
+ const subtreeRule = cloneRspackRule(originalRule);
77
+ subtreeRule.issuerLayer = RSBUILD_RSC_LAYERS.rsc;
78
+ enableReactServerComponentsOnRule(subtreeRule);
79
+ for (const key of Object.keys(rule)) delete rule[key];
80
+ rule.oneOf = [
81
+ providerRule,
82
+ routeSplitRule,
83
+ subtreeRule,
84
+ originalRule
85
+ ];
86
+ }
87
+ }
88
+ processRules();
89
+ }
90
+ //#endregion
91
+ export { enableSwcReactServerComponents };
92
+
93
+ //# sourceMappingURL=swc-rsc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swc-rsc.js","names":[],"sources":["../../../src/rsbuild/swc-rsc.ts"],"sourcesContent":["import { RSBUILD_RSC_LAYERS } from './planning'\nimport type { ModifyRspackConfigFn, Rspack } from '@rsbuild/core'\n\ntype RspackConfig = Parameters<ModifyRspackConfigFn>[0]\ntype RspackRule = Rspack.RuleSetRule\n\n/**\n * Walk the rspack config's module.rules and inject\n * `rspackExperiments.reactServerComponents: true` into SWC loaders.\n *\n * Recurses into `oneOf` arrays because rsbuild nests the main SWC loader\n * inside a `oneOf` rule (e.g. separate branches for asset/source vs\n * javascript/auto). Without recursion, only the mimetype-based fallback\n * SWC rule gets the flag, leaving most .js/.ts files without RSC\n * directive detection.\n */\nexport function enableSwcReactServerComponents(\n config: RspackConfig,\n scope: 'all' | 'rsc-subtree',\n): void {\n const isRspackRule = (\n rule: NonNullable<RspackConfig['module']['rules']>[number],\n ): rule is RspackRule => !!rule && rule !== '...'\n const getRuleLoaders = (rule: RspackRule) => {\n const { use } = rule\n if (!use) {\n return []\n }\n\n return typeof use === 'function' ? [] : Array.isArray(use) ? use : [use]\n }\n const getLoaderPath = (\n loader: ReturnType<typeof getRuleLoaders>[number],\n ): string | undefined => (typeof loader === 'string' ? loader : loader.loader)\n const cloneLoader = (\n loader: ReturnType<typeof getRuleLoaders>[number],\n ): ReturnType<typeof getRuleLoaders>[number] => {\n if (typeof loader === 'string') {\n return loader\n }\n\n const options = loader.options\n return {\n ...loader,\n ...(options && typeof options === 'object' && !Array.isArray(options)\n ? {\n options: {\n ...options,\n ...(options.rspackExperiments &&\n typeof options.rspackExperiments === 'object' &&\n !Array.isArray(options.rspackExperiments)\n ? {\n rspackExperiments: {\n ...options.rspackExperiments,\n },\n }\n : {}),\n },\n }\n : {}),\n }\n }\n const cloneRuleUse = (use: RspackRule['use']): RspackRule['use'] => {\n if (!use || typeof use === 'function') {\n return use\n }\n\n if (Array.isArray(use)) {\n return use.map((loader) => cloneLoader(loader)) as RspackRule['use']\n }\n\n return cloneLoader(use) as RspackRule['use']\n }\n const cloneRspackRule = (rule: RspackRule): RspackRule => {\n return {\n ...rule,\n use: cloneRuleUse(rule.use),\n resolve: rule.resolve ? { ...rule.resolve } : rule.resolve,\n oneOf: Array.isArray(rule.oneOf)\n ? rule.oneOf.map((childRule) =>\n isRspackRule(childRule) ? cloneRspackRule(childRule) : childRule,\n )\n : rule.oneOf,\n } as unknown as RspackRule\n }\n const rootRules = (config.module.rules ??= []).filter(isRspackRule)\n\n function processRules(rules = rootRules): void {\n for (const rule of rules) {\n processRules(\n Array.isArray(rule.oneOf) ? rule.oneOf.filter(isRspackRule) : [],\n )\n\n const hasSwcLoader = getRuleLoaders(rule).some((loader) =>\n Boolean(getLoaderPath(loader)?.includes('swc-loader')),\n )\n if (!hasSwcLoader) continue\n\n const enableReactServerComponentsOnRule = (nextRule: RspackRule) => {\n for (const loader of getRuleLoaders(nextRule)) {\n if (typeof loader === 'string') {\n continue\n }\n\n const loaderPath = getLoaderPath(loader)\n if (!loaderPath || !loaderPath.includes('swc-loader')) {\n continue\n }\n\n const options =\n loader.options && typeof loader.options === 'object'\n ? loader.options\n : (loader.options = {})\n const experiments =\n options.rspackExperiments &&\n typeof options.rspackExperiments === 'object'\n ? options.rspackExperiments\n : (options.rspackExperiments = {})\n const current = experiments.reactServerComponents\n\n experiments.reactServerComponents =\n current === true || current == null\n ? {}\n : typeof current === 'object' &&\n current !== null &&\n !Array.isArray(current)\n ? { ...current }\n : {}\n }\n }\n\n if (scope === 'all') {\n enableReactServerComponentsOnRule(rule)\n continue\n }\n\n const originalRule = cloneRspackRule(rule)\n const providerRule = cloneRspackRule(originalRule)\n providerRule.resourceQuery = /(?:^|[?&])tss-serverfn-split(?:&|$)/\n enableReactServerComponentsOnRule(providerRule)\n\n const routeSplitRule = cloneRspackRule(originalRule)\n routeSplitRule.resourceQuery = /(?:^|[?&])tsr-split(?:=|&|$)/\n const routeSplitConditionNames = originalRule.resolve?.conditionNames\n routeSplitRule.resolve = {\n ...originalRule.resolve,\n conditionNames: Array.isArray(routeSplitConditionNames)\n ? routeSplitConditionNames.includes('...')\n ? [...routeSplitConditionNames]\n : ['...', ...routeSplitConditionNames]\n : ['...'],\n }\n\n const subtreeRule = cloneRspackRule(originalRule)\n subtreeRule.issuerLayer = RSBUILD_RSC_LAYERS.rsc\n enableReactServerComponentsOnRule(subtreeRule)\n\n for (const key of Object.keys(rule) as Array<keyof RspackRule>) {\n delete rule[key]\n }\n rule.oneOf = [providerRule, routeSplitRule, subtreeRule, originalRule]\n }\n }\n\n processRules()\n}\n"],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { EnvironmentConfig } from '@rsbuild/core';
2
+ import { TanStackStartCoreOptions } from '../types.js';
3
+ export interface RsbuildEnvironmentOverrides {
4
+ all?: EnvironmentConfig | undefined;
5
+ client?: EnvironmentConfig | undefined;
6
+ server?: EnvironmentConfig | undefined;
7
+ provider?: EnvironmentConfig | undefined;
8
+ }
9
+ export interface RsbuildCoreOptions {
10
+ environments?: RsbuildEnvironmentOverrides | undefined;
11
+ }
12
+ export type TanStackStartRsbuildPluginCoreOptions = TanStackStartCoreOptions & {
13
+ providerEnvironmentName: string;
14
+ ssrIsProvider: boolean;
15
+ rsbuild?: RsbuildCoreOptions | undefined;
16
+ rsc?: boolean | undefined;
17
+ };
File without changes
@@ -0,0 +1,53 @@
1
+ import { RsbuildPluginAPI, rspack as rspackNamespaceType } from '@rsbuild/core';
2
+ import { GetConfigFn, NormalizedClientBuild, SerializationAdapterConfig } from '../types.js';
3
+ import { ServerFn } from '../start-compiler/types.js';
4
+ type RspackNamespace = typeof rspackNamespaceType;
5
+ type RspackVirtualModulesPlugin = InstanceType<RspackNamespace['experiments']['VirtualModulesPlugin']>;
6
+ export declare const START_MANIFEST_PLACEHOLDER = "__TSS_START_MANIFEST_PLACEHOLDER__";
7
+ export interface VirtualModuleState {
8
+ /** Call to update manifest content after client build completes */
9
+ updateManifest: (clientBuild: NormalizedClientBuild) => void;
10
+ /** Call to update server fn resolver content after compilation discovers fns */
11
+ updateServerFnResolver: () => void;
12
+ /** Try to write explicit resolver content now; queues if env not ready */
13
+ tryUpdateServerFnResolver: (content: string) => void;
14
+ /** Get the virtual path for a given module ID */
15
+ getVirtualPath: (moduleId: string) => string;
16
+ /** Generate resolver module content from current serverFnsById state.
17
+ * When forProvider=true, generates without isClientReferenced checks (RSC layer). */
18
+ generateCurrentResolverContent: (forProvider?: boolean) => string;
19
+ /** The absolute virtual path of the server fn resolver module */
20
+ serverFnResolverPath: string;
21
+ /** The absolute virtual path of the manifest module */
22
+ manifestPath: string;
23
+ /** Generate manifest module content from a given client build */
24
+ generateManifestContent: (clientBuild: NormalizedClientBuild) => string;
25
+ /** Generate the serialized manifest value literal for asset patching */
26
+ generateManifestValueLiteral: (clientBuild: NormalizedClientBuild) => string;
27
+ /** VirtualModulesPlugin instances keyed by environment name */
28
+ vmPlugins: Record<string, RspackVirtualModulesPlugin>;
29
+ }
30
+ export interface RegisterVirtualModulesOptions {
31
+ root: string;
32
+ getConfig: GetConfigFn;
33
+ serverFnsById: Record<string, ServerFn>;
34
+ providerEnvName: string;
35
+ ssrIsProvider: boolean;
36
+ serializationAdapters: Array<SerializationAdapterConfig> | undefined;
37
+ /**
38
+ * Get the URL at which the rsbuild dev server serves the client entry JS.
39
+ * Called lazily inside modifyRspackConfig when getConfig() is available.
40
+ * Example return: '/static/js/index.js'
41
+ */
42
+ getDevClientEntryUrl: (publicBase: string) => string;
43
+ /** Whether RSC virtual modules should be registered. */
44
+ rscEnabled?: boolean | undefined;
45
+ }
46
+ /**
47
+ * Registers virtual modules for the rsbuild adapter using VirtualModulesPlugin.
48
+ *
49
+ * Creates one VirtualModulesPlugin per environment and registers them via
50
+ * `modifyBundlerChain`. Provides update functions to refresh content dynamically.
51
+ */
52
+ export declare function registerVirtualModules(api: RsbuildPluginAPI, opts: RegisterVirtualModulesOptions): VirtualModuleState;
53
+ export {};