@hazeljs/cli 0.2.0-beta.1
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/README.md +61 -0
- package/@template/package.json +48 -0
- package/@template/src/app.module.ts +7 -0
- package/@template/src/hello.controller.ts +9 -0
- package/@template/src/index.ts +10 -0
- package/README.md +675 -0
- package/dist/commands/add.d.ts +2 -0
- package/dist/commands/add.js +90 -0
- package/dist/commands/build.d.ts +2 -0
- package/dist/commands/build.js +52 -0
- package/dist/commands/generate-agent.d.ts +2 -0
- package/dist/commands/generate-agent.js +56 -0
- package/dist/commands/generate-ai-service.d.ts +2 -0
- package/dist/commands/generate-ai-service.js +49 -0
- package/dist/commands/generate-app.d.ts +2 -0
- package/dist/commands/generate-app.js +246 -0
- package/dist/commands/generate-controller.d.ts +2 -0
- package/dist/commands/generate-controller.js +59 -0
- package/dist/commands/generate-crud.d.ts +2 -0
- package/dist/commands/generate-crud.js +203 -0
- package/dist/commands/generate-dto.d.ts +2 -0
- package/dist/commands/generate-dto.js +56 -0
- package/dist/commands/generate-exception-filter.d.ts +2 -0
- package/dist/commands/generate-exception-filter.js +50 -0
- package/dist/commands/generate-guard.d.ts +2 -0
- package/dist/commands/generate-guard.js +35 -0
- package/dist/commands/generate-interceptor.d.ts +2 -0
- package/dist/commands/generate-interceptor.js +37 -0
- package/dist/commands/generate-middleware.d.ts +2 -0
- package/dist/commands/generate-middleware.js +79 -0
- package/dist/commands/generate-module.d.ts +2 -0
- package/dist/commands/generate-module.js +96 -0
- package/dist/commands/generate-pipe.d.ts +2 -0
- package/dist/commands/generate-pipe.js +33 -0
- package/dist/commands/generate-repository.d.ts +2 -0
- package/dist/commands/generate-repository.js +38 -0
- package/dist/commands/generate-serverless-handler.d.ts +2 -0
- package/dist/commands/generate-serverless-handler.js +46 -0
- package/dist/commands/generate-service.d.ts +2 -0
- package/dist/commands/generate-service.js +51 -0
- package/dist/commands/generate-websocket-gateway.d.ts +2 -0
- package/dist/commands/generate-websocket-gateway.js +47 -0
- package/dist/commands/info.d.ts +2 -0
- package/dist/commands/info.js +91 -0
- package/dist/commands/start.d.ts +2 -0
- package/dist/commands/start.js +61 -0
- package/dist/commands/test.d.ts +2 -0
- package/dist/commands/test.js +63 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +61 -0
- package/dist/utils/generator.d.ts +14 -0
- package/dist/utils/generator.js +79 -0
- package/package.json +67 -0
- package/src/commands/add.ts +101 -0
- package/src/commands/build.ts +56 -0
- package/src/commands/generate-agent.ts +58 -0
- package/src/commands/generate-ai-service.ts +52 -0
- package/src/commands/generate-app.ts +270 -0
- package/src/commands/generate-controller.ts +61 -0
- package/src/commands/generate-crud.ts +214 -0
- package/src/commands/generate-dto.ts +61 -0
- package/src/commands/generate-exception-filter.ts +53 -0
- package/src/commands/generate-guard.ts +37 -0
- package/src/commands/generate-interceptor.ts +39 -0
- package/src/commands/generate-middleware.ts +86 -0
- package/src/commands/generate-module.ts +102 -0
- package/src/commands/generate-pipe.ts +36 -0
- package/src/commands/generate-repository.ts +41 -0
- package/src/commands/generate-serverless-handler.ts +53 -0
- package/src/commands/generate-service.ts +53 -0
- package/src/commands/generate-websocket-gateway.ts +50 -0
- package/src/commands/info.ts +106 -0
- package/src/commands/start.ts +61 -0
- package/src/commands/test.ts +70 -0
- package/src/index.ts +68 -0
- package/src/utils/generator.ts +93 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.addCommand = addCommand;
|
|
7
|
+
const child_process_1 = require("child_process");
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
10
|
+
const HAZEL_PACKAGES = {
|
|
11
|
+
ai: '@hazeljs/ai',
|
|
12
|
+
auth: '@hazeljs/auth',
|
|
13
|
+
cache: '@hazeljs/cache',
|
|
14
|
+
config: '@hazeljs/config',
|
|
15
|
+
cron: '@hazeljs/cron',
|
|
16
|
+
prisma: '@hazeljs/prisma',
|
|
17
|
+
rag: '@hazeljs/rag',
|
|
18
|
+
serverless: '@hazeljs/serverless',
|
|
19
|
+
swagger: '@hazeljs/swagger',
|
|
20
|
+
websocket: '@hazeljs/websocket',
|
|
21
|
+
discovery: '@hazeljs/discovery',
|
|
22
|
+
};
|
|
23
|
+
function addCommand(program) {
|
|
24
|
+
program
|
|
25
|
+
.command('add [package]')
|
|
26
|
+
.description('Add a HazelJS package to your project')
|
|
27
|
+
.option('--dev', 'Install as dev dependency')
|
|
28
|
+
.action(async (packageName, options) => {
|
|
29
|
+
try {
|
|
30
|
+
let selectedPackage = packageName;
|
|
31
|
+
// If no package specified, show interactive selection
|
|
32
|
+
if (!selectedPackage) {
|
|
33
|
+
const { package: pkg } = await inquirer_1.default.prompt([
|
|
34
|
+
{
|
|
35
|
+
type: 'list',
|
|
36
|
+
name: 'package',
|
|
37
|
+
message: 'Which HazelJS package would you like to add?',
|
|
38
|
+
choices: Object.keys(HAZEL_PACKAGES).map((key) => ({
|
|
39
|
+
name: `${key} - ${HAZEL_PACKAGES[key]}`,
|
|
40
|
+
value: key,
|
|
41
|
+
})),
|
|
42
|
+
},
|
|
43
|
+
]);
|
|
44
|
+
selectedPackage = pkg;
|
|
45
|
+
}
|
|
46
|
+
// Get the full package name
|
|
47
|
+
const fullPackageName = HAZEL_PACKAGES[selectedPackage];
|
|
48
|
+
if (!fullPackageName) {
|
|
49
|
+
console.log(chalk_1.default.yellow(`Unknown package: ${selectedPackage}`));
|
|
50
|
+
console.log(chalk_1.default.gray('\nAvailable packages:'));
|
|
51
|
+
Object.keys(HAZEL_PACKAGES).forEach((key) => {
|
|
52
|
+
console.log(chalk_1.default.gray(` - ${key}: ${HAZEL_PACKAGES[key]}`));
|
|
53
|
+
});
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
console.log(chalk_1.default.blue(`\n📦 Installing ${fullPackageName}...`));
|
|
57
|
+
const devFlag = options?.dev ? '--save-dev' : '';
|
|
58
|
+
const command = `npm install ${fullPackageName} ${devFlag}`.trim();
|
|
59
|
+
(0, child_process_1.execSync)(command, { stdio: 'inherit' });
|
|
60
|
+
console.log(chalk_1.default.green(`\n✓ Successfully installed ${fullPackageName}`));
|
|
61
|
+
// Show usage hints
|
|
62
|
+
console.log(chalk_1.default.gray('\nNext steps:'));
|
|
63
|
+
switch (selectedPackage) {
|
|
64
|
+
case 'ai':
|
|
65
|
+
console.log(chalk_1.default.gray(' import { AIModule } from "@hazeljs/ai";'));
|
|
66
|
+
break;
|
|
67
|
+
case 'auth':
|
|
68
|
+
console.log(chalk_1.default.gray(' import { AuthModule } from "@hazeljs/auth";'));
|
|
69
|
+
break;
|
|
70
|
+
case 'cache':
|
|
71
|
+
console.log(chalk_1.default.gray(' import { CacheModule } from "@hazeljs/cache";'));
|
|
72
|
+
break;
|
|
73
|
+
case 'prisma':
|
|
74
|
+
console.log(chalk_1.default.gray(' import { PrismaModule } from "@hazeljs/prisma";'));
|
|
75
|
+
break;
|
|
76
|
+
case 'swagger':
|
|
77
|
+
console.log(chalk_1.default.gray(' import { SwaggerModule } from "@hazeljs/swagger";'));
|
|
78
|
+
break;
|
|
79
|
+
case 'websocket':
|
|
80
|
+
console.log(chalk_1.default.gray(' import { WebSocketModule } from "@hazeljs/websocket";'));
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
console.log(chalk_1.default.gray(`\nDocumentation: https://hazeljs.com/docs/packages/${selectedPackage}`));
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
console.error(chalk_1.default.red('Error installing package:'), error);
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.buildCommand = buildCommand;
|
|
7
|
+
const child_process_1 = require("child_process");
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
function buildCommand(program) {
|
|
12
|
+
program
|
|
13
|
+
.command('build')
|
|
14
|
+
.description('Build the HazelJS project')
|
|
15
|
+
.option('-w, --watch', 'Watch mode')
|
|
16
|
+
.option('-p, --production', 'Production build')
|
|
17
|
+
.action((options) => {
|
|
18
|
+
try {
|
|
19
|
+
const packageJsonPath = path_1.default.join(process.cwd(), 'package.json');
|
|
20
|
+
if (!fs_1.default.existsSync(packageJsonPath)) {
|
|
21
|
+
console.log(chalk_1.default.red('✗ No package.json found'));
|
|
22
|
+
console.log(chalk_1.default.gray('Run this command from your project root'));
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf-8'));
|
|
26
|
+
if (!packageJson.scripts?.build) {
|
|
27
|
+
console.log(chalk_1.default.yellow('⚠ No build script found in package.json'));
|
|
28
|
+
console.log(chalk_1.default.gray('\nAdd a build script to your package.json:'));
|
|
29
|
+
console.log(chalk_1.default.gray(' "scripts": {'));
|
|
30
|
+
console.log(chalk_1.default.gray(' "build": "tsc"'));
|
|
31
|
+
console.log(chalk_1.default.gray(' }'));
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
console.log(chalk_1.default.blue('🔨 Building project...\n'));
|
|
35
|
+
let command = 'npm run build';
|
|
36
|
+
if (options.watch) {
|
|
37
|
+
command = 'npm run build -- --watch';
|
|
38
|
+
}
|
|
39
|
+
if (options.production) {
|
|
40
|
+
process.env.NODE_ENV = 'production';
|
|
41
|
+
}
|
|
42
|
+
(0, child_process_1.execSync)(command, { stdio: 'inherit' });
|
|
43
|
+
if (!options.watch) {
|
|
44
|
+
console.log(chalk_1.default.green('\n✓ Build completed successfully'));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
console.error(chalk_1.default.red('\n✗ Build failed'));
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateAgent = generateAgent;
|
|
4
|
+
const generator_1 = require("../utils/generator");
|
|
5
|
+
const AGENT_TEMPLATE = `import { Agent, Tool } from '@hazeljs/agent';
|
|
6
|
+
|
|
7
|
+
@Agent({
|
|
8
|
+
name: '{{fileName}}',
|
|
9
|
+
description: '{{description}}',
|
|
10
|
+
systemPrompt: 'You are a helpful {{className}} agent.',
|
|
11
|
+
enableMemory: true,
|
|
12
|
+
enableRAG: true,
|
|
13
|
+
})
|
|
14
|
+
export class {{className}}Agent {
|
|
15
|
+
@Tool({
|
|
16
|
+
description: 'Example tool for {{fileName}}',
|
|
17
|
+
parameters: [
|
|
18
|
+
{
|
|
19
|
+
name: 'input',
|
|
20
|
+
type: 'string',
|
|
21
|
+
description: 'Input parameter',
|
|
22
|
+
required: true,
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
})
|
|
26
|
+
async exampleTool(input: { input: string }): Promise<{ result: string }> {
|
|
27
|
+
// Implement your tool logic here
|
|
28
|
+
return {
|
|
29
|
+
result: \`Processed: \${input.input}\`,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
`;
|
|
34
|
+
class AgentGenerator extends generator_1.Generator {
|
|
35
|
+
getDefaultTemplate() {
|
|
36
|
+
return AGENT_TEMPLATE;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function generateAgent(program) {
|
|
40
|
+
program
|
|
41
|
+
.command('agent <name>')
|
|
42
|
+
.description('Generate a new AI agent with @Agent and @Tool decorators')
|
|
43
|
+
.option('-p, --path <path>', 'Path where the agent should be generated')
|
|
44
|
+
.action(async (name, options) => {
|
|
45
|
+
const generator = new AgentGenerator();
|
|
46
|
+
const generatorOptions = {
|
|
47
|
+
name,
|
|
48
|
+
path: options.path,
|
|
49
|
+
data: {
|
|
50
|
+
description: `A ${name} agent`,
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
const finalOptions = await generator.promptForOptions(generatorOptions);
|
|
54
|
+
await generator.generate(finalOptions);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateAIService = generateAIService;
|
|
4
|
+
const generator_1 = require("../utils/generator");
|
|
5
|
+
const AI_SERVICE_TEMPLATE = `import { Injectable } from '@hazeljs/core';
|
|
6
|
+
import { AIService } from '@hazeljs/ai';
|
|
7
|
+
import { AIFunction, AIPrompt } from '@hazeljs/ai';
|
|
8
|
+
|
|
9
|
+
@Injectable()
|
|
10
|
+
export class {{className}}AIService {
|
|
11
|
+
constructor(private readonly aiService: AIService) {}
|
|
12
|
+
|
|
13
|
+
@AIFunction({
|
|
14
|
+
provider: 'openai',
|
|
15
|
+
model: 'gpt-4',
|
|
16
|
+
streaming: false,
|
|
17
|
+
})
|
|
18
|
+
async {{fileName}}Task(@AIPrompt() prompt: string): Promise<unknown> {
|
|
19
|
+
const result = await this.aiService.complete({
|
|
20
|
+
provider: 'openai',
|
|
21
|
+
model: 'gpt-4',
|
|
22
|
+
messages: [{ role: 'user', content: prompt }],
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
return result;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
`;
|
|
29
|
+
class AIServiceGenerator extends generator_1.Generator {
|
|
30
|
+
getDefaultTemplate() {
|
|
31
|
+
return AI_SERVICE_TEMPLATE;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function generateAIService(program) {
|
|
35
|
+
program
|
|
36
|
+
.command('ai-service <name>')
|
|
37
|
+
.description('Generate a new AI service with decorators')
|
|
38
|
+
.alias('ai')
|
|
39
|
+
.option('-p, --path <path>', 'Path where the AI service should be generated')
|
|
40
|
+
.action(async (name, options) => {
|
|
41
|
+
const generator = new AIServiceGenerator();
|
|
42
|
+
const generatorOptions = {
|
|
43
|
+
name,
|
|
44
|
+
path: options.path,
|
|
45
|
+
};
|
|
46
|
+
const finalOptions = await generator.promptForOptions(generatorOptions);
|
|
47
|
+
await generator.generate(finalOptions);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.generateApp = generateApp;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const child_process_1 = require("child_process");
|
|
10
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
12
|
+
function copyRecursiveSync(src, dest) {
|
|
13
|
+
if (fs_1.default.existsSync(src)) {
|
|
14
|
+
fs_1.default.mkdirSync(dest, { recursive: true });
|
|
15
|
+
for (const entry of fs_1.default.readdirSync(src)) {
|
|
16
|
+
const srcPath = path_1.default.join(src, entry);
|
|
17
|
+
const destPath = path_1.default.join(dest, entry);
|
|
18
|
+
if (fs_1.default.lstatSync(srcPath).isDirectory()) {
|
|
19
|
+
copyRecursiveSync(srcPath, destPath);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
fs_1.default.copyFileSync(srcPath, destPath);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function updatePackageJson(destPath, appName, description) {
|
|
28
|
+
const packageJsonPath = path_1.default.join(destPath, 'package.json');
|
|
29
|
+
if (fs_1.default.existsSync(packageJsonPath)) {
|
|
30
|
+
const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf-8'));
|
|
31
|
+
packageJson.name = appName;
|
|
32
|
+
packageJson.description = description;
|
|
33
|
+
packageJson.version = '0.1.0';
|
|
34
|
+
fs_1.default.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function generateApp(program) {
|
|
38
|
+
program
|
|
39
|
+
.command('new <appName>')
|
|
40
|
+
.description('Create a new HazelJS application')
|
|
41
|
+
.option('-d, --dest <destPath>', 'Destination path', '.')
|
|
42
|
+
.option('--skip-install', 'Skip npm install')
|
|
43
|
+
.option('--skip-git', 'Skip git initialization')
|
|
44
|
+
.option('-i, --interactive', 'Interactive setup')
|
|
45
|
+
.action(async (appName, options) => {
|
|
46
|
+
try {
|
|
47
|
+
let projectConfig = {
|
|
48
|
+
name: appName,
|
|
49
|
+
description: `A HazelJS application`,
|
|
50
|
+
author: '',
|
|
51
|
+
license: 'MIT',
|
|
52
|
+
packages: [],
|
|
53
|
+
};
|
|
54
|
+
// Interactive setup
|
|
55
|
+
if (options.interactive) {
|
|
56
|
+
console.log(chalk_1.default.blue('\n🚀 Welcome to HazelJS project setup!\n'));
|
|
57
|
+
const answers = await inquirer_1.default.prompt([
|
|
58
|
+
{
|
|
59
|
+
type: 'input',
|
|
60
|
+
name: 'description',
|
|
61
|
+
message: 'Project description:',
|
|
62
|
+
default: projectConfig.description,
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
type: 'input',
|
|
66
|
+
name: 'author',
|
|
67
|
+
message: 'Author:',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
type: 'list',
|
|
71
|
+
name: 'license',
|
|
72
|
+
message: 'License:',
|
|
73
|
+
choices: ['MIT', 'Apache-2.0', 'GPL-3.0', 'BSD-3-Clause', 'ISC'],
|
|
74
|
+
default: 'MIT',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
type: 'checkbox',
|
|
78
|
+
name: 'packages',
|
|
79
|
+
message: 'Select additional HazelJS packages to install:',
|
|
80
|
+
choices: [
|
|
81
|
+
{ name: 'AI Integration (@hazeljs/ai)', value: '@hazeljs/ai' },
|
|
82
|
+
{ name: 'Authentication (@hazeljs/auth)', value: '@hazeljs/auth' },
|
|
83
|
+
{ name: 'Caching (@hazeljs/cache)', value: '@hazeljs/cache' },
|
|
84
|
+
{ name: 'Configuration (@hazeljs/config)', value: '@hazeljs/config' },
|
|
85
|
+
{ name: 'Cron Jobs (@hazeljs/cron)', value: '@hazeljs/cron' },
|
|
86
|
+
{ name: 'Prisma ORM (@hazeljs/prisma)', value: '@hazeljs/prisma' },
|
|
87
|
+
{ name: 'RAG/Vector Search (@hazeljs/rag)', value: '@hazeljs/rag' },
|
|
88
|
+
{ name: 'Serverless (@hazeljs/serverless)', value: '@hazeljs/serverless' },
|
|
89
|
+
{ name: 'Swagger/OpenAPI (@hazeljs/swagger)', value: '@hazeljs/swagger' },
|
|
90
|
+
{ name: 'WebSocket (@hazeljs/websocket)', value: '@hazeljs/websocket' },
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
]);
|
|
94
|
+
projectConfig = { ...projectConfig, ...answers };
|
|
95
|
+
}
|
|
96
|
+
const destPath = path_1.default.join(process.cwd(), options.dest || '.', appName);
|
|
97
|
+
console.log(chalk_1.default.blue('\n📦 Creating new HazelJS project...\n'));
|
|
98
|
+
console.log(chalk_1.default.gray(`Project: ${projectConfig.name}`));
|
|
99
|
+
console.log(chalk_1.default.gray(`Location: ${destPath}\n`));
|
|
100
|
+
// Check if destination exists
|
|
101
|
+
if (fs_1.default.existsSync(destPath)) {
|
|
102
|
+
console.error(chalk_1.default.red(`✗ Destination already exists: ${destPath}`));
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
// Use local template
|
|
106
|
+
const templatePath = path_1.default.join(__dirname, '../../@template');
|
|
107
|
+
if (fs_1.default.existsSync(templatePath)) {
|
|
108
|
+
console.log(chalk_1.default.blue('📋 Copying template files...'));
|
|
109
|
+
copyRecursiveSync(templatePath, destPath);
|
|
110
|
+
// Update package.json
|
|
111
|
+
updatePackageJson(destPath, projectConfig.name, projectConfig.description);
|
|
112
|
+
console.log(chalk_1.default.green('✓ Template files copied'));
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
console.log(chalk_1.default.yellow('⚠ Local template not found, creating basic structure...'));
|
|
116
|
+
// Create basic structure
|
|
117
|
+
fs_1.default.mkdirSync(destPath, { recursive: true });
|
|
118
|
+
fs_1.default.mkdirSync(path_1.default.join(destPath, 'src'), { recursive: true });
|
|
119
|
+
// Create package.json
|
|
120
|
+
const packageJson = {
|
|
121
|
+
name: projectConfig.name,
|
|
122
|
+
version: '0.1.0',
|
|
123
|
+
description: projectConfig.description,
|
|
124
|
+
main: 'dist/index.js',
|
|
125
|
+
scripts: {
|
|
126
|
+
build: 'tsc',
|
|
127
|
+
start: 'node dist/index.js',
|
|
128
|
+
dev: 'ts-node-dev --respawn --transpile-only src/index.ts',
|
|
129
|
+
test: 'jest',
|
|
130
|
+
lint: 'eslint "src/**/*.ts"',
|
|
131
|
+
},
|
|
132
|
+
dependencies: {
|
|
133
|
+
'@hazeljs/core': '^0.2.0',
|
|
134
|
+
},
|
|
135
|
+
devDependencies: {
|
|
136
|
+
'@types/node': '^20.0.0',
|
|
137
|
+
'typescript': '^5.0.0',
|
|
138
|
+
'ts-node-dev': '^2.0.0',
|
|
139
|
+
},
|
|
140
|
+
author: projectConfig.author,
|
|
141
|
+
license: projectConfig.license,
|
|
142
|
+
};
|
|
143
|
+
fs_1.default.writeFileSync(path_1.default.join(destPath, 'package.json'), JSON.stringify(packageJson, null, 2));
|
|
144
|
+
// Create basic index.ts
|
|
145
|
+
const indexContent = `import { HazelApp, HazelModule, Controller, Get } from '@hazeljs/core';
|
|
146
|
+
|
|
147
|
+
@Controller('/')
|
|
148
|
+
export class AppController {
|
|
149
|
+
@Get()
|
|
150
|
+
hello() {
|
|
151
|
+
return { message: 'Hello from HazelJS!' };
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
@HazelModule({
|
|
156
|
+
controllers: [AppController],
|
|
157
|
+
})
|
|
158
|
+
export class AppModule {}
|
|
159
|
+
|
|
160
|
+
async function bootstrap() {
|
|
161
|
+
const app = await HazelApp.create(AppModule);
|
|
162
|
+
await app.listen(3000);
|
|
163
|
+
console.log('🚀 Server running on http://localhost:3000');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
bootstrap();
|
|
167
|
+
`;
|
|
168
|
+
fs_1.default.writeFileSync(path_1.default.join(destPath, 'src', 'index.ts'), indexContent);
|
|
169
|
+
// Create tsconfig.json
|
|
170
|
+
const tsConfig = {
|
|
171
|
+
compilerOptions: {
|
|
172
|
+
target: 'ES2020',
|
|
173
|
+
module: 'commonjs',
|
|
174
|
+
lib: ['ES2020'],
|
|
175
|
+
outDir: './dist',
|
|
176
|
+
rootDir: './src',
|
|
177
|
+
strict: true,
|
|
178
|
+
esModuleInterop: true,
|
|
179
|
+
skipLibCheck: true,
|
|
180
|
+
forceConsistentCasingInFileNames: true,
|
|
181
|
+
experimentalDecorators: true,
|
|
182
|
+
emitDecoratorMetadata: true,
|
|
183
|
+
},
|
|
184
|
+
include: ['src/**/*'],
|
|
185
|
+
exclude: ['node_modules', 'dist'],
|
|
186
|
+
};
|
|
187
|
+
fs_1.default.writeFileSync(path_1.default.join(destPath, 'tsconfig.json'), JSON.stringify(tsConfig, null, 2));
|
|
188
|
+
console.log(chalk_1.default.green('✓ Basic structure created'));
|
|
189
|
+
}
|
|
190
|
+
// Initialize git
|
|
191
|
+
if (!options.skipGit) {
|
|
192
|
+
try {
|
|
193
|
+
console.log(chalk_1.default.blue('\n📝 Initializing git repository...'));
|
|
194
|
+
(0, child_process_1.execSync)('git init', { cwd: destPath, stdio: 'ignore' });
|
|
195
|
+
// Create .gitignore
|
|
196
|
+
const gitignore = `node_modules/
|
|
197
|
+
dist/
|
|
198
|
+
.env
|
|
199
|
+
.DS_Store
|
|
200
|
+
coverage/
|
|
201
|
+
*.log
|
|
202
|
+
`;
|
|
203
|
+
fs_1.default.writeFileSync(path_1.default.join(destPath, '.gitignore'), gitignore);
|
|
204
|
+
console.log(chalk_1.default.green('✓ Git initialized'));
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
console.log(chalk_1.default.yellow('⚠ Git initialization skipped'));
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// Install dependencies
|
|
211
|
+
if (!options.skipInstall) {
|
|
212
|
+
console.log(chalk_1.default.blue('\n📦 Installing dependencies...\n'));
|
|
213
|
+
try {
|
|
214
|
+
(0, child_process_1.execSync)('npm install', { cwd: destPath, stdio: 'inherit' });
|
|
215
|
+
// Install additional packages
|
|
216
|
+
if (projectConfig.packages.length > 0) {
|
|
217
|
+
console.log(chalk_1.default.blue('\n📦 Installing additional packages...\n'));
|
|
218
|
+
(0, child_process_1.execSync)(`npm install ${projectConfig.packages.join(' ')}`, {
|
|
219
|
+
cwd: destPath,
|
|
220
|
+
stdio: 'inherit',
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
console.log(chalk_1.default.green('\n✓ Dependencies installed'));
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
console.log(chalk_1.default.yellow('\n⚠ Dependency installation failed'));
|
|
227
|
+
console.log(chalk_1.default.gray('You can install them manually with: npm install'));
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
// Success message
|
|
231
|
+
console.log(chalk_1.default.green.bold('\n✨ Project created successfully!\n'));
|
|
232
|
+
console.log(chalk_1.default.gray('Next steps:'));
|
|
233
|
+
console.log(chalk_1.default.gray(` cd ${appName}`));
|
|
234
|
+
if (options.skipInstall) {
|
|
235
|
+
console.log(chalk_1.default.gray(' npm install'));
|
|
236
|
+
}
|
|
237
|
+
console.log(chalk_1.default.gray(' npm run dev'));
|
|
238
|
+
console.log(chalk_1.default.gray('\nDocumentation: https://hazeljs.com/docs'));
|
|
239
|
+
console.log(chalk_1.default.gray('Discord: https://discord.gg/hazeljs\n'));
|
|
240
|
+
}
|
|
241
|
+
catch (error) {
|
|
242
|
+
console.error(chalk_1.default.red('\n✗ Failed to create project:'), error);
|
|
243
|
+
process.exit(1);
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateController = generateController;
|
|
4
|
+
const generator_1 = require("../utils/generator");
|
|
5
|
+
const CONTROLLER_TEMPLATE = `import { Controller, Get, Post, Body, Param, Delete, Put } from '@hazeljs/core';
|
|
6
|
+
import { {{className}}Service } from './{{fileName}}.service';
|
|
7
|
+
import { Create{{className}}Dto } from './dto/create-{{fileName}}.dto';
|
|
8
|
+
import { Update{{className}}Dto } from './dto/update-{{fileName}}.dto';
|
|
9
|
+
|
|
10
|
+
@Controller('{{fileName}}')
|
|
11
|
+
export class {{className}}Controller {
|
|
12
|
+
constructor(private readonly {{fileName}}Service: {{className}}Service) {}
|
|
13
|
+
|
|
14
|
+
@Get()
|
|
15
|
+
findAll() {
|
|
16
|
+
return this.{{fileName}}Service.findAll();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@Get(':id')
|
|
20
|
+
findOne(@Param('id') id: string) {
|
|
21
|
+
return this.{{fileName}}Service.findOne(id);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@Post()
|
|
25
|
+
create(@Body(Create{{className}}Dto) create{{className}}Dto: Create{{className}}Dto) {
|
|
26
|
+
return this.{{fileName}}Service.create(create{{className}}Dto);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@Put(':id')
|
|
30
|
+
update(@Param('id') id: string, @Body(Update{{className}}Dto) update{{className}}Dto: Update{{className}}Dto) {
|
|
31
|
+
return this.{{fileName}}Service.update(id, update{{className}}Dto);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@Delete(':id')
|
|
35
|
+
remove(@Param('id') id: string) {
|
|
36
|
+
return this.{{fileName}}Service.remove(id);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
`;
|
|
40
|
+
class ControllerGenerator extends generator_1.Generator {
|
|
41
|
+
getDefaultTemplate() {
|
|
42
|
+
return CONTROLLER_TEMPLATE;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function generateController(program) {
|
|
46
|
+
program
|
|
47
|
+
.command('controller <name>')
|
|
48
|
+
.description('Generate a new controller')
|
|
49
|
+
.option('-p, --path <path>', 'Path where the controller should be generated')
|
|
50
|
+
.action(async (name, options) => {
|
|
51
|
+
const generator = new ControllerGenerator();
|
|
52
|
+
const generatorOptions = {
|
|
53
|
+
name,
|
|
54
|
+
path: options.path,
|
|
55
|
+
};
|
|
56
|
+
const finalOptions = await generator.promptForOptions(generatorOptions);
|
|
57
|
+
await generator.generate(finalOptions);
|
|
58
|
+
});
|
|
59
|
+
}
|