@sohan_fahad/wilt 0.1.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 (97) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +250 -0
  3. package/bin/commands/add.ts +155 -0
  4. package/bin/commands/generate.ts +74 -0
  5. package/bin/commands/new.ts +457 -0
  6. package/bin/create-wilt-app.ts +3 -0
  7. package/bin/generators/module.generator.ts +266 -0
  8. package/bin/utils/config.ts +46 -0
  9. package/bin/utils/paths.ts +32 -0
  10. package/bin/utils/wrangler.ts +216 -0
  11. package/bin/wilt.ts +79 -0
  12. package/dist/lib/bin/create-wilt-app.js +413 -0
  13. package/dist/lib/bin/create-wilt-app.js.map +1 -0
  14. package/dist/lib/bin/wilt.js +1151 -0
  15. package/dist/lib/bin/wilt.js.map +1 -0
  16. package/dist/lib/chunk-EUXUH3YW.js +15 -0
  17. package/dist/lib/chunk-EUXUH3YW.js.map +1 -0
  18. package/dist/lib/chunk-FIEODUMV.js +234 -0
  19. package/dist/lib/chunk-FIEODUMV.js.map +1 -0
  20. package/dist/lib/chunk-MOVXD653.cjs +234 -0
  21. package/dist/lib/chunk-MOVXD653.cjs.map +1 -0
  22. package/dist/lib/chunk-ZBDE64SD.cjs +15 -0
  23. package/dist/lib/chunk-ZBDE64SD.cjs.map +1 -0
  24. package/dist/lib/config.cjs +10 -0
  25. package/dist/lib/config.cjs.map +1 -0
  26. package/dist/lib/config.d.cts +13 -0
  27. package/dist/lib/config.d.ts +13 -0
  28. package/dist/lib/config.js +10 -0
  29. package/dist/lib/config.js.map +1 -0
  30. package/dist/lib/index.cjs +974 -0
  31. package/dist/lib/index.cjs.map +1 -0
  32. package/dist/lib/index.d.cts +255 -0
  33. package/dist/lib/index.d.ts +255 -0
  34. package/dist/lib/index.js +974 -0
  35. package/dist/lib/index.js.map +1 -0
  36. package/dist/lib/middleware/index.cjs +10 -0
  37. package/dist/lib/middleware/index.cjs.map +1 -0
  38. package/dist/lib/middleware/index.d.cts +18 -0
  39. package/dist/lib/middleware/index.d.ts +18 -0
  40. package/dist/lib/middleware/index.js +10 -0
  41. package/dist/lib/middleware/index.js.map +1 -0
  42. package/package.json +78 -0
  43. package/src/wilt/README.md +285 -0
  44. package/src/wilt/config.ts +14 -0
  45. package/src/wilt/context/execution-context.ts +36 -0
  46. package/src/wilt/context/index.ts +1 -0
  47. package/src/wilt/decorators/core/exception-filters.decorator.ts +24 -0
  48. package/src/wilt/decorators/core/index.ts +6 -0
  49. package/src/wilt/decorators/core/injectable.decorator.ts +41 -0
  50. package/src/wilt/decorators/core/optional.decorator.ts +9 -0
  51. package/src/wilt/decorators/core/set-metadata.decorator.ts +20 -0
  52. package/src/wilt/decorators/core/use-guards.decorator.ts +14 -0
  53. package/src/wilt/decorators/core/use-interceptors.decorator.ts +16 -0
  54. package/src/wilt/decorators/http/controller.decorator.ts +230 -0
  55. package/src/wilt/decorators/http/header.decorator.ts +11 -0
  56. package/src/wilt/decorators/http/http-code.decorator.ts +8 -0
  57. package/src/wilt/decorators/http/index.ts +6 -0
  58. package/src/wilt/decorators/http/redirect.decorator.ts +13 -0
  59. package/src/wilt/decorators/http/route-mapping.decorator.ts +22 -0
  60. package/src/wilt/decorators/http/route-params.decorator.ts +60 -0
  61. package/src/wilt/decorators/index.ts +3 -0
  62. package/src/wilt/decorators/modules/global.decorator.ts +8 -0
  63. package/src/wilt/decorators/modules/index.ts +2 -0
  64. package/src/wilt/decorators/modules/module.decorator.ts +16 -0
  65. package/src/wilt/exceptions/http-exception.ts +17 -0
  66. package/src/wilt/exceptions/http-exceptions.ts +85 -0
  67. package/src/wilt/exceptions/index.ts +2 -0
  68. package/src/wilt/index.ts +11 -0
  69. package/src/wilt/injector/index.ts +1 -0
  70. package/src/wilt/injector/injector.ts +103 -0
  71. package/src/wilt/injector/module-compiler.ts +48 -0
  72. package/src/wilt/injector/module.factory.ts +74 -0
  73. package/src/wilt/interfaces/core/filter.interface.ts +5 -0
  74. package/src/wilt/interfaces/core/guard.interface.ts +5 -0
  75. package/src/wilt/interfaces/core/index.ts +5 -0
  76. package/src/wilt/interfaces/core/interceptor.interface.ts +9 -0
  77. package/src/wilt/interfaces/core/lifecycle.interface.ts +19 -0
  78. package/src/wilt/interfaces/core/pipe.interface.ts +9 -0
  79. package/src/wilt/interfaces/http/index.ts +1 -0
  80. package/src/wilt/interfaces/http/response.interface.ts +27 -0
  81. package/src/wilt/interfaces/index.ts +3 -0
  82. package/src/wilt/interfaces/modules/index.ts +1 -0
  83. package/src/wilt/interfaces/modules/module.interface.ts +17 -0
  84. package/src/wilt/middleware/error-handler.middleware.ts +63 -0
  85. package/src/wilt/middleware/index.ts +2 -0
  86. package/src/wilt/middleware/request-logger.middleware.ts +17 -0
  87. package/src/wilt/pipes/index.ts +3 -0
  88. package/src/wilt/pipes/validate.pipe.ts +79 -0
  89. package/src/wilt/pipes/zod-query.pipe.ts +42 -0
  90. package/src/wilt/pipes/zod-validate.pipe.ts +49 -0
  91. package/src/wilt/services/index.ts +1 -0
  92. package/src/wilt/services/reflector.service.ts +24 -0
  93. package/src/wilt/utils/apply-decorators.util.ts +17 -0
  94. package/src/wilt/utils/forward-ref.util.ts +14 -0
  95. package/src/wilt/utils/index.ts +22 -0
  96. package/src/wilt/utils/logger.util.ts +189 -0
  97. package/src/wilt/utils/response.util.ts +72 -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,250 @@
1
+ # Wilt
2
+
3
+ A NestJS-like framework for **Cloudflare Workers** built on [Hono](https://hono.dev). Write modular, decorator-driven APIs that deploy to the edge — no server required.
4
+
5
+ ```bash
6
+ npx wilt new my-app
7
+ ```
8
+
9
+ ## Features
10
+
11
+ - **Module system** — `@Module`, `@Controller`, `@Injectable` decorators like NestJS
12
+ - **Dependency injection** — powered by [tsyringe](https://github.com/microsoft/tsyringe)
13
+ - **Validation** — Zod schema decorators for body, query, and params
14
+ - **Built-in middleware** — request logger, CORS, secure headers
15
+ - **CLI** — scaffold projects, modules, services, controllers, and Cloudflare service bindings
16
+
17
+ ## Requirements
18
+
19
+ - Node 20+
20
+ - [pnpm](https://pnpm.io/), npm, or bun
21
+
22
+ ## Quick Start
23
+
24
+ ```bash
25
+ npx wilt new my-app
26
+ cd my-app
27
+ pnpm db:migrate # apply local D1 migrations
28
+ pnpm dev # http://localhost:4001
29
+ ```
30
+
31
+ ```bash
32
+ curl http://localhost:4001/health
33
+ curl http://localhost:4001/hello
34
+ ```
35
+
36
+ ## CLI
37
+
38
+ ### `wilt new`
39
+
40
+ Scaffold a new Wilt project with a Hello module, D1 setup, Drizzle config, and Wrangler config.
41
+
42
+ ```bash
43
+ npx wilt new <project-name>
44
+ ```
45
+
46
+ ### `wilt generate`
47
+
48
+ Scaffold files inside an existing project.
49
+
50
+ ```bash
51
+ npx wilt generate module <name> # module + controller + service + dto
52
+ npx wilt generate service <name>
53
+ npx wilt generate controller <name>
54
+
55
+ # --path to target a specific directory
56
+ npx wilt generate service payment --path src/modules/app/payment
57
+
58
+ # Short aliases
59
+ npx wilt g m <name>
60
+ npx wilt g s <name>
61
+ npx wilt g c <name>
62
+ ```
63
+
64
+ ### `wilt add`
65
+
66
+ Add a Cloudflare service binding directly to `wrangler.jsonc`.
67
+
68
+ ```bash
69
+ npx wilt add d1 <BINDING> <database-name>
70
+ npx wilt add r2 <BINDING> <bucket-name>
71
+ npx wilt add kv <BINDING>
72
+ npx wilt add queue <BINDING> <queue-name>
73
+ npx wilt add ai <BINDING>
74
+ npx wilt add durable-object <BINDING> <ClassName>
75
+ npx wilt add vectorize <BINDING> <index-name> [dimensions]
76
+ npx wilt add browser <BINDING>
77
+ npx wilt add hyperdrive <BINDING> <connection-string>
78
+ ```
79
+
80
+ **Examples:**
81
+
82
+ ```bash
83
+ npx wilt add d1 PAYMENTS_DB payments-db
84
+ npx wilt add r2 ASSETS_BUCKET my-assets
85
+ npx wilt add kv SESSION_KV
86
+ npx wilt add queue MAIL_QUEUE mailer
87
+ npx wilt add durable-object CHAT_ROOM ChatRoom
88
+ npx wilt add vectorize VECTOR_IDX my-index 1536
89
+ ```
90
+
91
+ ## Framework API
92
+
93
+ ### Decorators
94
+
95
+ ```ts
96
+ import { Module, Controller, Injectable, Inject, Get, Post, Put, Delete } from "wilt";
97
+ ```
98
+
99
+ | Decorator | Target | Description |
100
+ | --- | --- | --- |
101
+ | `@Module({ imports, controllers, providers })` | Class | Define a module |
102
+ | `@Controller(prefix)` | Class | Register HTTP routes under a prefix |
103
+ | `@Injectable()` | Class | Mark a class for DI |
104
+ | `@Inject(token)` | Constructor param | Inject a dependency |
105
+ | `@Get(path?)` | Method | GET route |
106
+ | `@Post(path?)` | Method | POST route |
107
+ | `@Put(path?)` | Method | PUT route |
108
+ | `@Delete(path?)` | Method | DELETE route |
109
+
110
+ ### Validation
111
+
112
+ ```ts
113
+ import { ZodBody, ZodQuery } from "wilt";
114
+ import { z } from "zod";
115
+
116
+ const CreatePostDto = z.object({ title: z.string(), body: z.string() });
117
+
118
+ @Post()
119
+ @ZodBody(CreatePostDto)
120
+ async create(c: Context) { ... }
121
+ ```
122
+
123
+ ### `createModule`
124
+
125
+ Bootstrap your app from the root module.
126
+
127
+ ```ts
128
+ import { createModule } from "wilt";
129
+ import { cors } from "hono/cors";
130
+ import { requestLogger } from "wilt/middleware";
131
+ import { AppModule } from "./app.module";
132
+
133
+ const app = createModule(AppModule, {
134
+ middlewares: [cors(), requestLogger],
135
+ });
136
+
137
+ export default { fetch: app.fetch };
138
+ ```
139
+
140
+ ### `ResponseUtil`
141
+
142
+ ```ts
143
+ import { ResponseUtil } from "wilt";
144
+
145
+ return ResponseUtil.success(c, data);
146
+ return ResponseUtil.error(c, "Not found", 404);
147
+ ```
148
+
149
+ ## Example Module
150
+
151
+ ```ts
152
+ // posts/posts.module.ts
153
+ import { Module } from "wilt";
154
+ import { PostsController } from "./posts.controller";
155
+ import { PostsService } from "./posts.service";
156
+
157
+ @Module({
158
+ controllers: [PostsController],
159
+ providers: [PostsService],
160
+ })
161
+ export class PostsModule {}
162
+ ```
163
+
164
+ ```ts
165
+ // posts/posts.controller.ts
166
+ import type { Context } from "hono";
167
+ import { Controller, Get, Post, Inject } from "wilt";
168
+ import { ResponseUtil } from "wilt";
169
+ import { ZodBody } from "wilt";
170
+ import { PostsService } from "./posts.service";
171
+ import { CreatePostDto } from "./posts.dto";
172
+
173
+ @Controller("/posts")
174
+ export class PostsController {
175
+ constructor(@Inject(PostsService) private postsService: PostsService) {}
176
+
177
+ @Get()
178
+ async list(c: Context) {
179
+ const posts = await this.postsService.findAll();
180
+ return ResponseUtil.success(c, posts);
181
+ }
182
+
183
+ @Post()
184
+ @ZodBody(CreatePostDto)
185
+ async create(c: Context) {
186
+ const body = await c.req.json();
187
+ const post = await this.postsService.create(body);
188
+ return ResponseUtil.success(c, post, 201);
189
+ }
190
+ }
191
+ ```
192
+
193
+ ```ts
194
+ // posts/posts.service.ts
195
+ import { Injectable } from "wilt";
196
+
197
+ @Injectable()
198
+ export class PostsService {
199
+ async findAll() { ... }
200
+ async create(data: unknown) { ... }
201
+ }
202
+ ```
203
+
204
+ ## Project Structure (generated)
205
+
206
+ ```
207
+ my-app/
208
+ ├── src/
209
+ │ ├── index.ts # Worker entry
210
+ │ ├── app.module.ts # Root module
211
+ │ ├── database/
212
+ │ │ └── connection.ts # Drizzle + D1
213
+ │ └── modules/
214
+ │ └── hello/ # Starter module
215
+ ├── migrations/ # D1 SQL migrations
216
+ ├── worker-configuration.d.ts # Cloudflare binding types (includes TEST_MIGRATIONS for tests)
217
+ ├── wrangler.jsonc # Cloudflare Worker config
218
+ ├── tsconfig.json
219
+ ├── vite.config.ts
220
+ └── .dev.vars.example # Local secrets template (only needed for auth features)
221
+ ```
222
+
223
+ ## Peer Dependencies
224
+
225
+ Installed automatically in generated projects:
226
+
227
+ ```json
228
+ {
229
+ "hono": ">=4",
230
+ "reflect-metadata": ">=0.2",
231
+ "tsyringe": ">=4",
232
+ "zod": ">=3"
233
+ }
234
+ ```
235
+
236
+ ## Deploy
237
+
238
+ ```bash
239
+ pnpm deploy
240
+ ```
241
+
242
+ Set your Cloudflare secrets before deploying to production:
243
+
244
+ ```bash
245
+ wrangler secret put JWT_SECRET
246
+ ```
247
+
248
+ ## License
249
+
250
+ MIT
@@ -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 wilt add d1 <BINDING_NAME> <database-name>
16
+ pnpm wilt add r2 <BINDING_NAME> <bucket-name>
17
+ pnpm wilt add kv <BINDING_NAME>
18
+ pnpm wilt add queue <BINDING_NAME> <queue-name>
19
+ pnpm wilt add ai <BINDING_NAME>
20
+ pnpm wilt add durable-object <BINDING_NAME> <ClassName>
21
+ pnpm wilt add vectorize <BINDING_NAME> <index-name> [dimensions]
22
+ pnpm wilt add browser <BINDING_NAME>
23
+ pnpm wilt add hyperdrive <BINDING_NAME> <connection-string>
24
+
25
+ Examples:
26
+ pnpm wilt add d1 PAYMENTS_DB payments-db
27
+ pnpm wilt add r2 ASSETS_BUCKET my-assets
28
+ pnpm wilt add kv SESSION_KV
29
+ pnpm wilt add queue MAIL_QUEUE mailer
30
+ pnpm wilt add ai AI
31
+ pnpm wilt add durable-object CHAT_ROOM ChatRoom
32
+ pnpm wilt add vectorize VECTOR_IDX my-index 1536
33
+ pnpm wilt add browser BROWSER
34
+ pnpm wilt 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 wilt 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 wilt 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 wilt 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 wilt 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 wilt 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 wilt 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 wilt 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 wilt 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 wilt 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 wilt generate module <name> [--path <dir>] [--no-test]
11
+ pnpm wilt generate service <name> [--path <dir>]
12
+ pnpm wilt 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 wilt generate module payment
24
+ pnpm wilt g m payment
25
+ pnpm wilt generate module payment --no-test
26
+ pnpm wilt 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
+ }