@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.
Files changed (117) hide show
  1. package/@template-ai-native/package.json +1 -1
  2. package/README.md +140 -588
  3. package/cli-manifest.json +940 -0
  4. package/dist/commands/add.d.ts +9 -0
  5. package/dist/commands/add.js +35 -126
  6. package/dist/commands/generate-app.js +17 -230
  7. package/dist/commands/generate-auth.d.ts +12 -0
  8. package/dist/commands/generate-auth.js +12 -0
  9. package/dist/commands/generate-crud.d.ts +12 -0
  10. package/dist/commands/generate-crud.js +12 -0
  11. package/dist/commands/generate-dto.d.ts +12 -0
  12. package/dist/commands/generate-dto.js +12 -0
  13. package/dist/commands/generate-module.d.ts +12 -0
  14. package/dist/commands/generate-module.js +12 -0
  15. package/dist/commands/generate-simple.d.ts +74 -0
  16. package/dist/commands/generate-simple.js +104 -0
  17. package/dist/commands/generate-simple.test.js +100 -0
  18. package/dist/commands/info.d.ts +12 -0
  19. package/dist/commands/info.js +12 -0
  20. package/dist/commands/templates.d.ts +34 -0
  21. package/dist/commands/templates.js +387 -0
  22. package/dist/index.d.ts +40 -0
  23. package/dist/index.js +50 -48
  24. package/dist/index.list.test.js +8 -22
  25. package/dist/index.test.js +19 -56
  26. package/dist/utils/generator-registry.d.ts +5 -0
  27. package/dist/utils/generator-registry.js +34 -65
  28. package/dist/utils/generator.d.ts +0 -1
  29. package/dist/utils/generator.js +0 -22
  30. package/dist/utils/generator.test.js +0 -28
  31. package/dist/utils/packages-registry.d.ts +34 -0
  32. package/dist/utils/packages-registry.js +380 -0
  33. package/package.json +7 -7
  34. package/dist/commands/build.d.ts +0 -2
  35. package/dist/commands/build.js +0 -52
  36. package/dist/commands/generate-agent.d.ts +0 -4
  37. package/dist/commands/generate-agent.js +0 -64
  38. package/dist/commands/generate-agent.test.js +0 -36
  39. package/dist/commands/generate-ai-service.d.ts +0 -4
  40. package/dist/commands/generate-ai-service.js +0 -54
  41. package/dist/commands/generate-ai-service.test.d.ts +0 -1
  42. package/dist/commands/generate-ai-service.test.js +0 -41
  43. package/dist/commands/generate-cache.d.ts +0 -4
  44. package/dist/commands/generate-cache.js +0 -66
  45. package/dist/commands/generate-cache.test.d.ts +0 -1
  46. package/dist/commands/generate-cache.test.js +0 -36
  47. package/dist/commands/generate-config.d.ts +0 -4
  48. package/dist/commands/generate-config.js +0 -59
  49. package/dist/commands/generate-config.test.d.ts +0 -1
  50. package/dist/commands/generate-config.test.js +0 -35
  51. package/dist/commands/generate-controller.d.ts +0 -4
  52. package/dist/commands/generate-controller.js +0 -66
  53. package/dist/commands/generate-controller.test.d.ts +0 -1
  54. package/dist/commands/generate-controller.test.js +0 -48
  55. package/dist/commands/generate-cron.d.ts +0 -4
  56. package/dist/commands/generate-cron.js +0 -61
  57. package/dist/commands/generate-cron.test.d.ts +0 -1
  58. package/dist/commands/generate-cron.test.js +0 -42
  59. package/dist/commands/generate-discovery.d.ts +0 -4
  60. package/dist/commands/generate-discovery.js +0 -63
  61. package/dist/commands/generate-discovery.test.d.ts +0 -1
  62. package/dist/commands/generate-discovery.test.js +0 -36
  63. package/dist/commands/generate-exception-filter.d.ts +0 -4
  64. package/dist/commands/generate-exception-filter.js +0 -54
  65. package/dist/commands/generate-exception-filter.test.d.ts +0 -1
  66. package/dist/commands/generate-exception-filter.test.js +0 -43
  67. package/dist/commands/generate-guard.d.ts +0 -4
  68. package/dist/commands/generate-guard.js +0 -42
  69. package/dist/commands/generate-guard.test.d.ts +0 -1
  70. package/dist/commands/generate-guard.test.js +0 -41
  71. package/dist/commands/generate-interceptor.d.ts +0 -4
  72. package/dist/commands/generate-interceptor.js +0 -43
  73. package/dist/commands/generate-interceptor.test.d.ts +0 -1
  74. package/dist/commands/generate-interceptor.test.js +0 -41
  75. package/dist/commands/generate-middleware.d.ts +0 -4
  76. package/dist/commands/generate-middleware.js +0 -47
  77. package/dist/commands/generate-middleware.test.d.ts +0 -1
  78. package/dist/commands/generate-middleware.test.js +0 -41
  79. package/dist/commands/generate-pipe.d.ts +0 -4
  80. package/dist/commands/generate-pipe.js +0 -39
  81. package/dist/commands/generate-pipe.test.d.ts +0 -1
  82. package/dist/commands/generate-pipe.test.js +0 -35
  83. package/dist/commands/generate-rag.d.ts +0 -4
  84. package/dist/commands/generate-rag.js +0 -68
  85. package/dist/commands/generate-rag.test.d.ts +0 -1
  86. package/dist/commands/generate-rag.test.js +0 -35
  87. package/dist/commands/generate-repository.d.ts +0 -4
  88. package/dist/commands/generate-repository.js +0 -46
  89. package/dist/commands/generate-repository.test.d.ts +0 -1
  90. package/dist/commands/generate-repository.test.js +0 -41
  91. package/dist/commands/generate-serverless-handler.d.ts +0 -4
  92. package/dist/commands/generate-serverless-handler.js +0 -57
  93. package/dist/commands/generate-serverless-handler.test.d.ts +0 -1
  94. package/dist/commands/generate-serverless-handler.test.js +0 -42
  95. package/dist/commands/generate-service.d.ts +0 -4
  96. package/dist/commands/generate-service.js +0 -58
  97. package/dist/commands/generate-service.test.d.ts +0 -1
  98. package/dist/commands/generate-service.test.js +0 -41
  99. package/dist/commands/generate-setup.d.ts +0 -4
  100. package/dist/commands/generate-setup.js +0 -187
  101. package/dist/commands/generate-setup.test.d.ts +0 -1
  102. package/dist/commands/generate-setup.test.js +0 -50
  103. package/dist/commands/generate-websocket-gateway.d.ts +0 -4
  104. package/dist/commands/generate-websocket-gateway.js +0 -53
  105. package/dist/commands/generate-websocket-gateway.test.d.ts +0 -1
  106. package/dist/commands/generate-websocket-gateway.test.js +0 -41
  107. package/dist/commands/pdf-to-audio.d.ts +0 -2
  108. package/dist/commands/pdf-to-audio.js +0 -170
  109. package/dist/commands/pdf-to-audio.test.d.ts +0 -1
  110. package/dist/commands/pdf-to-audio.test.js +0 -92
  111. package/dist/commands/start.d.ts +0 -2
  112. package/dist/commands/start.js +0 -61
  113. package/dist/commands/test.d.ts +0 -2
  114. package/dist/commands/test.js +0 -63
  115. package/dist/commands/utility-commands.test.d.ts +0 -1
  116. package/dist/commands/utility-commands.test.js +0 -95
  117. /package/dist/commands/{generate-agent.test.d.ts → generate-simple.test.d.ts} +0 -0
@@ -1,2 +1,11 @@
1
1
  import { Command } from 'commander';
2
+ /**
3
+ * Register the `hazel add [package]` command.
4
+ *
5
+ * Installs a HazelJS package via npm and prints import/usage hints.
6
+ * When called without a package name, shows an interactive selection list.
7
+ * Use `--setup` to also generate a minimal `*.setup.ts` starter file.
8
+ *
9
+ * @param program - The root Commander program instance
10
+ */
2
11
  export declare function addCommand(program: Command): void;
@@ -6,130 +6,27 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.addCommand = addCommand;
7
7
  const child_process_1 = require("child_process");
8
8
  const chalk_1 = __importDefault(require("chalk"));
9
+ const fs_1 = __importDefault(require("fs"));
10
+ const path_1 = __importDefault(require("path"));
9
11
  const inquirer_1 = __importDefault(require("inquirer"));
10
- const HAZEL_PACKAGES = {
11
- ai: {
12
- npm: '@hazeljs/ai',
13
- hint: 'import { AIModule } from "@hazeljs/ai";',
14
- },
15
- agent: {
16
- npm: '@hazeljs/agent',
17
- hint: 'import { AgentModule } from "@hazeljs/agent";',
18
- },
19
- audit: {
20
- npm: '@hazeljs/audit',
21
- hint: 'import { AuditModule, ConsoleAuditTransport } from "@hazeljs/audit";\n // AuditModule.forRoot({ transports: [new ConsoleAuditTransport()] })',
22
- },
23
- auth: {
24
- npm: '@hazeljs/auth',
25
- hint: 'import { JwtModule } from "@hazeljs/auth";\n // JwtModule.forRoot({ secret: "your-secret", expiresIn: "1d" })',
26
- },
27
- oauth: {
28
- npm: '@hazeljs/oauth',
29
- hint: 'import { OAuthModule } from "@hazeljs/oauth";\n // OAuthModule.forRoot({ providers: { google: {...}, microsoft: {...}, github: {...} } })',
30
- },
31
- cache: {
32
- npm: '@hazeljs/cache',
33
- hint: 'import { CacheModule } from "@hazeljs/cache";',
34
- },
35
- config: {
36
- npm: '@hazeljs/config',
37
- hint: 'import { ConfigModule } from "@hazeljs/config";\n // ConfigModule.forRoot({ envFilePath: ".env" })',
38
- },
39
- cron: {
40
- npm: '@hazeljs/cron',
41
- hint: 'import { CronModule } from "@hazeljs/cron";',
42
- },
43
- data: {
44
- npm: '@hazeljs/data',
45
- hint: 'import { DataModule } from "@hazeljs/data";',
46
- },
47
- discovery: {
48
- npm: '@hazeljs/discovery',
49
- hint: 'import { ServiceRegistry, DiscoveryClient } from "@hazeljs/discovery";',
50
- },
51
- 'event-emitter': {
52
- npm: '@hazeljs/event-emitter',
53
- hint: 'import { EventEmitterModule } from "@hazeljs/event-emitter";',
54
- },
55
- gateway: {
56
- npm: '@hazeljs/gateway',
57
- hint: 'import { GatewayModule } from "@hazeljs/gateway";',
58
- },
59
- guardrails: {
60
- npm: '@hazeljs/guardrails',
61
- hint: 'import { GuardrailsModule } from "@hazeljs/guardrails";\n // GuardrailsModule.forRoot({ redactPIIByDefault: true })',
62
- },
63
- graphql: {
64
- npm: '@hazeljs/graphql',
65
- hint: 'import { GraphQLModule } from "@hazeljs/graphql";',
66
- },
67
- grpc: {
68
- npm: '@hazeljs/grpc',
69
- hint: 'import { GrpcModule } from "@hazeljs/grpc";',
70
- },
71
- kafka: {
72
- npm: '@hazeljs/kafka',
73
- hint: 'import { KafkaModule } from "@hazeljs/kafka";',
74
- },
75
- messaging: {
76
- npm: '@hazeljs/messaging',
77
- hint: 'import { MessagingModule } from "@hazeljs/messaging";',
78
- },
79
- mcp: {
80
- npm: '@hazeljs/mcp',
81
- hint: 'import { createMcpServer } from "@hazeljs/mcp";\n // createMcpServer({ name, version, toolRegistry }).listenStdio();',
82
- },
83
- ml: {
84
- npm: '@hazeljs/ml',
85
- hint: 'import { MLModule } from "@hazeljs/ml";',
86
- },
87
- prompts: {
88
- npm: '@hazeljs/prompts',
89
- hint: 'import { PromptTemplate, PromptRegistry } from "@hazeljs/prompts";',
90
- },
91
- prisma: {
92
- npm: '@hazeljs/prisma',
93
- hint: 'import { PrismaModule } from "@hazeljs/prisma";',
94
- },
95
- typeorm: {
96
- npm: '@hazeljs/typeorm',
97
- hint: 'import { TypeOrmModule } from "@hazeljs/typeorm";',
98
- },
99
- queue: {
100
- npm: '@hazeljs/queue',
101
- hint: 'import { QueueModule } from "@hazeljs/queue";',
102
- },
103
- rag: {
104
- npm: '@hazeljs/rag',
105
- hint: 'import { RAGPipeline } from "@hazeljs/rag";',
106
- },
107
- resilience: {
108
- npm: '@hazeljs/resilience',
109
- hint: 'import { CircuitBreaker, WithRetry, WithTimeout } from "@hazeljs/resilience";',
110
- },
111
- 'pdf-to-audio': {
112
- npm: '@hazeljs/pdf-to-audio',
113
- hint: 'import { PdfToAudioModule } from "@hazeljs/pdf-to-audio";\n // PdfToAudioModule converts PDFs to audio via TTS',
114
- },
115
- serverless: {
116
- npm: '@hazeljs/serverless',
117
- hint: 'import { createLambdaHandler } from "@hazeljs/serverless";',
118
- },
119
- swagger: {
120
- npm: '@hazeljs/swagger',
121
- hint: 'import { SwaggerModule } from "@hazeljs/swagger";',
122
- },
123
- websocket: {
124
- npm: '@hazeljs/websocket',
125
- hint: 'import { WebSocketModule } from "@hazeljs/websocket";',
126
- },
127
- };
12
+ const packages_registry_1 = require("../utils/packages-registry");
13
+ const generator_1 = require("../utils/generator");
14
+ /**
15
+ * Register the `hazel add [package]` command.
16
+ *
17
+ * Installs a HazelJS package via npm and prints import/usage hints.
18
+ * When called without a package name, shows an interactive selection list.
19
+ * Use `--setup` to also generate a minimal `*.setup.ts` starter file.
20
+ *
21
+ * @param program - The root Commander program instance
22
+ */
128
23
  function addCommand(program) {
129
24
  program
130
25
  .command('add [package]')
131
- .description('Add a HazelJS package to your project')
26
+ .description('Add a HazelJS package to your project (optionally generate a setup file with --setup)')
132
27
  .option('--dev', 'Install as dev dependency')
28
+ .option('--setup', 'Also generate a minimal setup/starter file in src/')
29
+ .option('--setup-path <path>', 'Path for the setup file', 'src')
133
30
  .action(async (packageName, options) => {
134
31
  try {
135
32
  let selectedPackage = packageName;
@@ -140,21 +37,21 @@ function addCommand(program) {
140
37
  type: 'list',
141
38
  name: 'package',
142
39
  message: 'Which HazelJS package would you like to add?',
143
- choices: Object.keys(HAZEL_PACKAGES).map((key) => ({
144
- name: `${key} - ${HAZEL_PACKAGES[key].npm}`,
145
- value: key,
40
+ choices: packages_registry_1.HAZEL_PACKAGES.map((p) => ({
41
+ name: `${p.shortName} - ${p.npm}`,
42
+ value: p.shortName,
146
43
  })),
147
44
  },
148
45
  ]);
149
46
  selectedPackage = pkg;
150
47
  }
151
48
  // Get the package info
152
- const pkgInfo = HAZEL_PACKAGES[selectedPackage];
49
+ const pkgInfo = (0, packages_registry_1.findPackage)(selectedPackage);
153
50
  if (!pkgInfo) {
154
51
  console.log(chalk_1.default.yellow(`Unknown package: ${selectedPackage}`));
155
52
  console.log(chalk_1.default.gray('\nAvailable packages:'));
156
- Object.keys(HAZEL_PACKAGES).forEach((key) => {
157
- console.log(chalk_1.default.gray(` - ${key}: ${HAZEL_PACKAGES[key].npm}`));
53
+ packages_registry_1.HAZEL_PACKAGES.forEach((p) => {
54
+ console.log(chalk_1.default.gray(` - ${p.shortName}: ${p.npm}`));
158
55
  });
159
56
  return;
160
57
  }
@@ -163,10 +60,22 @@ function addCommand(program) {
163
60
  const command = `npm install ${pkgInfo.npm} ${devFlag}`.trim();
164
61
  (0, child_process_1.execSync)(command, { stdio: 'inherit' });
165
62
  console.log(chalk_1.default.green(`\n\u2713 Successfully installed ${pkgInfo.npm}`));
63
+ // Generate setup file if requested
64
+ if (options?.setup && pkgInfo.setupTemplate) {
65
+ const setupDir = path_1.default.join(process.cwd(), options.setupPath || 'src');
66
+ const setupFile = path_1.default.join(setupDir, `${(0, generator_1.toKebabCase)(pkgInfo.shortName)}.setup.ts`);
67
+ if (!fs_1.default.existsSync(setupDir))
68
+ fs_1.default.mkdirSync(setupDir, { recursive: true });
69
+ fs_1.default.writeFileSync(setupFile, pkgInfo.setupTemplate);
70
+ console.log(chalk_1.default.green(`\u2713 Generated setup file: ${setupFile}`));
71
+ }
72
+ else if (options?.setup && !pkgInfo.setupTemplate) {
73
+ console.log(chalk_1.default.gray('\nNo setup template available for this package.'));
74
+ }
166
75
  // Show usage hints
167
76
  console.log(chalk_1.default.gray('\nUsage:'));
168
77
  console.log(chalk_1.default.gray(` ${pkgInfo.hint}`));
169
- console.log(chalk_1.default.gray(`\nDocumentation: https://hazeljs.ai/docs/packages/${selectedPackage}`));
78
+ console.log(chalk_1.default.gray(`\nDocumentation: https://hazeljs.ai/docs/packages/${pkgInfo.shortName}`));
170
79
  }
171
80
  catch (error) {
172
81
  console.error(chalk_1.default.red('Error installing package:'), error);
@@ -12,6 +12,7 @@ const child_process_1 = require("child_process");
12
12
  const chalk_1 = __importDefault(require("chalk"));
13
13
  const inquirer_1 = __importDefault(require("inquirer"));
14
14
  const generator_1 = require("../utils/generator");
15
+ const packages_registry_1 = require("../utils/packages-registry");
15
16
  function copyRecursiveSync(src, dest) {
16
17
  if (fs_1.default.existsSync(src)) {
17
18
  fs_1.default.mkdirSync(dest, { recursive: true });
@@ -61,7 +62,7 @@ function createSkeletonAtDest(destPath, appName, description) {
61
62
  'lint:fix': 'eslint "src/**/*.ts" --fix',
62
63
  format: 'prettier --write "src/**/*.ts"',
63
64
  },
64
- dependencies: { '@hazeljs/core': '^0.2.0', 'reflect-metadata': '^0.2.2' },
65
+ dependencies: { '@hazeljs/core': '^0.2.0' },
65
66
  devDependencies: {
66
67
  '@types/jest': '^29.5.12',
67
68
  '@types/node': '^20.0.0',
@@ -78,8 +79,7 @@ function createSkeletonAtDest(destPath, appName, description) {
78
79
  },
79
80
  };
80
81
  fs_1.default.writeFileSync(path_1.default.join(destPath, 'package.json'), JSON.stringify(packageJson, null, 2));
81
- const indexContent = `import 'reflect-metadata';
82
- import { HazelApp, HazelModule, Controller, Get } from '@hazeljs/core';
82
+ const indexContent = `import { HazelApp, HazelModule, Controller, Get } from '@hazeljs/core';
83
83
 
84
84
  @Controller('/')
85
85
  export class AppController {
@@ -134,114 +134,21 @@ function scaffoldPackageBoilerplate(destPath, packages) {
134
134
  // Always include the default HelloController
135
135
  imports.push("import { HelloController } from './hello.controller';");
136
136
  controllers.push('HelloController');
137
+ // Special handling for config: create .env files
137
138
  if (packages.includes('@hazeljs/config')) {
138
- imports.push("import { ConfigModule } from '@hazeljs/config';");
139
- moduleImports.push("ConfigModule.forRoot({ envFilePath: '.env' })");
140
- // Create .env file
141
139
  fs_1.default.writeFileSync(path_1.default.join(destPath, '.env'), 'PORT=3000\nNODE_ENV=development\n');
142
140
  fs_1.default.writeFileSync(path_1.default.join(destPath, '.env.example'), 'PORT=3000\nNODE_ENV=development\n');
143
141
  console.log(chalk_1.default.green(' ✓ Created .env and .env.example'));
144
142
  }
145
- if (packages.includes('@hazeljs/swagger')) {
146
- imports.push("import { SwaggerModule } from '@hazeljs/swagger';");
147
- moduleImports.push('SwaggerModule');
148
- }
149
- if (packages.includes('@hazeljs/prisma')) {
150
- imports.push("import { PrismaModule } from '@hazeljs/prisma';");
151
- moduleImports.push('PrismaModule');
152
- }
153
- if (packages.includes('@hazeljs/typeorm')) {
154
- imports.push("import { TypeOrmModule } from '@hazeljs/typeorm';");
155
- moduleImports.push('TypeOrmModule');
156
- }
157
- if (packages.includes('@hazeljs/audit')) {
158
- imports.push("import { AuditModule, ConsoleAuditTransport } from '@hazeljs/audit';");
159
- moduleImports.push("AuditModule.forRoot({ transports: [new ConsoleAuditTransport()] })");
160
- }
161
- if (packages.includes('@hazeljs/auth')) {
162
- imports.push("import { JwtModule } from '@hazeljs/auth';");
163
- moduleImports.push("JwtModule.forRoot({ secret: process.env.JWT_SECRET || 'change-me', expiresIn: '1d' })");
164
- }
165
- if (packages.includes('@hazeljs/oauth')) {
166
- imports.push("import { OAuthModule } from '@hazeljs/oauth';");
167
- moduleImports.push("OAuthModule.forRoot({ providers: { google: { clientId: process.env.GOOGLE_CLIENT_ID!, clientSecret: process.env.GOOGLE_CLIENT_SECRET!, redirectUri: process.env.OAUTH_REDIRECT_URI! } } })");
168
- }
169
- if (packages.includes('@hazeljs/cache')) {
170
- imports.push("import { CacheModule } from '@hazeljs/cache';");
171
- moduleImports.push('CacheModule');
172
- }
173
- if (packages.includes('@hazeljs/cron')) {
174
- imports.push("import { CronModule } from '@hazeljs/cron';");
175
- moduleImports.push('CronModule');
176
- }
177
- if (packages.includes('@hazeljs/websocket')) {
178
- imports.push("import { WebSocketModule } from '@hazeljs/websocket';");
179
- moduleImports.push('WebSocketModule');
180
- }
181
- if (packages.includes('@hazeljs/ai')) {
182
- imports.push("import { AIModule } from '@hazeljs/ai';");
183
- moduleImports.push('AIModule');
184
- }
185
- if (packages.includes('@hazeljs/agent')) {
186
- imports.push("import { AgentModule } from '@hazeljs/agent';");
187
- moduleImports.push('AgentModule');
188
- }
189
- if (packages.includes('@hazeljs/rag')) {
190
- imports.push("import { RAGModule } from '@hazeljs/rag';");
191
- moduleImports.push('RAGModule');
192
- }
193
- if (packages.includes('@hazeljs/discovery')) {
194
- // Discovery uses ServiceRegistry/DiscoveryClient programmatically - no module import
195
- }
196
- if (packages.includes('@hazeljs/prompts')) {
197
- // Prompts is a library (PromptTemplate, PromptRegistry) - no module import
198
- }
199
- if (packages.includes('@hazeljs/mcp')) {
200
- // MCP uses createMcpServer() programmatically - no module import
201
- }
202
- if (packages.includes('@hazeljs/pdf-to-audio')) {
203
- imports.push("import { PdfToAudioModule } from '@hazeljs/pdf-to-audio';");
204
- moduleImports.push('PdfToAudioModule');
205
- }
206
- if (packages.includes('@hazeljs/data')) {
207
- imports.push("import { DataModule } from '@hazeljs/data';");
208
- moduleImports.push('DataModule.forRoot()');
209
- }
210
- if (packages.includes('@hazeljs/event-emitter')) {
211
- imports.push("import { EventEmitterModule } from '@hazeljs/event-emitter';");
212
- moduleImports.push('EventEmitterModule.forRoot()');
213
- }
214
- if (packages.includes('@hazeljs/gateway')) {
215
- imports.push("import { GatewayModule } from '@hazeljs/gateway';");
216
- moduleImports.push('GatewayModule');
217
- }
218
- if (packages.includes('@hazeljs/graphql')) {
219
- imports.push("import { GraphQLModule } from '@hazeljs/graphql';");
220
- moduleImports.push('GraphQLModule');
221
- }
222
- if (packages.includes('@hazeljs/grpc')) {
223
- imports.push("import { GrpcModule } from '@hazeljs/grpc';");
224
- moduleImports.push('GrpcModule');
225
- }
226
- if (packages.includes('@hazeljs/kafka')) {
227
- imports.push("import { KafkaModule } from '@hazeljs/kafka';");
228
- moduleImports.push('KafkaModule');
229
- }
230
- if (packages.includes('@hazeljs/messaging')) {
231
- imports.push("import { MessagingModule } from '@hazeljs/messaging';");
232
- moduleImports.push('MessagingModule');
233
- }
234
- if (packages.includes('@hazeljs/ml')) {
235
- imports.push("import { MLModule } from '@hazeljs/ml';");
236
- moduleImports.push('MLModule.forRoot()');
237
- }
238
- if (packages.includes('@hazeljs/queue')) {
239
- imports.push("import { QueueModule } from '@hazeljs/queue';");
240
- moduleImports.push('QueueModule');
241
- }
242
- if (packages.includes('@hazeljs/resilience')) {
243
- // Resilience is a library of decorators, not a module - no import needed in app.module
244
- // User can import { CircuitBreaker, WithRetry } in their services
143
+ // Data-driven: derive imports from centralized registry
144
+ for (const npmName of packages) {
145
+ const meta = (0, packages_registry_1.findPackage)(npmName);
146
+ if (!meta)
147
+ continue;
148
+ if (meta.moduleImport)
149
+ imports.push(meta.moduleImport);
150
+ if (meta.moduleExpression)
151
+ moduleImports.push(meta.moduleExpression);
245
152
  }
246
153
  // Generate the enhanced app.module.ts
247
154
  const importsSection = moduleImports.length > 0
@@ -258,8 +165,7 @@ export class AppModule {}
258
165
  console.log(chalk_1.default.green(' ✓ Updated app.module.ts with package imports'));
259
166
  // Update index.ts / main.ts if swagger is selected
260
167
  if (packages.includes('@hazeljs/swagger')) {
261
- const mainContent = `import 'reflect-metadata';
262
- import { HazelApp } from '@hazeljs/core';
168
+ const mainContent = `import { HazelApp } from '@hazeljs/core';
263
169
  import { SwaggerModule } from '@hazeljs/swagger';
264
170
  import { AppModule } from './app.module';
265
171
 
@@ -329,36 +235,7 @@ function generateApp(program) {
329
235
  type: 'checkbox',
330
236
  name: 'packages',
331
237
  message: 'Select additional HazelJS packages to install:',
332
- choices: [
333
- { name: 'AI Integration (@hazeljs/ai)', value: '@hazeljs/ai' },
334
- { name: 'AI Agents (@hazeljs/agent)', value: '@hazeljs/agent' },
335
- { name: 'Audit Logging (@hazeljs/audit)', value: '@hazeljs/audit' },
336
- { name: 'Authentication (@hazeljs/auth)', value: '@hazeljs/auth' },
337
- { name: 'OAuth - Google/Microsoft/GitHub (@hazeljs/oauth)', value: '@hazeljs/oauth' },
338
- { name: 'Caching (@hazeljs/cache)', value: '@hazeljs/cache' },
339
- { name: 'Configuration (@hazeljs/config)', value: '@hazeljs/config' },
340
- { name: 'Cron Jobs (@hazeljs/cron)', value: '@hazeljs/cron' },
341
- { name: 'Data/ETL (@hazeljs/data)', value: '@hazeljs/data' },
342
- { name: 'Service Discovery (@hazeljs/discovery)', value: '@hazeljs/discovery' },
343
- { name: 'Event Emitter (@hazeljs/event-emitter)', value: '@hazeljs/event-emitter' },
344
- { name: 'API Gateway (@hazeljs/gateway)', value: '@hazeljs/gateway' },
345
- { name: 'GraphQL (@hazeljs/graphql)', value: '@hazeljs/graphql' },
346
- { name: 'gRPC (@hazeljs/grpc)', value: '@hazeljs/grpc' },
347
- { name: 'Kafka (@hazeljs/kafka)', value: '@hazeljs/kafka' },
348
- { name: 'Messaging - WhatsApp/Telegram (@hazeljs/messaging)', value: '@hazeljs/messaging' },
349
- { name: 'Machine Learning (@hazeljs/ml)', value: '@hazeljs/ml' },
350
- { name: 'MCP - Model Context Protocol (@hazeljs/mcp)', value: '@hazeljs/mcp' },
351
- { name: 'PDF to Audio (@hazeljs/pdf-to-audio)', value: '@hazeljs/pdf-to-audio' },
352
- { name: 'Prompts - typed templates (@hazeljs/prompts)', value: '@hazeljs/prompts' },
353
- { name: 'Prisma ORM (@hazeljs/prisma)', value: '@hazeljs/prisma' },
354
- { name: 'TypeORM (@hazeljs/typeorm)', value: '@hazeljs/typeorm' },
355
- { name: 'Queue/BullMQ (@hazeljs/queue)', value: '@hazeljs/queue' },
356
- { name: 'RAG/Vector Search (@hazeljs/rag)', value: '@hazeljs/rag' },
357
- { name: 'Resilience - Circuit Breaker (@hazeljs/resilience)', value: '@hazeljs/resilience' },
358
- { name: 'Serverless (@hazeljs/serverless)', value: '@hazeljs/serverless' },
359
- { name: 'Swagger/OpenAPI (@hazeljs/swagger)', value: '@hazeljs/swagger' },
360
- { name: 'WebSocket (@hazeljs/websocket)', value: '@hazeljs/websocket' },
361
- ],
238
+ choices: packages_registry_1.HAZEL_PACKAGES.map((p) => ({ name: p.label, value: p.npm })),
362
239
  },
363
240
  ]);
364
241
  projectConfig = { ...projectConfig, ...answers };
@@ -384,97 +261,7 @@ function generateApp(program) {
384
261
  }
385
262
  else {
386
263
  console.log(chalk_1.default.yellow(`⚠ ${options.template} template not found, creating basic structure...`));
387
- // Create basic structure
388
- fs_1.default.mkdirSync(destPath, { recursive: true });
389
- fs_1.default.mkdirSync(path_1.default.join(destPath, 'src'), { recursive: true });
390
- // Create package.json
391
- const packageJson = {
392
- name: projectConfig.name,
393
- version: '0.1.0',
394
- description: projectConfig.description,
395
- main: 'dist/index.js',
396
- scripts: {
397
- build: 'tsc',
398
- start: 'node dist/index.js',
399
- dev: 'ts-node-dev --respawn --transpile-only src/index.ts',
400
- test: 'jest',
401
- lint: 'eslint "src/**/*.ts"',
402
- 'lint:fix': 'eslint "src/**/*.ts" --fix',
403
- format: 'prettier --write "src/**/*.ts"',
404
- },
405
- dependencies: {
406
- '@hazeljs/core': '^0.2.0',
407
- 'reflect-metadata': '^0.2.2',
408
- },
409
- devDependencies: {
410
- '@types/jest': '^29.5.12',
411
- '@types/node': '^20.0.0',
412
- '@typescript-eslint/eslint-plugin': '^8.18.2',
413
- '@typescript-eslint/parser': '^8.18.2',
414
- 'eslint': '^8.56.0',
415
- 'eslint-config-prettier': '^9.1.0',
416
- 'eslint-plugin-prettier': '^5.1.3',
417
- 'jest': '^29.7.0',
418
- 'prettier': '^3.2.5',
419
- 'ts-jest': '^29.1.2',
420
- 'ts-node-dev': '^2.0.0',
421
- 'typescript': '^5.3.3',
422
- },
423
- author: projectConfig.author,
424
- license: projectConfig.license,
425
- };
426
- fs_1.default.writeFileSync(path_1.default.join(destPath, 'package.json'), JSON.stringify(packageJson, null, 2));
427
- // Create basic index.ts
428
- const indexContent = `import 'reflect-metadata';
429
- import { HazelApp, HazelModule, Controller, Get } from '@hazeljs/core';
430
-
431
- @Controller('/')
432
- export class AppController {
433
- @Get()
434
- hello() {
435
- return { message: 'Hello from HazelJS!' };
436
- }
437
- }
438
-
439
- @HazelModule({
440
- controllers: [AppController],
441
- })
442
- export class AppModule {}
443
-
444
- async function bootstrap() {
445
- const app = new HazelApp(AppModule);
446
-
447
- app.enableCors({
448
- origin: '*',
449
- methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
450
- });
451
-
452
- const port = parseInt(process.env.PORT || '3000', 10);
453
- await app.listen(port);
454
- }
455
-
456
- bootstrap();
457
- `;
458
- fs_1.default.writeFileSync(path_1.default.join(destPath, 'src', 'index.ts'), indexContent);
459
- // Create tsconfig.json
460
- const tsConfig = {
461
- compilerOptions: {
462
- target: 'ES2020',
463
- module: 'commonjs',
464
- lib: ['ES2020'],
465
- outDir: './dist',
466
- rootDir: './src',
467
- strict: true,
468
- esModuleInterop: true,
469
- skipLibCheck: true,
470
- forceConsistentCasingInFileNames: true,
471
- experimentalDecorators: true,
472
- emitDecoratorMetadata: true,
473
- },
474
- include: ['src/**/*'],
475
- exclude: ['node_modules', 'dist'],
476
- };
477
- fs_1.default.writeFileSync(path_1.default.join(destPath, 'tsconfig.json'), JSON.stringify(tsConfig, null, 2));
264
+ createSkeletonAtDest(destPath, projectConfig.name, projectConfig.description);
478
265
  console.log(chalk_1.default.green('✓ Basic structure created'));
479
266
  }
480
267
  // Initialize git
@@ -531,7 +318,7 @@ coverage/
531
318
  }
532
319
  console.log(chalk_1.default.gray(' npm run dev'));
533
320
  console.log(chalk_1.default.gray('\nDocumentation: https://hazeljs.ai/docs'));
534
- console.log(chalk_1.default.gray('Discord: https://discord.gg/xe495BvE\n'));
321
+ console.log(chalk_1.default.gray('Discord: https://discord.com/channels/1448263814238965833/1448263814859456575\n'));
535
322
  }
536
323
  catch (error) {
537
324
  console.error(chalk_1.default.red('\n✗ Failed to create project:'), error);
@@ -1,4 +1,16 @@
1
1
  import { Command } from 'commander';
2
2
  import { GenerateResult, GenerateCLIOptions } from '../utils/generator';
3
+ /**
4
+ * Generate a complete auth module (6 files: module, service, controller, JWT guard, 2 DTOs).
5
+ *
6
+ * @param _name - Unused (auth generator doesn't need a custom name)
7
+ * @param options - Standard CLI options (--path, --dry-run, --json)
8
+ * @returns GenerateResult with paths of all created files and setup next-steps
9
+ */
3
10
  export declare function runAuth(_name: string, options: GenerateCLIOptions): Promise<GenerateResult>;
11
+ /**
12
+ * Register `hazel g auth` as a sub-command of the generate command.
13
+ *
14
+ * @param command - The Commander `generate` parent command
15
+ */
4
16
  export declare function generateAuth(command: Command): void;
@@ -145,6 +145,13 @@ export class LoginDto {
145
145
  password: string;
146
146
  }
147
147
  `;
148
+ /**
149
+ * Generate a complete auth module (6 files: module, service, controller, JWT guard, 2 DTOs).
150
+ *
151
+ * @param _name - Unused (auth generator doesn't need a custom name)
152
+ * @param options - Standard CLI options (--path, --dry-run, --json)
153
+ * @returns GenerateResult with paths of all created files and setup next-steps
154
+ */
148
155
  async function runAuth(_name, options) {
149
156
  const basePath = path_1.default.join(process.cwd(), options.path || 'src/auth');
150
157
  const data = {};
@@ -179,6 +186,11 @@ async function runAuth(_name, options) {
179
186
  ],
180
187
  };
181
188
  }
189
+ /**
190
+ * Register `hazel g auth` as a sub-command of the generate command.
191
+ *
192
+ * @param command - The Commander `generate` parent command
193
+ */
182
194
  function generateAuth(command) {
183
195
  command
184
196
  .command('auth')
@@ -1,4 +1,16 @@
1
1
  import { Command } from 'commander';
2
2
  import { GenerateResult, GenerateCLIOptions } from '../utils/generator';
3
+ /**
4
+ * Generate a complete CRUD resource (4 files: controller, service, DTOs, module).
5
+ *
6
+ * @param name - Resource name (e.g. 'product') — determines file and class names
7
+ * @param options - Standard CLI options (--path, --dry-run, --json, --route)
8
+ * @returns GenerateResult with paths of all created files
9
+ */
3
10
  export declare function runCrud(name: string, options: GenerateCLIOptions): Promise<GenerateResult>;
11
+ /**
12
+ * Register `hazel g crud <name>` as a sub-command of the generate command.
13
+ *
14
+ * @param command - The Commander `generate` parent command
15
+ */
4
16
  export declare function generateCrud(command: Command): void;
@@ -127,6 +127,13 @@ import { {{className}}Service } from './{{fileName}}.service';
127
127
  })
128
128
  export class {{className}}Module {}
129
129
  `;
130
+ /**
131
+ * Generate a complete CRUD resource (4 files: controller, service, DTOs, module).
132
+ *
133
+ * @param name - Resource name (e.g. 'product') — determines file and class names
134
+ * @param options - Standard CLI options (--path, --dry-run, --json, --route)
135
+ * @returns GenerateResult with paths of all created files
136
+ */
130
137
  async function runCrud(name, options) {
131
138
  try {
132
139
  const className = (0, generator_1.toPascalCase)(name);
@@ -171,6 +178,11 @@ async function runCrud(name, options) {
171
178
  };
172
179
  }
173
180
  }
181
+ /**
182
+ * Register `hazel g crud <name>` as a sub-command of the generate command.
183
+ *
184
+ * @param command - The Commander `generate` parent command
185
+ */
174
186
  function generateCrud(command) {
175
187
  command
176
188
  .command('crud <name>')
@@ -1,4 +1,16 @@
1
1
  import { Command } from 'commander';
2
2
  import { GenerateResult, GenerateCLIOptions } from '../utils/generator';
3
+ /**
4
+ * Generate a pair of DTOs (create + update) for the given name.
5
+ *
6
+ * @param name - Entity name (e.g. 'product') — determines file and class names
7
+ * @param options - Standard CLI options (--path, --dry-run, --json)
8
+ * @returns GenerateResult with paths of both created DTO files
9
+ */
3
10
  export declare function runDto(name: string, options: GenerateCLIOptions): Promise<GenerateResult>;
11
+ /**
12
+ * Register `hazel g dto <name>` as a sub-command of the generate command.
13
+ *
14
+ * @param program - The Commander `generate` parent command
15
+ */
4
16
  export declare function generateDto(program: Command): void;
@@ -59,10 +59,22 @@ class DtoGenerator extends generator_1.Generator {
59
59
  };
60
60
  }
61
61
  }
62
+ /**
63
+ * Generate a pair of DTOs (create + update) for the given name.
64
+ *
65
+ * @param name - Entity name (e.g. 'product') — determines file and class names
66
+ * @param options - Standard CLI options (--path, --dry-run, --json)
67
+ * @returns GenerateResult with paths of both created DTO files
68
+ */
62
69
  async function runDto(name, options) {
63
70
  const generator = new DtoGenerator();
64
71
  return generator.generate({ name, path: options.path, dryRun: options.dryRun });
65
72
  }
73
+ /**
74
+ * Register `hazel g dto <name>` as a sub-command of the generate command.
75
+ *
76
+ * @param program - The Commander `generate` parent command
77
+ */
66
78
  function generateDto(program) {
67
79
  program
68
80
  .command('dto <name>')