create-bunli 0.7.0 → 0.8.1
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.
- package/README.md +18 -6
- package/dist/cli.d.ts +1 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +372 -195
- package/dist/create-project.d.ts +5 -4
- package/dist/create-project.d.ts.map +1 -0
- package/dist/create.d.ts +4 -3
- package/dist/create.d.ts.map +1 -0
- package/dist/index.d.ts +6 -3
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +344 -187
- package/dist/steps.d.ts +36 -0
- package/dist/steps.d.ts.map +1 -0
- package/dist/template-engine.d.ts +3 -2
- package/dist/template-engine.d.ts.map +1 -0
- package/dist/templates/advanced/README.md +8 -4
- package/dist/templates/advanced/bunli.config.ts +19 -19
- package/dist/templates/advanced/package.json +9 -4
- package/dist/templates/advanced/src/commands/config.ts +129 -118
- package/dist/templates/advanced/src/commands/init.ts +53 -59
- package/dist/templates/advanced/src/commands/serve.ts +77 -82
- package/dist/templates/advanced/src/commands/validate.ts +58 -64
- package/dist/templates/advanced/src/index.ts +30 -29
- package/dist/templates/advanced/src/utils/config.ts +48 -47
- package/dist/templates/advanced/src/utils/constants.ts +6 -6
- package/dist/templates/advanced/src/utils/glob.ts +29 -28
- package/dist/templates/advanced/src/utils/validator.ts +60 -61
- package/dist/templates/advanced/template.json +2 -6
- package/dist/templates/advanced/tsconfig.json +1 -1
- package/dist/templates/basic/README.md +1 -1
- package/dist/templates/basic/bunli.config.ts +17 -17
- package/dist/templates/basic/package.json +4 -3
- package/dist/templates/basic/src/commands/hello.ts +20 -25
- package/dist/templates/basic/src/index.ts +9 -8
- package/dist/templates/basic/template.json +2 -6
- package/dist/templates/basic/tsconfig.json +1 -1
- package/dist/templates/monorepo/README.md +1 -1
- package/dist/templates/monorepo/bunli.config.ts +21 -21
- package/dist/templates/monorepo/package.json +3 -2
- package/dist/templates/monorepo/packages/cli/package.json +10 -5
- package/dist/templates/monorepo/packages/cli/src/index.ts +13 -13
- package/dist/templates/monorepo/packages/cli/tsconfig.json +3 -6
- package/dist/templates/monorepo/packages/core/package.json +6 -5
- package/dist/templates/monorepo/packages/core/scripts/build.ts +10 -10
- package/dist/templates/monorepo/packages/core/src/commands/analyze.ts +58 -56
- package/dist/templates/monorepo/packages/core/src/commands/process.ts +39 -46
- package/dist/templates/monorepo/packages/core/src/index.ts +3 -3
- package/dist/templates/monorepo/packages/core/src/types.ts +15 -15
- package/dist/templates/monorepo/packages/core/tsconfig.json +3 -5
- package/dist/templates/monorepo/packages/utils/package.json +6 -5
- package/dist/templates/monorepo/packages/utils/scripts/build.ts +10 -10
- package/dist/templates/monorepo/packages/utils/src/format.ts +19 -19
- package/dist/templates/monorepo/packages/utils/src/index.ts +3 -3
- package/dist/templates/monorepo/packages/utils/src/json.ts +4 -4
- package/dist/templates/monorepo/packages/utils/src/logger.ts +9 -9
- package/dist/templates/monorepo/packages/utils/tsconfig.json +2 -2
- package/dist/templates/monorepo/template.json +2 -6
- package/dist/templates/monorepo/tsconfig.json +1 -1
- package/dist/templates/monorepo/turbo.json +1 -1
- package/dist/types.d.ts +2 -1
- package/dist/types.d.ts.map +1 -0
- package/package.json +35 -34
- package/templates/advanced/README.md +8 -4
- package/templates/advanced/bunli.config.ts +19 -19
- package/templates/advanced/package.json +9 -4
- package/templates/advanced/src/commands/config.ts +129 -118
- package/templates/advanced/src/commands/init.ts +53 -59
- package/templates/advanced/src/commands/serve.ts +77 -82
- package/templates/advanced/src/commands/validate.ts +58 -64
- package/templates/advanced/src/index.ts +30 -29
- package/templates/advanced/src/utils/config.ts +48 -47
- package/templates/advanced/src/utils/constants.ts +6 -6
- package/templates/advanced/src/utils/glob.ts +29 -28
- package/templates/advanced/src/utils/validator.ts +60 -61
- package/templates/advanced/template.json +2 -6
- package/templates/advanced/tsconfig.json +1 -1
- package/templates/basic/README.md +1 -1
- package/templates/basic/bunli.config.ts +17 -17
- package/templates/basic/package.json +4 -3
- package/templates/basic/src/commands/hello.ts +20 -25
- package/templates/basic/src/index.ts +9 -8
- package/templates/basic/template.json +2 -6
- package/templates/basic/tsconfig.json +1 -1
- package/templates/monorepo/README.md +1 -1
- package/templates/monorepo/bunli.config.ts +21 -21
- package/templates/monorepo/package.json +3 -2
- package/templates/monorepo/packages/cli/package.json +10 -5
- package/templates/monorepo/packages/cli/src/index.ts +13 -13
- package/templates/monorepo/packages/cli/tsconfig.json +3 -6
- package/templates/monorepo/packages/core/package.json +6 -5
- package/templates/monorepo/packages/core/scripts/build.ts +10 -10
- package/templates/monorepo/packages/core/src/commands/analyze.ts +58 -56
- package/templates/monorepo/packages/core/src/commands/process.ts +39 -46
- package/templates/monorepo/packages/core/src/index.ts +3 -3
- package/templates/monorepo/packages/core/src/types.ts +15 -15
- package/templates/monorepo/packages/core/tsconfig.json +3 -5
- package/templates/monorepo/packages/utils/package.json +6 -5
- package/templates/monorepo/packages/utils/scripts/build.ts +10 -10
- package/templates/monorepo/packages/utils/src/format.ts +19 -19
- package/templates/monorepo/packages/utils/src/index.ts +3 -3
- package/templates/monorepo/packages/utils/src/json.ts +4 -4
- package/templates/monorepo/packages/utils/src/logger.ts +9 -9
- package/templates/monorepo/packages/utils/tsconfig.json +2 -2
- package/templates/monorepo/template.json +2 -6
- package/templates/monorepo/tsconfig.json +1 -1
- package/templates/monorepo/turbo.json +1 -1
|
@@ -1,112 +1,107 @@
|
|
|
1
|
-
import { defineCommand, option } from
|
|
2
|
-
import { z } from
|
|
3
|
-
|
|
1
|
+
import { defineCommand, option } from "@bunli/core";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
import { loadConfig } from "../utils/config.js";
|
|
4
5
|
|
|
5
6
|
const serveCommand = defineCommand({
|
|
6
|
-
name:
|
|
7
|
-
description:
|
|
7
|
+
name: "serve",
|
|
8
|
+
description: "Start a development server",
|
|
8
9
|
options: {
|
|
9
|
-
port: option(
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
),
|
|
23
|
-
open: option(
|
|
24
|
-
z.boolean().default(true),
|
|
25
|
-
{
|
|
26
|
-
description: 'Open browser on start'
|
|
27
|
-
}
|
|
28
|
-
)
|
|
10
|
+
port: option(z.coerce.number().int().min(1).max(65535).default(3000), {
|
|
11
|
+
short: "p",
|
|
12
|
+
description: "Port to listen on",
|
|
13
|
+
}),
|
|
14
|
+
host: option(z.string().default("localhost"), {
|
|
15
|
+
short: "h",
|
|
16
|
+
description: "Host to bind to",
|
|
17
|
+
}),
|
|
18
|
+
open: option(z.boolean().default(true), {
|
|
19
|
+
description: "Open browser on start",
|
|
20
|
+
argumentKind: "flag",
|
|
21
|
+
}),
|
|
29
22
|
},
|
|
30
23
|
handler: async ({ flags, colors, spinner, shell }) => {
|
|
31
|
-
const spin = spinner(
|
|
32
|
-
spin.start()
|
|
33
|
-
|
|
24
|
+
const spin = spinner("Starting server...");
|
|
25
|
+
spin.start();
|
|
26
|
+
|
|
34
27
|
try {
|
|
35
28
|
// Load config
|
|
36
|
-
const config = await loadConfig()
|
|
37
|
-
|
|
29
|
+
const config = await loadConfig();
|
|
30
|
+
|
|
38
31
|
// Merge flags with config
|
|
39
|
-
const port = flags.port || config.server?.port || 3000
|
|
40
|
-
const host = flags.host || config.server?.host ||
|
|
41
|
-
const shouldOpen = flags.open ?? config.server?.open ?? true
|
|
42
|
-
|
|
32
|
+
const port = flags.port || config.server?.port || 3000;
|
|
33
|
+
const host = flags.host || config.server?.host || "localhost";
|
|
34
|
+
const shouldOpen = flags.open ?? config.server?.open ?? true;
|
|
35
|
+
|
|
43
36
|
// Create server
|
|
44
37
|
const server = Bun.serve({
|
|
45
38
|
port,
|
|
46
39
|
hostname: host,
|
|
47
40
|
fetch(req) {
|
|
48
|
-
const url = new URL(req.url)
|
|
49
|
-
|
|
41
|
+
const url = new URL(req.url);
|
|
42
|
+
|
|
50
43
|
// Simple router
|
|
51
|
-
if (url.pathname ===
|
|
44
|
+
if (url.pathname === "/") {
|
|
52
45
|
return new Response(getHomePage(), {
|
|
53
|
-
headers: {
|
|
54
|
-
})
|
|
46
|
+
headers: { "Content-Type": "text/html" },
|
|
47
|
+
});
|
|
55
48
|
}
|
|
56
|
-
|
|
57
|
-
if (url.pathname ===
|
|
49
|
+
|
|
50
|
+
if (url.pathname === "/api/status") {
|
|
58
51
|
return Response.json({
|
|
59
|
-
status:
|
|
60
|
-
version:
|
|
61
|
-
uptime: process.uptime()
|
|
62
|
-
})
|
|
52
|
+
status: "ok",
|
|
53
|
+
version: "0.1.0",
|
|
54
|
+
uptime: process.uptime(),
|
|
55
|
+
});
|
|
63
56
|
}
|
|
64
|
-
|
|
65
|
-
return new Response(
|
|
66
|
-
}
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
spin.succeed(`Server running at http://${host}:${port}`)
|
|
70
|
-
|
|
57
|
+
|
|
58
|
+
return new Response("Not Found", { status: 404 });
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
spin.succeed(`Server running at http://${host}:${port}`);
|
|
63
|
+
|
|
71
64
|
// Open browser
|
|
72
65
|
if (shouldOpen) {
|
|
73
|
-
const openSpin = spinner(
|
|
74
|
-
openSpin.start()
|
|
75
|
-
|
|
66
|
+
const openSpin = spinner("Opening browser...");
|
|
67
|
+
openSpin.start();
|
|
68
|
+
|
|
76
69
|
try {
|
|
77
|
-
const url = `http://${host ===
|
|
78
|
-
|
|
70
|
+
const url = `http://${host === "0.0.0.0" ? "localhost" : host}:${port}`;
|
|
71
|
+
|
|
79
72
|
// Platform-specific open commands
|
|
80
|
-
const openCommand =
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
73
|
+
const openCommand =
|
|
74
|
+
process.platform === "darwin"
|
|
75
|
+
? "open"
|
|
76
|
+
: process.platform === "win32"
|
|
77
|
+
? "start"
|
|
78
|
+
: "xdg-open";
|
|
79
|
+
|
|
80
|
+
await shell`${openCommand} ${url}`.quiet();
|
|
81
|
+
openSpin.succeed("Browser opened");
|
|
86
82
|
} catch {
|
|
87
|
-
openSpin.fail(
|
|
83
|
+
openSpin.fail("Failed to open browser");
|
|
88
84
|
}
|
|
89
85
|
}
|
|
90
|
-
|
|
86
|
+
|
|
91
87
|
// Keep server running
|
|
92
|
-
console.log()
|
|
93
|
-
console.log(colors.dim(
|
|
94
|
-
|
|
88
|
+
console.log();
|
|
89
|
+
console.log(colors.dim("Press Ctrl+C to stop the server"));
|
|
90
|
+
|
|
95
91
|
// Handle shutdown
|
|
96
|
-
process.on(
|
|
97
|
-
console.log()
|
|
98
|
-
console.log(colors.yellow(
|
|
99
|
-
server.stop()
|
|
100
|
-
process.exit(0)
|
|
101
|
-
})
|
|
102
|
-
|
|
92
|
+
process.on("SIGINT", () => {
|
|
93
|
+
console.log();
|
|
94
|
+
console.log(colors.yellow("Shutting down server..."));
|
|
95
|
+
server.stop();
|
|
96
|
+
process.exit(0);
|
|
97
|
+
});
|
|
103
98
|
} catch (error) {
|
|
104
|
-
spin.fail(
|
|
105
|
-
console.error(colors.red(String(error)))
|
|
106
|
-
process.exit(1)
|
|
99
|
+
spin.fail("Failed to start server");
|
|
100
|
+
console.error(colors.red(String(error)));
|
|
101
|
+
process.exit(1);
|
|
107
102
|
}
|
|
108
|
-
}
|
|
109
|
-
})
|
|
103
|
+
},
|
|
104
|
+
});
|
|
110
105
|
|
|
111
106
|
function getHomePage(): string {
|
|
112
107
|
return `
|
|
@@ -172,7 +167,7 @@ function getHomePage(): string {
|
|
|
172
167
|
</div>
|
|
173
168
|
</body>
|
|
174
169
|
</html>
|
|
175
|
-
`.trim()
|
|
170
|
+
`.trim();
|
|
176
171
|
}
|
|
177
172
|
|
|
178
|
-
export default serveCommand
|
|
173
|
+
export default serveCommand;
|
|
@@ -1,113 +1,107 @@
|
|
|
1
|
-
import { defineCommand, option } from
|
|
2
|
-
import { z } from
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
import { glob } from
|
|
1
|
+
import { defineCommand, option } from "@bunli/core";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
import { loadConfig } from "../utils/config.js";
|
|
5
|
+
import { glob } from "../utils/glob.js";
|
|
6
|
+
import { validateFiles } from "../utils/validator.js";
|
|
6
7
|
|
|
7
8
|
const validateCommand = defineCommand({
|
|
8
|
-
name:
|
|
9
|
-
description:
|
|
9
|
+
name: "validate",
|
|
10
|
+
description: "Validate files against defined rules",
|
|
10
11
|
options: {
|
|
11
|
-
config: option(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
),
|
|
25
|
-
cache: option(
|
|
26
|
-
z.boolean().default(true),
|
|
27
|
-
{
|
|
28
|
-
description: 'Enable caching'
|
|
29
|
-
}
|
|
30
|
-
)
|
|
12
|
+
config: option(z.string().optional(), {
|
|
13
|
+
short: "c",
|
|
14
|
+
description: "Path to config file",
|
|
15
|
+
}),
|
|
16
|
+
fix: option(z.boolean().default(false), {
|
|
17
|
+
short: "f",
|
|
18
|
+
description: "Auto-fix issues",
|
|
19
|
+
argumentKind: "flag",
|
|
20
|
+
}),
|
|
21
|
+
cache: option(z.boolean().default(true), {
|
|
22
|
+
description: "Enable caching",
|
|
23
|
+
argumentKind: "flag",
|
|
24
|
+
}),
|
|
31
25
|
},
|
|
32
26
|
handler: async ({ positional, flags, colors, spinner }) => {
|
|
33
|
-
const spin = spinner(
|
|
34
|
-
spin.start()
|
|
27
|
+
const spin = spinner("Loading configuration...");
|
|
28
|
+
spin.start();
|
|
35
29
|
|
|
36
30
|
try {
|
|
37
|
-
const config = await loadConfig(flags.config)
|
|
38
|
-
spin.succeed(
|
|
31
|
+
const config = await loadConfig(flags.config);
|
|
32
|
+
spin.succeed("Configuration loaded");
|
|
39
33
|
|
|
40
|
-
const patterns = positional.length > 0 ? positional : config.include || [
|
|
34
|
+
const patterns = positional.length > 0 ? positional : config.include || ["src/**/*.{js,ts}"];
|
|
41
35
|
|
|
42
|
-
const fileSpin = spinner(
|
|
43
|
-
fileSpin.start()
|
|
36
|
+
const fileSpin = spinner("Resolving files...");
|
|
37
|
+
fileSpin.start();
|
|
44
38
|
|
|
45
39
|
const files = await glob(patterns, {
|
|
46
40
|
include: config.include,
|
|
47
|
-
exclude: config.exclude
|
|
48
|
-
})
|
|
41
|
+
exclude: config.exclude,
|
|
42
|
+
});
|
|
49
43
|
|
|
50
|
-
fileSpin.succeed(`Found ${files.length} files to validate`)
|
|
44
|
+
fileSpin.succeed(`Found ${files.length} files to validate`);
|
|
51
45
|
|
|
52
46
|
if (files.length === 0) {
|
|
53
|
-
console.log(colors.yellow(
|
|
54
|
-
return
|
|
47
|
+
console.log(colors.yellow("No files matched the pattern"));
|
|
48
|
+
return;
|
|
55
49
|
}
|
|
56
50
|
|
|
57
|
-
const validateSpin = spinner(
|
|
58
|
-
validateSpin.start()
|
|
51
|
+
const validateSpin = spinner("Validating files...");
|
|
52
|
+
validateSpin.start();
|
|
59
53
|
|
|
60
54
|
const results = await validateFiles(files, {
|
|
61
55
|
rules: config.rules,
|
|
62
56
|
fix: flags.fix,
|
|
63
|
-
cache: flags.cache && config.cache?.enabled
|
|
64
|
-
})
|
|
57
|
+
cache: flags.cache && config.cache?.enabled,
|
|
58
|
+
});
|
|
65
59
|
|
|
66
|
-
validateSpin.stop()
|
|
60
|
+
validateSpin.stop();
|
|
67
61
|
|
|
68
|
-
let hasErrors = false
|
|
62
|
+
let hasErrors = false;
|
|
69
63
|
|
|
70
64
|
for (const result of results) {
|
|
71
65
|
if (result.errors.length > 0 || result.warnings.length > 0) {
|
|
72
|
-
console.log()
|
|
73
|
-
console.log(colors.bold(result.file))
|
|
66
|
+
console.log();
|
|
67
|
+
console.log(colors.bold(result.file));
|
|
74
68
|
|
|
75
69
|
for (const error of result.errors) {
|
|
76
|
-
console.log(colors.red(` ✗ ${error.line}:${error.column} ${error.message}`))
|
|
77
|
-
hasErrors = true
|
|
70
|
+
console.log(colors.red(` ✗ ${error.line}:${error.column} ${error.message}`));
|
|
71
|
+
hasErrors = true;
|
|
78
72
|
}
|
|
79
73
|
|
|
80
74
|
for (const warning of result.warnings) {
|
|
81
|
-
console.log(colors.yellow(` ⚠ ${warning.line}:${warning.column} ${warning.message}`))
|
|
75
|
+
console.log(colors.yellow(` ⚠ ${warning.line}:${warning.column} ${warning.message}`));
|
|
82
76
|
}
|
|
83
77
|
}
|
|
84
78
|
}
|
|
85
79
|
|
|
86
|
-
const totalErrors = results.reduce((sum, r) => sum + r.errors.length, 0)
|
|
87
|
-
const totalWarnings = results.reduce((sum, r) => sum + r.warnings.length, 0)
|
|
80
|
+
const totalErrors = results.reduce((sum, r) => sum + r.errors.length, 0);
|
|
81
|
+
const totalWarnings = results.reduce((sum, r) => sum + r.warnings.length, 0);
|
|
88
82
|
|
|
89
|
-
console.log()
|
|
83
|
+
console.log();
|
|
90
84
|
if (totalErrors === 0 && totalWarnings === 0) {
|
|
91
|
-
console.log(colors.green(
|
|
85
|
+
console.log(colors.green("✅ All files passed validation!"));
|
|
92
86
|
} else {
|
|
93
|
-
console.log(colors.bold(
|
|
87
|
+
console.log(colors.bold("Summary:"));
|
|
94
88
|
if (totalErrors > 0) {
|
|
95
|
-
console.log(colors.red(` ${totalErrors} error${totalErrors !== 1 ?
|
|
89
|
+
console.log(colors.red(` ${totalErrors} error${totalErrors !== 1 ? "s" : ""}`));
|
|
96
90
|
}
|
|
97
91
|
if (totalWarnings > 0) {
|
|
98
|
-
console.log(colors.yellow(` ${totalWarnings} warning${totalWarnings !== 1 ?
|
|
92
|
+
console.log(colors.yellow(` ${totalWarnings} warning${totalWarnings !== 1 ? "s" : ""}`));
|
|
99
93
|
}
|
|
100
94
|
|
|
101
95
|
if (hasErrors) {
|
|
102
|
-
process.exit(1)
|
|
96
|
+
process.exit(1);
|
|
103
97
|
}
|
|
104
98
|
}
|
|
105
99
|
} catch (error) {
|
|
106
|
-
spin.fail(
|
|
107
|
-
console.error(colors.red(String(error)))
|
|
108
|
-
process.exit(1)
|
|
100
|
+
spin.fail("Validation failed");
|
|
101
|
+
console.error(colors.red(String(error)));
|
|
102
|
+
process.exit(1);
|
|
109
103
|
}
|
|
110
|
-
}
|
|
111
|
-
})
|
|
104
|
+
},
|
|
105
|
+
});
|
|
112
106
|
|
|
113
|
-
export default validateCommand
|
|
107
|
+
export default validateCommand;
|
|
@@ -1,55 +1,56 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
import { createCLI } from
|
|
3
|
-
import { Result, TaggedError } from
|
|
4
|
-
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
2
|
+
import { createCLI } from "@bunli/core";
|
|
3
|
+
import { Result, TaggedError } from "better-result";
|
|
4
|
+
|
|
5
|
+
import configCommand from "./commands/config.js";
|
|
6
|
+
import initCommand from "./commands/init.js";
|
|
7
|
+
import serveCommand from "./commands/serve.js";
|
|
8
|
+
import validateCommand from "./commands/validate.js";
|
|
9
|
+
import { loadConfig } from "./utils/config.js";
|
|
9
10
|
|
|
10
11
|
const toErrorMessage = (error: unknown): string =>
|
|
11
|
-
error instanceof Error ? error.message : String(error)
|
|
12
|
+
error instanceof Error ? error.message : String(error);
|
|
12
13
|
|
|
13
|
-
class CliStartupError extends TaggedError(
|
|
14
|
-
message: string
|
|
15
|
-
cause: unknown
|
|
14
|
+
class CliStartupError extends TaggedError("CliStartupError")<{
|
|
15
|
+
message: string;
|
|
16
|
+
cause: unknown;
|
|
16
17
|
}>() {
|
|
17
18
|
constructor(cause: unknown) {
|
|
18
|
-
super({ message: `Failed to start CLI: ${toErrorMessage(cause)}`, cause })
|
|
19
|
+
super({ message: `Failed to start CLI: ${toErrorMessage(cause)}`, cause });
|
|
19
20
|
}
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
const cli = await createCLI({
|
|
23
|
-
name:
|
|
24
|
-
version:
|
|
25
|
-
description:
|
|
26
|
-
})
|
|
24
|
+
name: "{{name}}",
|
|
25
|
+
version: "0.1.0",
|
|
26
|
+
description: "{{description}}",
|
|
27
|
+
});
|
|
27
28
|
|
|
28
|
-
cli.command(initCommand)
|
|
29
|
-
cli.command(validateCommand)
|
|
30
|
-
cli.command(serveCommand)
|
|
31
|
-
cli.command(configCommand)
|
|
29
|
+
cli.command(initCommand);
|
|
30
|
+
cli.command(validateCommand);
|
|
31
|
+
cli.command(serveCommand);
|
|
32
|
+
cli.command(configCommand);
|
|
32
33
|
|
|
33
34
|
async function run(): Promise<Result<void, CliStartupError>> {
|
|
34
35
|
const configResult = await Result.tryPromise({
|
|
35
36
|
try: () => loadConfig(),
|
|
36
|
-
catch: (cause) => new CliStartupError(cause)
|
|
37
|
-
})
|
|
37
|
+
catch: (cause) => new CliStartupError(cause),
|
|
38
|
+
});
|
|
38
39
|
|
|
39
40
|
if (Result.isError(configResult)) {
|
|
40
|
-
return configResult
|
|
41
|
+
return configResult;
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
return Result.tryPromise({
|
|
44
45
|
try: async () => {
|
|
45
|
-
await cli.run()
|
|
46
|
+
await cli.run();
|
|
46
47
|
},
|
|
47
|
-
catch: (cause) => new CliStartupError(cause)
|
|
48
|
-
})
|
|
48
|
+
catch: (cause) => new CliStartupError(cause),
|
|
49
|
+
});
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
const result = await run()
|
|
52
|
+
const result = await run();
|
|
52
53
|
if (Result.isError(result)) {
|
|
53
|
-
console.error(result.error.message)
|
|
54
|
-
process.exit(1)
|
|
54
|
+
console.error(result.error.message);
|
|
55
|
+
process.exit(1);
|
|
55
56
|
}
|
|
@@ -1,84 +1,85 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
|
|
3
|
+
import { CONFIG_FILE_NAME, DEFAULT_CONFIG } from "./constants.js";
|
|
3
4
|
|
|
4
5
|
export interface Config {
|
|
5
|
-
rules?: Record<string, any
|
|
6
|
+
rules?: Record<string, any>;
|
|
6
7
|
server?: {
|
|
7
|
-
port?: number
|
|
8
|
-
host?: string
|
|
9
|
-
open?: boolean
|
|
10
|
-
cors?: boolean
|
|
11
|
-
}
|
|
12
|
-
include?: string[]
|
|
13
|
-
exclude?: string[]
|
|
8
|
+
port?: number;
|
|
9
|
+
host?: string;
|
|
10
|
+
open?: boolean;
|
|
11
|
+
cors?: boolean;
|
|
12
|
+
};
|
|
13
|
+
include?: string[];
|
|
14
|
+
exclude?: string[];
|
|
14
15
|
cache?: {
|
|
15
|
-
enabled?: boolean
|
|
16
|
-
directory?: string
|
|
17
|
-
}
|
|
16
|
+
enabled?: boolean;
|
|
17
|
+
directory?: string;
|
|
18
|
+
};
|
|
18
19
|
hooks?: {
|
|
19
|
-
beforeValidate?: (files: string[]) => Promise<void
|
|
20
|
-
afterValidate?: (results: any) => Promise<void
|
|
21
|
-
}
|
|
20
|
+
beforeValidate?: (files: string[]) => Promise<void>;
|
|
21
|
+
afterValidate?: (results: any) => Promise<void>;
|
|
22
|
+
};
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
let cachedConfig: Config | null = null
|
|
25
|
+
let cachedConfig: Config | null = null;
|
|
25
26
|
|
|
26
27
|
export async function loadConfig(configPath?: string): Promise<Config> {
|
|
27
28
|
// Return cached config if available
|
|
28
29
|
if (cachedConfig && !configPath) {
|
|
29
|
-
return cachedConfig
|
|
30
|
+
return cachedConfig;
|
|
30
31
|
}
|
|
31
|
-
|
|
32
|
-
const finalPath = configPath || path.join(process.cwd(), CONFIG_FILE_NAME)
|
|
33
|
-
|
|
32
|
+
|
|
33
|
+
const finalPath = configPath || path.join(process.cwd(), CONFIG_FILE_NAME);
|
|
34
|
+
|
|
34
35
|
try {
|
|
35
36
|
// Check if config file exists
|
|
36
|
-
const file = Bun.file(finalPath)
|
|
37
|
+
const file = Bun.file(finalPath);
|
|
37
38
|
if (!(await file.exists())) {
|
|
38
|
-
return DEFAULT_CONFIG
|
|
39
|
+
return DEFAULT_CONFIG;
|
|
39
40
|
}
|
|
40
|
-
|
|
41
|
+
|
|
41
42
|
// Import the config file
|
|
42
|
-
const configModule = await import(finalPath)
|
|
43
|
-
const config = configModule.default || configModule
|
|
44
|
-
|
|
43
|
+
const configModule = await import(finalPath);
|
|
44
|
+
const config = configModule.default || configModule;
|
|
45
|
+
|
|
45
46
|
// Merge with defaults
|
|
46
47
|
const mergedConfig: Config = {
|
|
47
48
|
...DEFAULT_CONFIG,
|
|
48
49
|
...config,
|
|
49
50
|
server: {
|
|
50
51
|
...DEFAULT_CONFIG.server,
|
|
51
|
-
...(config.server || {})
|
|
52
|
-
}
|
|
53
|
-
}
|
|
52
|
+
...(config.server || {}),
|
|
53
|
+
},
|
|
54
|
+
};
|
|
54
55
|
|
|
55
|
-
cachedConfig = mergedConfig
|
|
56
|
-
return mergedConfig
|
|
56
|
+
cachedConfig = mergedConfig;
|
|
57
|
+
return mergedConfig;
|
|
57
58
|
} catch (error) {
|
|
58
|
-
console.warn(`Failed to load config from ${finalPath}:`, error)
|
|
59
|
-
return DEFAULT_CONFIG
|
|
59
|
+
console.warn(`Failed to load config from ${finalPath}:`, error);
|
|
60
|
+
return DEFAULT_CONFIG;
|
|
60
61
|
}
|
|
61
62
|
}
|
|
62
63
|
|
|
63
64
|
export async function saveConfig(config: Config): Promise<void> {
|
|
64
|
-
const configPath = path.join(process.cwd(), CONFIG_FILE_NAME)
|
|
65
|
-
|
|
65
|
+
const configPath = path.join(process.cwd(), CONFIG_FILE_NAME);
|
|
66
|
+
|
|
66
67
|
// Convert config to ES module format
|
|
67
|
-
const content = `export default ${JSON.stringify(config, null, 2)}
|
|
68
|
-
|
|
69
|
-
await Bun.write(configPath, content)
|
|
70
|
-
|
|
68
|
+
const content = `export default ${JSON.stringify(config, null, 2)}`;
|
|
69
|
+
|
|
70
|
+
await Bun.write(configPath, content);
|
|
71
|
+
|
|
71
72
|
// Clear cache
|
|
72
|
-
cachedConfig = null
|
|
73
|
+
cachedConfig = null;
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
export async function getConfigPath(): Promise<string> {
|
|
76
|
-
const configPath = path.join(process.cwd(), CONFIG_FILE_NAME)
|
|
77
|
-
const file = Bun.file(configPath)
|
|
78
|
-
|
|
77
|
+
const configPath = path.join(process.cwd(), CONFIG_FILE_NAME);
|
|
78
|
+
const file = Bun.file(configPath);
|
|
79
|
+
|
|
79
80
|
if (await file.exists()) {
|
|
80
|
-
return configPath
|
|
81
|
+
return configPath;
|
|
81
82
|
}
|
|
82
|
-
|
|
83
|
-
return
|
|
83
|
+
|
|
84
|
+
return "No config file found";
|
|
84
85
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
export const CONFIG_FILE_NAME =
|
|
1
|
+
export const CONFIG_FILE_NAME = "{{name}}.config.js";
|
|
2
2
|
|
|
3
3
|
export const DEFAULT_CONFIG = {
|
|
4
4
|
rules: {},
|
|
5
5
|
server: {
|
|
6
6
|
port: 3000,
|
|
7
|
-
host:
|
|
8
|
-
open: true
|
|
7
|
+
host: "localhost",
|
|
8
|
+
open: true,
|
|
9
9
|
},
|
|
10
|
-
include: [
|
|
11
|
-
exclude: [
|
|
12
|
-
}
|
|
10
|
+
include: ["src/**/*.{js,ts}"],
|
|
11
|
+
exclude: ["node_modules", "dist"],
|
|
12
|
+
};
|