Skip to content

Commit 17ac969

Browse files
committed
feat(cli): add support for Bun + Vite runtime and update related configurations
1 parent 9ca12be commit 17ac969

File tree

11 files changed

+92
-13
lines changed

11 files changed

+92
-13
lines changed

packages/cli/src/commands/init/InitCmd.spec.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ describe("InitCmd", () => {
6767
vi.stubGlobal("Bun", {});
6868

6969
const command = await CliPlatformTest.invoke<InitCmd>(InitCmd);
70-
vi.spyOn((command as any).runtimes, "list").mockReturnValue(["node", "bun"]);
70+
vi.spyOn((command as any).runtimes, "list").mockReturnValue(["node", "bun", "bun-vite"]);
7171
vi.spyOn((command as any).packageManagers, "list").mockReturnValue(["yarn", "npm", "pnpm", "bun"]);
7272

7373
const prompts = await command.$prompt({
@@ -79,7 +79,7 @@ describe("InitCmd", () => {
7979

8080
expect(runtime).toBeDefined();
8181
expect(packageManager).toBeDefined();
82-
expect((runtime as any).choices.map((choice: any) => choice.value)).toEqual(["bun"]);
82+
expect((runtime as any).choices.map((choice: any) => choice.value)).toEqual(["bun", "bun-vite"]);
8383
expect((packageManager as any).choices.map((choice: any) => choice.value)).toEqual(["bun"]);
8484
});
8585

@@ -99,6 +99,22 @@ describe("InitCmd", () => {
9999
expect(mapped.packageManager).toEqual("bun");
100100
});
101101

102+
it("should preserve bun-vite runtime in bunx mode", async () => {
103+
vi.stubGlobal("Bun", {});
104+
105+
const command = await CliPlatformTest.invoke<InitCmd>(InitCmd);
106+
const mapped = command.$mapContext({
107+
root: ".",
108+
projectName: "project",
109+
features: [],
110+
runtime: "bun-vite",
111+
packageManager: "npm"
112+
});
113+
114+
expect(mapped.runtime).toEqual("bun-vite");
115+
expect(mapped.packageManager).toEqual("bun");
116+
});
117+
102118
it("should write premium RC files without returning task-like results", async () => {
103119
const command = await CliPlatformTest.invoke<InitCmd>(InitCmd);
104120
const createFromTemplate = vi.spyOn((command as any).project, "createFromTemplate").mockResolvedValue({rendered: true});

packages/cli/src/commands/init/InitCmd.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import type {InitOptions} from "../../interfaces/InitCmdOptions.js";
3232
import {PlatformsModule} from "../../platforms/PlatformsModule.js";
3333
import {RuntimesModule} from "../../runtimes/RuntimesModule.js";
3434
import {BunRuntime} from "../../runtimes/supports/BunRuntime.js";
35+
import {BunViteRuntime} from "../../runtimes/supports/BunViteRuntime.js";
3536
import {NodeRuntime} from "../../runtimes/supports/NodeRuntime.js";
3637
import {ViteRuntime} from "../../runtimes/supports/ViteRuntime.js";
3738
import {CliProjectService} from "../../services/CliProjectService.js";
@@ -102,7 +103,7 @@ export class InitCmd implements CommandProvider {
102103
ctx = mapToContext(ctx);
103104

104105
if (this.isLaunchedWithBunx()) {
105-
ctx.runtime = "bun";
106+
ctx.runtime ??= "bun";
106107
ctx.packageManager = "bun";
107108
}
108109

@@ -128,7 +129,7 @@ export class InitCmd implements CommandProvider {
128129
}
129130

130131
protected filterOnlyBun(values: string[]) {
131-
const filtered = values.filter((value) => value === "bun");
132+
const filtered = values.filter((value) => ["bun", "bun-vite"].includes(value));
132133

133134
return filtered.length ? filtered : values;
134135
}
@@ -188,8 +189,9 @@ export class InitCmd implements CommandProvider {
188189
ctx = {
189190
...ctx,
190191
node: runtime instanceof NodeRuntime,
191-
bun: runtime instanceof BunRuntime,
192-
vite: runtime instanceof ViteRuntime,
192+
bun: runtime instanceof BunRuntime || runtime instanceof BunViteRuntime,
193+
bunVite: runtime instanceof BunViteRuntime,
194+
vite: runtime instanceof ViteRuntime || runtime instanceof BunViteRuntime,
193195
compiled: runtime.isCompiled()
194196
};
195197

packages/cli/src/commands/init/config/FeaturesPrompt.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,10 @@ export const FeaturesMap: Record<string, Feature> = {
366366
name: "Node.js + Vite",
367367
checked: false
368368
},
369+
"bun-vite": {
370+
name: "Bun + Vite",
371+
checked: false
372+
},
369373
node: {
370374
name: "Node.js + SWC",
371375
checked: true

packages/cli/src/commands/init/config/InitSchema.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,10 @@ export const InitSchema = () => {
282282
label: "Node.js + Vite",
283283
value: "vite"
284284
},
285+
{
286+
label: "Bun.js + Vite",
287+
value: "bun-vite"
288+
},
285289
{
286290
label: "Node.js + SWC",
287291
value: "node"
@@ -295,7 +299,7 @@ export const InitSchema = () => {
295299
value: "webpack"
296300
},
297301
{
298-
label: "Bun",
302+
label: "Bun.js",
299303
value: "bun"
300304
}
301305
].filter((o) => availableRuntimes.includes(o.value))
@@ -306,7 +310,7 @@ export const InitSchema = () => {
306310
packageManager: s
307311
.enums<PackageManager[]>(availablePackageManagers as any[])
308312
.prompt("Choose the package manager:")
309-
.when((answers) => answers.runtime !== "bun")
313+
.when((answers) => !["bun", "bun-vite"].includes(answers.runtime))
310314
.default(PackageManager.NPM)
311315
.choices(
312316
[

packages/cli/src/commands/init/prompts/getFeaturesPrompt.spec.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,19 @@ describe("getFeaturesPrompt", () => {
2020
);
2121
});
2222

23+
it("should map bun-vite runtime choice without throwing", () => {
24+
const prompt = getFeaturesPrompt(["bun", "bun-vite"], ["bun"], {});
25+
const runtimePrompt = prompt.find((item: any) => item.name === "runtime");
26+
27+
expect(runtimePrompt).toBeDefined();
28+
expect((runtimePrompt as any).choices).toEqual(
29+
expect.arrayContaining([
30+
expect.objectContaining({value: "bun", name: "Bun.js"}),
31+
expect.objectContaining({value: "bun-vite", name: "Bun + Vite"})
32+
])
33+
);
34+
});
35+
2336
it("should add a provider info", () => {
2437
const prompt = getFeaturesPrompt(["node", "bun"], ["yarn", "npm", "pnpm", "bun"], {});
2538

packages/cli/src/commands/mcp/schema/ProjectPreferencesSchema.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ export const ProjectPreferenceSchema = s
1010
packageManager: s.string().enum(PackageManager).description("Used project manager to install dependencies"),
1111
runtime: s
1212
.string()
13-
.enum("vite", "node", "babel", "swc", "webpack", "bun")
14-
.description("The javascript runtime used to start application (node, node + webpack, node + swc, node + babel, bun, vite)"),
13+
.enum("vite", "bun-vite", "node", "babel", "swc", "webpack", "bun")
14+
.description(
15+
"The javascript runtime used to start application (node + vite, bun + vite, node + webpack, node + swc, node + babel, bun)"
16+
),
1517
platform: s.string().enum(PlatformType).description("Node.js framework used to run server (Express, Koa, Fastify)")
1618
})
1719
.optional()

packages/cli/src/interfaces/RenderDataContext.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export interface RenderDataContext extends CommandData, TsED.RenderDataContext {
5050
configPostgres?: boolean;
5151
barrels?: string;
5252
bun?: boolean;
53+
bunVite?: boolean;
5354
vite?: boolean;
5455
node?: boolean;
5556
compiled?: boolean;

packages/cli/src/interfaces/RuntimeTypes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export type RuntimeTypes = "node" | "babel" | "swc" | "webpack" | "bun" | "vite";
1+
export type RuntimeTypes = "node" | "babel" | "swc" | "webpack" | "bun" | "vite" | "bun-vite";
22

33
declare global {
44
namespace TsED {

packages/cli/src/runtimes/RuntimesModule.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {inject, injectable, injectMany} from "@tsed/di";
44
import {BabelRuntime} from "./supports/BabelRuntime.js";
55
import {BaseRuntime} from "./supports/BaseRuntime.js";
66
import {BunRuntime} from "./supports/BunRuntime.js";
7+
import {BunViteRuntime} from "./supports/BunViteRuntime.js";
78
import {NodeRuntime} from "./supports/NodeRuntime.js";
89
import {ViteRuntime} from "./supports/ViteRuntime.js";
910
import {WebpackRuntime} from "./supports/WebpackRuntime.js";
@@ -24,7 +25,7 @@ export class RuntimesModule {
2425
init(ctx: RuntimeInitOptions) {
2526
ctx.runtime = ctx.runtime || this.get().name;
2627

27-
if (ctx.runtime === "bun") {
28+
if (ctx.runtime.startsWith("bun")) {
2829
ctx.packageManager = "bun";
2930
}
3031
}
@@ -63,4 +64,4 @@ export class RuntimesModule {
6364
}
6465
}
6566

66-
injectable(RuntimesModule).imports([ViteRuntime, NodeRuntime, BabelRuntime, WebpackRuntime, BunRuntime]);
67+
injectable(RuntimesModule).imports([ViteRuntime, BunViteRuntime, NodeRuntime, BabelRuntime, WebpackRuntime, BunRuntime]);

packages/cli/src/runtimes/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export * from "./RuntimesModule.js";
22
export * from "./supports/BabelRuntime.js";
33
export * from "./supports/BaseRuntime.js";
44
export * from "./supports/BunRuntime.js";
5+
export * from "./supports/BunViteRuntime.js";
56
export * from "./supports/NodeRuntime.js";
67
export * from "./supports/ViteRuntime.js";
78
export * from "./supports/WebpackRuntime.js";

0 commit comments

Comments
 (0)