genrex 0.1.0 → 0.2.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 +214 -50
- package/dist/src/create.js +33 -15
- package/dist/src/index.js +20 -13
- package/dist/src/pm.js +1 -1
- package/dist/src/prompt.js +55 -0
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -11,95 +11,200 @@
|
|
|
11
11
|
</p>
|
|
12
12
|
|
|
13
13
|
<p align="center">
|
|
14
|
-
<img src="https://img.shields.io/
|
|
14
|
+
<a href="https://www.npmjs.com/package/genrex"><img src="https://img.shields.io/npm/v/genrex?style=flat-square&color=cb3837" alt="npm version" /></a>
|
|
15
15
|
<img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="License" />
|
|
16
|
+
<img src="https://img.shields.io/badge/node-%3E%3D20-brightgreen?style=flat-square" alt="Node version" />
|
|
16
17
|
</p>
|
|
17
18
|
|
|
18
19
|
> **Forge production-ready projects from configurable blueprints.**
|
|
19
20
|
|
|
20
|
-
`genrex` is a modern, lightweight
|
|
21
|
+
`genrex` is a modern, lightweight CLI scaffolding engine. Rather than copying bare-bones or obsolete boilerplates, it generates strictly-typed, coherent software projects equipped with modern standards: **Biome**, **Vitest**, native ESM, **GitHub Actions CI**, and multi-stage **Dockerfiles**.
|
|
21
22
|
|
|
22
23
|
---
|
|
23
24
|
|
|
24
|
-
##
|
|
25
|
+
## ⚡ Installation & Execution
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
- **Code Quality & Testing:** Biome (Format/Lint), Vitest
|
|
28
|
-
- **API Framework:** Fastify + `tsx` hot-reload
|
|
29
|
-
- **DevOps & Containers:** Multi-stage Docker, GitHub Actions CI
|
|
30
|
-
- **Package Managers:** `pnpm`, `npm`, `yarn`, `bun`
|
|
27
|
+
You have two ways to run `genrex`:
|
|
31
28
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
## Quick Start
|
|
29
|
+
### 1. One-Time Run (Recommended — No Install Needed)
|
|
35
30
|
|
|
36
|
-
Run
|
|
31
|
+
Run the latest version instantly using `npx`:
|
|
37
32
|
|
|
38
33
|
```bash
|
|
39
|
-
npx genrex create
|
|
34
|
+
npx genrex create
|
|
40
35
|
```
|
|
41
36
|
|
|
42
|
-
|
|
37
|
+
Or target a specific name directly:
|
|
43
38
|
|
|
44
39
|
```bash
|
|
45
|
-
npx genrex create my-
|
|
40
|
+
npx genrex create my-app
|
|
46
41
|
```
|
|
47
42
|
|
|
48
43
|
---
|
|
49
44
|
|
|
50
|
-
|
|
45
|
+
### 2. Global Installation
|
|
51
46
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
47
|
+
If you frequently scaffold new projects, install `genrex` globally:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Using npm
|
|
51
|
+
npm install -g genrex
|
|
52
|
+
|
|
53
|
+
# Using pnpm
|
|
54
|
+
pnpm add -g genrex
|
|
55
|
+
|
|
56
|
+
# Using yarn
|
|
57
|
+
yarn global add genrex
|
|
58
|
+
|
|
59
|
+
# Using bun
|
|
60
|
+
bun add -g genrex
|
|
61
|
+
```
|
|
57
62
|
|
|
58
|
-
|
|
63
|
+
Once installed, use the `genrex` command anywhere:
|
|
59
64
|
|
|
60
65
|
```bash
|
|
61
|
-
genrex
|
|
62
|
-
genrex info ts-cli
|
|
66
|
+
genrex create
|
|
63
67
|
```
|
|
64
68
|
|
|
65
69
|
---
|
|
66
70
|
|
|
67
|
-
##
|
|
71
|
+
## 🎯 Interactive Wizard Mode
|
|
68
72
|
|
|
69
|
-
|
|
73
|
+
Running `genrex create` without options launches an interactive step-by-step setup wizard:
|
|
70
74
|
|
|
71
|
-
```
|
|
72
|
-
genrex
|
|
75
|
+
```text
|
|
76
|
+
genrex — Project Blueprint Engine
|
|
77
|
+
|
|
78
|
+
? Project name: my-fastify-api
|
|
79
|
+
|
|
80
|
+
? Choose a blueprint:
|
|
81
|
+
1) TypeScript CLI (ts-cli)
|
|
82
|
+
2) Node.js API (node-api)
|
|
83
|
+
3) TypeScript Library (ts-lib)
|
|
84
|
+
Select [1-3] (1): 2
|
|
85
|
+
|
|
86
|
+
? Package manager:
|
|
87
|
+
1) pnpm
|
|
88
|
+
2) npm
|
|
89
|
+
3) yarn
|
|
90
|
+
4) bun
|
|
91
|
+
Select [1-4] (1): 1
|
|
92
|
+
|
|
93
|
+
? Initialize Git? (Y/n): y
|
|
94
|
+
? Add GitHub Actions CI? (y/N): y
|
|
95
|
+
? Add Docker? (y/N): y
|
|
96
|
+
|
|
97
|
+
✓ Project scaffolded in /path/to/my-fastify-api
|
|
98
|
+
Installing dependencies using pnpm...
|
|
99
|
+
✓ Dependencies installed
|
|
100
|
+
Initializing Git repository...
|
|
101
|
+
✓ Git repository initialized
|
|
102
|
+
|
|
103
|
+
Done. Next steps:
|
|
104
|
+
cd my-fastify-api
|
|
105
|
+
pnpm run dev
|
|
106
|
+
pnpm test
|
|
73
107
|
```
|
|
74
108
|
|
|
75
|
-
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## 📖 Complete Command Reference
|
|
112
|
+
|
|
113
|
+
| Command | Description |
|
|
114
|
+
|---|---|
|
|
115
|
+
| `genrex create [name]` | Scaffold a new project (interactive wizard by default) |
|
|
116
|
+
| `genrex list` | Show all available blueprints and descriptions |
|
|
117
|
+
| `genrex info <id>` | Inspect detailed metadata & capabilities of a blueprint |
|
|
118
|
+
| `genrex doctor` | Audit local development environment tools and versions |
|
|
119
|
+
| `genrex -v, --version` | Output current CLI version |
|
|
120
|
+
| `genrex -h, --help` | Display command usage and option flags |
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
### 1. `genrex create [name] [options]`
|
|
125
|
+
|
|
126
|
+
Scaffold a project. You can skip interactive prompts entirely using flags (ideal for CI/automation scripts).
|
|
127
|
+
|
|
128
|
+
#### Command Flags:
|
|
76
129
|
|
|
77
130
|
| Flag | Description | Default |
|
|
78
131
|
|---|---|---|
|
|
79
|
-
|
|
|
132
|
+
| `-i, --interactive` | Force interactive wizard even if name is supplied | `false` |
|
|
133
|
+
| `--blueprint <id>` | Target blueprint: `ts-cli`, `node-api`, or `ts-lib` | `ts-cli` |
|
|
80
134
|
| `--package-manager <pm>` | `npm`, `pnpm`, `yarn`, or `bun` | `pnpm` |
|
|
81
135
|
| `--git` | Initialize empty Git repository | `false` |
|
|
82
|
-
| `--github-actions` | Generate
|
|
83
|
-
| `--docker` | Generate
|
|
84
|
-
| `--dry-run` | Preview
|
|
85
|
-
| `--skip-install` | Scaffold files without
|
|
136
|
+
| `--github-actions` | Generate `.github/workflows/ci.yml` CI workflow | `false` |
|
|
137
|
+
| `--docker` | Generate multi-stage `Dockerfile` and `.dockerignore` | `false` |
|
|
138
|
+
| `--dry-run` | Preview files and packages without writing to disk | `false` |
|
|
139
|
+
| `--skip-install` | Scaffold files without executing package manager install | `false` |
|
|
86
140
|
|
|
87
|
-
|
|
141
|
+
#### Non-Interactive Examples:
|
|
88
142
|
|
|
89
143
|
```bash
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
144
|
+
# Preview what would be created without writing any files
|
|
145
|
+
genrex create my-tool --blueprint ts-cli --dry-run
|
|
146
|
+
|
|
147
|
+
# Node.js API with pnpm, Git, and GitHub Actions
|
|
148
|
+
genrex create backend-service --blueprint node-api --package-manager pnpm --git --github-actions
|
|
149
|
+
|
|
150
|
+
# Lightweight library without waiting for dependency installation
|
|
151
|
+
genrex create math-utils --blueprint ts-lib --skip-install
|
|
152
|
+
|
|
153
|
+
# Full-stack microservice with Docker containerization
|
|
154
|
+
genrex create auth-service --blueprint node-api --docker --github-actions --git
|
|
96
155
|
```
|
|
97
156
|
|
|
98
157
|
---
|
|
99
158
|
|
|
100
|
-
### 2.
|
|
159
|
+
### 2. `genrex list`
|
|
101
160
|
|
|
102
|
-
|
|
161
|
+
List all built-in blueprint architectures:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
genrex list
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
```text
|
|
168
|
+
Available blueprints:
|
|
169
|
+
|
|
170
|
+
ts-cli TypeScript CLI (TypeScript)
|
|
171
|
+
Production-ready TypeScript CLI tool.
|
|
172
|
+
|
|
173
|
+
node-api Node.js API (TypeScript)
|
|
174
|
+
Node.js REST API with routing and healthchecks.
|
|
175
|
+
|
|
176
|
+
ts-lib TypeScript Library (TypeScript)
|
|
177
|
+
Publishable TypeScript library blueprint.
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
### 3. `genrex info <blueprint-id>`
|
|
183
|
+
|
|
184
|
+
Inspect capabilities and metadata of any blueprint:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
genrex info node-api
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
```text
|
|
191
|
+
Node.js API (node-api)
|
|
192
|
+
Version: 1.0.0
|
|
193
|
+
Language: TypeScript
|
|
194
|
+
Description: Node.js REST API with routing and healthchecks.
|
|
195
|
+
Capabilities:
|
|
196
|
+
- testing
|
|
197
|
+
- formatting
|
|
198
|
+
- git
|
|
199
|
+
- github-actions
|
|
200
|
+
- docker
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
### 4. `genrex doctor`
|
|
206
|
+
|
|
207
|
+
Audit your machine's environment and ensure required developer tools are installed:
|
|
103
208
|
|
|
104
209
|
```bash
|
|
105
210
|
genrex doctor
|
|
@@ -122,27 +227,86 @@ Environment is ready.
|
|
|
122
227
|
|
|
123
228
|
---
|
|
124
229
|
|
|
125
|
-
##
|
|
230
|
+
## 🏗️ Available Blueprints & Project Structures
|
|
126
231
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
-
|
|
232
|
+
### 1. TypeScript CLI (`ts-cli`)
|
|
233
|
+
Tailored for building standalone developer tools and CLI applications.
|
|
234
|
+
```text
|
|
235
|
+
my-cli/
|
|
236
|
+
├── src/
|
|
237
|
+
│ └── index.ts # Executable binary entry point with shebang
|
|
238
|
+
├── tests/
|
|
239
|
+
│ └── index.test.ts # Vitest unit test suite
|
|
240
|
+
├── .gitignore
|
|
241
|
+
├── biome.json # High-performance linter & formatter
|
|
242
|
+
├── package.json # Configured with "bin" field and ESM
|
|
243
|
+
├── tsconfig.json # Strict NodeNext configuration
|
|
244
|
+
└── README.md
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### 2. Node.js API (`node-api`)
|
|
248
|
+
Production-ready REST API built with Fastify.
|
|
249
|
+
```text
|
|
250
|
+
my-api/
|
|
251
|
+
├── src/
|
|
252
|
+
│ └── server.ts # Fastify server with /health route
|
|
253
|
+
├── tests/
|
|
254
|
+
│ └── server.test.ts # Vitest route testing
|
|
255
|
+
├── .gitignore
|
|
256
|
+
├── biome.json
|
|
257
|
+
├── package.json # Development with "tsx watch" hot-reload
|
|
258
|
+
├── tsconfig.json
|
|
259
|
+
└── README.md
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### 3. TypeScript Library (`ts-lib`)
|
|
263
|
+
Ready for distribution on npm with dual type declarations.
|
|
264
|
+
```text
|
|
265
|
+
my-lib/
|
|
266
|
+
├── src/
|
|
267
|
+
│ └── index.ts # Library exports
|
|
268
|
+
├── tests/
|
|
269
|
+
│ └── index.test.ts # Vitest test suite
|
|
270
|
+
├── .gitignore
|
|
271
|
+
├── .npmignore # Keeps source and tests out of npm tarball
|
|
272
|
+
├── biome.json
|
|
273
|
+
├── package.json # "exports", "main", "types", "prepublishOnly"
|
|
274
|
+
├── tsconfig.json # Generates declaration maps (.d.ts)
|
|
275
|
+
└── README.md
|
|
276
|
+
```
|
|
131
277
|
|
|
132
278
|
---
|
|
133
279
|
|
|
134
|
-
##
|
|
280
|
+
## 🛡️ Safety & Core Philosophy
|
|
281
|
+
|
|
282
|
+
- **Zero Accidental Overwriting:** Refuses to generate files inside non-empty folders.
|
|
283
|
+
- **Shell Injection Safe:** Child processes use direct executable arguments (`shell: false`) rather than concatenated shell strings.
|
|
284
|
+
- **Fail Fast:** Project names, blueprint availability, and Git binary presence are validated before modifying the filesystem.
|
|
285
|
+
- **Zero Heavy Runtime Dependencies:** Blazing fast execution using native Node.js APIs (`node:readline/promises`, `node:child_process`, `node:fs`).
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## 💻 Development & Contributing
|
|
290
|
+
|
|
291
|
+
Want to add new blueprints or improve the CLI?
|
|
135
292
|
|
|
136
293
|
```bash
|
|
294
|
+
# Clone the repository
|
|
137
295
|
git clone https://github.com/waeterr/genrex.git
|
|
138
296
|
cd genrex
|
|
297
|
+
|
|
298
|
+
# Install dev dependencies
|
|
139
299
|
npm install
|
|
300
|
+
|
|
301
|
+
# Run automated tests (native Node test runner + TypeScript strip)
|
|
140
302
|
npm test
|
|
303
|
+
|
|
304
|
+
# Build TypeScript to dist/
|
|
141
305
|
npm run build
|
|
142
306
|
```
|
|
143
307
|
|
|
144
308
|
---
|
|
145
309
|
|
|
146
|
-
## License
|
|
310
|
+
## 📄 License
|
|
147
311
|
|
|
148
312
|
MIT © [waeterr](https://github.com/waeterr)
|
package/dist/src/create.js
CHANGED
|
@@ -6,21 +6,39 @@ import { buildNodeApiFiles } from "./generators/node-api.js";
|
|
|
6
6
|
import { buildTsLibFiles } from "./generators/ts-lib.js";
|
|
7
7
|
import { checkGit, initGit } from "./git.js";
|
|
8
8
|
import { installDependencies } from "./pm.js";
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
import { promptWizard } from "./prompt.js";
|
|
10
|
+
export async function createProject(name, options) {
|
|
11
|
+
let targetName = name;
|
|
12
|
+
let targetBlueprint = options.blueprint ?? "ts-cli";
|
|
13
|
+
let targetPm = options.packageManager ?? "pnpm";
|
|
14
|
+
let targetGit = options.git;
|
|
15
|
+
let targetCi = options.githubActions;
|
|
16
|
+
let targetDocker = options.docker;
|
|
17
|
+
const shouldPrompt = Boolean(process.stdin.isTTY) &&
|
|
18
|
+
(!targetName || options.interactive || (!options.blueprint && !options.dryRun));
|
|
19
|
+
if (shouldPrompt) {
|
|
20
|
+
const answers = await promptWizard(targetName);
|
|
21
|
+
targetName = answers.name;
|
|
22
|
+
targetBlueprint = answers.blueprint;
|
|
23
|
+
targetPm = answers.packageManager;
|
|
24
|
+
targetGit = answers.git;
|
|
25
|
+
targetCi = answers.githubActions;
|
|
26
|
+
targetDocker = answers.docker;
|
|
27
|
+
}
|
|
28
|
+
if (!targetName) {
|
|
11
29
|
fail("Project name is required. Example: genrex create my-project");
|
|
12
30
|
return;
|
|
13
31
|
}
|
|
14
32
|
const config = {
|
|
15
|
-
name: basename(
|
|
16
|
-
destination: resolve(
|
|
17
|
-
blueprint:
|
|
18
|
-
packageManager:
|
|
33
|
+
name: basename(targetName),
|
|
34
|
+
destination: resolve(targetName),
|
|
35
|
+
blueprint: targetBlueprint,
|
|
36
|
+
packageManager: targetPm,
|
|
19
37
|
testing: "vitest",
|
|
20
38
|
formatter: "biome",
|
|
21
|
-
git:
|
|
22
|
-
githubActions:
|
|
23
|
-
docker:
|
|
39
|
+
git: targetGit,
|
|
40
|
+
githubActions: targetCi,
|
|
41
|
+
docker: targetDocker,
|
|
24
42
|
};
|
|
25
43
|
const errors = validateConfig(config);
|
|
26
44
|
const blueprint = getBlueprint(config.blueprint);
|
|
@@ -57,16 +75,16 @@ export function createProject(name, options) {
|
|
|
57
75
|
console.log(`Blueprint: ${blueprint.name}`);
|
|
58
76
|
console.log(`Destination: ${config.destination}`);
|
|
59
77
|
console.log(`Package manager: ${config.packageManager}`);
|
|
60
|
-
console.log(`Git: ${
|
|
61
|
-
console.log(`GitHub Actions: ${
|
|
62
|
-
console.log(`Docker: ${
|
|
78
|
+
console.log(`Git: ${config.git ? "yes" : "no"}`);
|
|
79
|
+
console.log(`GitHub Actions: ${config.githubActions ? "yes" : "no"}`);
|
|
80
|
+
console.log(`Docker: ${config.docker ? "yes" : "no"}`);
|
|
63
81
|
console.log("\nWould create:");
|
|
64
82
|
for (const f of files) {
|
|
65
83
|
console.log(` - ${f.path}`);
|
|
66
84
|
}
|
|
67
85
|
console.log("\nWould install:");
|
|
68
86
|
console.log(" devDependencies: typescript, vitest, @biomejs/biome, @types/node");
|
|
69
|
-
if (
|
|
87
|
+
if (config.git) {
|
|
70
88
|
console.log("\nWould execute:");
|
|
71
89
|
console.log(" git init");
|
|
72
90
|
}
|
|
@@ -84,13 +102,13 @@ export function createProject(name, options) {
|
|
|
84
102
|
installDependencies(config.packageManager, config.destination);
|
|
85
103
|
console.log("✓ Dependencies installed");
|
|
86
104
|
}
|
|
87
|
-
if (
|
|
105
|
+
if (config.git) {
|
|
88
106
|
console.log("Initializing Git repository...");
|
|
89
107
|
initGit(config.destination);
|
|
90
108
|
console.log("✓ Git repository initialized");
|
|
91
109
|
}
|
|
92
110
|
console.log("\nDone. Next steps:");
|
|
93
|
-
console.log(` cd ${
|
|
111
|
+
console.log(` cd ${targetName}`);
|
|
94
112
|
if (options.skipInstall) {
|
|
95
113
|
console.log(` ${config.packageManager} install`);
|
|
96
114
|
}
|
package/dist/src/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { blueprints, getBlueprint } from "./blueprints.js";
|
|
|
5
5
|
const [command, ...args] = process.argv.slice(2);
|
|
6
6
|
switch (command) {
|
|
7
7
|
case "create":
|
|
8
|
-
runCreate(args);
|
|
8
|
+
await runCreate(args);
|
|
9
9
|
break;
|
|
10
10
|
case "list":
|
|
11
11
|
listBlueprints();
|
|
@@ -23,24 +23,27 @@ switch (command) {
|
|
|
23
23
|
break;
|
|
24
24
|
case "--version":
|
|
25
25
|
case "-v":
|
|
26
|
-
console.log("0.1
|
|
26
|
+
console.log("0.2.1");
|
|
27
27
|
break;
|
|
28
28
|
default:
|
|
29
29
|
console.error(`Unknown command: ${command}`);
|
|
30
30
|
console.error("Run 'genrex --help' for usage.");
|
|
31
31
|
process.exitCode = 1;
|
|
32
32
|
}
|
|
33
|
-
function runCreate(args) {
|
|
34
|
-
const [
|
|
33
|
+
async function runCreate(args) {
|
|
34
|
+
const [firstArg, ...flags] = args;
|
|
35
|
+
let name = firstArg?.startsWith("-") ? undefined : firstArg;
|
|
36
|
+
const allFlags = firstArg?.startsWith("-") ? [firstArg, ...flags] : flags;
|
|
35
37
|
const options = {
|
|
36
38
|
dryRun: false,
|
|
37
39
|
skipInstall: false,
|
|
38
40
|
git: false,
|
|
39
41
|
githubActions: false,
|
|
40
42
|
docker: false,
|
|
43
|
+
interactive: false,
|
|
41
44
|
};
|
|
42
|
-
for (let index = 0; index <
|
|
43
|
-
const flag =
|
|
45
|
+
for (let index = 0; index < allFlags.length; index += 1) {
|
|
46
|
+
const flag = allFlags[index];
|
|
44
47
|
if (flag === "--dry-run") {
|
|
45
48
|
options.dryRun = true;
|
|
46
49
|
}
|
|
@@ -56,11 +59,14 @@ function runCreate(args) {
|
|
|
56
59
|
else if (flag === "--docker") {
|
|
57
60
|
options.docker = true;
|
|
58
61
|
}
|
|
62
|
+
else if (flag === "-i" || flag === "--interactive") {
|
|
63
|
+
options.interactive = true;
|
|
64
|
+
}
|
|
59
65
|
else if (flag === "--blueprint") {
|
|
60
|
-
options.blueprint =
|
|
66
|
+
options.blueprint = allFlags[++index];
|
|
61
67
|
}
|
|
62
68
|
else if (flag === "--package-manager") {
|
|
63
|
-
const packageManager =
|
|
69
|
+
const packageManager = allFlags[++index];
|
|
64
70
|
if (!["npm", "pnpm", "yarn", "bun"].includes(packageManager)) {
|
|
65
71
|
console.error(`Error: Unsupported package manager '${packageManager}'.`);
|
|
66
72
|
process.exitCode = 1;
|
|
@@ -74,7 +80,7 @@ function runCreate(args) {
|
|
|
74
80
|
return;
|
|
75
81
|
}
|
|
76
82
|
}
|
|
77
|
-
createProject(name, options);
|
|
83
|
+
await createProject(name, options);
|
|
78
84
|
}
|
|
79
85
|
function listBlueprints() {
|
|
80
86
|
console.log("Available blueprints:\n");
|
|
@@ -111,19 +117,20 @@ Usage:
|
|
|
111
117
|
genrex <command> [options]
|
|
112
118
|
|
|
113
119
|
Commands:
|
|
120
|
+
create [name] Create a project (interactive wizard by default)
|
|
114
121
|
list List available blueprints
|
|
115
122
|
info <name> Show blueprint details
|
|
116
|
-
create <name> --dry-run Preview project generation
|
|
117
123
|
doctor Check local environment
|
|
118
124
|
|
|
119
125
|
Create options:
|
|
120
|
-
--
|
|
126
|
+
-i, --interactive Launch interactive prompt wizard
|
|
127
|
+
--blueprint <id> Blueprint ID (ts-cli, node-api, ts-lib)
|
|
121
128
|
--package-manager <manager> npm, pnpm, yarn, or bun (default: pnpm)
|
|
122
|
-
--dry-run Preview without filesystem changes
|
|
123
|
-
--skip-install Do not install dependencies
|
|
124
129
|
--git Initialize a Git repository
|
|
125
130
|
--github-actions Generate GitHub Actions CI workflow
|
|
126
131
|
--docker Generate Dockerfile & .dockerignore
|
|
132
|
+
--dry-run Preview without filesystem changes
|
|
133
|
+
--skip-install Do not install dependencies
|
|
127
134
|
|
|
128
135
|
Options:
|
|
129
136
|
-h, --help Show help
|
package/dist/src/pm.js
CHANGED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { createInterface } from "node:readline/promises";
|
|
2
|
+
import { stdin, stdout } from "node:process";
|
|
3
|
+
import { blueprints } from "./blueprints.js";
|
|
4
|
+
export async function promptWizard(initialName) {
|
|
5
|
+
const rl = createInterface({ input: stdin, output: stdout });
|
|
6
|
+
try {
|
|
7
|
+
console.log("\ngenrex — Project Blueprint Engine\n");
|
|
8
|
+
let name = initialName;
|
|
9
|
+
if (name) {
|
|
10
|
+
console.log(`? Project name: ${name}`);
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
while (!name || name.trim() === "") {
|
|
14
|
+
const answer = await rl.question("? Project name: ");
|
|
15
|
+
name = answer.trim();
|
|
16
|
+
if (!name) {
|
|
17
|
+
console.log(" Project name cannot be empty.");
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
console.log("\n? Choose a blueprint:");
|
|
22
|
+
blueprints.forEach((b, i) => {
|
|
23
|
+
console.log(` ${i + 1}) ${b.name.padEnd(22)} (${b.id})`);
|
|
24
|
+
});
|
|
25
|
+
const bpChoice = await rl.question(`Select [1-${blueprints.length}] (1): `);
|
|
26
|
+
const bpIndex = Number.parseInt(bpChoice.trim() || "1", 10) - 1;
|
|
27
|
+
const blueprint = (blueprints[bpIndex] ?? blueprints[0]).id;
|
|
28
|
+
const pms = ["pnpm", "npm", "yarn", "bun"];
|
|
29
|
+
console.log("\n? Package manager:");
|
|
30
|
+
pms.forEach((pm, i) => {
|
|
31
|
+
console.log(` ${i + 1}) ${pm}`);
|
|
32
|
+
});
|
|
33
|
+
const pmChoice = await rl.question(`Select [1-${pms.length}] (1): `);
|
|
34
|
+
const pmIndex = Number.parseInt(pmChoice.trim() || "1", 10) - 1;
|
|
35
|
+
const packageManager = pms[pmIndex] ?? "pnpm";
|
|
36
|
+
const gitAns = await rl.question("\n? Initialize Git? (Y/n): ");
|
|
37
|
+
const git = gitAns.trim().toLowerCase() !== "n";
|
|
38
|
+
const ciAns = await rl.question("? Add GitHub Actions CI? (y/N): ");
|
|
39
|
+
const githubActions = ciAns.trim().toLowerCase() === "y";
|
|
40
|
+
const dockerAns = await rl.question("? Add Docker? (y/N): ");
|
|
41
|
+
const docker = dockerAns.trim().toLowerCase() === "y";
|
|
42
|
+
console.log();
|
|
43
|
+
return {
|
|
44
|
+
name,
|
|
45
|
+
blueprint,
|
|
46
|
+
packageManager,
|
|
47
|
+
git,
|
|
48
|
+
githubActions,
|
|
49
|
+
docker,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
rl.close();
|
|
54
|
+
}
|
|
55
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genrex",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Forge production-ready TypeScript projects from blueprints",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -38,5 +38,8 @@
|
|
|
38
38
|
},
|
|
39
39
|
"engines": {
|
|
40
40
|
"node": ">=20"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"genrex": "^0.1.0"
|
|
41
44
|
}
|
|
42
45
|
}
|