create-crust 0.0.2

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 (3) hide show
  1. package/README.md +23 -0
  2. package/dist/index.js +170 -0
  3. package/package.json +48 -0
package/README.md ADDED
@@ -0,0 +1,23 @@
1
+ # @crustjs/create-crust
2
+
3
+ Scaffold a new [Crust](https://crust.cyanlabs.co) CLI project in seconds.
4
+
5
+ ## Usage
6
+
7
+ ```sh
8
+ bun create crust my-cli
9
+ ```
10
+
11
+ This will prompt for project details and generate a ready-to-go project with:
12
+
13
+ - `src/cli.ts` — entry point with a sample command
14
+ - `package.json` — configured with `crust build` and `bun run` dev scripts
15
+ - `tsconfig.json` — strict TypeScript config
16
+
17
+ ## Documentation
18
+
19
+ See the full docs at [crust.cyanlabs.co](https://crust.cyanlabs.co).
20
+
21
+ ## License
22
+
23
+ MIT
package/dist/index.js ADDED
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env bun
2
+ // @bun
3
+
4
+ // src/index.ts
5
+ import { existsSync, mkdirSync, writeFileSync } from "fs";
6
+ import { basename, resolve } from "path";
7
+ import { createInterface } from "readline/promises";
8
+ function templatePackageJson(name, description, author) {
9
+ const pkg = {
10
+ name,
11
+ version: "0.0.0",
12
+ type: "module",
13
+ bin: {
14
+ [name]: "dist/cli.js"
15
+ },
16
+ scripts: {
17
+ build: "crust build",
18
+ dev: "bun run src/cli.ts"
19
+ },
20
+ dependencies: {
21
+ "@crustjs/crust": "latest"
22
+ },
23
+ devDependencies: {
24
+ typescript: "^5"
25
+ }
26
+ };
27
+ if (description) {
28
+ pkg.description = description;
29
+ }
30
+ if (author) {
31
+ pkg.author = author;
32
+ }
33
+ return JSON.stringify(pkg, null, 2);
34
+ }
35
+ function templateTsconfig() {
36
+ return JSON.stringify({
37
+ compilerOptions: {
38
+ lib: ["ESNext"],
39
+ target: "ESNext",
40
+ module: "Preserve",
41
+ moduleDetection: "force",
42
+ moduleResolution: "bundler",
43
+ allowImportingTsExtensions: true,
44
+ verbatimModuleSyntax: true,
45
+ noEmit: true,
46
+ strict: true,
47
+ skipLibCheck: true,
48
+ noFallthroughCasesInSwitch: true,
49
+ noUncheckedIndexedAccess: true
50
+ },
51
+ include: ["src"]
52
+ }, null, 2);
53
+ }
54
+ function templateCliTs(name) {
55
+ return `#!/usr/bin/env bun
56
+
57
+ import { defineCommand, helpPlugin, runMain, versionPlugin } from "@crustjs/crust";
58
+ import pkg from "../package.json";
59
+
60
+ const main = defineCommand({
61
+ meta: {
62
+ name: "${name}",
63
+ description: "A CLI built with Crust",
64
+ },
65
+ args: [
66
+ {
67
+ name: "name",
68
+ type: String,
69
+ description: "Your name",
70
+ default: "world",
71
+ },
72
+ ],
73
+ flags: {
74
+ greet: {
75
+ type: String,
76
+ description: "Greeting to use",
77
+ default: "Hello",
78
+ alias: "g",
79
+ },
80
+ },
81
+ run({ args, flags }) {
82
+ console.log(\`\${flags.greet}, \${args.name}!\`);
83
+ },
84
+ });
85
+
86
+ runMain(main, {
87
+ plugins: [versionPlugin(pkg.version), helpPlugin()],
88
+ });
89
+ `;
90
+ }
91
+ async function prompt(rl, question, defaultValue) {
92
+ const suffix = defaultValue ? ` (${defaultValue})` : "";
93
+ const answer = await rl.question(`${question}${suffix}: `);
94
+ return answer.trim() || defaultValue;
95
+ }
96
+ var INVALID_NAME_CHARS = /[<>:"|?*\\]/;
97
+ function validateProjectName(name) {
98
+ if (!name) {
99
+ return "Project name cannot be empty";
100
+ }
101
+ if (INVALID_NAME_CHARS.test(name)) {
102
+ return `Project name contains invalid characters: ${name}`;
103
+ }
104
+ return null;
105
+ }
106
+ function scaffold(options) {
107
+ const { dir, name, description, author } = options;
108
+ mkdirSync(resolve(dir, "src"), { recursive: true });
109
+ writeFileSync(resolve(dir, "package.json"), `${templatePackageJson(name, description, author)}
110
+ `);
111
+ writeFileSync(resolve(dir, "tsconfig.json"), `${templateTsconfig()}
112
+ `);
113
+ writeFileSync(resolve(dir, "src", "cli.ts"), templateCliTs(name));
114
+ }
115
+ async function main(argv = process.argv.slice(2)) {
116
+ const rl = createInterface({
117
+ input: process.stdin,
118
+ output: process.stdout
119
+ });
120
+ try {
121
+ let targetDir = argv[0];
122
+ if (!targetDir) {
123
+ targetDir = await prompt(rl, "Project directory", "my-cli");
124
+ }
125
+ const resolvedDir = resolve(process.cwd(), targetDir);
126
+ const dirName = basename(resolvedDir);
127
+ if (existsSync(resolvedDir)) {
128
+ const answer = await prompt(rl, `Directory "${dirName}" already exists. Overwrite?`, "no");
129
+ if (answer.toLowerCase() !== "yes" && answer.toLowerCase() !== "y") {
130
+ console.log("Aborted.");
131
+ return;
132
+ }
133
+ }
134
+ const name = await prompt(rl, "Project name", dirName);
135
+ const nameError = validateProjectName(name);
136
+ if (nameError) {
137
+ throw new Error(nameError);
138
+ }
139
+ const description = await prompt(rl, "Description", "A CLI built with Crust");
140
+ const author = await prompt(rl, "Author", "");
141
+ scaffold({ dir: resolvedDir, name, description, author });
142
+ console.log(`
143
+ Installing dependencies...
144
+ `);
145
+ const install = Bun.spawn(["bun", "install"], {
146
+ cwd: resolvedDir,
147
+ stdout: "inherit",
148
+ stderr: "inherit"
149
+ });
150
+ await install.exited;
151
+ const relativeDir = targetDir.startsWith("/") ? targetDir : `./${targetDir}`;
152
+ console.log(`
153
+ Created ${name}!
154
+ `);
155
+ console.log("Next steps:");
156
+ console.log(` cd ${relativeDir}`);
157
+ console.log(" bun run dev");
158
+ console.log(" bun run build");
159
+ } finally {
160
+ rl.close();
161
+ }
162
+ }
163
+ var isMainModule = process.argv[1] === import.meta.filename || process.argv[1]?.endsWith("/create-crust/dist/index.js") || process.argv[1]?.endsWith("/create-crust/src/index.ts");
164
+ if (isMainModule) {
165
+ main();
166
+ }
167
+ export {
168
+ scaffold,
169
+ main
170
+ };
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "create-crust",
3
+ "version": "0.0.2",
4
+ "description": "Scaffold a new Crust CLI project.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "chenxin-yan",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/chenxin-yan/crust.git",
11
+ "directory": "packages/create-crust"
12
+ },
13
+ "homepage": "https://crust.cyanlabs.co",
14
+ "bugs": {
15
+ "url": "https://github.com/chenxin-yan/crust/issues"
16
+ },
17
+ "keywords": [
18
+ "cli",
19
+ "scaffold",
20
+ "create",
21
+ "generator",
22
+ "bun",
23
+ "typescript",
24
+ "crust"
25
+ ],
26
+ "files": [
27
+ "dist"
28
+ ],
29
+ "publishConfig": {
30
+ "access": "public"
31
+ },
32
+ "bin": {
33
+ "create-crust": "dist/index.js"
34
+ },
35
+ "scripts": {
36
+ "build": "bunup",
37
+ "dev": "bunup --watch",
38
+ "check:types": "tsc --noEmit",
39
+ "test": "bun test"
40
+ },
41
+ "devDependencies": {
42
+ "@crustjs/config": "workspace:*",
43
+ "bunup": "catalog:"
44
+ },
45
+ "peerDependencies": {
46
+ "typescript": "catalog:"
47
+ }
48
+ }