@ajke/cli 0.1.0
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/LICENSE +21 -0
- package/README.md +163 -0
- package/bin/ajke.ts +80 -0
- package/bin/commands/add.ts +155 -0
- package/bin/commands/generate.ts +74 -0
- package/bin/commands/new.ts +457 -0
- package/bin/generators/module.generator.ts +266 -0
- package/bin/utils/config.ts +43 -0
- package/bin/utils/paths.ts +32 -0
- package/bin/utils/wrangler.ts +216 -0
- package/dist/bin/ajke.js +1150 -0
- package/dist/bin/ajke.js.map +1 -0
- package/package.json +34 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Wilt Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# @ajke/cli
|
|
2
|
+
|
|
3
|
+
The official CLI for the [Ajke framework](../core/README.md). Scaffold new Cloudflare Workers projects and generate modules, services, and controllers.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @ajke/cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or run without installing:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx @ajke/cli new my-app
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Commands
|
|
20
|
+
|
|
21
|
+
### `ajke new <project-name>`
|
|
22
|
+
|
|
23
|
+
Scaffold a new Ajke project with a Hello module, D1 database setup, and all config files pre-configured.
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
ajke new my-app
|
|
27
|
+
cd my-app
|
|
28
|
+
pnpm dev # http://localhost:4001
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**What gets created:**
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
my-app/
|
|
35
|
+
├── src/
|
|
36
|
+
│ ├── index.ts
|
|
37
|
+
│ ├── app.module.ts
|
|
38
|
+
│ └── modules/app/hello/
|
|
39
|
+
│ ├── hello.module.ts
|
|
40
|
+
│ ├── hello.controller.ts
|
|
41
|
+
│ └── hello.service.ts
|
|
42
|
+
├── src/database/
|
|
43
|
+
│ ├── schema.ts
|
|
44
|
+
│ └── connection.ts
|
|
45
|
+
├── migrations/
|
|
46
|
+
├── ajke.config.ts
|
|
47
|
+
├── wrangler.jsonc
|
|
48
|
+
├── tsconfig.json
|
|
49
|
+
├── vite.config.ts
|
|
50
|
+
├── vitest.config.ts
|
|
51
|
+
└── package.json
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
### `ajke generate <subcommand> <name>`
|
|
57
|
+
|
|
58
|
+
Aliases: `g`
|
|
59
|
+
|
|
60
|
+
Scaffold files inside an existing project. Reads `ajke.config.ts` for the modules directory.
|
|
61
|
+
|
|
62
|
+
#### `ajke generate module <name>` (alias: `g m`)
|
|
63
|
+
|
|
64
|
+
Generates a full module: module, controller, service, DTO, entity, and test file.
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
ajke generate module payment
|
|
68
|
+
ajke g m payment
|
|
69
|
+
ajke g m payment --no-test # skip test file
|
|
70
|
+
ajke g m payment --path src/modules/billing/payment
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Output:**
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
src/modules/app/payment/
|
|
77
|
+
├── payment.module.ts
|
|
78
|
+
├── payment.controller.ts
|
|
79
|
+
├── payment.service.ts
|
|
80
|
+
├── payment.dto.ts
|
|
81
|
+
├── payment.entity.ts
|
|
82
|
+
└── payment.test.ts
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
#### `ajke generate service <name>` (alias: `g s`)
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
ajke generate service payment
|
|
89
|
+
ajke g s payment --path src/modules/app/payment
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
#### `ajke generate controller <name>` (alias: `g c`)
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
ajke generate controller payment
|
|
96
|
+
ajke g c payment --path src/modules/app/payment
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
### `ajke add <service> [args]`
|
|
102
|
+
|
|
103
|
+
Add a Cloudflare service binding to `wrangler.jsonc`.
|
|
104
|
+
|
|
105
|
+
| Subcommand | Usage | Example |
|
|
106
|
+
|---|---|---|
|
|
107
|
+
| `d1` | `ajke add d1 <BINDING> <db-name>` | `ajke add d1 DB my-database` |
|
|
108
|
+
| `r2` | `ajke add r2 <BINDING> <bucket-name>` | `ajke add r2 ASSETS my-bucket` |
|
|
109
|
+
| `kv` | `ajke add kv <BINDING>` | `ajke add kv SESSION_KV` |
|
|
110
|
+
| `queue` | `ajke add queue <BINDING> <queue-name>` | `ajke add queue MAIL mail-queue` |
|
|
111
|
+
| `ai` | `ajke add ai <BINDING>` | `ajke add ai AI` |
|
|
112
|
+
| `durable-object` | `ajke add durable-object <BINDING> <ClassName>` | `ajke add durable-object CHAT ChatRoom` |
|
|
113
|
+
| `vectorize` | `ajke add vectorize <BINDING> <index-name> [dims]` | `ajke add vectorize VEC my-index 1536` |
|
|
114
|
+
| `browser` | `ajke add browser <BINDING>` | `ajke add browser BROWSER` |
|
|
115
|
+
| `hyperdrive` | `ajke add hyperdrive <BINDING> <connection-string>` | `ajke add hyperdrive HD postgres://...` |
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Config (`ajke.config.ts`)
|
|
120
|
+
|
|
121
|
+
Place this file in your project root to customise the CLI behaviour.
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
import { defineConfig } from "@ajke/core/config";
|
|
125
|
+
|
|
126
|
+
export default defineConfig({
|
|
127
|
+
// Where generated modules are placed (relative to project root)
|
|
128
|
+
modulesDir: "src/modules/app",
|
|
129
|
+
|
|
130
|
+
// Which files are scaffolded by `ajke generate module <name>`
|
|
131
|
+
// Remove "test" to skip test files, or pass --no-test per-command
|
|
132
|
+
generate: {
|
|
133
|
+
files: ["module", "controller", "service", "dto", "entity", "test"],
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Usage Inside a Project
|
|
141
|
+
|
|
142
|
+
When `@ajke/cli` is installed locally as a dev dependency, add a script to `package.json`:
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"scripts": {
|
|
147
|
+
"ajke": "tsx node_modules/@ajke/cli/bin/ajke.ts"
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Then run:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
pnpm ajke generate module posts
|
|
156
|
+
pnpm ajke add d1 DB my-database
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## License
|
|
162
|
+
|
|
163
|
+
MIT
|
package/bin/ajke.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { runNew } from "./commands/new.js";
|
|
3
|
+
import { runGenerate } from "./commands/generate.js";
|
|
4
|
+
import { runAdd } from "./commands/add.js";
|
|
5
|
+
|
|
6
|
+
const BANNER = `
|
|
7
|
+
█████╗ ██╗██╗ ██╗███████╗
|
|
8
|
+
██╔══██╗ ██║██║ ██╔╝██╔════╝
|
|
9
|
+
███████║ ██║█████╔╝ █████╗
|
|
10
|
+
██╔══██║██ ██║██╔═██╗ ██╔══╝
|
|
11
|
+
██║ ██║╚█████╔╝██║ ██╗███████╗
|
|
12
|
+
╚═╝ ╚═╝ ╚════╝ ╚═╝ ╚═╝╚══════╝
|
|
13
|
+
Ajke CLI — Cloudflare Workers & Hono Framework
|
|
14
|
+
`.trim();
|
|
15
|
+
|
|
16
|
+
const HELP = `
|
|
17
|
+
${BANNER}
|
|
18
|
+
|
|
19
|
+
Usage:
|
|
20
|
+
pnpm ajke <command> [subcommand] [args...]
|
|
21
|
+
|
|
22
|
+
Commands:
|
|
23
|
+
new Create a new Ajke project
|
|
24
|
+
generate (g) Scaffold module, service, or controller files
|
|
25
|
+
add Add a Cloudflare service binding to wrangler.jsonc
|
|
26
|
+
help Show this help message
|
|
27
|
+
|
|
28
|
+
Generate subcommands:
|
|
29
|
+
module (m) Scaffold a full module (module + controller + service + dto)
|
|
30
|
+
service (s) Scaffold a service file
|
|
31
|
+
controller (c) Scaffold a controller file
|
|
32
|
+
|
|
33
|
+
Add subcommands:
|
|
34
|
+
d1 D1 database binding
|
|
35
|
+
r2 R2 bucket binding
|
|
36
|
+
kv KV namespace binding
|
|
37
|
+
queue Queue producer + consumer
|
|
38
|
+
ai Workers AI binding
|
|
39
|
+
durable-object Durable Object binding + migration
|
|
40
|
+
vectorize Vectorize index binding
|
|
41
|
+
browser Browser rendering binding
|
|
42
|
+
hyperdrive Hyperdrive binding
|
|
43
|
+
|
|
44
|
+
Examples:
|
|
45
|
+
pnpm ajke new my-app
|
|
46
|
+
pnpm ajke generate module payment
|
|
47
|
+
pnpm ajke g m payment
|
|
48
|
+
pnpm ajke add d1 PAYMENTS_DB payments-db
|
|
49
|
+
pnpm ajke add r2 ASSETS_BUCKET my-assets
|
|
50
|
+
pnpm ajke add kv SESSION_KV
|
|
51
|
+
pnpm ajke add queue MAIL_QUEUE mailer
|
|
52
|
+
pnpm ajke add ai AI
|
|
53
|
+
pnpm ajke add durable-object CHAT_ROOM ChatRoom
|
|
54
|
+
`.trim();
|
|
55
|
+
|
|
56
|
+
async function main(): Promise<void> {
|
|
57
|
+
const args = process.argv.slice(2);
|
|
58
|
+
const [command, ...rest] = args;
|
|
59
|
+
|
|
60
|
+
if (!command || command === "help" || command === "--help" || command === "-h") {
|
|
61
|
+
console.log(`\n${HELP}\n`);
|
|
62
|
+
process.exit(0);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const cmd = command.toLowerCase();
|
|
66
|
+
|
|
67
|
+
if (cmd === "new" || cmd === "n") {
|
|
68
|
+
runNew(rest);
|
|
69
|
+
} else if (cmd === "generate" || cmd === "g") {
|
|
70
|
+
await runGenerate(rest);
|
|
71
|
+
} else if (cmd === "add") {
|
|
72
|
+
runAdd(rest);
|
|
73
|
+
} else {
|
|
74
|
+
console.error(` ✗ Unknown command: "${command}"\n`);
|
|
75
|
+
console.log(HELP);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
main();
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import {
|
|
2
|
+
addD1,
|
|
3
|
+
addR2,
|
|
4
|
+
addKv,
|
|
5
|
+
addQueue,
|
|
6
|
+
addAi,
|
|
7
|
+
addDurableObject,
|
|
8
|
+
addVectorize,
|
|
9
|
+
addBrowser,
|
|
10
|
+
addHyperdrive,
|
|
11
|
+
} from "../utils/wrangler.js";
|
|
12
|
+
|
|
13
|
+
const USAGE = `
|
|
14
|
+
Usage:
|
|
15
|
+
pnpm ajke add d1 <BINDING_NAME> <database-name>
|
|
16
|
+
pnpm ajke add r2 <BINDING_NAME> <bucket-name>
|
|
17
|
+
pnpm ajke add kv <BINDING_NAME>
|
|
18
|
+
pnpm ajke add queue <BINDING_NAME> <queue-name>
|
|
19
|
+
pnpm ajke add ai <BINDING_NAME>
|
|
20
|
+
pnpm ajke add durable-object <BINDING_NAME> <ClassName>
|
|
21
|
+
pnpm ajke add vectorize <BINDING_NAME> <index-name> [dimensions]
|
|
22
|
+
pnpm ajke add browser <BINDING_NAME>
|
|
23
|
+
pnpm ajke add hyperdrive <BINDING_NAME> <connection-string>
|
|
24
|
+
|
|
25
|
+
Examples:
|
|
26
|
+
pnpm ajke add d1 PAYMENTS_DB payments-db
|
|
27
|
+
pnpm ajke add r2 ASSETS_BUCKET my-assets
|
|
28
|
+
pnpm ajke add kv SESSION_KV
|
|
29
|
+
pnpm ajke add queue MAIL_QUEUE mailer
|
|
30
|
+
pnpm ajke add ai AI
|
|
31
|
+
pnpm ajke add durable-object CHAT_ROOM ChatRoom
|
|
32
|
+
pnpm ajke add vectorize VECTOR_IDX my-index 1536
|
|
33
|
+
pnpm ajke add browser BROWSER
|
|
34
|
+
pnpm ajke add hyperdrive HYPERDRIVE postgres://user:pass@host/db
|
|
35
|
+
`.trim();
|
|
36
|
+
|
|
37
|
+
export function runAdd(args: string[]): void {
|
|
38
|
+
const [service, ...rest] = args;
|
|
39
|
+
|
|
40
|
+
if (!service) {
|
|
41
|
+
console.error(` ✗ Missing service type.\n\n${USAGE}`);
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const svc = service.toLowerCase();
|
|
46
|
+
|
|
47
|
+
switch (svc) {
|
|
48
|
+
case "d1": {
|
|
49
|
+
const [binding, dbName] = rest;
|
|
50
|
+
if (!binding || !dbName) {
|
|
51
|
+
console.error(` ✗ Usage: pnpm ajke add d1 <BINDING_NAME> <database-name>`);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
console.log(`\n Adding D1 binding to wrangler.jsonc...\n`);
|
|
55
|
+
addD1(binding, dbName);
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
case "r2": {
|
|
60
|
+
const [binding, bucketName] = rest;
|
|
61
|
+
if (!binding || !bucketName) {
|
|
62
|
+
console.error(` ✗ Usage: pnpm ajke add r2 <BINDING_NAME> <bucket-name>`);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
console.log(`\n Adding R2 binding to wrangler.jsonc...\n`);
|
|
66
|
+
addR2(binding, bucketName);
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
case "kv": {
|
|
71
|
+
const [binding] = rest;
|
|
72
|
+
if (!binding) {
|
|
73
|
+
console.error(` ✗ Usage: pnpm ajke add kv <BINDING_NAME>`);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
console.log(`\n Adding KV namespace binding to wrangler.jsonc...\n`);
|
|
77
|
+
addKv(binding);
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
case "queue": {
|
|
82
|
+
const [binding, queueName] = rest;
|
|
83
|
+
if (!binding || !queueName) {
|
|
84
|
+
console.error(` ✗ Usage: pnpm ajke add queue <BINDING_NAME> <queue-name>`);
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
console.log(`\n Adding Queue binding to wrangler.jsonc...\n`);
|
|
88
|
+
addQueue(binding, queueName);
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
case "ai": {
|
|
93
|
+
const [binding] = rest;
|
|
94
|
+
if (!binding) {
|
|
95
|
+
console.error(` ✗ Usage: pnpm ajke add ai <BINDING_NAME>`);
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
console.log(`\n Adding AI binding to wrangler.jsonc...\n`);
|
|
99
|
+
addAi(binding);
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
case "durable-object":
|
|
104
|
+
case "do": {
|
|
105
|
+
const [binding, className] = rest;
|
|
106
|
+
if (!binding || !className) {
|
|
107
|
+
console.error(` ✗ Usage: pnpm ajke add durable-object <BINDING_NAME> <ClassName>`);
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
console.log(`\n Adding Durable Object binding to wrangler.jsonc...\n`);
|
|
111
|
+
addDurableObject(binding, className);
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
case "vectorize":
|
|
116
|
+
case "vector": {
|
|
117
|
+
const [binding, indexName, rawDimensions] = rest;
|
|
118
|
+
if (!binding || !indexName) {
|
|
119
|
+
console.error(` ✗ Usage: pnpm ajke add vectorize <BINDING_NAME> <index-name> [dimensions]`);
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
const dimensions = rawDimensions ? parseInt(rawDimensions, 10) : 1536;
|
|
123
|
+
console.log(`\n Adding Vectorize binding to wrangler.jsonc...\n`);
|
|
124
|
+
addVectorize(binding, indexName, dimensions);
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
case "browser": {
|
|
129
|
+
const [binding] = rest;
|
|
130
|
+
if (!binding) {
|
|
131
|
+
console.error(` ✗ Usage: pnpm ajke add browser <BINDING_NAME>`);
|
|
132
|
+
process.exit(1);
|
|
133
|
+
}
|
|
134
|
+
console.log(`\n Adding Browser rendering binding to wrangler.jsonc...\n`);
|
|
135
|
+
addBrowser(binding);
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
case "hyperdrive": {
|
|
140
|
+
const [binding, connectionString] = rest;
|
|
141
|
+
if (!binding || !connectionString) {
|
|
142
|
+
console.error(` ✗ Usage: pnpm ajke add hyperdrive <BINDING_NAME> <connection-string>`);
|
|
143
|
+
process.exit(1);
|
|
144
|
+
}
|
|
145
|
+
console.log(`\n Adding Hyperdrive binding to wrangler.jsonc...\n`);
|
|
146
|
+
addHyperdrive(binding, connectionString);
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
default: {
|
|
151
|
+
console.error(` ✗ Unknown service type: "${service}"\n\n${USAGE}`);
|
|
152
|
+
process.exit(1);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import {
|
|
2
|
+
generateModule,
|
|
3
|
+
generateService,
|
|
4
|
+
generateController,
|
|
5
|
+
} from "../generators/module.generator.js";
|
|
6
|
+
import { loadConfig } from "../utils/config.js";
|
|
7
|
+
|
|
8
|
+
const USAGE = `
|
|
9
|
+
Usage:
|
|
10
|
+
pnpm ajke generate module <name> [--path <dir>] [--no-test]
|
|
11
|
+
pnpm ajke generate service <name> [--path <dir>]
|
|
12
|
+
pnpm ajke generate controller <name> [--path <dir>]
|
|
13
|
+
|
|
14
|
+
Aliases:
|
|
15
|
+
g m → generate module
|
|
16
|
+
g s → generate service
|
|
17
|
+
g c → generate controller
|
|
18
|
+
|
|
19
|
+
Flags:
|
|
20
|
+
--no-test Skip generating the .test.ts file for a module
|
|
21
|
+
|
|
22
|
+
Examples:
|
|
23
|
+
pnpm ajke generate module payment
|
|
24
|
+
pnpm ajke g m payment
|
|
25
|
+
pnpm ajke generate module payment --no-test
|
|
26
|
+
pnpm ajke generate service payment --path src/modules/app/payment
|
|
27
|
+
`.trim();
|
|
28
|
+
|
|
29
|
+
function parsePath(args: string[]): { args: string[]; path?: string } {
|
|
30
|
+
const idx = args.indexOf("--path");
|
|
31
|
+
if (idx === -1) return { args };
|
|
32
|
+
const path = args[idx + 1];
|
|
33
|
+
const cleaned = args.filter((_, i) => i !== idx && i !== idx + 1);
|
|
34
|
+
return { args: cleaned, path };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function parseNoTest(args: string[]): { args: string[]; noTest: boolean } {
|
|
38
|
+
const idx = args.indexOf("--no-test");
|
|
39
|
+
if (idx === -1) return { args, noTest: false };
|
|
40
|
+
return { args: args.filter((_, i) => i !== idx), noTest: true };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function runGenerate(args: string[]): Promise<void> {
|
|
44
|
+
const { args: withoutPath, path: targetPath } = parsePath(args);
|
|
45
|
+
const { args: cleanArgs, noTest } = parseNoTest(withoutPath);
|
|
46
|
+
const [subcommand, name] = cleanArgs;
|
|
47
|
+
|
|
48
|
+
if (!subcommand || !name) {
|
|
49
|
+
console.error(` ✗ Missing arguments.\n\n${USAGE}`);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const config = await loadConfig();
|
|
54
|
+
const sub = subcommand.toLowerCase();
|
|
55
|
+
|
|
56
|
+
if (sub === "module" || sub === "m") {
|
|
57
|
+
console.log(`\n Generating module "${name}"...\n`);
|
|
58
|
+
generateModule(name, {
|
|
59
|
+
dir: targetPath,
|
|
60
|
+
modulesDir: config.modulesDir,
|
|
61
|
+
defaultFiles: config.generate.files,
|
|
62
|
+
noTest,
|
|
63
|
+
});
|
|
64
|
+
} else if (sub === "service" || sub === "s") {
|
|
65
|
+
console.log(`\n Generating service "${name}"...\n`);
|
|
66
|
+
generateService(name, targetPath, config.modulesDir);
|
|
67
|
+
} else if (sub === "controller" || sub === "c") {
|
|
68
|
+
console.log(`\n Generating controller "${name}"...\n`);
|
|
69
|
+
generateController(name, targetPath, config.modulesDir);
|
|
70
|
+
} else {
|
|
71
|
+
console.error(` ✗ Unknown generate subcommand: "${subcommand}"\n\n${USAGE}`);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
}
|