Skip to content

Commit cd1a3af

Browse files
committed
feat: add ability to select runtimes
1 parent 4d1439f commit cd1a3af

8 files changed

Lines changed: 554 additions & 68 deletions

File tree

package.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,14 @@
100100
"lodash@>=4.0.0 <=4.17.23": ">=4.18.0",
101101
"lodash-es@<=4.17.23": ">=4.18.0",
102102
"lodash@<=4.17.23": ">=4.18.0",
103-
"defu@<=6.1.4": ">=6.1.5"
103+
"defu@<=6.1.4": ">=6.1.5",
104+
"@nestjs/core@<=11.1.17": ">=11.1.18",
105+
"vite@>=7.0.0 <=7.3.1": ">=7.3.2",
106+
"vite@>=7.1.0 <=7.3.1": ">=7.3.2",
107+
"hono@<4.12.12": ">=4.12.12",
108+
"hono@>=4.0.0 <=4.12.11": ">=4.12.12",
109+
"@hono/node-server@<1.19.13": ">=1.19.13",
110+
"axios@<1.15.0": ">=1.15.0"
104111
}
105112
},
106113
"dependencies": {

packages/commandkit/src/cli/app-process.ts

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { DevEnv, ProdEnv } from './env';
33
import { join } from 'node:path';
44
import { existsSync } from 'node:fs';
55
import { panic } from './common';
6+
import { ResolvedCommandKitConfig } from '../config/utils';
7+
import { CommandKitJsRuntime } from '../config/types';
68

79
/**
810
* @private
@@ -16,6 +18,40 @@ function getStdio(supportsCommands: boolean) {
1618
return ['pipe', 'pipe', 'pipe'];
1719
}
1820

21+
const RuntimeLookup: [CommandKitJsRuntime, () => boolean][] = [
22+
// @ts-ignore Bun types
23+
['bun', () => typeof Bun !== 'undefined' && typeof Bun.version === 'string'],
24+
[
25+
'deno',
26+
() =>
27+
// @ts-ignore Deno types
28+
typeof Deno !== 'undefined' &&
29+
// @ts-ignore Deno types
30+
typeof Deno.version === 'object' &&
31+
// @ts-ignore Deno types
32+
typeof Deno.version.deno === 'string',
33+
],
34+
];
35+
36+
function resolveRuntime(config: ResolvedCommandKitConfig): CommandKitJsRuntime {
37+
const maybeRuntime = config?.experimental?.devServerRuntime;
38+
39+
// TODO: once stable enough, we should try 'auto' option here
40+
if (!maybeRuntime) return 'node';
41+
42+
if (maybeRuntime === 'auto') {
43+
for (const [runtime, check] of RuntimeLookup) {
44+
if (check()) {
45+
return runtime as CommandKitJsRuntime;
46+
}
47+
}
48+
49+
return 'node';
50+
}
51+
52+
return maybeRuntime;
53+
}
54+
1955
/**
2056
* @private
2157
* @internal
@@ -24,17 +60,22 @@ export function createAppProcess(
2460
fileName: string,
2561
cwd: string,
2662
isDev: boolean,
63+
config: ResolvedCommandKitConfig,
2764
) {
2865
if (!existsSync(join(cwd, fileName))) {
2966
panic(`Could not locate the entrypoint file: ${fileName}`);
3067
}
3168

3269
const stdio = getStdio(isDev) as IOType[];
70+
const targetRuntime = resolveRuntime(config);
3371

34-
const baseArgs = [
35-
`--title="CommandKit ${isDev ? 'Development' : 'Production'}"`,
36-
'--enable-source-maps',
37-
];
72+
const baseArgs =
73+
targetRuntime === 'node'
74+
? [
75+
`--title="CommandKit ${isDev ? 'Development' : 'Production'}"`,
76+
'--enable-source-maps',
77+
]
78+
: [];
3879

3980
const nodeOptions = process.env.CK_NODE_OPTIONS || process.env.NODE_OPTIONS;
4081
let nodeArgs = [...baseArgs];
@@ -58,7 +99,7 @@ export function createAppProcess(
5899

59100
nodeArgs.push(fileName);
60101

61-
const ps = spawn('node', nodeArgs, {
102+
const ps = spawn(targetRuntime, nodeArgs, {
62103
cwd,
63104
windowsHide: true,
64105
env: isDev ? DevEnv() : ProdEnv(),

packages/commandkit/src/cli/development.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ async function buildAndStart(configPath: string, skipStart = false) {
2929

3030
if (skipStart) return null as never;
3131

32-
const ps = createAppProcess(mainFile, configPath, true);
32+
const ps = createAppProcess(mainFile, configPath, true, config);
3333

3434
return ps;
3535
}
@@ -52,7 +52,15 @@ const isEventSource = (p: string) =>
5252
* @private
5353
* @internal
5454
*/
55-
export async function bootstrapDevelopmentServer(configPath?: string) {
55+
export async function bootstrapDevelopmentServer(configPath?: string): Promise<{
56+
watcher: ReturnType<typeof watch>;
57+
isConfigUpdate: (path: string) => boolean;
58+
performHMR: (path?: string) => Promise<boolean>;
59+
hmrHandler: (path: string) => Promise<void>;
60+
sendHmrEvent: (event: HMREventType, path?: string) => Promise<boolean>;
61+
getProcess: () => ChildProcess | null;
62+
buildAndStart: typeof buildAndStart;
63+
}> {
5664
process.env.COMMANDKIT_BOOTSTRAP_MODE = 'development';
5765
process.env.COMMANDKIT_INTERNAL_IS_CLI_PROCESS = 'true';
5866
const start = performance.now();

packages/commandkit/src/cli/production.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export async function bootstrapProductionServer(configPath?: string) {
2323
);
2424
}
2525

26-
return createAppProcess(mainFile, cwd, false);
26+
return createAppProcess(mainFile, cwd, false, config);
2727
}
2828

2929
/**

packages/commandkit/src/config/config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ export function defineConfig(
8080
jsxDefaultOptionalComponents:
8181
config.jsxDefaultOptionalComponents ??
8282
defaultConfig.jsxDefaultOptionalComponents,
83+
experimental: {
84+
...defaultConfig.experimental,
85+
...config.experimental,
86+
},
8387
};
8488

8589
return defined;

packages/commandkit/src/config/default.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,7 @@ export const defaultConfig: ResolvedCommandKitConfig = {
3535
production: false,
3636
},
3737
jsxDefaultOptionalComponents: true,
38+
experimental: {
39+
devServerRuntime: null,
40+
},
3841
};

packages/commandkit/src/config/types.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ import { MaybeArray } from '../components';
22
import { CommandKitPlugin } from '../plugins';
33
import type { InlineConfig as TsDownOptions } from 'tsdown';
44

5+
/**
6+
* The JavaScript runtime to use for the development server.
7+
*/
8+
export type CommandKitJsRuntime = 'node' | 'bun' | 'deno' | 'auto';
9+
510
export interface CommandKitCompilerOptions {
611
/**
712
* The macro compiler options to use with CommandKit.
@@ -119,4 +124,14 @@ export interface CommandKitConfig {
119124
* @default true
120125
*/
121126
jsxDefaultOptionalComponents?: boolean;
127+
/**
128+
* Experimental features configuration. These features are not stable and may be removed or changed without a major version bump. Use with caution.
129+
*/
130+
experimental?: {
131+
/**
132+
* The runtime to use for the development server. This is an experimental feature and may be removed or changed without a major version bump. Use with caution.
133+
* @default null
134+
*/
135+
devServerRuntime?: CommandKitJsRuntime | null;
136+
};
122137
}

0 commit comments

Comments
 (0)