@hazeljs/cli 0.2.0-alpha.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/.eslintrc.js +36 -0
- package/@template/.lintstagedrc +6 -0
- package/@template/README.md +61 -0
- package/@template/jest.config.js +28 -0
- package/@template/jest.setup.js +81 -0
- package/@template/package.json +34 -0
- package/@template/src/app.module.ts +7 -0
- package/@template/src/hello.controller.ts +9 -0
- package/@template/src/index.ts +18 -0
- package/@template/tsconfig.json +25 -0
- package/LICENSE +192 -0
- package/README.md +683 -0
- package/dist/commands/add.d.ts +2 -0
- package/dist/commands/add.js +176 -0
- package/dist/commands/add.test.d.ts +1 -0
- package/dist/commands/add.test.js +51 -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 +58 -0
- package/dist/commands/generate-agent.test.d.ts +1 -0
- package/dist/commands/generate-agent.test.js +36 -0
- package/dist/commands/generate-ai-service.d.ts +2 -0
- package/dist/commands/generate-ai-service.js +48 -0
- package/dist/commands/generate-ai-service.test.d.ts +1 -0
- package/dist/commands/generate-ai-service.test.js +41 -0
- package/dist/commands/generate-app.d.ts +2 -0
- package/dist/commands/generate-app.js +448 -0
- package/dist/commands/generate-auth.d.ts +2 -0
- package/dist/commands/generate-auth.js +194 -0
- package/dist/commands/generate-auth.test.d.ts +1 -0
- package/dist/commands/generate-auth.test.js +48 -0
- package/dist/commands/generate-cache.d.ts +2 -0
- package/dist/commands/generate-cache.js +64 -0
- package/dist/commands/generate-cache.test.d.ts +1 -0
- package/dist/commands/generate-cache.test.js +36 -0
- package/dist/commands/generate-config.d.ts +2 -0
- package/dist/commands/generate-config.js +57 -0
- package/dist/commands/generate-config.test.d.ts +1 -0
- package/dist/commands/generate-config.test.js +35 -0
- package/dist/commands/generate-controller.d.ts +2 -0
- package/dist/commands/generate-controller.js +60 -0
- package/dist/commands/generate-controller.test.d.ts +1 -0
- package/dist/commands/generate-controller.test.js +48 -0
- package/dist/commands/generate-cron.d.ts +2 -0
- package/dist/commands/generate-cron.js +59 -0
- package/dist/commands/generate-cron.test.d.ts +1 -0
- package/dist/commands/generate-cron.test.js +42 -0
- package/dist/commands/generate-crud.d.ts +2 -0
- package/dist/commands/generate-crud.js +177 -0
- package/dist/commands/generate-crud.test.d.ts +1 -0
- package/dist/commands/generate-crud.test.js +52 -0
- package/dist/commands/generate-discovery.d.ts +2 -0
- package/dist/commands/generate-discovery.js +61 -0
- package/dist/commands/generate-discovery.test.d.ts +1 -0
- package/dist/commands/generate-discovery.test.js +36 -0
- package/dist/commands/generate-dto.d.ts +2 -0
- package/dist/commands/generate-dto.js +69 -0
- package/dist/commands/generate-dto.test.d.ts +1 -0
- package/dist/commands/generate-dto.test.js +44 -0
- package/dist/commands/generate-exception-filter.d.ts +2 -0
- package/dist/commands/generate-exception-filter.js +48 -0
- package/dist/commands/generate-exception-filter.test.d.ts +1 -0
- package/dist/commands/generate-exception-filter.test.js +43 -0
- package/dist/commands/generate-guard.d.ts +2 -0
- package/dist/commands/generate-guard.js +36 -0
- package/dist/commands/generate-guard.test.d.ts +1 -0
- package/dist/commands/generate-guard.test.js +41 -0
- package/dist/commands/generate-interceptor.d.ts +2 -0
- package/dist/commands/generate-interceptor.js +37 -0
- package/dist/commands/generate-interceptor.test.d.ts +1 -0
- package/dist/commands/generate-interceptor.test.js +41 -0
- package/dist/commands/generate-middleware.d.ts +2 -0
- package/dist/commands/generate-middleware.js +46 -0
- package/dist/commands/generate-middleware.test.d.ts +1 -0
- package/dist/commands/generate-middleware.test.js +41 -0
- package/dist/commands/generate-module.d.ts +2 -0
- package/dist/commands/generate-module.js +106 -0
- package/dist/commands/generate-module.test.d.ts +1 -0
- package/dist/commands/generate-module.test.js +54 -0
- package/dist/commands/generate-pipe.d.ts +2 -0
- package/dist/commands/generate-pipe.js +33 -0
- package/dist/commands/generate-pipe.test.d.ts +1 -0
- package/dist/commands/generate-pipe.test.js +35 -0
- package/dist/commands/generate-rag.d.ts +2 -0
- package/dist/commands/generate-rag.js +66 -0
- package/dist/commands/generate-rag.test.d.ts +1 -0
- package/dist/commands/generate-rag.test.js +35 -0
- package/dist/commands/generate-repository.d.ts +2 -0
- package/dist/commands/generate-repository.js +40 -0
- package/dist/commands/generate-repository.test.d.ts +1 -0
- package/dist/commands/generate-repository.test.js +41 -0
- package/dist/commands/generate-serverless-handler.d.ts +2 -0
- package/dist/commands/generate-serverless-handler.js +46 -0
- package/dist/commands/generate-serverless-handler.test.d.ts +1 -0
- package/dist/commands/generate-serverless-handler.test.js +42 -0
- package/dist/commands/generate-service.d.ts +2 -0
- package/dist/commands/generate-service.js +52 -0
- package/dist/commands/generate-service.test.d.ts +1 -0
- package/dist/commands/generate-service.test.js +41 -0
- package/dist/commands/generate-websocket-gateway.d.ts +2 -0
- package/dist/commands/generate-websocket-gateway.js +47 -0
- package/dist/commands/generate-websocket-gateway.test.d.ts +1 -0
- package/dist/commands/generate-websocket-gateway.test.js +41 -0
- package/dist/commands/info.d.ts +2 -0
- package/dist/commands/info.js +91 -0
- package/dist/commands/pdf-to-audio.d.ts +2 -0
- package/dist/commands/pdf-to-audio.js +170 -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 +75 -0
- package/dist/index.test.d.ts +1 -0
- package/dist/index.test.js +93 -0
- package/dist/utils/generator.d.ts +25 -0
- package/dist/utils/generator.js +107 -0
- package/dist/utils/generator.test.d.ts +1 -0
- package/dist/utils/generator.test.js +137 -0
- package/package.json +73 -0
|
@@ -0,0 +1,176 @@
|
|
|
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: {
|
|
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
|
+
};
|
|
128
|
+
function addCommand(program) {
|
|
129
|
+
program
|
|
130
|
+
.command('add [package]')
|
|
131
|
+
.description('Add a HazelJS package to your project')
|
|
132
|
+
.option('--dev', 'Install as dev dependency')
|
|
133
|
+
.action(async (packageName, options) => {
|
|
134
|
+
try {
|
|
135
|
+
let selectedPackage = packageName;
|
|
136
|
+
// If no package specified, show interactive selection
|
|
137
|
+
if (!selectedPackage) {
|
|
138
|
+
const { package: pkg } = await inquirer_1.default.prompt([
|
|
139
|
+
{
|
|
140
|
+
type: 'list',
|
|
141
|
+
name: 'package',
|
|
142
|
+
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,
|
|
146
|
+
})),
|
|
147
|
+
},
|
|
148
|
+
]);
|
|
149
|
+
selectedPackage = pkg;
|
|
150
|
+
}
|
|
151
|
+
// Get the package info
|
|
152
|
+
const pkgInfo = HAZEL_PACKAGES[selectedPackage];
|
|
153
|
+
if (!pkgInfo) {
|
|
154
|
+
console.log(chalk_1.default.yellow(`Unknown package: ${selectedPackage}`));
|
|
155
|
+
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}`));
|
|
158
|
+
});
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
console.log(chalk_1.default.blue(`\n\uD83D\uDCE6 Installing ${pkgInfo.npm}...`));
|
|
162
|
+
const devFlag = options?.dev ? '--save-dev' : '';
|
|
163
|
+
const command = `npm install ${pkgInfo.npm} ${devFlag}`.trim();
|
|
164
|
+
(0, child_process_1.execSync)(command, { stdio: 'inherit' });
|
|
165
|
+
console.log(chalk_1.default.green(`\n\u2713 Successfully installed ${pkgInfo.npm}`));
|
|
166
|
+
// Show usage hints
|
|
167
|
+
console.log(chalk_1.default.gray('\nUsage:'));
|
|
168
|
+
console.log(chalk_1.default.gray(` ${pkgInfo.hint}`));
|
|
169
|
+
console.log(chalk_1.default.gray(`\nDocumentation: https://hazeljs.com/docs/packages/${selectedPackage}`));
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
console.error(chalk_1.default.red('Error installing package:'), error);
|
|
173
|
+
process.exit(1);
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const child_process_1 = require("child_process");
|
|
4
|
+
const commander_1 = require("commander");
|
|
5
|
+
const add_1 = require("./add");
|
|
6
|
+
jest.mock('child_process');
|
|
7
|
+
jest.mock('inquirer');
|
|
8
|
+
describe('addCommand', () => {
|
|
9
|
+
const mockExecSync = child_process_1.execSync;
|
|
10
|
+
let program;
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
jest.clearAllMocks();
|
|
13
|
+
mockExecSync.mockImplementation(() => Buffer.from(''));
|
|
14
|
+
jest.spyOn(console, 'log').mockImplementation();
|
|
15
|
+
program = new commander_1.Command();
|
|
16
|
+
});
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
jest.restoreAllMocks();
|
|
19
|
+
});
|
|
20
|
+
it('should register the add command', () => {
|
|
21
|
+
(0, add_1.addCommand)(program);
|
|
22
|
+
const cmd = program.commands.find(c => c.name() === 'add');
|
|
23
|
+
expect(cmd).toBeDefined();
|
|
24
|
+
});
|
|
25
|
+
it('should install a known package', async () => {
|
|
26
|
+
(0, add_1.addCommand)(program);
|
|
27
|
+
await program.parseAsync(['node', 'test', 'add', 'auth']);
|
|
28
|
+
expect(mockExecSync).toHaveBeenCalledWith(expect.stringContaining('@hazeljs/auth'), expect.objectContaining({ stdio: 'inherit' }));
|
|
29
|
+
});
|
|
30
|
+
it('should handle unknown packages gracefully', async () => {
|
|
31
|
+
const consoleSpy = jest.spyOn(console, 'log').mockImplementation();
|
|
32
|
+
(0, add_1.addCommand)(program);
|
|
33
|
+
await program.parseAsync(['node', 'test', 'add', 'unknown-package']);
|
|
34
|
+
expect(mockExecSync).not.toHaveBeenCalled();
|
|
35
|
+
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('Unknown package'));
|
|
36
|
+
consoleSpy.mockRestore();
|
|
37
|
+
});
|
|
38
|
+
it('should include all hazeljs packages', async () => {
|
|
39
|
+
(0, add_1.addCommand)(program);
|
|
40
|
+
// Test that all documented packages are available
|
|
41
|
+
const expectedPackages = [
|
|
42
|
+
'ai', 'agent', 'auth', 'cache', 'config', 'cron',
|
|
43
|
+
'discovery', 'mcp', 'prompts', 'prisma', 'typeorm', 'rag', 'serverless', 'swagger', 'websocket'
|
|
44
|
+
];
|
|
45
|
+
for (const pkg of expectedPackages) {
|
|
46
|
+
mockExecSync.mockClear();
|
|
47
|
+
await program.parseAsync(['node', 'test', 'add', pkg]);
|
|
48
|
+
expect(mockExecSync).toHaveBeenCalledWith(expect.stringContaining(`@hazeljs/${pkg}`), expect.any(Object));
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -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,58 @@
|
|
|
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
|
+
constructor() {
|
|
36
|
+
super(...arguments);
|
|
37
|
+
this.suffix = 'agent';
|
|
38
|
+
}
|
|
39
|
+
getDefaultTemplate() {
|
|
40
|
+
return AGENT_TEMPLATE;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function generateAgent(program) {
|
|
44
|
+
program
|
|
45
|
+
.command('agent <name>')
|
|
46
|
+
.description('Generate a new AI agent with @Agent and @Tool decorators')
|
|
47
|
+
.option('-p, --path <path>', 'Path where the agent should be generated')
|
|
48
|
+
.option('--dry-run', 'Preview files without writing them')
|
|
49
|
+
.action(async (name, options) => {
|
|
50
|
+
const generator = new AgentGenerator();
|
|
51
|
+
await generator.generate({
|
|
52
|
+
name,
|
|
53
|
+
path: options.path,
|
|
54
|
+
dryRun: options.dryRun,
|
|
55
|
+
data: { description: `A ${name} agent` },
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
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
|
+
const fs_1 = __importDefault(require("fs"));
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const generate_agent_1 = require("./generate-agent");
|
|
9
|
+
jest.mock('fs');
|
|
10
|
+
describe('generateAgent', () => {
|
|
11
|
+
const mockFs = fs_1.default;
|
|
12
|
+
let program;
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
jest.clearAllMocks();
|
|
15
|
+
mockFs.existsSync.mockReturnValue(true);
|
|
16
|
+
mockFs.writeFileSync.mockImplementation(() => { });
|
|
17
|
+
jest.spyOn(console, 'log').mockImplementation();
|
|
18
|
+
program = new commander_1.Command();
|
|
19
|
+
});
|
|
20
|
+
afterEach(() => {
|
|
21
|
+
jest.restoreAllMocks();
|
|
22
|
+
});
|
|
23
|
+
it('should generate an agent file with correct suffix', async () => {
|
|
24
|
+
(0, generate_agent_1.generateAgent)(program);
|
|
25
|
+
await program.parseAsync(['node', 'test', 'agent', 'research']);
|
|
26
|
+
expect(mockFs.writeFileSync).toHaveBeenCalledWith(expect.stringContaining('research.agent.ts'), expect.stringContaining('ResearchAgent'));
|
|
27
|
+
});
|
|
28
|
+
it('should import from @hazeljs/agent', async () => {
|
|
29
|
+
(0, generate_agent_1.generateAgent)(program);
|
|
30
|
+
await program.parseAsync(['node', 'test', 'agent', 'research']);
|
|
31
|
+
const writtenContent = mockFs.writeFileSync.mock.calls[0][1];
|
|
32
|
+
expect(writtenContent).toContain("from '@hazeljs/agent'");
|
|
33
|
+
expect(writtenContent).toContain('@Agent');
|
|
34
|
+
expect(writtenContent).toContain('@Tool');
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
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 { Service } from '@hazeljs/core';
|
|
6
|
+
import { AIService, AIFunction, AIPrompt } from '@hazeljs/ai';
|
|
7
|
+
|
|
8
|
+
@Service()
|
|
9
|
+
export class {{className}}AIService {
|
|
10
|
+
constructor(private readonly aiService: AIService) {}
|
|
11
|
+
|
|
12
|
+
@AIFunction({
|
|
13
|
+
provider: 'openai',
|
|
14
|
+
model: 'gpt-4',
|
|
15
|
+
streaming: false,
|
|
16
|
+
})
|
|
17
|
+
async {{camelName}}Task(@AIPrompt() prompt: string): Promise<unknown> {
|
|
18
|
+
const result = await this.aiService.complete({
|
|
19
|
+
provider: 'openai',
|
|
20
|
+
model: 'gpt-4',
|
|
21
|
+
messages: [{ role: 'user', content: prompt }],
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
`;
|
|
28
|
+
class AIServiceGenerator extends generator_1.Generator {
|
|
29
|
+
constructor() {
|
|
30
|
+
super(...arguments);
|
|
31
|
+
this.suffix = 'ai-service';
|
|
32
|
+
}
|
|
33
|
+
getDefaultTemplate() {
|
|
34
|
+
return AI_SERVICE_TEMPLATE;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function generateAIService(program) {
|
|
38
|
+
program
|
|
39
|
+
.command('ai-service <name>')
|
|
40
|
+
.description('Generate a new AI service with decorators')
|
|
41
|
+
.alias('ai')
|
|
42
|
+
.option('-p, --path <path>', 'Path where the AI service should be generated')
|
|
43
|
+
.option('--dry-run', 'Preview files without writing them')
|
|
44
|
+
.action(async (name, options) => {
|
|
45
|
+
const generator = new AIServiceGenerator();
|
|
46
|
+
await generator.generate({ name, path: options.path, dryRun: options.dryRun });
|
|
47
|
+
});
|
|
48
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
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
|
+
const fs_1 = __importDefault(require("fs"));
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const generate_ai_service_1 = require("./generate-ai-service");
|
|
9
|
+
jest.mock('fs');
|
|
10
|
+
describe('generateAIService', () => {
|
|
11
|
+
const mockFs = fs_1.default;
|
|
12
|
+
let program;
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
jest.clearAllMocks();
|
|
15
|
+
mockFs.existsSync.mockReturnValue(true);
|
|
16
|
+
mockFs.writeFileSync.mockImplementation(() => { });
|
|
17
|
+
jest.spyOn(console, 'log').mockImplementation();
|
|
18
|
+
program = new commander_1.Command();
|
|
19
|
+
});
|
|
20
|
+
afterEach(() => {
|
|
21
|
+
jest.restoreAllMocks();
|
|
22
|
+
});
|
|
23
|
+
it('should register the ai-service command with alias', () => {
|
|
24
|
+
(0, generate_ai_service_1.generateAIService)(program);
|
|
25
|
+
const cmd = program.commands.find(c => c.name() === 'ai-service');
|
|
26
|
+
expect(cmd).toBeDefined();
|
|
27
|
+
expect(cmd?.alias()).toBe('ai');
|
|
28
|
+
});
|
|
29
|
+
it('should generate an AI service file with correct suffix', async () => {
|
|
30
|
+
(0, generate_ai_service_1.generateAIService)(program);
|
|
31
|
+
await program.parseAsync(['node', 'test', 'ai-service', 'chat']);
|
|
32
|
+
expect(mockFs.writeFileSync).toHaveBeenCalledWith(expect.stringContaining('chat.ai-service.ts'), expect.stringContaining('ChatAIService'));
|
|
33
|
+
});
|
|
34
|
+
it('should import from @hazeljs/ai', async () => {
|
|
35
|
+
(0, generate_ai_service_1.generateAIService)(program);
|
|
36
|
+
await program.parseAsync(['node', 'test', 'ai-service', 'chat']);
|
|
37
|
+
const writtenContent = mockFs.writeFileSync.mock.calls[0][1];
|
|
38
|
+
expect(writtenContent).toContain("from '@hazeljs/ai'");
|
|
39
|
+
expect(writtenContent).toContain('AIFunction');
|
|
40
|
+
});
|
|
41
|
+
});
|