create-crust 0.0.5 → 0.0.7
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 +3 -1
- package/dist/index.js +58 -140
- package/package.json +8 -2
- package/templates/base/README.md +24 -0
- package/templates/base/_gitignore +34 -0
- package/templates/base/package.json +24 -0
- package/templates/base/src/cli.ts +33 -0
- package/templates/base/tsconfig.json +17 -0
package/README.md
CHANGED
|
@@ -8,11 +8,13 @@ Scaffold a new [Crust](https://crustjs.com) CLI project in seconds.
|
|
|
8
8
|
bun create crust my-cli
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
This will prompt for project
|
|
11
|
+
This will prompt for your project directory, install dependencies, and optionally initialize a git repository. The package name is inferred from the directory name. The generated project includes:
|
|
12
12
|
|
|
13
13
|
- `src/cli.ts` — entry point with a sample command
|
|
14
14
|
- `package.json` — configured with `crust build` and `bun run` dev scripts
|
|
15
15
|
- `tsconfig.json` — strict TypeScript config
|
|
16
|
+
- `README.md` — getting started instructions
|
|
17
|
+
- `.gitignore` — sensible defaults for Node/Bun projects
|
|
16
18
|
|
|
17
19
|
## Documentation
|
|
18
20
|
|
package/dist/index.js
CHANGED
|
@@ -2,97 +2,11 @@
|
|
|
2
2
|
// @bun
|
|
3
3
|
|
|
4
4
|
// src/index.ts
|
|
5
|
-
import { existsSync
|
|
5
|
+
import { existsSync } from "fs";
|
|
6
6
|
import { basename, resolve } from "path";
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
}
|
|
7
|
+
import { defineCommand, runMain } from "@crustjs/core";
|
|
8
|
+
import { detectPackageManager, runSteps, scaffold } from "@crustjs/create";
|
|
9
|
+
import { confirm, input, spinner } from "@crustjs/prompts";
|
|
96
10
|
var INVALID_NAME_CHARS = /[<>:"|?*\\]/;
|
|
97
11
|
function validateProjectName(name) {
|
|
98
12
|
if (!name) {
|
|
@@ -101,70 +15,74 @@ function validateProjectName(name) {
|
|
|
101
15
|
if (INVALID_NAME_CHARS.test(name)) {
|
|
102
16
|
return `Project name contains invalid characters: ${name}`;
|
|
103
17
|
}
|
|
104
|
-
return
|
|
18
|
+
return true;
|
|
105
19
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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");
|
|
20
|
+
var command = defineCommand({
|
|
21
|
+
meta: {
|
|
22
|
+
name: "create-crust",
|
|
23
|
+
description: "Scaffold a new Crust CLI project"
|
|
24
|
+
},
|
|
25
|
+
args: [
|
|
26
|
+
{
|
|
27
|
+
name: "directory",
|
|
28
|
+
type: "string",
|
|
29
|
+
description: "Project directory to scaffold into"
|
|
124
30
|
}
|
|
31
|
+
],
|
|
32
|
+
async run({ args }) {
|
|
33
|
+
const targetDir = args.directory ?? await input({
|
|
34
|
+
message: "Project directory",
|
|
35
|
+
placeholder: "my-cli",
|
|
36
|
+
validate: validateProjectName
|
|
37
|
+
});
|
|
125
38
|
const resolvedDir = resolve(process.cwd(), targetDir);
|
|
126
39
|
const dirName = basename(resolvedDir);
|
|
127
|
-
if (existsSync(resolvedDir)) {
|
|
128
|
-
const
|
|
129
|
-
|
|
40
|
+
if (targetDir !== "." && existsSync(resolvedDir)) {
|
|
41
|
+
const overwrite = await confirm({
|
|
42
|
+
message: `Directory "${dirName}" already exists. Overwrite?`,
|
|
43
|
+
default: false
|
|
44
|
+
});
|
|
45
|
+
if (!overwrite) {
|
|
130
46
|
console.log("Aborted.");
|
|
131
47
|
return;
|
|
132
48
|
}
|
|
133
49
|
}
|
|
134
|
-
const name =
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
50
|
+
const name = dirName;
|
|
51
|
+
await scaffold({
|
|
52
|
+
template: "./templates/base",
|
|
53
|
+
dest: resolvedDir,
|
|
54
|
+
context: { name },
|
|
55
|
+
conflict: "overwrite"
|
|
56
|
+
});
|
|
57
|
+
const installDeps = await confirm({
|
|
58
|
+
message: "Install dependencies?",
|
|
59
|
+
default: true
|
|
60
|
+
});
|
|
61
|
+
if (installDeps) {
|
|
62
|
+
const pm = detectPackageManager(resolvedDir);
|
|
63
|
+
const installCmd = pm === "npm" ? "npm install" : `${pm} install`;
|
|
64
|
+
await runSteps([{ type: "command", cmd: installCmd }], resolvedDir);
|
|
138
65
|
}
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
console.log(`
|
|
143
|
-
Installing dependencies...
|
|
144
|
-
`);
|
|
145
|
-
const install = Bun.spawn(["bun", "install"], {
|
|
146
|
-
cwd: resolvedDir,
|
|
147
|
-
stdout: "inherit",
|
|
148
|
-
stderr: "inherit"
|
|
66
|
+
const initGit = await confirm({
|
|
67
|
+
message: "Initialize a git repository?",
|
|
68
|
+
default: true
|
|
149
69
|
});
|
|
150
|
-
|
|
151
|
-
|
|
70
|
+
if (initGit) {
|
|
71
|
+
await spinner({
|
|
72
|
+
message: "Initializing git repository...",
|
|
73
|
+
task: () => runSteps([{ type: "git-init", commit: "chore: initial commit" }], resolvedDir)
|
|
74
|
+
});
|
|
75
|
+
}
|
|
152
76
|
console.log(`
|
|
153
77
|
Created ${name}!
|
|
154
78
|
`);
|
|
155
79
|
console.log("Next steps:");
|
|
156
|
-
|
|
80
|
+
if (targetDir !== ".") {
|
|
81
|
+
const relativeDir = targetDir.startsWith("/") ? targetDir : `./${targetDir}`;
|
|
82
|
+
console.log(` cd ${relativeDir}`);
|
|
83
|
+
}
|
|
157
84
|
console.log(" bun run dev");
|
|
158
85
|
console.log(" bun run build");
|
|
159
|
-
} finally {
|
|
160
|
-
rl.close();
|
|
161
86
|
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
if (isMainModule) {
|
|
165
|
-
main();
|
|
166
|
-
}
|
|
167
|
-
export {
|
|
168
|
-
scaffold,
|
|
169
|
-
main
|
|
170
|
-
};
|
|
87
|
+
});
|
|
88
|
+
runMain(command);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-crust",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"description": "Scaffold a new Crust CLI project.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
"crust"
|
|
25
25
|
],
|
|
26
26
|
"files": [
|
|
27
|
-
"dist"
|
|
27
|
+
"dist",
|
|
28
|
+
"templates"
|
|
28
29
|
],
|
|
29
30
|
"publishConfig": {
|
|
30
31
|
"access": "public"
|
|
@@ -38,6 +39,11 @@
|
|
|
38
39
|
"check:types": "tsc --noEmit",
|
|
39
40
|
"test": "bun test"
|
|
40
41
|
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@crustjs/core": "0.0.6",
|
|
44
|
+
"@crustjs/create": "0.0.2",
|
|
45
|
+
"@crustjs/prompts": "0.0.1"
|
|
46
|
+
},
|
|
41
47
|
"devDependencies": {
|
|
42
48
|
"@crustjs/config": "0.0.0",
|
|
43
49
|
"bunup": "^0.16.29"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# {{name}}
|
|
2
|
+
|
|
3
|
+
A CLI built with [Crust](https://crustjs.com).
|
|
4
|
+
|
|
5
|
+
## Development
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
# Run in dev mode
|
|
9
|
+
bun run dev
|
|
10
|
+
|
|
11
|
+
# Type-check
|
|
12
|
+
bun run check:types
|
|
13
|
+
|
|
14
|
+
# Build standalone executable
|
|
15
|
+
bun run build
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
# Run the CLI
|
|
22
|
+
{{name}} world
|
|
23
|
+
{{name}} --greet Hey world
|
|
24
|
+
```
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# dependencies (bun install)
|
|
2
|
+
node_modules
|
|
3
|
+
|
|
4
|
+
# output
|
|
5
|
+
out
|
|
6
|
+
dist
|
|
7
|
+
*.tgz
|
|
8
|
+
|
|
9
|
+
# code coverage
|
|
10
|
+
coverage
|
|
11
|
+
*.lcov
|
|
12
|
+
|
|
13
|
+
# logs
|
|
14
|
+
logs
|
|
15
|
+
_.log
|
|
16
|
+
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
|
17
|
+
|
|
18
|
+
# dotenv environment variable files
|
|
19
|
+
.env
|
|
20
|
+
.env.development.local
|
|
21
|
+
.env.test.local
|
|
22
|
+
.env.production.local
|
|
23
|
+
.env.local
|
|
24
|
+
|
|
25
|
+
# caches
|
|
26
|
+
.eslintcache
|
|
27
|
+
.cache
|
|
28
|
+
*.tsbuildinfo
|
|
29
|
+
|
|
30
|
+
# IntelliJ based IDEs
|
|
31
|
+
.idea
|
|
32
|
+
|
|
33
|
+
# Finder (MacOS) folder config
|
|
34
|
+
.DS_Store
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{name}}",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "A CLI built with Crust",
|
|
6
|
+
"bin": {
|
|
7
|
+
"{{name}}": "dist/cli"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"dev": "bun run src/cli.ts",
|
|
11
|
+
"build": "crust build",
|
|
12
|
+
"start": "./dist/cli",
|
|
13
|
+
"check:types": "tsc --noEmit"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@crustjs/core": "latest",
|
|
17
|
+
"@crustjs/plugins": "latest"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@crustjs/crust": "latest",
|
|
21
|
+
"@types/bun": "latest",
|
|
22
|
+
"typescript": "^5"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { defineCommand, runMain } from "@crustjs/core";
|
|
2
|
+
import { helpPlugin, versionPlugin } from "@crustjs/plugins";
|
|
3
|
+
import pkg from "../package.json";
|
|
4
|
+
|
|
5
|
+
const main = defineCommand({
|
|
6
|
+
meta: {
|
|
7
|
+
name: "{{name}}",
|
|
8
|
+
description: "A CLI built with Crust",
|
|
9
|
+
},
|
|
10
|
+
args: [
|
|
11
|
+
{
|
|
12
|
+
name: "name",
|
|
13
|
+
type: "string",
|
|
14
|
+
description: "Your name",
|
|
15
|
+
default: "world",
|
|
16
|
+
},
|
|
17
|
+
],
|
|
18
|
+
flags: {
|
|
19
|
+
greet: {
|
|
20
|
+
type: "string",
|
|
21
|
+
description: "Greeting to use",
|
|
22
|
+
default: "Hello",
|
|
23
|
+
alias: "g",
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
run({ args, flags }) {
|
|
27
|
+
console.log(`${flags.greet}, ${args.name}!`);
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
runMain(main, {
|
|
32
|
+
plugins: [versionPlugin(pkg.version), helpPlugin()],
|
|
33
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"lib": ["ESNext"],
|
|
4
|
+
"target": "ESNext",
|
|
5
|
+
"module": "Preserve",
|
|
6
|
+
"moduleDetection": "force",
|
|
7
|
+
"moduleResolution": "bundler",
|
|
8
|
+
"allowImportingTsExtensions": true,
|
|
9
|
+
"verbatimModuleSyntax": true,
|
|
10
|
+
"noEmit": true,
|
|
11
|
+
"strict": true,
|
|
12
|
+
"skipLibCheck": true,
|
|
13
|
+
"noFallthroughCasesInSwitch": true,
|
|
14
|
+
"noUncheckedIndexedAccess": true
|
|
15
|
+
},
|
|
16
|
+
"include": ["src"]
|
|
17
|
+
}
|