@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.
Files changed (121) hide show
  1. package/@template/.eslintrc.js +36 -0
  2. package/@template/.lintstagedrc +6 -0
  3. package/@template/README.md +61 -0
  4. package/@template/jest.config.js +28 -0
  5. package/@template/jest.setup.js +81 -0
  6. package/@template/package.json +34 -0
  7. package/@template/src/app.module.ts +7 -0
  8. package/@template/src/hello.controller.ts +9 -0
  9. package/@template/src/index.ts +18 -0
  10. package/@template/tsconfig.json +25 -0
  11. package/LICENSE +192 -0
  12. package/README.md +683 -0
  13. package/dist/commands/add.d.ts +2 -0
  14. package/dist/commands/add.js +176 -0
  15. package/dist/commands/add.test.d.ts +1 -0
  16. package/dist/commands/add.test.js +51 -0
  17. package/dist/commands/build.d.ts +2 -0
  18. package/dist/commands/build.js +52 -0
  19. package/dist/commands/generate-agent.d.ts +2 -0
  20. package/dist/commands/generate-agent.js +58 -0
  21. package/dist/commands/generate-agent.test.d.ts +1 -0
  22. package/dist/commands/generate-agent.test.js +36 -0
  23. package/dist/commands/generate-ai-service.d.ts +2 -0
  24. package/dist/commands/generate-ai-service.js +48 -0
  25. package/dist/commands/generate-ai-service.test.d.ts +1 -0
  26. package/dist/commands/generate-ai-service.test.js +41 -0
  27. package/dist/commands/generate-app.d.ts +2 -0
  28. package/dist/commands/generate-app.js +448 -0
  29. package/dist/commands/generate-auth.d.ts +2 -0
  30. package/dist/commands/generate-auth.js +194 -0
  31. package/dist/commands/generate-auth.test.d.ts +1 -0
  32. package/dist/commands/generate-auth.test.js +48 -0
  33. package/dist/commands/generate-cache.d.ts +2 -0
  34. package/dist/commands/generate-cache.js +64 -0
  35. package/dist/commands/generate-cache.test.d.ts +1 -0
  36. package/dist/commands/generate-cache.test.js +36 -0
  37. package/dist/commands/generate-config.d.ts +2 -0
  38. package/dist/commands/generate-config.js +57 -0
  39. package/dist/commands/generate-config.test.d.ts +1 -0
  40. package/dist/commands/generate-config.test.js +35 -0
  41. package/dist/commands/generate-controller.d.ts +2 -0
  42. package/dist/commands/generate-controller.js +60 -0
  43. package/dist/commands/generate-controller.test.d.ts +1 -0
  44. package/dist/commands/generate-controller.test.js +48 -0
  45. package/dist/commands/generate-cron.d.ts +2 -0
  46. package/dist/commands/generate-cron.js +59 -0
  47. package/dist/commands/generate-cron.test.d.ts +1 -0
  48. package/dist/commands/generate-cron.test.js +42 -0
  49. package/dist/commands/generate-crud.d.ts +2 -0
  50. package/dist/commands/generate-crud.js +177 -0
  51. package/dist/commands/generate-crud.test.d.ts +1 -0
  52. package/dist/commands/generate-crud.test.js +52 -0
  53. package/dist/commands/generate-discovery.d.ts +2 -0
  54. package/dist/commands/generate-discovery.js +61 -0
  55. package/dist/commands/generate-discovery.test.d.ts +1 -0
  56. package/dist/commands/generate-discovery.test.js +36 -0
  57. package/dist/commands/generate-dto.d.ts +2 -0
  58. package/dist/commands/generate-dto.js +69 -0
  59. package/dist/commands/generate-dto.test.d.ts +1 -0
  60. package/dist/commands/generate-dto.test.js +44 -0
  61. package/dist/commands/generate-exception-filter.d.ts +2 -0
  62. package/dist/commands/generate-exception-filter.js +48 -0
  63. package/dist/commands/generate-exception-filter.test.d.ts +1 -0
  64. package/dist/commands/generate-exception-filter.test.js +43 -0
  65. package/dist/commands/generate-guard.d.ts +2 -0
  66. package/dist/commands/generate-guard.js +36 -0
  67. package/dist/commands/generate-guard.test.d.ts +1 -0
  68. package/dist/commands/generate-guard.test.js +41 -0
  69. package/dist/commands/generate-interceptor.d.ts +2 -0
  70. package/dist/commands/generate-interceptor.js +37 -0
  71. package/dist/commands/generate-interceptor.test.d.ts +1 -0
  72. package/dist/commands/generate-interceptor.test.js +41 -0
  73. package/dist/commands/generate-middleware.d.ts +2 -0
  74. package/dist/commands/generate-middleware.js +46 -0
  75. package/dist/commands/generate-middleware.test.d.ts +1 -0
  76. package/dist/commands/generate-middleware.test.js +41 -0
  77. package/dist/commands/generate-module.d.ts +2 -0
  78. package/dist/commands/generate-module.js +106 -0
  79. package/dist/commands/generate-module.test.d.ts +1 -0
  80. package/dist/commands/generate-module.test.js +54 -0
  81. package/dist/commands/generate-pipe.d.ts +2 -0
  82. package/dist/commands/generate-pipe.js +33 -0
  83. package/dist/commands/generate-pipe.test.d.ts +1 -0
  84. package/dist/commands/generate-pipe.test.js +35 -0
  85. package/dist/commands/generate-rag.d.ts +2 -0
  86. package/dist/commands/generate-rag.js +66 -0
  87. package/dist/commands/generate-rag.test.d.ts +1 -0
  88. package/dist/commands/generate-rag.test.js +35 -0
  89. package/dist/commands/generate-repository.d.ts +2 -0
  90. package/dist/commands/generate-repository.js +40 -0
  91. package/dist/commands/generate-repository.test.d.ts +1 -0
  92. package/dist/commands/generate-repository.test.js +41 -0
  93. package/dist/commands/generate-serverless-handler.d.ts +2 -0
  94. package/dist/commands/generate-serverless-handler.js +46 -0
  95. package/dist/commands/generate-serverless-handler.test.d.ts +1 -0
  96. package/dist/commands/generate-serverless-handler.test.js +42 -0
  97. package/dist/commands/generate-service.d.ts +2 -0
  98. package/dist/commands/generate-service.js +52 -0
  99. package/dist/commands/generate-service.test.d.ts +1 -0
  100. package/dist/commands/generate-service.test.js +41 -0
  101. package/dist/commands/generate-websocket-gateway.d.ts +2 -0
  102. package/dist/commands/generate-websocket-gateway.js +47 -0
  103. package/dist/commands/generate-websocket-gateway.test.d.ts +1 -0
  104. package/dist/commands/generate-websocket-gateway.test.js +41 -0
  105. package/dist/commands/info.d.ts +2 -0
  106. package/dist/commands/info.js +91 -0
  107. package/dist/commands/pdf-to-audio.d.ts +2 -0
  108. package/dist/commands/pdf-to-audio.js +170 -0
  109. package/dist/commands/start.d.ts +2 -0
  110. package/dist/commands/start.js +61 -0
  111. package/dist/commands/test.d.ts +2 -0
  112. package/dist/commands/test.js +63 -0
  113. package/dist/index.d.ts +2 -0
  114. package/dist/index.js +75 -0
  115. package/dist/index.test.d.ts +1 -0
  116. package/dist/index.test.js +93 -0
  117. package/dist/utils/generator.d.ts +25 -0
  118. package/dist/utils/generator.js +107 -0
  119. package/dist/utils/generator.test.d.ts +1 -0
  120. package/dist/utils/generator.test.js +137 -0
  121. package/package.json +73 -0
@@ -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
+ const fs_1 = __importDefault(require("fs"));
7
+ const commander_1 = require("commander");
8
+ const generate_crud_1 = require("./generate-crud");
9
+ jest.mock('fs');
10
+ describe('generateCrud', () => {
11
+ const mockFs = fs_1.default;
12
+ let program;
13
+ beforeEach(() => {
14
+ jest.clearAllMocks();
15
+ mockFs.existsSync.mockReturnValue(false);
16
+ mockFs.mkdirSync.mockImplementation(() => undefined);
17
+ mockFs.writeFileSync.mockImplementation(() => { });
18
+ jest.spyOn(console, 'log').mockImplementation();
19
+ program = new commander_1.Command();
20
+ });
21
+ afterEach(() => {
22
+ jest.restoreAllMocks();
23
+ });
24
+ it('should generate all CRUD files', async () => {
25
+ (0, generate_crud_1.generateCrud)(program);
26
+ await program.parseAsync(['node', 'test', 'crud', 'product']);
27
+ const writtenFiles = mockFs.writeFileSync.mock.calls.map(call => call[0]);
28
+ expect(writtenFiles.some(f => f.includes('product.controller.ts'))).toBe(true);
29
+ expect(writtenFiles.some(f => f.includes('product.service.ts'))).toBe(true);
30
+ expect(writtenFiles.some(f => f.includes('product.dto.ts'))).toBe(true);
31
+ expect(writtenFiles.some(f => f.includes('product.module.ts'))).toBe(true);
32
+ });
33
+ it('should use @hazeljs/core imports', async () => {
34
+ (0, generate_crud_1.generateCrud)(program);
35
+ await program.parseAsync(['node', 'test', 'crud', 'product']);
36
+ const controllerContent = mockFs.writeFileSync.mock.calls
37
+ .find(call => call[0].includes('controller'))?.[1];
38
+ expect(controllerContent).toContain("from '@hazeljs/core'");
39
+ });
40
+ it('should support --dry-run flag', async () => {
41
+ (0, generate_crud_1.generateCrud)(program);
42
+ await program.parseAsync(['node', 'test', 'crud', 'product', '--dry-run']);
43
+ expect(mockFs.writeFileSync).not.toHaveBeenCalled();
44
+ });
45
+ it('should support custom route path', async () => {
46
+ (0, generate_crud_1.generateCrud)(program);
47
+ await program.parseAsync(['node', 'test', 'crud', 'product', '-r', 'api/products']);
48
+ const controllerContent = mockFs.writeFileSync.mock.calls
49
+ .find(call => call[0].includes('controller'))?.[1];
50
+ expect(controllerContent).toContain('api/products');
51
+ });
52
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function generateDiscovery(command: Command): void;
@@ -0,0 +1,61 @@
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.generateDiscovery = generateDiscovery;
7
+ const generator_1 = require("../utils/generator");
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const DISCOVERY_TEMPLATE = `import { Service } from '@hazeljs/core';
10
+ import { ServiceRegistry, DiscoveryClient } from '@hazeljs/discovery';
11
+
12
+ @Service()
13
+ export class {{className}}DiscoveryService {
14
+ constructor(
15
+ private readonly registry: ServiceRegistry,
16
+ private readonly client: DiscoveryClient,
17
+ ) {}
18
+
19
+ async registerService() {
20
+ await this.registry.register({
21
+ name: '{{fileName}}-service',
22
+ host: 'localhost',
23
+ port: 3000,
24
+ metadata: {
25
+ version: '1.0.0',
26
+ },
27
+ });
28
+ }
29
+
30
+ async discoverService(serviceName: string) {
31
+ const instances = await this.client.getInstances(serviceName);
32
+ return instances;
33
+ }
34
+ }
35
+ `;
36
+ class DiscoveryGenerator extends generator_1.Generator {
37
+ constructor() {
38
+ super(...arguments);
39
+ this.suffix = 'discovery';
40
+ }
41
+ getDefaultTemplate() {
42
+ return DISCOVERY_TEMPLATE;
43
+ }
44
+ }
45
+ function generateDiscovery(command) {
46
+ command
47
+ .command('discovery <name>')
48
+ .description('Generate a service discovery setup')
49
+ .option('-p, --path <path>', 'Specify the path')
50
+ .option('--dry-run', 'Preview files without writing them')
51
+ .action(async (name, options) => {
52
+ const generator = new DiscoveryGenerator();
53
+ await generator.generate({ name, path: options.path, dryRun: options.dryRun });
54
+ if (!options.dryRun) {
55
+ console.log(chalk_1.default.gray('\nNext steps:'));
56
+ console.log(chalk_1.default.gray(' 1. npm install @hazeljs/discovery'));
57
+ console.log(chalk_1.default.gray(' 2. Register this service as a provider in your module'));
58
+ console.log(chalk_1.default.gray(' 3. Configure your discovery backend (memory, redis, consul, or kubernetes)'));
59
+ }
60
+ });
61
+ }
@@ -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_discovery_1 = require("./generate-discovery");
9
+ jest.mock('fs');
10
+ describe('generateDiscovery', () => {
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 a discovery service file', async () => {
24
+ (0, generate_discovery_1.generateDiscovery)(program);
25
+ await program.parseAsync(['node', 'test', 'discovery', 'app']);
26
+ expect(mockFs.writeFileSync).toHaveBeenCalledWith(expect.stringContaining('app.discovery.ts'), expect.stringContaining('AppDiscoveryService'));
27
+ });
28
+ it('should import from @hazeljs/discovery', async () => {
29
+ (0, generate_discovery_1.generateDiscovery)(program);
30
+ await program.parseAsync(['node', 'test', 'discovery', 'app']);
31
+ const writtenContent = mockFs.writeFileSync.mock.calls[0][1];
32
+ expect(writtenContent).toContain("from '@hazeljs/discovery'");
33
+ expect(writtenContent).toContain('ServiceRegistry');
34
+ expect(writtenContent).toContain('DiscoveryClient');
35
+ });
36
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function generateDto(program: Command): void;
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateDto = generateDto;
4
+ const generator_1 = require("../utils/generator");
5
+ const CREATE_DTO_TEMPLATE = `import { IsString, IsOptional } from 'class-validator';
6
+
7
+ export class Create{{className}}Dto {
8
+ @IsString()
9
+ name: string;
10
+
11
+ @IsString()
12
+ @IsOptional()
13
+ description?: string;
14
+ }
15
+ `;
16
+ const UPDATE_DTO_TEMPLATE = `import { IsString, IsOptional } from 'class-validator';
17
+
18
+ export class Update{{className}}Dto {
19
+ @IsString()
20
+ @IsOptional()
21
+ name?: string;
22
+
23
+ @IsString()
24
+ @IsOptional()
25
+ description?: string;
26
+ }
27
+ `;
28
+ class DtoGenerator extends generator_1.Generator {
29
+ constructor() {
30
+ super(...arguments);
31
+ this.suffix = 'dto';
32
+ }
33
+ getDefaultTemplate() {
34
+ return CREATE_DTO_TEMPLATE;
35
+ }
36
+ async generate(options) {
37
+ // Generate create DTO
38
+ await super.generate({
39
+ ...options,
40
+ template: CREATE_DTO_TEMPLATE,
41
+ path: options.path ? `${options.path}/dto` : 'src/dto',
42
+ });
43
+ // Generate update DTO — use a different file name
44
+ const origSuffix = this.suffix;
45
+ this.suffix = 'dto';
46
+ const updateOptions = {
47
+ ...options,
48
+ name: `update-${options.name}`,
49
+ template: UPDATE_DTO_TEMPLATE,
50
+ path: options.path ? `${options.path}/dto` : 'src/dto',
51
+ };
52
+ // Override suffix for the update variant — we prepend "update-" to the name
53
+ // so the file is update-<name>.dto.ts rather than <name>.dto.ts (which would conflict)
54
+ await super.generate(updateOptions);
55
+ this.suffix = origSuffix;
56
+ }
57
+ }
58
+ function generateDto(program) {
59
+ program
60
+ .command('dto <name>')
61
+ .description('Generate create and update DTOs')
62
+ .alias('d')
63
+ .option('-p, --path <path>', 'Path where the DTOs should be generated')
64
+ .option('--dry-run', 'Preview files without writing them')
65
+ .action(async (name, options) => {
66
+ const generator = new DtoGenerator();
67
+ await generator.generate({ name, path: options.path, dryRun: options.dryRun });
68
+ });
69
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,44 @@
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_dto_1 = require("./generate-dto");
9
+ jest.mock('fs');
10
+ describe('generateDto', () => {
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 dto command with alias', () => {
24
+ (0, generate_dto_1.generateDto)(program);
25
+ const cmd = program.commands.find(c => c.name() === 'dto');
26
+ expect(cmd).toBeDefined();
27
+ expect(cmd?.alias()).toBe('d');
28
+ });
29
+ it('should generate both create and update DTOs', async () => {
30
+ (0, generate_dto_1.generateDto)(program);
31
+ await program.parseAsync(['node', 'test', 'dto', 'user']);
32
+ expect(mockFs.writeFileSync).toHaveBeenCalledTimes(2);
33
+ const writtenFiles = mockFs.writeFileSync.mock.calls.map(call => call[0]);
34
+ expect(writtenFiles.some(f => f.includes('user.dto.ts'))).toBe(true);
35
+ expect(writtenFiles.some(f => f.includes('update-user.dto.ts'))).toBe(true);
36
+ });
37
+ it('should include class-validator decorators', async () => {
38
+ (0, generate_dto_1.generateDto)(program);
39
+ await program.parseAsync(['node', 'test', 'dto', 'user']);
40
+ const writtenContent = mockFs.writeFileSync.mock.calls[0][1];
41
+ expect(writtenContent).toContain('class-validator');
42
+ expect(writtenContent).toContain('IsString');
43
+ });
44
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function generateExceptionFilter(program: Command): void;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateExceptionFilter = generateExceptionFilter;
4
+ const generator_1 = require("../utils/generator");
5
+ const EXCEPTION_FILTER_TEMPLATE = `import { Catch, type ExceptionFilter, type ArgumentsHost, HttpError, logger } from '@hazeljs/core';
6
+
7
+ @Catch(HttpError)
8
+ export class {{className}}ExceptionFilter implements ExceptionFilter<HttpError> {
9
+ catch(exception: HttpError, host: ArgumentsHost): void {
10
+ const ctx = host.switchToHttp();
11
+ const response = ctx.getResponse();
12
+ const request = ctx.getRequest();
13
+
14
+ const status = exception.statusCode || 500;
15
+ const message = exception.message || 'Internal server error';
16
+
17
+ logger.error(\`[\${request.method}] \${request.url} - \${message} (\${status})\`);
18
+
19
+ response.status(status).json({
20
+ statusCode: status,
21
+ message,
22
+ timestamp: new Date().toISOString(),
23
+ path: request.url,
24
+ });
25
+ }
26
+ }
27
+ `;
28
+ class ExceptionFilterGenerator extends generator_1.Generator {
29
+ constructor() {
30
+ super(...arguments);
31
+ this.suffix = 'filter';
32
+ }
33
+ getDefaultTemplate() {
34
+ return EXCEPTION_FILTER_TEMPLATE;
35
+ }
36
+ }
37
+ function generateExceptionFilter(program) {
38
+ program
39
+ .command('filter <name>')
40
+ .description('Generate a new exception filter')
41
+ .alias('f')
42
+ .option('-p, --path <path>', 'Path where the filter should be generated')
43
+ .option('--dry-run', 'Preview files without writing them')
44
+ .action(async (name, options) => {
45
+ const generator = new ExceptionFilterGenerator();
46
+ await generator.generate({ name, path: options.path, dryRun: options.dryRun });
47
+ });
48
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,43 @@
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_exception_filter_1 = require("./generate-exception-filter");
9
+ jest.mock('fs');
10
+ describe('generateExceptionFilter', () => {
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 filter command with alias', () => {
24
+ (0, generate_exception_filter_1.generateExceptionFilter)(program);
25
+ const cmd = program.commands.find(c => c.name() === 'filter');
26
+ expect(cmd).toBeDefined();
27
+ expect(cmd?.alias()).toBe('f');
28
+ });
29
+ it('should generate a filter file with correct suffix', async () => {
30
+ (0, generate_exception_filter_1.generateExceptionFilter)(program);
31
+ await program.parseAsync(['node', 'test', 'filter', 'http']);
32
+ expect(mockFs.writeFileSync).toHaveBeenCalledWith(expect.stringContaining('http.filter.ts'), expect.stringContaining('HttpExceptionFilter'));
33
+ });
34
+ it('should import correctly from @hazeljs/core', async () => {
35
+ (0, generate_exception_filter_1.generateExceptionFilter)(program);
36
+ await program.parseAsync(['node', 'test', 'filter', 'http']);
37
+ const writtenContent = mockFs.writeFileSync.mock.calls[0][1];
38
+ expect(writtenContent).toContain("from '@hazeljs/core'");
39
+ expect(writtenContent).toContain('Catch');
40
+ expect(writtenContent).toContain('logger');
41
+ expect(writtenContent).not.toContain("import logger from");
42
+ });
43
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function generateGuard(program: Command): void;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateGuard = generateGuard;
4
+ const generator_1 = require("../utils/generator");
5
+ const GUARD_TEMPLATE = `import { Injectable, type CanActivate, type ExecutionContext } from '@hazeljs/core';
6
+
7
+ @Injectable()
8
+ export class {{className}}Guard implements CanActivate {
9
+ canActivate(context: ExecutionContext): boolean {
10
+ const request = context.switchToHttp().getRequest();
11
+ // Add your guard logic here
12
+ return true;
13
+ }
14
+ }
15
+ `;
16
+ class GuardGenerator extends generator_1.Generator {
17
+ constructor() {
18
+ super(...arguments);
19
+ this.suffix = 'guard';
20
+ }
21
+ getDefaultTemplate() {
22
+ return GUARD_TEMPLATE;
23
+ }
24
+ }
25
+ function generateGuard(program) {
26
+ program
27
+ .command('guard <name>')
28
+ .description('Generate a new guard')
29
+ .alias('gu')
30
+ .option('-p, --path <path>', 'Path where the guard should be generated')
31
+ .option('--dry-run', 'Preview files without writing them')
32
+ .action(async (name, options) => {
33
+ const generator = new GuardGenerator();
34
+ await generator.generate({ name, path: options.path, dryRun: options.dryRun });
35
+ });
36
+ }
@@ -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_guard_1 = require("./generate-guard");
9
+ jest.mock('fs');
10
+ describe('generateGuard', () => {
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 guard command with alias', () => {
24
+ (0, generate_guard_1.generateGuard)(program);
25
+ const cmd = program.commands.find(c => c.name() === 'guard');
26
+ expect(cmd).toBeDefined();
27
+ expect(cmd?.alias()).toBe('gu');
28
+ });
29
+ it('should generate a guard file with correct suffix', async () => {
30
+ (0, generate_guard_1.generateGuard)(program);
31
+ await program.parseAsync(['node', 'test', 'guard', 'auth']);
32
+ expect(mockFs.writeFileSync).toHaveBeenCalledWith(expect.stringContaining('auth.guard.ts'), expect.stringContaining('AuthGuard'));
33
+ });
34
+ it('should include CanActivate interface', async () => {
35
+ (0, generate_guard_1.generateGuard)(program);
36
+ await program.parseAsync(['node', 'test', 'guard', 'auth']);
37
+ const writtenContent = mockFs.writeFileSync.mock.calls[0][1];
38
+ expect(writtenContent).toContain('CanActivate');
39
+ expect(writtenContent).toContain('canActivate');
40
+ });
41
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function generateInterceptor(program: Command): void;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateInterceptor = generateInterceptor;
4
+ const generator_1 = require("../utils/generator");
5
+ const INTERCEPTOR_TEMPLATE = `import { Injectable, Interceptor, type ExecutionContext } from '@hazeljs/core';
6
+
7
+ @Injectable()
8
+ export class {{className}}Interceptor implements Interceptor {
9
+ async intercept(context: ExecutionContext, next: () => Promise<unknown>): Promise<unknown> {
10
+ // Pre-processing logic here (before handler execution)
11
+ const result = await next();
12
+ // Post-processing logic here (after handler execution)
13
+ return result;
14
+ }
15
+ }
16
+ `;
17
+ class InterceptorGenerator extends generator_1.Generator {
18
+ constructor() {
19
+ super(...arguments);
20
+ this.suffix = 'interceptor';
21
+ }
22
+ getDefaultTemplate() {
23
+ return INTERCEPTOR_TEMPLATE;
24
+ }
25
+ }
26
+ function generateInterceptor(program) {
27
+ program
28
+ .command('interceptor <name>')
29
+ .description('Generate a new interceptor')
30
+ .alias('i')
31
+ .option('-p, --path <path>', 'Path where the interceptor should be generated')
32
+ .option('--dry-run', 'Preview files without writing them')
33
+ .action(async (name, options) => {
34
+ const generator = new InterceptorGenerator();
35
+ await generator.generate({ name, path: options.path, dryRun: options.dryRun });
36
+ });
37
+ }
@@ -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_interceptor_1 = require("./generate-interceptor");
9
+ jest.mock('fs');
10
+ describe('generateInterceptor', () => {
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 interceptor command with alias', () => {
24
+ (0, generate_interceptor_1.generateInterceptor)(program);
25
+ const cmd = program.commands.find(c => c.name() === 'interceptor');
26
+ expect(cmd).toBeDefined();
27
+ expect(cmd?.alias()).toBe('i');
28
+ });
29
+ it('should generate an interceptor file with correct suffix', async () => {
30
+ (0, generate_interceptor_1.generateInterceptor)(program);
31
+ await program.parseAsync(['node', 'test', 'interceptor', 'logging']);
32
+ expect(mockFs.writeFileSync).toHaveBeenCalledWith(expect.stringContaining('logging.interceptor.ts'), expect.stringContaining('LoggingInterceptor'));
33
+ });
34
+ it('should implement the Interceptor interface', async () => {
35
+ (0, generate_interceptor_1.generateInterceptor)(program);
36
+ await program.parseAsync(['node', 'test', 'interceptor', 'logging']);
37
+ const writtenContent = mockFs.writeFileSync.mock.calls[0][1];
38
+ expect(writtenContent).toContain('implements Interceptor');
39
+ expect(writtenContent).toContain('intercept');
40
+ });
41
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function generateMiddleware(command: Command): void;
@@ -0,0 +1,46 @@
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.generateMiddleware = generateMiddleware;
7
+ const generator_1 = require("../utils/generator");
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const MIDDLEWARE_TEMPLATE = `import { Injectable, type MiddlewareHandler, type Request, type Response, type NextFunction } from '@hazeljs/core';
10
+
11
+ @Injectable()
12
+ export class {{className}}Middleware implements MiddlewareHandler {
13
+ use(req: Request, res: Response, next: NextFunction) {
14
+ // Add your middleware logic here
15
+ console.log(\`[{{className}}Middleware] \${req.method} \${req.url}\`);
16
+
17
+ // Continue to next middleware
18
+ next();
19
+ }
20
+ }
21
+ `;
22
+ class MiddlewareGenerator extends generator_1.Generator {
23
+ constructor() {
24
+ super(...arguments);
25
+ this.suffix = 'middleware';
26
+ }
27
+ getDefaultTemplate() {
28
+ return MIDDLEWARE_TEMPLATE;
29
+ }
30
+ }
31
+ function generateMiddleware(command) {
32
+ command
33
+ .command('middleware <name>')
34
+ .alias('mw')
35
+ .description('Generate a middleware')
36
+ .option('-p, --path <path>', 'Specify the path', 'src/middleware')
37
+ .option('--dry-run', 'Preview files without writing them')
38
+ .action(async (name, options) => {
39
+ const generator = new MiddlewareGenerator();
40
+ await generator.generate({ name, path: options.path, dryRun: options.dryRun });
41
+ if (!options.dryRun) {
42
+ console.log(chalk_1.default.gray('\nUsage:'));
43
+ console.log(chalk_1.default.gray(` Import the middleware in your module or apply it globally.`));
44
+ }
45
+ });
46
+ }
@@ -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_middleware_1 = require("./generate-middleware");
9
+ jest.mock('fs');
10
+ describe('generateMiddleware', () => {
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 middleware command with alias', () => {
24
+ (0, generate_middleware_1.generateMiddleware)(program);
25
+ const cmd = program.commands.find(c => c.name() === 'middleware');
26
+ expect(cmd).toBeDefined();
27
+ expect(cmd?.alias()).toBe('mw');
28
+ });
29
+ it('should generate a middleware file with correct suffix', async () => {
30
+ (0, generate_middleware_1.generateMiddleware)(program);
31
+ await program.parseAsync(['node', 'test', 'middleware', 'logger']);
32
+ expect(mockFs.writeFileSync).toHaveBeenCalledWith(expect.stringContaining('logger.middleware.ts'), expect.stringContaining('LoggerMiddleware'));
33
+ });
34
+ it('should import from @hazeljs/core not express', async () => {
35
+ (0, generate_middleware_1.generateMiddleware)(program);
36
+ await program.parseAsync(['node', 'test', 'middleware', 'logger']);
37
+ const writtenContent = mockFs.writeFileSync.mock.calls[0][1];
38
+ expect(writtenContent).toContain("from '@hazeljs/core'");
39
+ expect(writtenContent).not.toContain("from 'express'");
40
+ });
41
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function generateModule(program: Command): void;