@anaemia/bundler 0.3.2 → 0.3.4

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAU,MAAM,cAAc,CAAC;AAGrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAqB1D,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,aAAkB,GAAG,OAAO,CAAC,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC,CAoJ1H;AAED,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAU,MAAM,cAAc,CAAC;AAGrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAqB1D,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,aAAkB,GAAG,OAAO,CAAC,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC,CAgJ1H;AAED,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/index.js CHANGED
@@ -19,9 +19,7 @@ const __dirname = path.dirname(__filename);
19
19
  export async function getRspackConfig(appRoot, config = {}) {
20
20
  const isDev = process.env.NODE_ENV !== "production";
21
21
  const coreRuntimeDir = path.dirname(require.resolve("@anaemia/core/package.json"));
22
- const hasSrc = fs.existsSync(path.resolve(coreRuntimeDir, "./src/runtime"));
23
- const runtimeDir = hasSrc ? path.resolve(coreRuntimeDir, "./src/runtime") : path.resolve(coreRuntimeDir, "./dist/runtime");
24
- const runtimeExt = hasSrc ? "tsx" : "jsx";
22
+ const runtimeDir = path.resolve(coreRuntimeDir, "./dist/runtime");
25
23
  const routes = await scanRoutes(appRoot);
26
24
  const serverRoutes = scanServerRoutes(appRoot);
27
25
  writeManifest(appRoot, routes);
@@ -47,7 +45,7 @@ export async function getRspackConfig(appRoot, config = {}) {
47
45
  devtool: isDev ? "eval-cheap-module-source-map" : false,
48
46
  cache: isDev,
49
47
  entry: {
50
- client: [...(isDev ? [require.resolve("solid-refresh")] : []), path.resolve(runtimeDir, `entry-client.${runtimeExt}`)],
48
+ client: [...(isDev ? [require.resolve("solid-refresh")] : []), path.resolve(runtimeDir, "entry-client.jsx")],
51
49
  },
52
50
  output: {
53
51
  path: path.resolve(appRoot, "./dist/client"),
@@ -64,8 +62,7 @@ export async function getRspackConfig(appRoot, config = {}) {
64
62
  alias: {
65
63
  ...sharedResolve.alias,
66
64
  "solid-refresh": require.resolve("solid-refresh"),
67
- [path.resolve(coreRuntimeDir, "./src/runtime/context.ts")]: path.resolve(coreRuntimeDir, "./src/runtime/context.browser.ts"),
68
- [path.resolve(coreRuntimeDir, "./dist/runtime/context.js")]: path.resolve(coreRuntimeDir, "./src/runtime/context.browser.ts"),
65
+ [path.resolve(coreRuntimeDir, "./dist/runtime/context.js")]: path.resolve(coreRuntimeDir, "./dist/runtime/context.browser.js"),
69
66
  },
70
67
  fallback: { async_hooks: false, "node:async_hooks": false, fs: false, "node:fs": false, path: false, "node:path": false },
71
68
  },
@@ -116,7 +113,7 @@ export async function getRspackConfig(appRoot, config = {}) {
116
113
  devtool: isDev ? "source-map" : false,
117
114
  context: appRoot,
118
115
  target: "node",
119
- entry: { server: path.resolve(runtimeDir, `entry-server.${runtimeExt}`) },
116
+ entry: { server: path.resolve(runtimeDir, "entry-server.jsx") },
120
117
  output: { path: path.resolve(appRoot, "./dist/server"), filename: "index.js", module: true, chunkFormat: "module", chunkLoading: "import" },
121
118
  optimization: { nodeEnv: false },
122
119
  resolve: {
@@ -125,8 +122,8 @@ export async function getRspackConfig(appRoot, config = {}) {
125
122
  alias: {
126
123
  ...sharedResolve.alias,
127
124
  "solid-refresh": require.resolve("solid-refresh"),
128
- "@anaemia/core/config": hasSrc ? path.resolve(coreRuntimeDir, "./src/config.ts") : path.resolve(coreRuntimeDir, "./dist/config.js"),
129
- "@anaemia/core": hasSrc ? path.resolve(coreRuntimeDir, "./src/index.ts") : path.resolve(coreRuntimeDir, "./dist/index.js"),
125
+ "@anaemia/core/config": path.resolve(coreRuntimeDir, "./dist/config.js"),
126
+ "@anaemia/core": path.resolve(coreRuntimeDir, "./dist/index.js"),
130
127
  __anaemia_user_config__: path.resolve(appRoot, "./anaemia.config.ts"),
131
128
  __anaemia_server_routes__: serverRoutesFile,
132
129
  },
@@ -1 +1 @@
1
- {"version":3,"file":"generate-entry.d.ts","sourceRoot":"","sources":["../../src/router/generate-entry.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAgHpD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,CA2LzF"}
1
+ {"version":3,"file":"generate-entry.d.ts","sourceRoot":"","sources":["../../src/router/generate-entry.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAiHpD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,CAqMzF"}
@@ -1,5 +1,6 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
+ import { transform } from "sucrase";
3
4
  function buildTree(routes, strippedLayouts, routeIndices, routesDir, allLayouts, parentPrefix) {
4
5
  const nodes = [];
5
6
  const leafIndices = strippedLayouts.map((l, i) => (l.length === 0 ? i : -1)).filter((i) => i !== -1);
@@ -83,7 +84,9 @@ function buildPreloadMapString(routes, allLayouts) {
83
84
  export function generateRouterEntry(appRoot, routes) {
84
85
  const routesDir = path.resolve(appRoot, "./src/routes");
85
86
  const outDir = path.resolve(appRoot, "./.anaemia");
86
- const outPath = path.resolve(outDir, "./__anaemia_entry__.tsx");
87
+ const isTs = fs.existsSync(path.resolve(appRoot, "tsconfig.json"));
88
+ const ext = isTs ? "tsx" : "jsx";
89
+ const outPath = path.resolve(outDir, `__anaemia_entry__.${ext}`);
87
90
  const conventionalRoutes = routes.filter((r) => !r.filePath.endsWith("404.tsx") && !r.filePath.endsWith("500.tsx"));
88
91
  const errorRoutes = routes.filter((r) => r.filePath.endsWith("404.tsx") || r.filePath.endsWith("500.tsx"));
89
92
  const allLayouts = new Map();
@@ -203,7 +206,7 @@ export async function preloadActiveClientRoute(pathname: string) {
203
206
  await Promise.all(preloads);
204
207
  }
205
208
  `.trim();
206
- const code = `
209
+ const rawCode = `
207
210
  // @ts-nocheck
208
211
  // auto-generated by anaemia - do not edit!!
209
212
  import { lazy } from "solid-js";
@@ -232,9 +235,16 @@ ${finalJsx}
232
235
  );
233
236
  }
234
237
  `.trimStart();
238
+ const finalCode = isTs
239
+ ? rawCode
240
+ : transform(rawCode.replace("// @ts-nocheck\n", ""), {
241
+ transforms: ["typescript", "jsx"],
242
+ jsxRuntime: "preserve",
243
+ production: true,
244
+ }).code;
235
245
  if (!fs.existsSync(outDir)) {
236
246
  fs.mkdirSync(outDir, { recursive: true });
237
247
  }
238
- fs.writeFileSync(outPath, code);
248
+ fs.writeFileSync(outPath, finalCode);
239
249
  return outPath;
240
250
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anaemia/bundler",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "type": "module",
@@ -11,7 +11,7 @@
11
11
  }
12
12
  },
13
13
  "dependencies": {
14
- "@anaemia/core": "^0.3.2",
14
+ "@anaemia/core": "^0.3.4",
15
15
  "@babel/core": "^7.29.7",
16
16
  "@babel/preset-typescript": "^7.29.7",
17
17
  "@rspack/core": "^2.0.5",
@@ -21,7 +21,8 @@
21
21
  "jiti": "^2.7.0",
22
22
  "sass": "^1.100.0",
23
23
  "sass-loader": "^17.0.0",
24
- "solid-refresh": "^0.7.8"
24
+ "solid-refresh": "^0.7.8",
25
+ "sucrase": "^3.35.1"
25
26
  },
26
27
  "devDependencies": {
27
28
  "@types/babel__core": "^7.20.5"
package/src/index.ts CHANGED
@@ -25,9 +25,7 @@ const __dirname = path.dirname(__filename);
25
25
  export async function getRspackConfig(appRoot: string, config: AnaemiaConfig = {}): Promise<[Configuration, Configuration]> {
26
26
  const isDev = process.env.NODE_ENV !== "production";
27
27
  const coreRuntimeDir = path.dirname(require.resolve("@anaemia/core/package.json"));
28
- const hasSrc = fs.existsSync(path.resolve(coreRuntimeDir, "./src/runtime"));
29
- const runtimeDir = hasSrc ? path.resolve(coreRuntimeDir, "./src/runtime") : path.resolve(coreRuntimeDir, "./dist/runtime");
30
- const runtimeExt = hasSrc ? "tsx" : "jsx";
28
+ const runtimeDir = path.resolve(coreRuntimeDir, "./dist/runtime");
31
29
 
32
30
  const routes = await scanRoutes(appRoot);
33
31
  const serverRoutes = scanServerRoutes(appRoot);
@@ -40,7 +38,6 @@ export async function getRspackConfig(appRoot: string, config: AnaemiaConfig = {
40
38
 
41
39
  const entryFile = generateRouterEntry(appRoot, routes);
42
40
  const serverRoutesFile = generateServerRoutes(appRoot, serverRoutes);
43
-
44
41
  const styleRules = createStyleRules(config);
45
42
  const extraClientBabelPlugins = config.plugins?.flatMap((p) => p.babelPlugins?.client ?? []) ?? [];
46
43
  const extraServerBabelPlugins = config.plugins?.flatMap((p) => p.babelPlugins?.server ?? []) ?? [];
@@ -59,7 +56,7 @@ export async function getRspackConfig(appRoot: string, config: AnaemiaConfig = {
59
56
  devtool: isDev ? "eval-cheap-module-source-map" : false,
60
57
  cache: isDev,
61
58
  entry: {
62
- client: [...(isDev ? [require.resolve("solid-refresh")] : []), path.resolve(runtimeDir, `entry-client.${runtimeExt}`)],
59
+ client: [...(isDev ? [require.resolve("solid-refresh")] : []), path.resolve(runtimeDir, "entry-client.jsx")],
63
60
  },
64
61
  output: {
65
62
  path: path.resolve(appRoot, "./dist/client"),
@@ -76,8 +73,7 @@ export async function getRspackConfig(appRoot: string, config: AnaemiaConfig = {
76
73
  alias: {
77
74
  ...sharedResolve.alias,
78
75
  "solid-refresh": require.resolve("solid-refresh"),
79
- [path.resolve(coreRuntimeDir, "./src/runtime/context.ts")]: path.resolve(coreRuntimeDir, "./src/runtime/context.browser.ts"),
80
- [path.resolve(coreRuntimeDir, "./dist/runtime/context.js")]: path.resolve(coreRuntimeDir, "./src/runtime/context.browser.ts"),
76
+ [path.resolve(coreRuntimeDir, "./dist/runtime/context.js")]: path.resolve(coreRuntimeDir, "./dist/runtime/context.browser.js"),
81
77
  },
82
78
  fallback: { async_hooks: false, "node:async_hooks": false, fs: false, "node:fs": false, path: false, "node:path": false },
83
79
  },
@@ -132,7 +128,7 @@ export async function getRspackConfig(appRoot: string, config: AnaemiaConfig = {
132
128
  devtool: isDev ? "source-map" : false,
133
129
  context: appRoot,
134
130
  target: "node",
135
- entry: { server: path.resolve(runtimeDir, `entry-server.${runtimeExt}`) },
131
+ entry: { server: path.resolve(runtimeDir, "entry-server.jsx") },
136
132
  output: { path: path.resolve(appRoot, "./dist/server"), filename: "index.js", module: true, chunkFormat: "module", chunkLoading: "import" },
137
133
  optimization: { nodeEnv: false },
138
134
  resolve: {
@@ -141,8 +137,8 @@ export async function getRspackConfig(appRoot: string, config: AnaemiaConfig = {
141
137
  alias: {
142
138
  ...sharedResolve.alias,
143
139
  "solid-refresh": require.resolve("solid-refresh"),
144
- "@anaemia/core/config": hasSrc ? path.resolve(coreRuntimeDir, "./src/config.ts") : path.resolve(coreRuntimeDir, "./dist/config.js"),
145
- "@anaemia/core": hasSrc ? path.resolve(coreRuntimeDir, "./src/index.ts") : path.resolve(coreRuntimeDir, "./dist/index.js"),
140
+ "@anaemia/core/config": path.resolve(coreRuntimeDir, "./dist/config.js"),
141
+ "@anaemia/core": path.resolve(coreRuntimeDir, "./dist/index.js"),
146
142
  __anaemia_user_config__: path.resolve(appRoot, "./anaemia.config.ts"),
147
143
  __anaemia_server_routes__: serverRoutesFile,
148
144
  },
@@ -1,6 +1,7 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
3
  import type { RouteManifestEntry } from "./scan.js";
4
+ import { transform } from "sucrase";
4
5
 
5
6
  type LayoutNode = {
6
7
  kind: "layout";
@@ -89,7 +90,7 @@ function renderTree(nodes: TreeNode[], indent = 6): string {
89
90
  if (routePath === "") {
90
91
  return `${pad}<Route component={Route${node.routeIdx}Wrapped} />`;
91
92
  }
92
-
93
+
93
94
  return `${pad}<Route path="${routePath}" component={Route${node.routeIdx}Wrapped} />`;
94
95
  }
95
96
 
@@ -115,7 +116,9 @@ function buildPreloadMapString(routes: RouteManifestEntry[], allLayouts: Map<str
115
116
  export function generateRouterEntry(appRoot: string, routes: RouteManifestEntry[]): string {
116
117
  const routesDir = path.resolve(appRoot, "./src/routes");
117
118
  const outDir = path.resolve(appRoot, "./.anaemia");
118
- const outPath = path.resolve(outDir, "./__anaemia_entry__.tsx");
119
+ const isTs = fs.existsSync(path.resolve(appRoot, "tsconfig.json"));
120
+ const ext = isTs ? "tsx" : "jsx";
121
+ const outPath = path.resolve(outDir, `__anaemia_entry__.${ext}`);
119
122
 
120
123
  const conventionalRoutes = routes.filter((r) => !r.filePath.endsWith("404.tsx") && !r.filePath.endsWith("500.tsx"));
121
124
  const errorRoutes = routes.filter((r) => r.filePath.endsWith("404.tsx") || r.filePath.endsWith("500.tsx"));
@@ -263,7 +266,7 @@ export async function preloadActiveClientRoute(pathname: string) {
263
266
  }
264
267
  `.trim();
265
268
 
266
- const code = `
269
+ const rawCode = `
267
270
  // @ts-nocheck
268
271
  // auto-generated by anaemia - do not edit!!
269
272
  import { lazy } from "solid-js";
@@ -293,10 +296,18 @@ ${finalJsx}
293
296
  }
294
297
  `.trimStart();
295
298
 
299
+ const finalCode = isTs
300
+ ? rawCode
301
+ : transform(rawCode.replace("// @ts-nocheck\n", ""), {
302
+ transforms: ["typescript", "jsx"],
303
+ jsxRuntime: "preserve",
304
+ production: true,
305
+ }).code;
306
+
296
307
  if (!fs.existsSync(outDir)) {
297
308
  fs.mkdirSync(outDir, { recursive: true });
298
309
  }
299
310
 
300
- fs.writeFileSync(outPath, code);
311
+ fs.writeFileSync(outPath, finalCode);
301
312
  return outPath;
302
313
  }
@@ -0,0 +1,109 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import path from "node:path";
4
+ import fs from "node:fs";
5
+ import os from "node:os";
6
+ import { getRspackConfig } from "../dist/index.js";
7
+
8
+ async function createTmpProject(isTs = true) {
9
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), "anaemia-bundler-test-"));
10
+
11
+ fs.mkdirSync(path.join(dir, "src/routes"), { recursive: true });
12
+ fs.writeFileSync(path.join(dir, "src/routes/index.tsx"), `export default function Index() { return <div>hello</div>; }`);
13
+ fs.writeFileSync(path.join(dir, "index.html"), `<html><body><div anaemia-entry></div></body></html>`);
14
+
15
+ if (isTs) {
16
+ fs.writeFileSync(path.join(dir, "tsconfig.json"), JSON.stringify({ compilerOptions: { strict: true } }));
17
+ }
18
+
19
+ return dir;
20
+ }
21
+
22
+ test("getRspackConfig returns two configurations", async () => {
23
+ const dir = await createTmpProject();
24
+ try {
25
+ const configs = await getRspackConfig(dir, {});
26
+ assert.equal(Array.isArray(configs), true);
27
+ assert.equal(configs.length, 2);
28
+ } finally {
29
+ fs.rmSync(dir, { recursive: true, force: true });
30
+ }
31
+ });
32
+
33
+ test("client config targets web, server config targets node", async () => {
34
+ const dir = await createTmpProject();
35
+ try {
36
+ const [clientConfig, serverConfig] = await getRspackConfig(dir, {});
37
+ assert.equal(clientConfig.target, "web");
38
+ assert.equal(serverConfig.target, "node");
39
+ } finally {
40
+ fs.rmSync(dir, { recursive: true, force: true });
41
+ }
42
+ });
43
+
44
+ test("runtimeDir always resolves to dist, never src", async () => {
45
+ const dir = await createTmpProject();
46
+ try {
47
+ const [clientConfig, serverConfig] = await getRspackConfig(dir, {});
48
+ const clientEntry = Object.values(clientConfig.entry).flat().join(" ");
49
+ const serverEntry = Object.values(serverConfig.entry).flat().join(" ");
50
+ assert.ok(!clientEntry.includes("/src/runtime"), `client entry points into src: ${clientEntry}`);
51
+ assert.ok(!serverEntry.includes("/src/runtime"), `server entry points into src: ${serverEntry}`);
52
+ assert.ok(clientEntry.includes("/dist/runtime"), `client entry should point to dist: ${clientEntry}`);
53
+ assert.ok(serverEntry.includes("/dist/runtime"), `server entry should point to dist: ${serverEntry}`);
54
+ } finally {
55
+ fs.rmSync(dir, { recursive: true, force: true });
56
+ }
57
+ });
58
+
59
+ test("generated entry is .tsx for TypeScript projects", async () => {
60
+ const dir = await createTmpProject(true);
61
+ try {
62
+ await getRspackConfig(dir, {});
63
+ const entryFile = path.join(dir, ".anaemia/__anaemia_entry__.tsx");
64
+ assert.ok(fs.existsSync(entryFile), "expected .tsx entry file");
65
+ assert.ok(!fs.existsSync(path.join(dir, ".anaemia/__anaemia_entry__.jsx")), "unexpected .jsx entry file");
66
+ } finally {
67
+ fs.rmSync(dir, { recursive: true, force: true });
68
+ }
69
+ });
70
+
71
+ test("generated entry is .jsx for JavaScript projects", async () => {
72
+ const dir = await createTmpProject(false);
73
+ try {
74
+ await getRspackConfig(dir, {});
75
+ const entryFile = path.join(dir, ".anaemia/__anaemia_entry__.jsx");
76
+ assert.ok(fs.existsSync(entryFile), "expected .jsx entry file");
77
+ assert.ok(!fs.existsSync(path.join(dir, ".anaemia/__anaemia_entry__.tsx")), "unexpected .tsx entry file");
78
+ } finally {
79
+ fs.rmSync(dir, { recursive: true, force: true });
80
+ }
81
+ });
82
+
83
+ test("generated JS entry has no TypeScript syntax", async () => {
84
+ const dir = await createTmpProject(false);
85
+ try {
86
+ await getRspackConfig(dir, {});
87
+ const content = fs.readFileSync(path.join(dir, ".anaemia/__anaemia_entry__.jsx"), "utf-8");
88
+ assert.ok(!content.includes(": string"), "found TypeScript type annotation in JS entry");
89
+ assert.ok(!content.includes("// @ts-nocheck"), "found @ts-nocheck in JS entry");
90
+ } finally {
91
+ fs.rmSync(dir, { recursive: true, force: true });
92
+ }
93
+ });
94
+
95
+ test("server config aliases point to dist not src", async () => {
96
+ const dir = await createTmpProject();
97
+ try {
98
+ const [, serverConfig] = await getRspackConfig(dir, {});
99
+ const aliases = serverConfig.resolve?.alias ?? {};
100
+ for (const [key, val] of Object.entries(aliases)) {
101
+ if (typeof val === "string" && val.includes("@anaemia/core")) {
102
+ assert.ok(!val.includes("/src/"), `alias ${key} points to src: ${val}`);
103
+ assert.ok(val.includes("/dist/"), `alias ${key} should point to dist: ${val}`);
104
+ }
105
+ }
106
+ } finally {
107
+ fs.rmSync(dir, { recursive: true, force: true });
108
+ }
109
+ });