@hazeljs/cli 0.2.0-rc.7 → 0.2.0

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 (73) hide show
  1. package/@template/src/hello.controller.ts +1 -1
  2. package/README.md +40 -3
  3. package/dist/commands/generate-agent.d.ts +2 -0
  4. package/dist/commands/generate-agent.js +13 -7
  5. package/dist/commands/generate-ai-service.d.ts +2 -0
  6. package/dist/commands/generate-ai-service.js +8 -2
  7. package/dist/commands/generate-app.d.ts +7 -0
  8. package/dist/commands/generate-app.interactive-packages.test.d.ts +1 -0
  9. package/dist/commands/generate-app.interactive-packages.test.js +107 -0
  10. package/dist/commands/generate-app.js +141 -0
  11. package/dist/commands/generate-app.new-command.test.d.ts +1 -0
  12. package/dist/commands/generate-app.new-command.test.js +86 -0
  13. package/dist/commands/generate-app.skeleton.test.d.ts +1 -0
  14. package/dist/commands/generate-app.skeleton.test.js +51 -0
  15. package/dist/commands/generate-auth.d.ts +2 -0
  16. package/dist/commands/generate-auth.js +39 -40
  17. package/dist/commands/generate-cache.d.ts +2 -0
  18. package/dist/commands/generate-cache.js +14 -12
  19. package/dist/commands/generate-config.d.ts +2 -0
  20. package/dist/commands/generate-config.js +14 -12
  21. package/dist/commands/generate-controller.d.ts +2 -0
  22. package/dist/commands/generate-controller.js +8 -2
  23. package/dist/commands/generate-cron.d.ts +2 -0
  24. package/dist/commands/generate-cron.js +14 -12
  25. package/dist/commands/generate-crud.d.ts +2 -0
  26. package/dist/commands/generate-crud.js +44 -33
  27. package/dist/commands/generate-discovery.d.ts +2 -0
  28. package/dist/commands/generate-discovery.js +14 -12
  29. package/dist/commands/generate-dto.d.ts +2 -0
  30. package/dist/commands/generate-dto.js +15 -6
  31. package/dist/commands/generate-exception-filter.d.ts +2 -0
  32. package/dist/commands/generate-exception-filter.js +8 -2
  33. package/dist/commands/generate-guard.d.ts +2 -0
  34. package/dist/commands/generate-guard.js +8 -2
  35. package/dist/commands/generate-interceptor.d.ts +2 -0
  36. package/dist/commands/generate-interceptor.js +8 -2
  37. package/dist/commands/generate-middleware.d.ts +2 -0
  38. package/dist/commands/generate-middleware.js +11 -10
  39. package/dist/commands/generate-module.d.ts +2 -0
  40. package/dist/commands/generate-module.js +35 -31
  41. package/dist/commands/generate-pipe.d.ts +2 -0
  42. package/dist/commands/generate-pipe.js +8 -2
  43. package/dist/commands/generate-rag.d.ts +2 -0
  44. package/dist/commands/generate-rag.js +14 -12
  45. package/dist/commands/generate-repository.d.ts +2 -0
  46. package/dist/commands/generate-repository.js +8 -2
  47. package/dist/commands/generate-serverless-handler.d.ts +2 -0
  48. package/dist/commands/generate-serverless-handler.js +14 -3
  49. package/dist/commands/generate-service.d.ts +2 -0
  50. package/dist/commands/generate-service.js +8 -2
  51. package/dist/commands/generate-setup.d.ts +4 -0
  52. package/dist/commands/generate-setup.js +187 -0
  53. package/dist/commands/generate-setup.test.d.ts +1 -0
  54. package/dist/commands/generate-setup.test.js +50 -0
  55. package/dist/commands/generate-websocket-gateway.d.ts +2 -0
  56. package/dist/commands/generate-websocket-gateway.js +8 -2
  57. package/dist/commands/info.test.d.ts +1 -0
  58. package/dist/commands/info.test.js +58 -0
  59. package/dist/commands/pdf-to-audio.test.d.ts +1 -0
  60. package/dist/commands/pdf-to-audio.test.js +92 -0
  61. package/dist/commands/utility-commands.test.d.ts +1 -0
  62. package/dist/commands/utility-commands.test.js +95 -0
  63. package/dist/index.js +32 -3
  64. package/dist/index.list.test.d.ts +0 -0
  65. package/dist/index.list.test.js +70 -0
  66. package/dist/utils/generator-registry.d.ts +15 -0
  67. package/dist/utils/generator-registry.js +97 -0
  68. package/dist/utils/generator-registry.test.d.ts +1 -0
  69. package/dist/utils/generator-registry.test.js +10 -0
  70. package/dist/utils/generator.d.ts +21 -1
  71. package/dist/utils/generator.js +23 -4
  72. package/dist/utils/generator.test.js +5 -4
  73. package/package.json +2 -2
@@ -1,11 +1,8 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runMiddleware = runMiddleware;
6
4
  exports.generateMiddleware = generateMiddleware;
7
5
  const generator_1 = require("../utils/generator");
8
- const chalk_1 = __importDefault(require("chalk"));
9
6
  const MIDDLEWARE_TEMPLATE = `import { Injectable, type MiddlewareHandler, type Request, type Response, type NextFunction } from '@hazeljs/core';
10
7
 
11
8
  @Injectable()
@@ -28,6 +25,13 @@ class MiddlewareGenerator extends generator_1.Generator {
28
25
  return MIDDLEWARE_TEMPLATE;
29
26
  }
30
27
  }
28
+ async function runMiddleware(name, options) {
29
+ const generator = new MiddlewareGenerator();
30
+ const result = await generator.generate({ name, path: options.path, dryRun: options.dryRun });
31
+ result.nextSteps = result.nextSteps ?? [];
32
+ result.nextSteps.push('Import the middleware in your module or apply it globally.');
33
+ return result;
34
+ }
31
35
  function generateMiddleware(command) {
32
36
  command
33
37
  .command('middleware <name>')
@@ -35,12 +39,9 @@ function generateMiddleware(command) {
35
39
  .description('Generate a middleware')
36
40
  .option('-p, --path <path>', 'Specify the path', 'src/middleware')
37
41
  .option('--dry-run', 'Preview files without writing them')
42
+ .option('--json', 'Output result as JSON')
38
43
  .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
- }
44
+ const result = await runMiddleware(name, options);
45
+ (0, generator_1.printGenerateResult)(result, { json: options.json });
45
46
  });
46
47
  }
@@ -1,2 +1,4 @@
1
1
  import { Command } from 'commander';
2
+ import { GenerateResult, GenerateCLIOptions } from '../utils/generator';
3
+ export declare function runModule(name: string, options: GenerateCLIOptions): Promise<GenerateResult>;
2
4
  export declare function generateModule(program: Command): void;
@@ -3,10 +3,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.runModule = runModule;
6
7
  exports.generateModule = generateModule;
7
8
  const fs_1 = __importDefault(require("fs"));
8
9
  const path_1 = __importDefault(require("path"));
9
- const chalk_1 = __importDefault(require("chalk"));
10
10
  const generator_1 = require("../utils/generator");
11
11
  const MODULE_TEMPLATE = `import { HazelModule } from '@hazeljs/core';
12
12
  import { {{className}}Controller } from './{{fileName}}.controller';
@@ -64,6 +64,37 @@ const UPDATE_DTO_TEMPLATE = `export class Update{{className}}Dto {
64
64
  name?: string;
65
65
  }
66
66
  `;
67
+ async function runModule(name, options) {
68
+ const className = (0, generator_1.toPascalCase)(name);
69
+ const fileName = (0, generator_1.toKebabCase)(name);
70
+ const camelName = fileName.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
71
+ const baseDir = path_1.default.join(process.cwd(), options.path || 'src', fileName);
72
+ const data = { className, fileName, camelName };
73
+ const files = [
74
+ { file: `${fileName}.module.ts`, template: MODULE_TEMPLATE },
75
+ { file: `${fileName}.controller.ts`, template: CONTROLLER_TEMPLATE },
76
+ { file: `${fileName}.service.ts`, template: SERVICE_TEMPLATE },
77
+ { file: `dto/create-${fileName}.dto.ts`, template: CREATE_DTO_TEMPLATE },
78
+ { file: `dto/update-${fileName}.dto.ts`, template: UPDATE_DTO_TEMPLATE },
79
+ ];
80
+ const created = [];
81
+ for (const { file, template } of files) {
82
+ const filePath = path_1.default.join(baseDir, file);
83
+ created.push(filePath);
84
+ if (options.dryRun)
85
+ continue;
86
+ const dir = path_1.default.dirname(filePath);
87
+ if (!fs_1.default.existsSync(dir))
88
+ fs_1.default.mkdirSync(dir, { recursive: true });
89
+ fs_1.default.writeFileSync(filePath, (0, generator_1.renderTemplate)(template, data));
90
+ }
91
+ return {
92
+ ok: true,
93
+ created,
94
+ dryRun: options.dryRun,
95
+ nextSteps: [`Import ${className}Module in your app module.`],
96
+ };
97
+ }
67
98
  function generateModule(program) {
68
99
  program
69
100
  .command('module <name>')
@@ -71,36 +102,9 @@ function generateModule(program) {
71
102
  .alias('m')
72
103
  .option('-p, --path <path>', 'Path where the module should be generated')
73
104
  .option('--dry-run', 'Preview files without writing them')
105
+ .option('--json', 'Output result as JSON')
74
106
  .action(async (name, options) => {
75
- const className = (0, generator_1.toPascalCase)(name);
76
- const fileName = (0, generator_1.toKebabCase)(name);
77
- const camelName = fileName.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
78
- const baseDir = path_1.default.join(process.cwd(), options.path || 'src', fileName);
79
- const data = { className, fileName, camelName };
80
- const files = [
81
- { file: `${fileName}.module.ts`, template: MODULE_TEMPLATE },
82
- { file: `${fileName}.controller.ts`, template: CONTROLLER_TEMPLATE },
83
- { file: `${fileName}.service.ts`, template: SERVICE_TEMPLATE },
84
- { file: `dto/create-${fileName}.dto.ts`, template: CREATE_DTO_TEMPLATE },
85
- { file: `dto/update-${fileName}.dto.ts`, template: UPDATE_DTO_TEMPLATE },
86
- ];
87
- for (const { file, template } of files) {
88
- const filePath = path_1.default.join(baseDir, file);
89
- if (options.dryRun) {
90
- console.log(chalk_1.default.blue(`[dry-run] Would create ${filePath}`));
91
- continue;
92
- }
93
- const dir = path_1.default.dirname(filePath);
94
- if (!fs_1.default.existsSync(dir)) {
95
- fs_1.default.mkdirSync(dir, { recursive: true });
96
- }
97
- fs_1.default.writeFileSync(filePath, (0, generator_1.renderTemplate)(template, data));
98
- console.log(chalk_1.default.green(`✓ Generated ${filePath}`));
99
- }
100
- if (!options.dryRun) {
101
- console.log(chalk_1.default.blue(`\n📦 Module generated in ${baseDir}`));
102
- console.log(chalk_1.default.gray(`\nNext steps:`));
103
- console.log(chalk_1.default.gray(` Import ${className}Module in your app module.`));
104
- }
107
+ const result = await runModule(name, options);
108
+ (0, generator_1.printGenerateResult)(result, { json: options.json });
105
109
  });
106
110
  }
@@ -1,2 +1,4 @@
1
1
  import { Command } from 'commander';
2
+ import { GenerateResult, GenerateCLIOptions } from '../utils/generator';
3
+ export declare function runPipe(name: string, options: GenerateCLIOptions): Promise<GenerateResult>;
2
4
  export declare function generatePipe(program: Command): void;
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runPipe = runPipe;
3
4
  exports.generatePipe = generatePipe;
4
5
  const generator_1 = require("../utils/generator");
5
6
  const PIPE_TEMPLATE = `import { type PipeTransform, type RequestContext } from '@hazeljs/core';
@@ -20,14 +21,19 @@ class PipeGenerator extends generator_1.Generator {
20
21
  return PIPE_TEMPLATE;
21
22
  }
22
23
  }
24
+ async function runPipe(name, options) {
25
+ const generator = new PipeGenerator();
26
+ return generator.generate({ name, path: options.path, dryRun: options.dryRun });
27
+ }
23
28
  function generatePipe(program) {
24
29
  program
25
30
  .command('pipe <name>')
26
31
  .description('Generate a new pipe')
27
32
  .option('-p, --path <path>', 'Path where the pipe should be generated')
28
33
  .option('--dry-run', 'Preview files without writing them')
34
+ .option('--json', 'Output result as JSON')
29
35
  .action(async (name, options) => {
30
- const generator = new PipeGenerator();
31
- await generator.generate({ name, path: options.path, dryRun: options.dryRun });
36
+ const result = await runPipe(name, options);
37
+ (0, generator_1.printGenerateResult)(result, { json: options.json });
32
38
  });
33
39
  }
@@ -1,2 +1,4 @@
1
1
  import { Command } from 'commander';
2
+ import { GenerateResult, GenerateCLIOptions } from '../utils/generator';
3
+ export declare function runRag(name: string, options: GenerateCLIOptions): Promise<GenerateResult>;
2
4
  export declare function generateRag(command: Command): void;
@@ -1,11 +1,8 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runRag = runRag;
6
4
  exports.generateRag = generateRag;
7
5
  const generator_1 = require("../utils/generator");
8
- const chalk_1 = __importDefault(require("chalk"));
9
6
  const RAG_SERVICE_TEMPLATE = `import { Service } from '@hazeljs/core';
10
7
  import { RAGPipeline, MemoryVectorStore } from '@hazeljs/rag';
11
8
 
@@ -47,20 +44,25 @@ class RagServiceGenerator extends generator_1.Generator {
47
44
  return RAG_SERVICE_TEMPLATE;
48
45
  }
49
46
  }
47
+ async function runRag(name, options) {
48
+ const generator = new RagServiceGenerator();
49
+ const result = await generator.generate({ name, path: options.path, dryRun: options.dryRun });
50
+ result.nextSteps = [
51
+ 'npm install @hazeljs/rag',
52
+ 'Register this service as a provider in your module',
53
+ 'Configure your embedding provider and vector store',
54
+ ];
55
+ return result;
56
+ }
50
57
  function generateRag(command) {
51
58
  command
52
59
  .command('rag <name>')
53
60
  .description('Generate a RAG (Retrieval-Augmented Generation) service')
54
61
  .option('-p, --path <path>', 'Specify the path')
55
62
  .option('--dry-run', 'Preview files without writing them')
63
+ .option('--json', 'Output result as JSON')
56
64
  .action(async (name, options) => {
57
- const generator = new RagServiceGenerator();
58
- await generator.generate({ name, path: options.path, dryRun: options.dryRun });
59
- if (!options.dryRun) {
60
- console.log(chalk_1.default.gray('\nNext steps:'));
61
- console.log(chalk_1.default.gray(' 1. npm install @hazeljs/rag'));
62
- console.log(chalk_1.default.gray(' 2. Register this service as a provider in your module'));
63
- console.log(chalk_1.default.gray(' 3. Configure your embedding provider and vector store'));
64
- }
65
+ const result = await runRag(name, options);
66
+ (0, generator_1.printGenerateResult)(result, { json: options.json });
65
67
  });
66
68
  }
@@ -1,2 +1,4 @@
1
1
  import { Command } from 'commander';
2
+ import { GenerateResult, GenerateCLIOptions } from '../utils/generator';
3
+ export declare function runRepository(name: string, options: GenerateCLIOptions): Promise<GenerateResult>;
2
4
  export declare function generateRepository(program: Command): void;
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runRepository = runRepository;
3
4
  exports.generateRepository = generateRepository;
4
5
  const generator_1 = require("../utils/generator");
5
6
  const REPOSITORY_TEMPLATE = `import { Repository, BaseRepository, PrismaService } from '@hazeljs/prisma';
@@ -26,6 +27,10 @@ class RepositoryGenerator extends generator_1.Generator {
26
27
  return REPOSITORY_TEMPLATE;
27
28
  }
28
29
  }
30
+ async function runRepository(name, options) {
31
+ const generator = new RepositoryGenerator();
32
+ return generator.generate({ name, path: options.path, dryRun: options.dryRun });
33
+ }
29
34
  function generateRepository(program) {
30
35
  program
31
36
  .command('repository <name>')
@@ -33,8 +38,9 @@ function generateRepository(program) {
33
38
  .alias('repo')
34
39
  .option('-p, --path <path>', 'Path where the repository should be generated')
35
40
  .option('--dry-run', 'Preview files without writing them')
41
+ .option('--json', 'Output result as JSON')
36
42
  .action(async (name, options) => {
37
- const generator = new RepositoryGenerator();
38
- await generator.generate({ name, path: options.path, dryRun: options.dryRun });
43
+ const result = await runRepository(name, options);
44
+ (0, generator_1.printGenerateResult)(result, { json: options.json });
39
45
  });
40
46
  }
@@ -1,2 +1,4 @@
1
1
  import { Command } from 'commander';
2
+ import { GenerateResult, GenerateCLIOptions } from '../utils/generator';
3
+ export declare function runServerlessHandler(name: string, options: GenerateCLIOptions): Promise<GenerateResult>;
2
4
  export declare function generateServerlessHandler(program: Command): void;
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runServerlessHandler = runServerlessHandler;
3
4
  exports.generateServerlessHandler = generateServerlessHandler;
4
5
  const generator_1 = require("../utils/generator");
5
6
  const SERVERLESS_LAMBDA_TEMPLATE = `import { createLambdaHandler } from '@hazeljs/serverless';
@@ -25,12 +26,21 @@ class ServerlessHandlerGenerator extends generator_1.Generator {
25
26
  const template = platform === 'lambda'
26
27
  ? SERVERLESS_LAMBDA_TEMPLATE
27
28
  : SERVERLESS_CLOUD_FUNCTION_TEMPLATE;
28
- await super.generate({
29
+ return super.generate({
29
30
  ...restOptions,
30
31
  template,
31
32
  });
32
33
  }
33
34
  }
35
+ async function runServerlessHandler(name, options) {
36
+ const generator = new ServerlessHandlerGenerator();
37
+ return generator.generate({
38
+ name,
39
+ path: options.path,
40
+ platform: options.platform,
41
+ dryRun: options.dryRun,
42
+ });
43
+ }
34
44
  function generateServerlessHandler(program) {
35
45
  program
36
46
  .command('serverless <name>')
@@ -39,8 +49,9 @@ function generateServerlessHandler(program) {
39
49
  .option('-p, --path <path>', 'Path where the handler should be generated', 'src')
40
50
  .option('--platform <platform>', 'Platform: lambda or cloud-function', 'lambda')
41
51
  .option('--dry-run', 'Preview files without writing them')
52
+ .option('--json', 'Output result as JSON')
42
53
  .action(async (name, options) => {
43
- const generator = new ServerlessHandlerGenerator();
44
- await generator.generate({ name, path: options.path, platform: options.platform, dryRun: options.dryRun });
54
+ const result = await runServerlessHandler(name, options);
55
+ (0, generator_1.printGenerateResult)(result, { json: options.json });
45
56
  });
46
57
  }
@@ -1,2 +1,4 @@
1
1
  import { Command } from 'commander';
2
+ import { GenerateResult, GenerateCLIOptions } from '../utils/generator';
3
+ export declare function runService(name: string, options: GenerateCLIOptions): Promise<GenerateResult>;
2
4
  export declare function generateService(program: Command): void;
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runService = runService;
3
4
  exports.generateService = generateService;
4
5
  const generator_1 = require("../utils/generator");
5
6
  const SERVICE_TEMPLATE = `import { Service } from '@hazeljs/core';
@@ -38,6 +39,10 @@ class ServiceGenerator extends generator_1.Generator {
38
39
  return SERVICE_TEMPLATE;
39
40
  }
40
41
  }
42
+ async function runService(name, options) {
43
+ const generator = new ServiceGenerator();
44
+ return generator.generate({ name, path: options.path, dryRun: options.dryRun });
45
+ }
41
46
  function generateService(program) {
42
47
  program
43
48
  .command('service <name>')
@@ -45,8 +50,9 @@ function generateService(program) {
45
50
  .alias('s')
46
51
  .option('-p, --path <path>', 'Path where the service should be generated')
47
52
  .option('--dry-run', 'Preview files without writing them')
53
+ .option('--json', 'Output result as JSON')
48
54
  .action(async (name, options) => {
49
- const generator = new ServiceGenerator();
50
- await generator.generate({ name, path: options.path, dryRun: options.dryRun });
55
+ const result = await runService(name, options);
56
+ (0, generator_1.printGenerateResult)(result, { json: options.json });
51
57
  });
52
58
  }
@@ -0,0 +1,4 @@
1
+ import { Command } from 'commander';
2
+ import { GenerateCLIOptions, GenerateResult } from '../utils/generator';
3
+ export declare function runSetup(pkg: string, options: GenerateCLIOptions): Promise<GenerateResult>;
4
+ export declare function generateSetup(program: Command): void;
@@ -0,0 +1,187 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runSetup = runSetup;
4
+ exports.generateSetup = generateSetup;
5
+ const generator_1 = require("../utils/generator");
6
+ function packageToNpmName(input) {
7
+ if (input.startsWith('@hazeljs/'))
8
+ return input;
9
+ return `@hazeljs/${input}`;
10
+ }
11
+ function packageToTemplate(pkg) {
12
+ const npmName = packageToNpmName(pkg);
13
+ const short = npmName.replace('@hazeljs/', '');
14
+ // Keep these templates intentionally minimal: a real import + a tiny “hello usage”
15
+ // so users can immediately search/expand, without forcing a specific app structure.
16
+ switch (short) {
17
+ case 'swagger':
18
+ return `import { SwaggerModule } from '@hazeljs/swagger';
19
+ import { AppModule } from './app.module';
20
+
21
+ // Setup Swagger once before creating your app:
22
+ SwaggerModule.setRootModule(AppModule);
23
+ `;
24
+ case 'prisma':
25
+ return `import { PrismaModule } from '@hazeljs/prisma';
26
+
27
+ // Add PrismaModule to your HazelModule imports.
28
+ export const prismaImports = [PrismaModule];
29
+ `;
30
+ case 'typeorm':
31
+ return `import { TypeOrmModule } from '@hazeljs/typeorm';
32
+
33
+ // Add TypeOrmModule to your HazelModule imports.
34
+ export const typeormImports = [TypeOrmModule];
35
+ `;
36
+ case 'oauth':
37
+ return `import { OAuthModule } from '@hazeljs/oauth';
38
+
39
+ // Example (Google). Put secrets in env vars:
40
+ // GOOGLE_CLIENT_ID=...
41
+ // GOOGLE_CLIENT_SECRET=...
42
+ // OAUTH_REDIRECT_URI=...
43
+ export const oauthImports = [
44
+ OAuthModule.forRoot({
45
+ providers: {
46
+ google: {
47
+ clientId: process.env.GOOGLE_CLIENT_ID!,
48
+ clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
49
+ redirectUri: process.env.OAUTH_REDIRECT_URI!,
50
+ },
51
+ },
52
+ }),
53
+ ];
54
+ `;
55
+ case 'kafka':
56
+ return `import { KafkaModule } from '@hazeljs/kafka';
57
+
58
+ // Add KafkaModule to your HazelModule imports and configure brokers via env/config.
59
+ export const kafkaImports = [KafkaModule];
60
+ `;
61
+ case 'grpc':
62
+ return `import { GrpcModule } from '@hazeljs/grpc';
63
+
64
+ // Add GrpcModule to your HazelModule imports. Define services in your module.
65
+ export const grpcImports = [GrpcModule];
66
+ `;
67
+ case 'graphql':
68
+ return `import { GraphQLModule } from '@hazeljs/graphql';
69
+
70
+ // Add GraphQLModule to your HazelModule imports.
71
+ export const graphqlImports = [GraphQLModule];
72
+ `;
73
+ case 'gateway':
74
+ return `import { GatewayModule } from '@hazeljs/gateway';
75
+
76
+ // Add GatewayModule to your HazelModule imports.
77
+ export const gatewayImports = [GatewayModule];
78
+ `;
79
+ case 'event-emitter':
80
+ return `import { EventEmitterModule } from '@hazeljs/event-emitter';
81
+
82
+ // Add EventEmitterModule.forRoot() to your HazelModule imports.
83
+ export const eventEmitterImports = [EventEmitterModule.forRoot()];
84
+ `;
85
+ case 'audit':
86
+ return `import { AuditModule, ConsoleAuditTransport } from '@hazeljs/audit';
87
+
88
+ // Add AuditModule.forRoot(...) to your HazelModule imports.
89
+ export const auditImports = [AuditModule.forRoot({ transports: [new ConsoleAuditTransport()] })];
90
+ `;
91
+ case 'queue':
92
+ return `import { QueueModule } from '@hazeljs/queue';
93
+
94
+ // Add QueueModule to your HazelModule imports. Configure Redis / BullMQ via env/config.
95
+ export const queueImports = [QueueModule];
96
+ `;
97
+ case 'messaging':
98
+ return `import { MessagingModule } from '@hazeljs/messaging';
99
+
100
+ // Add MessagingModule to your HazelModule imports. Configure channels (WhatsApp/Telegram) via env/config.
101
+ export const messagingImports = [MessagingModule];
102
+ `;
103
+ case 'mcp':
104
+ return `import { createMcpServer } from '@hazeljs/mcp';
105
+
106
+ // Minimal MCP server example:
107
+ const server = createMcpServer({ name: 'hazel-mcp', version: '0.1.0' });
108
+ server.start();
109
+ `;
110
+ case 'prompts':
111
+ return `import { PromptTemplate } from '@hazeljs/prompts';
112
+
113
+ export const helloPrompt = new PromptTemplate({
114
+ name: 'hello',
115
+ template: 'Hello {{name}}',
116
+ });
117
+ `;
118
+ case 'data':
119
+ return `import { DataModule } from '@hazeljs/data';
120
+
121
+ // Add DataModule.forRoot() to your HazelModule imports.
122
+ export const dataImports = [DataModule.forRoot()];
123
+ `;
124
+ case 'ml':
125
+ return `import { MLModule } from '@hazeljs/ml';
126
+
127
+ // Add MLModule.forRoot() to your HazelModule imports.
128
+ export const mlImports = [MLModule.forRoot()];
129
+ `;
130
+ case 'resilience':
131
+ return `import { CircuitBreaker, WithRetry } from '@hazeljs/resilience';
132
+
133
+ export class ExampleResilienceService {
134
+ @WithRetry({ retries: 3 })
135
+ @CircuitBreaker({ failureThreshold: 5, resetTimeoutMs: 10000 })
136
+ async callRemote(): Promise<string> {
137
+ return 'ok';
138
+ }
139
+ }
140
+ `;
141
+ case 'pdf-to-audio':
142
+ return `import { PdfToAudioModule } from '@hazeljs/pdf-to-audio';
143
+
144
+ // Add PdfToAudioModule to your HazelModule imports.
145
+ export const pdfToAudioImports = [PdfToAudioModule];
146
+ `;
147
+ default:
148
+ return `import '${npmName}';
149
+
150
+ // Starter file generated for ${npmName}.
151
+ // Tip: check the package README for setup details and examples.
152
+ `;
153
+ }
154
+ }
155
+ class SetupGenerator extends generator_1.Generator {
156
+ constructor() {
157
+ super(...arguments);
158
+ this.suffix = 'setup';
159
+ }
160
+ }
161
+ async function runSetup(pkg, options) {
162
+ const npmName = packageToNpmName(pkg);
163
+ const template = packageToTemplate(pkg);
164
+ const generator = new SetupGenerator();
165
+ const result = await generator.generate({
166
+ name: pkg,
167
+ path: options.path,
168
+ template,
169
+ dryRun: options.dryRun,
170
+ });
171
+ result.nextSteps = result.nextSteps ?? [];
172
+ result.nextSteps.push(`npm install ${npmName}`);
173
+ return result;
174
+ }
175
+ function generateSetup(program) {
176
+ program
177
+ .command('setup <package>')
178
+ .description('Generate a minimal setup starter file for a HazelJS package')
179
+ .alias('st')
180
+ .option('-p, --path <path>', 'Path where the setup file should be generated', 'src')
181
+ .option('--dry-run', 'Preview files without writing them')
182
+ .option('--json', 'Output result as JSON')
183
+ .action(async (pkg, options) => {
184
+ const result = await runSetup(pkg, options);
185
+ (0, generator_1.printGenerateResult)(result, { json: options.json });
186
+ });
187
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,50 @@
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 path_1 = __importDefault(require("path"));
8
+ const generate_setup_1 = require("./generate-setup");
9
+ const commander_1 = require("commander");
10
+ jest.mock('fs');
11
+ describe('generateSetup', () => {
12
+ const mockFs = fs_1.default;
13
+ beforeEach(() => {
14
+ jest.clearAllMocks();
15
+ mockFs.existsSync.mockReturnValue(true);
16
+ mockFs.writeFileSync.mockImplementation(() => { });
17
+ mockFs.mkdirSync.mockImplementation(() => undefined);
18
+ });
19
+ it('should register setup command with alias', () => {
20
+ const program = new commander_1.Command();
21
+ (0, generate_setup_1.generateSetup)(program);
22
+ const cmd = program.commands.find((c) => c.name() === 'setup');
23
+ expect(cmd).toBeTruthy();
24
+ expect(cmd?.aliases()).toContain('st');
25
+ });
26
+ it('runSetup should generate a setup file and include npm install in next steps', async () => {
27
+ const result = await (0, generate_setup_1.runSetup)('swagger', { path: 'src', dryRun: false });
28
+ expect(result.ok).toBe(true);
29
+ expect(result.created).toHaveLength(1);
30
+ expect(result.created[0]).toBe(path_1.default.join(process.cwd(), 'src', 'swagger.setup.ts'));
31
+ expect(result.nextSteps?.some((s) => s.includes('npm install @hazeljs/swagger'))).toBe(true);
32
+ });
33
+ it('runSetup should accept package names with and without @hazeljs prefix', async () => {
34
+ const r1 = await (0, generate_setup_1.runSetup)('oauth', { path: 'src', dryRun: true });
35
+ expect(r1.ok).toBe(true);
36
+ expect(r1.dryRun).toBe(true);
37
+ expect(r1.nextSteps?.some((s) => s.includes('npm install @hazeljs/oauth'))).toBe(true);
38
+ const r2 = await (0, generate_setup_1.runSetup)('@hazeljs/oauth', { path: 'src', dryRun: true });
39
+ expect(r2.ok).toBe(true);
40
+ expect(r2.nextSteps?.some((s) => s.includes('npm install @hazeljs/oauth'))).toBe(true);
41
+ });
42
+ it('covers several common setup templates', async () => {
43
+ const pkgs = ['grpc', 'graphql', 'kafka', 'resilience', 'mcp', 'pdf-to-audio'];
44
+ for (const p of pkgs) {
45
+ const result = await (0, generate_setup_1.runSetup)(p, { path: 'src', dryRun: true });
46
+ expect(result.ok).toBe(true);
47
+ expect(result.created[0]).toContain(`${p}.setup.ts`);
48
+ }
49
+ });
50
+ });
@@ -1,2 +1,4 @@
1
1
  import { Command } from 'commander';
2
+ import { GenerateResult, GenerateCLIOptions } from '../utils/generator';
3
+ export declare function runWebSocketGateway(name: string, options: GenerateCLIOptions): Promise<GenerateResult>;
2
4
  export declare function generateWebSocketGateway(program: Command): void;
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runWebSocketGateway = runWebSocketGateway;
3
4
  exports.generateWebSocketGateway = generateWebSocketGateway;
4
5
  const generator_1 = require("../utils/generator");
5
6
  const WEBSOCKET_GATEWAY_TEMPLATE = `import { Realtime, OnConnect, OnDisconnect, OnMessage, Subscribe, Client, Data, WebSocketClient } from '@hazeljs/websocket';
@@ -33,6 +34,10 @@ class WebSocketGatewayGenerator extends generator_1.Generator {
33
34
  return WEBSOCKET_GATEWAY_TEMPLATE;
34
35
  }
35
36
  }
37
+ async function runWebSocketGateway(name, options) {
38
+ const generator = new WebSocketGatewayGenerator();
39
+ return generator.generate({ name, path: options.path, dryRun: options.dryRun });
40
+ }
36
41
  function generateWebSocketGateway(program) {
37
42
  program
38
43
  .command('gateway <name>')
@@ -40,8 +45,9 @@ function generateWebSocketGateway(program) {
40
45
  .alias('ws')
41
46
  .option('-p, --path <path>', 'Path where the gateway should be generated')
42
47
  .option('--dry-run', 'Preview files without writing them')
48
+ .option('--json', 'Output result as JSON')
43
49
  .action(async (name, options) => {
44
- const generator = new WebSocketGatewayGenerator();
45
- await generator.generate({ name, path: options.path, dryRun: options.dryRun });
50
+ const result = await runWebSocketGateway(name, options);
51
+ (0, generator_1.printGenerateResult)(result, { json: options.json });
46
52
  });
47
53
  }
@@ -0,0 +1 @@
1
+ export {};