@hazeljs/cli 0.5.4 → 0.6.5
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/@template-ai-native/package.json +1 -1
- package/README.md +140 -588
- package/cli-manifest.json +940 -0
- package/dist/commands/add.d.ts +9 -0
- package/dist/commands/add.js +35 -126
- package/dist/commands/generate-app.js +17 -230
- package/dist/commands/generate-auth.d.ts +12 -0
- package/dist/commands/generate-auth.js +12 -0
- package/dist/commands/generate-crud.d.ts +12 -0
- package/dist/commands/generate-crud.js +12 -0
- package/dist/commands/generate-dto.d.ts +12 -0
- package/dist/commands/generate-dto.js +12 -0
- package/dist/commands/generate-module.d.ts +12 -0
- package/dist/commands/generate-module.js +12 -0
- package/dist/commands/generate-simple.d.ts +74 -0
- package/dist/commands/generate-simple.js +104 -0
- package/dist/commands/generate-simple.test.js +100 -0
- package/dist/commands/info.d.ts +12 -0
- package/dist/commands/info.js +12 -0
- package/dist/commands/templates.d.ts +34 -0
- package/dist/commands/templates.js +387 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.js +50 -48
- package/dist/index.list.test.js +8 -22
- package/dist/index.test.js +19 -56
- package/dist/utils/generator-registry.d.ts +5 -0
- package/dist/utils/generator-registry.js +34 -65
- package/dist/utils/generator.d.ts +0 -1
- package/dist/utils/generator.js +0 -22
- package/dist/utils/generator.test.js +0 -28
- package/dist/utils/packages-registry.d.ts +34 -0
- package/dist/utils/packages-registry.js +380 -0
- package/package.json +7 -7
- package/dist/commands/build.d.ts +0 -2
- package/dist/commands/build.js +0 -52
- package/dist/commands/generate-agent.d.ts +0 -4
- package/dist/commands/generate-agent.js +0 -64
- package/dist/commands/generate-agent.test.js +0 -36
- package/dist/commands/generate-ai-service.d.ts +0 -4
- package/dist/commands/generate-ai-service.js +0 -54
- package/dist/commands/generate-ai-service.test.d.ts +0 -1
- package/dist/commands/generate-ai-service.test.js +0 -41
- package/dist/commands/generate-cache.d.ts +0 -4
- package/dist/commands/generate-cache.js +0 -66
- package/dist/commands/generate-cache.test.d.ts +0 -1
- package/dist/commands/generate-cache.test.js +0 -36
- package/dist/commands/generate-config.d.ts +0 -4
- package/dist/commands/generate-config.js +0 -59
- package/dist/commands/generate-config.test.d.ts +0 -1
- package/dist/commands/generate-config.test.js +0 -35
- package/dist/commands/generate-controller.d.ts +0 -4
- package/dist/commands/generate-controller.js +0 -66
- package/dist/commands/generate-controller.test.d.ts +0 -1
- package/dist/commands/generate-controller.test.js +0 -48
- package/dist/commands/generate-cron.d.ts +0 -4
- package/dist/commands/generate-cron.js +0 -61
- package/dist/commands/generate-cron.test.d.ts +0 -1
- package/dist/commands/generate-cron.test.js +0 -42
- package/dist/commands/generate-discovery.d.ts +0 -4
- package/dist/commands/generate-discovery.js +0 -63
- package/dist/commands/generate-discovery.test.d.ts +0 -1
- package/dist/commands/generate-discovery.test.js +0 -36
- package/dist/commands/generate-exception-filter.d.ts +0 -4
- package/dist/commands/generate-exception-filter.js +0 -54
- package/dist/commands/generate-exception-filter.test.d.ts +0 -1
- package/dist/commands/generate-exception-filter.test.js +0 -43
- package/dist/commands/generate-guard.d.ts +0 -4
- package/dist/commands/generate-guard.js +0 -42
- package/dist/commands/generate-guard.test.d.ts +0 -1
- package/dist/commands/generate-guard.test.js +0 -41
- package/dist/commands/generate-interceptor.d.ts +0 -4
- package/dist/commands/generate-interceptor.js +0 -43
- package/dist/commands/generate-interceptor.test.d.ts +0 -1
- package/dist/commands/generate-interceptor.test.js +0 -41
- package/dist/commands/generate-middleware.d.ts +0 -4
- package/dist/commands/generate-middleware.js +0 -47
- package/dist/commands/generate-middleware.test.d.ts +0 -1
- package/dist/commands/generate-middleware.test.js +0 -41
- package/dist/commands/generate-pipe.d.ts +0 -4
- package/dist/commands/generate-pipe.js +0 -39
- package/dist/commands/generate-pipe.test.d.ts +0 -1
- package/dist/commands/generate-pipe.test.js +0 -35
- package/dist/commands/generate-rag.d.ts +0 -4
- package/dist/commands/generate-rag.js +0 -68
- package/dist/commands/generate-rag.test.d.ts +0 -1
- package/dist/commands/generate-rag.test.js +0 -35
- package/dist/commands/generate-repository.d.ts +0 -4
- package/dist/commands/generate-repository.js +0 -46
- package/dist/commands/generate-repository.test.d.ts +0 -1
- package/dist/commands/generate-repository.test.js +0 -41
- package/dist/commands/generate-serverless-handler.d.ts +0 -4
- package/dist/commands/generate-serverless-handler.js +0 -57
- package/dist/commands/generate-serverless-handler.test.d.ts +0 -1
- package/dist/commands/generate-serverless-handler.test.js +0 -42
- package/dist/commands/generate-service.d.ts +0 -4
- package/dist/commands/generate-service.js +0 -58
- package/dist/commands/generate-service.test.d.ts +0 -1
- package/dist/commands/generate-service.test.js +0 -41
- package/dist/commands/generate-setup.d.ts +0 -4
- package/dist/commands/generate-setup.js +0 -187
- package/dist/commands/generate-setup.test.d.ts +0 -1
- package/dist/commands/generate-setup.test.js +0 -50
- package/dist/commands/generate-websocket-gateway.d.ts +0 -4
- package/dist/commands/generate-websocket-gateway.js +0 -53
- package/dist/commands/generate-websocket-gateway.test.d.ts +0 -1
- package/dist/commands/generate-websocket-gateway.test.js +0 -41
- package/dist/commands/pdf-to-audio.d.ts +0 -2
- package/dist/commands/pdf-to-audio.js +0 -170
- package/dist/commands/pdf-to-audio.test.d.ts +0 -1
- package/dist/commands/pdf-to-audio.test.js +0 -92
- package/dist/commands/start.d.ts +0 -2
- package/dist/commands/start.js +0 -61
- package/dist/commands/test.d.ts +0 -2
- package/dist/commands/test.js +0 -63
- package/dist/commands/utility-commands.test.d.ts +0 -1
- package/dist/commands/utility-commands.test.js +0 -95
- /package/dist/commands/{generate-agent.test.d.ts → generate-simple.test.d.ts} +0 -0
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Mustache templates for all simple (single-file) generators.
|
|
4
|
+
*
|
|
5
|
+
* Each template uses three standard variables provided by the Generator base class:
|
|
6
|
+
* - {{className}} — PascalCase name (e.g. "Users")
|
|
7
|
+
* - {{fileName}} — kebab-case name (e.g. "users")
|
|
8
|
+
* - {{camelName}} — camelCase name (e.g. "users")
|
|
9
|
+
*
|
|
10
|
+
* Some templates accept additional data via `extraData` in SimpleGeneratorConfig:
|
|
11
|
+
* - AGENT_TEMPLATE — {{description}}
|
|
12
|
+
* - REPOSITORY_TEMPLATE — {{modelName}} (defaults to fileName)
|
|
13
|
+
*
|
|
14
|
+
* Templates are imported by generate-simple.ts and referenced in the
|
|
15
|
+
* SIMPLE_GENERATORS config array. To add a new generator, create a template
|
|
16
|
+
* here and add a config entry in generate-simple.ts.
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.SERVERLESS_CLOUD_FUNCTION_TEMPLATE = exports.SERVERLESS_LAMBDA_TEMPLATE = exports.CONFIG_TEMPLATE = exports.DISCOVERY_TEMPLATE = exports.RAG_SERVICE_TEMPLATE = exports.CRON_SERVICE_TEMPLATE = exports.CACHE_SERVICE_TEMPLATE = exports.AGENT_TEMPLATE = exports.AI_SERVICE_TEMPLATE = exports.WEBSOCKET_GATEWAY_TEMPLATE = exports.REPOSITORY_TEMPLATE = exports.EXCEPTION_FILTER_TEMPLATE = exports.PIPE_TEMPLATE = exports.MIDDLEWARE_TEMPLATE = exports.INTERCEPTOR_TEMPLATE = exports.GUARD_TEMPLATE = exports.SERVICE_TEMPLATE = exports.CONTROLLER_TEMPLATE = void 0;
|
|
20
|
+
// ── Core framework generators ────────────────────────────────────────────────
|
|
21
|
+
exports.CONTROLLER_TEMPLATE = `import { Controller, Get, Post, Body, Param, Delete, Put } from '@hazeljs/core';
|
|
22
|
+
import { {{className}}Service } from './{{fileName}}.service';
|
|
23
|
+
import { Create{{className}}Dto } from './dto/create-{{fileName}}.dto';
|
|
24
|
+
import { Update{{className}}Dto } from './dto/update-{{fileName}}.dto';
|
|
25
|
+
|
|
26
|
+
@Controller('{{fileName}}')
|
|
27
|
+
export class {{className}}Controller {
|
|
28
|
+
constructor(private readonly {{camelName}}Service: {{className}}Service) {}
|
|
29
|
+
|
|
30
|
+
@Get()
|
|
31
|
+
findAll() {
|
|
32
|
+
return this.{{camelName}}Service.findAll();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@Get(':id')
|
|
36
|
+
findOne(@Param('id') id: string) {
|
|
37
|
+
return this.{{camelName}}Service.findOne(id);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@Post()
|
|
41
|
+
create(@Body(Create{{className}}Dto) createDto: Create{{className}}Dto) {
|
|
42
|
+
return this.{{camelName}}Service.create(createDto);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@Put(':id')
|
|
46
|
+
update(@Param('id') id: string, @Body(Update{{className}}Dto) updateDto: Update{{className}}Dto) {
|
|
47
|
+
return this.{{camelName}}Service.update(id, updateDto);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@Delete(':id')
|
|
51
|
+
remove(@Param('id') id: string) {
|
|
52
|
+
return this.{{camelName}}Service.remove(id);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
`;
|
|
56
|
+
exports.SERVICE_TEMPLATE = `import { Service } from '@hazeljs/core';
|
|
57
|
+
|
|
58
|
+
@Service()
|
|
59
|
+
export class {{className}}Service {
|
|
60
|
+
constructor() {}
|
|
61
|
+
|
|
62
|
+
async findAll() {
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async findOne(id: string) {
|
|
67
|
+
return { id };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async create(createDto: any) {
|
|
71
|
+
return createDto;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async update(id: string, updateDto: any) {
|
|
75
|
+
return { id, ...updateDto };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async remove(id: string) {
|
|
79
|
+
return { id };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
`;
|
|
83
|
+
exports.GUARD_TEMPLATE = `import { Injectable, type CanActivate, type ExecutionContext } from '@hazeljs/core';
|
|
84
|
+
|
|
85
|
+
@Injectable()
|
|
86
|
+
export class {{className}}Guard implements CanActivate {
|
|
87
|
+
canActivate(context: ExecutionContext): boolean {
|
|
88
|
+
const request = context.switchToHttp().getRequest();
|
|
89
|
+
// Add your guard logic here
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
`;
|
|
94
|
+
exports.INTERCEPTOR_TEMPLATE = `import { Injectable, Interceptor, type ExecutionContext } from '@hazeljs/core';
|
|
95
|
+
|
|
96
|
+
@Injectable()
|
|
97
|
+
export class {{className}}Interceptor implements Interceptor {
|
|
98
|
+
async intercept(context: ExecutionContext, next: () => Promise<unknown>): Promise<unknown> {
|
|
99
|
+
// Pre-processing logic here (before handler execution)
|
|
100
|
+
const result = await next();
|
|
101
|
+
// Post-processing logic here (after handler execution)
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
`;
|
|
106
|
+
exports.MIDDLEWARE_TEMPLATE = `import { Injectable, type MiddlewareHandler, type Request, type Response, type NextFunction } from '@hazeljs/core';
|
|
107
|
+
|
|
108
|
+
@Injectable()
|
|
109
|
+
export class {{className}}Middleware implements MiddlewareHandler {
|
|
110
|
+
use(req: Request, res: Response, next: NextFunction) {
|
|
111
|
+
// Add your middleware logic here
|
|
112
|
+
console.log(\`[{{className}}Middleware] \${req.method} \${req.url}\`);
|
|
113
|
+
|
|
114
|
+
// Continue to next middleware
|
|
115
|
+
next();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
`;
|
|
119
|
+
exports.PIPE_TEMPLATE = `import { type PipeTransform, type RequestContext } from '@hazeljs/core';
|
|
120
|
+
|
|
121
|
+
export class {{className}}Pipe implements PipeTransform {
|
|
122
|
+
transform(value: unknown, context: RequestContext): unknown {
|
|
123
|
+
// Transform logic here
|
|
124
|
+
return value;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
`;
|
|
128
|
+
exports.EXCEPTION_FILTER_TEMPLATE = `import { Catch, type ExceptionFilter, type ArgumentsHost, HttpError, logger } from '@hazeljs/core';
|
|
129
|
+
|
|
130
|
+
@Catch(HttpError)
|
|
131
|
+
export class {{className}}ExceptionFilter implements ExceptionFilter<HttpError> {
|
|
132
|
+
catch(exception: HttpError, host: ArgumentsHost): void {
|
|
133
|
+
const ctx = host.switchToHttp();
|
|
134
|
+
const response = ctx.getResponse();
|
|
135
|
+
const request = ctx.getRequest();
|
|
136
|
+
|
|
137
|
+
const status = exception.statusCode || 500;
|
|
138
|
+
const message = exception.message || 'Internal server error';
|
|
139
|
+
|
|
140
|
+
logger.error(\`[\${request.method}] \${request.url} - \${message} (\${status})\`);
|
|
141
|
+
|
|
142
|
+
response.status(status).json({
|
|
143
|
+
statusCode: status,
|
|
144
|
+
message,
|
|
145
|
+
timestamp: new Date().toISOString(),
|
|
146
|
+
path: request.url,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
`;
|
|
151
|
+
// ── Package-specific generators ──────────────────────────────────────────────
|
|
152
|
+
exports.REPOSITORY_TEMPLATE = `import { Repository, BaseRepository, PrismaService } from '@hazeljs/prisma';
|
|
153
|
+
|
|
154
|
+
// @Repository implies @Injectable() — no need for both decorators
|
|
155
|
+
@Repository({ model: '{{modelName}}' })
|
|
156
|
+
export class {{className}}Repository extends BaseRepository<any> {
|
|
157
|
+
constructor(prisma: PrismaService) {
|
|
158
|
+
super(prisma, '{{modelName}}');
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Add custom repository methods here
|
|
162
|
+
async findByName(name: string) {
|
|
163
|
+
return this.findMany({ where: { name } });
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
`;
|
|
167
|
+
exports.WEBSOCKET_GATEWAY_TEMPLATE = `import { Realtime, OnConnect, OnDisconnect, OnMessage, Subscribe, Client, Data, WebSocketClient } from '@hazeljs/websocket';
|
|
168
|
+
|
|
169
|
+
@Realtime('/{{fileName}}')
|
|
170
|
+
export class {{className}}Gateway {
|
|
171
|
+
@OnConnect()
|
|
172
|
+
handleConnection(@Client() client: WebSocketClient) {
|
|
173
|
+
console.log('Client connected:', client.id);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
@OnDisconnect()
|
|
177
|
+
handleDisconnect(@Client() client: WebSocketClient) {
|
|
178
|
+
console.log('Client disconnected:', client.id);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
@Subscribe('message')
|
|
182
|
+
@OnMessage('message')
|
|
183
|
+
handleMessage(@Client() client: WebSocketClient, @Data() data: unknown) {
|
|
184
|
+
console.log('Message received from', client.id, ':', data);
|
|
185
|
+
// Handle message logic here
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
`;
|
|
189
|
+
exports.AI_SERVICE_TEMPLATE = `import { Service } from '@hazeljs/core';
|
|
190
|
+
import { AIService, AIFunction, AIPrompt } from '@hazeljs/ai';
|
|
191
|
+
|
|
192
|
+
@Service()
|
|
193
|
+
export class {{className}}AIService {
|
|
194
|
+
constructor(private readonly aiService: AIService) {}
|
|
195
|
+
|
|
196
|
+
@AIFunction({
|
|
197
|
+
provider: 'openai',
|
|
198
|
+
model: 'gpt-4',
|
|
199
|
+
streaming: false,
|
|
200
|
+
})
|
|
201
|
+
async {{camelName}}Task(@AIPrompt() prompt: string): Promise<unknown> {
|
|
202
|
+
const result = await this.aiService.complete({
|
|
203
|
+
provider: 'openai',
|
|
204
|
+
model: 'gpt-4',
|
|
205
|
+
messages: [{ role: 'user', content: prompt }],
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
return result;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
`;
|
|
212
|
+
exports.AGENT_TEMPLATE = `import { Agent, Tool } from '@hazeljs/agent';
|
|
213
|
+
|
|
214
|
+
@Agent({
|
|
215
|
+
name: '{{fileName}}',
|
|
216
|
+
description: '{{description}}',
|
|
217
|
+
systemPrompt: 'You are a helpful {{className}} agent.',
|
|
218
|
+
enableMemory: true,
|
|
219
|
+
enableRAG: true,
|
|
220
|
+
})
|
|
221
|
+
export class {{className}}Agent {
|
|
222
|
+
@Tool({
|
|
223
|
+
description: 'Example tool for {{fileName}}',
|
|
224
|
+
parameters: [
|
|
225
|
+
{
|
|
226
|
+
name: 'input',
|
|
227
|
+
type: 'string',
|
|
228
|
+
description: 'Input parameter',
|
|
229
|
+
required: true,
|
|
230
|
+
},
|
|
231
|
+
],
|
|
232
|
+
})
|
|
233
|
+
async exampleTool(input: { input: string }): Promise<{ result: string }> {
|
|
234
|
+
// Implement your tool logic here
|
|
235
|
+
return {
|
|
236
|
+
result: \`Processed: \${input.input}\`,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
`;
|
|
241
|
+
exports.CACHE_SERVICE_TEMPLATE = `import { Service } from '@hazeljs/core';
|
|
242
|
+
import { CacheService, Cacheable, CacheEvict } from '@hazeljs/cache';
|
|
243
|
+
|
|
244
|
+
@Service()
|
|
245
|
+
export class {{className}}CacheService {
|
|
246
|
+
constructor(private readonly cacheService: CacheService) {}
|
|
247
|
+
|
|
248
|
+
@Cacheable({ key: '{{fileName}}:all', ttl: 60 })
|
|
249
|
+
async findAll() {
|
|
250
|
+
// This result will be cached for 60 seconds
|
|
251
|
+
return [];
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
@Cacheable({ key: '{{fileName}}:{{=<% %>=}}#{id}<%={{ }}=%>', ttl: 300 })
|
|
255
|
+
async findOne(id: string) {
|
|
256
|
+
// This result will be cached for 5 minutes
|
|
257
|
+
return { id };
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
@CacheEvict({ key: '{{fileName}}:all' })
|
|
261
|
+
async create(data: any) {
|
|
262
|
+
// Creating a new item evicts the list cache
|
|
263
|
+
return data;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
async clearAll() {
|
|
267
|
+
await this.cacheService.clear();
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
`;
|
|
271
|
+
exports.CRON_SERVICE_TEMPLATE = `import { Service } from '@hazeljs/core';
|
|
272
|
+
import { Cron, CronExpression } from '@hazeljs/cron';
|
|
273
|
+
|
|
274
|
+
@Service()
|
|
275
|
+
export class {{className}}CronService {
|
|
276
|
+
@Cron(CronExpression.EVERY_MINUTE)
|
|
277
|
+
handleEveryMinute() {
|
|
278
|
+
console.log('[{{className}}Cron] Running every minute...');
|
|
279
|
+
// Add your cron job logic here
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
@Cron('0 0 * * *') // Every day at midnight
|
|
283
|
+
handleDaily() {
|
|
284
|
+
console.log('[{{className}}Cron] Running daily task...');
|
|
285
|
+
// Add your daily task logic here
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
@Cron(CronExpression.EVERY_HOUR)
|
|
289
|
+
handleHourly() {
|
|
290
|
+
console.log('[{{className}}Cron] Running hourly cleanup...');
|
|
291
|
+
// Add your hourly task logic here
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
`;
|
|
295
|
+
exports.RAG_SERVICE_TEMPLATE = `import { Service } from '@hazeljs/core';
|
|
296
|
+
import { RAGPipeline, MemoryVectorStore } from '@hazeljs/rag';
|
|
297
|
+
|
|
298
|
+
@Service()
|
|
299
|
+
export class {{className}}RagService {
|
|
300
|
+
private pipeline: RAGPipeline;
|
|
301
|
+
|
|
302
|
+
constructor() {
|
|
303
|
+
// Initialize with a memory vector store (swap for Pinecone, Qdrant, etc. in production)
|
|
304
|
+
const vectorStore = new MemoryVectorStore();
|
|
305
|
+
|
|
306
|
+
this.pipeline = new RAGPipeline({
|
|
307
|
+
vectorStore,
|
|
308
|
+
topK: 5,
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
async addDocument(content: string, metadata?: Record<string, unknown>) {
|
|
313
|
+
// Add a document to the vector store for retrieval
|
|
314
|
+
await this.pipeline.addDocument({
|
|
315
|
+
content,
|
|
316
|
+
metadata: metadata || {},
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
async query(question: string) {
|
|
321
|
+
// Retrieve relevant documents and generate a response
|
|
322
|
+
const results = await this.pipeline.query(question);
|
|
323
|
+
return results;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
`;
|
|
327
|
+
exports.DISCOVERY_TEMPLATE = `import { Service } from '@hazeljs/core';
|
|
328
|
+
import { ServiceRegistry, DiscoveryClient } from '@hazeljs/discovery';
|
|
329
|
+
|
|
330
|
+
@Service()
|
|
331
|
+
export class {{className}}DiscoveryService {
|
|
332
|
+
constructor(
|
|
333
|
+
private readonly registry: ServiceRegistry,
|
|
334
|
+
private readonly client: DiscoveryClient,
|
|
335
|
+
) {}
|
|
336
|
+
|
|
337
|
+
async registerService() {
|
|
338
|
+
await this.registry.register({
|
|
339
|
+
name: '{{fileName}}-service',
|
|
340
|
+
host: 'localhost',
|
|
341
|
+
port: 3000,
|
|
342
|
+
metadata: {
|
|
343
|
+
version: '1.0.0',
|
|
344
|
+
},
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
async discoverService(serviceName: string) {
|
|
349
|
+
const instances = await this.client.getInstances(serviceName);
|
|
350
|
+
return instances;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
`;
|
|
354
|
+
exports.CONFIG_TEMPLATE = `import { HazelModule } from '@hazeljs/core';
|
|
355
|
+
import { ConfigModule, ConfigService } from '@hazeljs/config';
|
|
356
|
+
|
|
357
|
+
// Import ConfigModule.forRoot() in your app module:
|
|
358
|
+
//
|
|
359
|
+
// @HazelModule({
|
|
360
|
+
// imports: [
|
|
361
|
+
// ConfigModule.forRoot({
|
|
362
|
+
// envFilePath: '.env',
|
|
363
|
+
// }),
|
|
364
|
+
// ],
|
|
365
|
+
// })
|
|
366
|
+
//
|
|
367
|
+
// Then inject ConfigService wherever you need it:
|
|
368
|
+
//
|
|
369
|
+
// constructor(private readonly config: ConfigService) {}
|
|
370
|
+
//
|
|
371
|
+
// Usage:
|
|
372
|
+
// this.config.get('DATABASE_URL');
|
|
373
|
+
// this.config.get('PORT', '3000'); // with default value
|
|
374
|
+
|
|
375
|
+
export { ConfigModule, ConfigService };
|
|
376
|
+
`;
|
|
377
|
+
// ── Serverless generators ────────────────────────────────────────────────────
|
|
378
|
+
exports.SERVERLESS_LAMBDA_TEMPLATE = `import { createLambdaHandler } from '@hazeljs/serverless';
|
|
379
|
+
import { AppModule } from './app.module';
|
|
380
|
+
|
|
381
|
+
export const handler = createLambdaHandler(AppModule);
|
|
382
|
+
`;
|
|
383
|
+
exports.SERVERLESS_CLOUD_FUNCTION_TEMPLATE = `import { createCloudFunctionHandler } from '@hazeljs/serverless';
|
|
384
|
+
import { AppModule } from './app.module';
|
|
385
|
+
|
|
386
|
+
export const handler = createCloudFunctionHandler(AppModule);
|
|
387
|
+
`;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,42 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* HazelJS CLI — Entry point and command registration
|
|
4
|
+
*
|
|
5
|
+
* Architecture Overview:
|
|
6
|
+
* =====================
|
|
7
|
+
*
|
|
8
|
+
* index.ts — Entry point, registers all commands with Commander
|
|
9
|
+
* ├─ commands/
|
|
10
|
+
* │ ├─ generate-app.ts — `hazel new` (full scaffolding) and `hazel g app` (skeleton)
|
|
11
|
+
* │ ├─ add.ts — `hazel add [pkg]` with --setup flag (replaces generate-setup)
|
|
12
|
+
* │ ├─ info.ts — `hazel info` (project diagnostics)
|
|
13
|
+
* │ ├─ generate-simple.ts — Config-driven single-file generators (18 types)
|
|
14
|
+
* │ ├─ generate-module.ts — Multi-file module generator
|
|
15
|
+
* │ ├─ generate-dto.ts — DTO pair generator
|
|
16
|
+
* │ ├─ generate-crud.ts — Full CRUD resource generator
|
|
17
|
+
* │ ├─ generate-auth.ts — Auth module with JWT guard
|
|
18
|
+
* │ └─ templates.ts — Mustache templates for all simple generators
|
|
19
|
+
* └─ utils/
|
|
20
|
+
* ├─ generator.ts — Base Generator class, shared types, string utils
|
|
21
|
+
* ├─ generator-registry.ts — Unified registry + runGenerator dispatcher
|
|
22
|
+
* └─ packages-registry.ts — All HazelJS package metadata (single source of truth)
|
|
23
|
+
*
|
|
24
|
+
* Command Structure:
|
|
25
|
+
* =================
|
|
26
|
+
*
|
|
27
|
+
* hazel new <app> — Full interactive scaffolding (packages, git, install)
|
|
28
|
+
* hazel g app <name> — Minimal skeleton app (no install/git)
|
|
29
|
+
* hazel g <type> <name> — Unified generator for 23+ types (see --list)
|
|
30
|
+
* hazel add <pkg> [--setup] — Install HazelJS packages + optional setup file
|
|
31
|
+
* hazel info — Project diagnostics
|
|
32
|
+
*
|
|
33
|
+
* Design Principles:
|
|
34
|
+
* ===================
|
|
35
|
+
*
|
|
36
|
+
* 1. Config-driven generators: SIMPLE_GENERATORS array defines 18+ single-file generators
|
|
37
|
+
* 2. Centralized package registry: HAZEL_PACKAGES drives `hazel add` and `hazel new -i`
|
|
38
|
+
* 3. Machine-readable output: --json and --list --list-json for LLM tool-use
|
|
39
|
+
* 4. Consistent CLI options: --path, --dry-run, --json available everywhere
|
|
40
|
+
* 5. Separation of concerns: Templates live separately from logic; registry is data-driven
|
|
41
|
+
*/
|
|
2
42
|
export {};
|
package/dist/index.js
CHANGED
|
@@ -1,51 +1,70 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* HazelJS CLI — Entry point and command registration
|
|
5
|
+
*
|
|
6
|
+
* Architecture Overview:
|
|
7
|
+
* =====================
|
|
8
|
+
*
|
|
9
|
+
* index.ts — Entry point, registers all commands with Commander
|
|
10
|
+
* ├─ commands/
|
|
11
|
+
* │ ├─ generate-app.ts — `hazel new` (full scaffolding) and `hazel g app` (skeleton)
|
|
12
|
+
* │ ├─ add.ts — `hazel add [pkg]` with --setup flag (replaces generate-setup)
|
|
13
|
+
* │ ├─ info.ts — `hazel info` (project diagnostics)
|
|
14
|
+
* │ ├─ generate-simple.ts — Config-driven single-file generators (18 types)
|
|
15
|
+
* │ ├─ generate-module.ts — Multi-file module generator
|
|
16
|
+
* │ ├─ generate-dto.ts — DTO pair generator
|
|
17
|
+
* │ ├─ generate-crud.ts — Full CRUD resource generator
|
|
18
|
+
* │ ├─ generate-auth.ts — Auth module with JWT guard
|
|
19
|
+
* │ └─ templates.ts — Mustache templates for all simple generators
|
|
20
|
+
* └─ utils/
|
|
21
|
+
* ├─ generator.ts — Base Generator class, shared types, string utils
|
|
22
|
+
* ├─ generator-registry.ts — Unified registry + runGenerator dispatcher
|
|
23
|
+
* └─ packages-registry.ts — All HazelJS package metadata (single source of truth)
|
|
24
|
+
*
|
|
25
|
+
* Command Structure:
|
|
26
|
+
* =================
|
|
27
|
+
*
|
|
28
|
+
* hazel new <app> — Full interactive scaffolding (packages, git, install)
|
|
29
|
+
* hazel g app <name> — Minimal skeleton app (no install/git)
|
|
30
|
+
* hazel g <type> <name> — Unified generator for 23+ types (see --list)
|
|
31
|
+
* hazel add <pkg> [--setup] — Install HazelJS packages + optional setup file
|
|
32
|
+
* hazel info — Project diagnostics
|
|
33
|
+
*
|
|
34
|
+
* Design Principles:
|
|
35
|
+
* ===================
|
|
36
|
+
*
|
|
37
|
+
* 1. Config-driven generators: SIMPLE_GENERATORS array defines 18+ single-file generators
|
|
38
|
+
* 2. Centralized package registry: HAZEL_PACKAGES drives `hazel add` and `hazel new -i`
|
|
39
|
+
* 3. Machine-readable output: --json and --list --list-json for LLM tool-use
|
|
40
|
+
* 4. Consistent CLI options: --path, --dry-run, --json available everywhere
|
|
41
|
+
* 5. Separation of concerns: Templates live separately from logic; registry is data-driven
|
|
42
|
+
*/
|
|
3
43
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
44
|
const commander_1 = require("commander");
|
|
5
|
-
const
|
|
45
|
+
const fs_1 = require("fs");
|
|
46
|
+
const path_1 = require("path");
|
|
6
47
|
const generate_app_1 = require("./commands/generate-app");
|
|
7
|
-
const
|
|
8
|
-
const generate_service_1 = require("./commands/generate-service");
|
|
48
|
+
const generate_module_1 = require("./commands/generate-module");
|
|
9
49
|
const generate_dto_1 = require("./commands/generate-dto");
|
|
10
|
-
const generate_guard_1 = require("./commands/generate-guard");
|
|
11
|
-
const generate_interceptor_1 = require("./commands/generate-interceptor");
|
|
12
|
-
const generate_websocket_gateway_1 = require("./commands/generate-websocket-gateway");
|
|
13
|
-
const generate_exception_filter_1 = require("./commands/generate-exception-filter");
|
|
14
|
-
const generate_pipe_1 = require("./commands/generate-pipe");
|
|
15
|
-
const generate_repository_1 = require("./commands/generate-repository");
|
|
16
|
-
const generate_ai_service_1 = require("./commands/generate-ai-service");
|
|
17
|
-
const generate_agent_1 = require("./commands/generate-agent");
|
|
18
|
-
const generate_serverless_handler_1 = require("./commands/generate-serverless-handler");
|
|
19
50
|
const generate_crud_1 = require("./commands/generate-crud");
|
|
20
|
-
const generate_middleware_1 = require("./commands/generate-middleware");
|
|
21
51
|
const generate_auth_1 = require("./commands/generate-auth");
|
|
22
|
-
const
|
|
23
|
-
const generate_cache_1 = require("./commands/generate-cache");
|
|
24
|
-
const generate_cron_1 = require("./commands/generate-cron");
|
|
25
|
-
const generate_rag_1 = require("./commands/generate-rag");
|
|
26
|
-
const generate_discovery_1 = require("./commands/generate-discovery");
|
|
27
|
-
const generate_setup_1 = require("./commands/generate-setup");
|
|
52
|
+
const generate_simple_1 = require("./commands/generate-simple");
|
|
28
53
|
const generator_registry_1 = require("./utils/generator-registry");
|
|
29
54
|
const info_1 = require("./commands/info");
|
|
30
55
|
const add_1 = require("./commands/add");
|
|
31
|
-
|
|
32
|
-
const
|
|
33
|
-
const start_1 = require("./commands/start");
|
|
34
|
-
const test_1 = require("./commands/test");
|
|
56
|
+
// Read version from package.json to ensure consistency
|
|
57
|
+
const packageJson = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, '../package.json'), 'utf8'));
|
|
35
58
|
const program = new commander_1.Command();
|
|
36
59
|
program
|
|
37
60
|
.name('hazel')
|
|
38
61
|
.description('CLI for generating HazelJS components and applications')
|
|
39
|
-
.version(
|
|
62
|
+
.version(packageJson.version);
|
|
40
63
|
// New app command
|
|
41
64
|
(0, generate_app_1.generateApp)(program);
|
|
42
65
|
// Utility commands
|
|
43
66
|
(0, info_1.infoCommand)(program);
|
|
44
67
|
(0, add_1.addCommand)(program);
|
|
45
|
-
(0, build_1.buildCommand)(program);
|
|
46
|
-
(0, pdf_to_audio_1.pdfToAudioCommand)(program);
|
|
47
|
-
(0, start_1.startCommand)(program);
|
|
48
|
-
(0, test_1.testCommand)(program);
|
|
49
68
|
// Generate command group (unified: hazel g <type> <name> [--path] [--dry-run] [--json], or hazel g --list)
|
|
50
69
|
const generateCommand = program
|
|
51
70
|
.command('generate')
|
|
@@ -77,28 +96,11 @@ const generateCommand = program
|
|
|
77
96
|
});
|
|
78
97
|
// Skeleton app
|
|
79
98
|
(0, generate_app_1.registerGenerateApp)(generateCommand);
|
|
80
|
-
//
|
|
81
|
-
(0, generate_controller_1.generateController)(generateCommand);
|
|
82
|
-
(0, generate_service_1.generateService)(generateCommand);
|
|
99
|
+
// Complex generators (multi-file output)
|
|
83
100
|
(0, generate_module_1.generateModule)(generateCommand);
|
|
84
101
|
(0, generate_dto_1.generateDto)(generateCommand);
|
|
85
|
-
(0, generate_guard_1.generateGuard)(generateCommand);
|
|
86
|
-
(0, generate_interceptor_1.generateInterceptor)(generateCommand);
|
|
87
|
-
(0, generate_middleware_1.generateMiddleware)(generateCommand);
|
|
88
|
-
// Advanced generators
|
|
89
102
|
(0, generate_crud_1.generateCrud)(generateCommand);
|
|
90
103
|
(0, generate_auth_1.generateAuth)(generateCommand);
|
|
91
|
-
(
|
|
92
|
-
(0,
|
|
93
|
-
(0, generate_pipe_1.generatePipe)(generateCommand);
|
|
94
|
-
(0, generate_repository_1.generateRepository)(generateCommand);
|
|
95
|
-
(0, generate_ai_service_1.generateAIService)(generateCommand);
|
|
96
|
-
(0, generate_agent_1.generateAgent)(generateCommand);
|
|
97
|
-
(0, generate_serverless_handler_1.generateServerlessHandler)(generateCommand);
|
|
98
|
-
(0, generate_config_1.generateConfig)(generateCommand);
|
|
99
|
-
(0, generate_cache_1.generateCache)(generateCommand);
|
|
100
|
-
(0, generate_cron_1.generateCron)(generateCommand);
|
|
101
|
-
(0, generate_rag_1.generateRag)(generateCommand);
|
|
102
|
-
(0, generate_discovery_1.generateDiscovery)(generateCommand);
|
|
103
|
-
(0, generate_setup_1.generateSetup)(generateCommand);
|
|
104
|
+
// Simple generators (config-driven single-file output)
|
|
105
|
+
(0, generate_simple_1.registerSimpleGenerators)(generateCommand);
|
|
104
106
|
program.parse(process.argv);
|
package/dist/index.list.test.js
CHANGED
|
@@ -4,34 +4,20 @@ jest.mock('./commands/generate-app', () => ({
|
|
|
4
4
|
generateApp: jest.fn(),
|
|
5
5
|
registerGenerateApp: jest.fn(),
|
|
6
6
|
}));
|
|
7
|
-
jest.mock('./commands/generate-controller', () => ({ generateController: jest.fn() }));
|
|
8
|
-
jest.mock('./commands/generate-service', () => ({ generateService: jest.fn() }));
|
|
9
7
|
jest.mock('./commands/generate-module', () => ({ generateModule: jest.fn() }));
|
|
10
8
|
jest.mock('./commands/generate-dto', () => ({ generateDto: jest.fn() }));
|
|
11
|
-
jest.mock('./commands/generate-guard', () => ({ generateGuard: jest.fn() }));
|
|
12
|
-
jest.mock('./commands/generate-interceptor', () => ({ generateInterceptor: jest.fn() }));
|
|
13
|
-
jest.mock('./commands/generate-middleware', () => ({ generateMiddleware: jest.fn() }));
|
|
14
9
|
jest.mock('./commands/generate-crud', () => ({ generateCrud: jest.fn() }));
|
|
15
10
|
jest.mock('./commands/generate-auth', () => ({ generateAuth: jest.fn() }));
|
|
16
|
-
jest.mock('./commands/generate-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
jest.mock('./commands/generate-cache', () => ({ generateCache: jest.fn() }));
|
|
25
|
-
jest.mock('./commands/generate-cron', () => ({ generateCron: jest.fn() }));
|
|
26
|
-
jest.mock('./commands/generate-rag', () => ({ generateRag: jest.fn() }));
|
|
27
|
-
jest.mock('./commands/generate-discovery', () => ({ generateDiscovery: jest.fn() }));
|
|
28
|
-
jest.mock('./commands/generate-setup', () => ({ generateSetup: jest.fn() }));
|
|
11
|
+
jest.mock('./commands/generate-simple', () => ({
|
|
12
|
+
registerSimpleGenerators: jest.fn(),
|
|
13
|
+
SIMPLE_GENERATORS: [
|
|
14
|
+
{ type: 'controller', description: 'REST controller', suffix: 'controller', template: '', nameRequired: true },
|
|
15
|
+
],
|
|
16
|
+
findSimpleGenerator: jest.fn(),
|
|
17
|
+
runSimpleGenerator: jest.fn(),
|
|
18
|
+
}));
|
|
29
19
|
jest.mock('./commands/info', () => ({ infoCommand: jest.fn() }));
|
|
30
20
|
jest.mock('./commands/add', () => ({ addCommand: jest.fn() }));
|
|
31
|
-
jest.mock('./commands/build', () => ({ buildCommand: jest.fn() }));
|
|
32
|
-
jest.mock('./commands/pdf-to-audio', () => ({ pdfToAudioCommand: jest.fn() }));
|
|
33
|
-
jest.mock('./commands/start', () => ({ startCommand: jest.fn() }));
|
|
34
|
-
jest.mock('./commands/test', () => ({ testCommand: jest.fn() }));
|
|
35
21
|
describe('CLI generate --list', () => {
|
|
36
22
|
let logSpy;
|
|
37
23
|
beforeAll(() => {
|