@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
package/dist/commands/add.d.ts
CHANGED
|
@@ -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;
|
package/dist/commands/add.js
CHANGED
|
@@ -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
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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:
|
|
144
|
-
name: `${
|
|
145
|
-
value:
|
|
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 =
|
|
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
|
-
|
|
157
|
-
console.log(chalk_1.default.gray(` - ${
|
|
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/${
|
|
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'
|
|
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 '
|
|
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
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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 '
|
|
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
|
-
|
|
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.
|
|
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>')
|