@asyncapi/cli 3.4.2 → 3.5.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 (47) hide show
  1. package/lib/apps/cli/commands/generate/client.d.ts +30 -0
  2. package/lib/apps/cli/commands/generate/client.js +94 -0
  3. package/lib/apps/cli/commands/generate/fromTemplate.d.ts +28 -16
  4. package/lib/apps/cli/commands/generate/fromTemplate.js +29 -296
  5. package/lib/apps/cli/commands/start/preview.d.ts +1 -0
  6. package/lib/apps/cli/commands/start/preview.js +1 -1
  7. package/lib/apps/cli/commands/start/studio.d.ts +1 -0
  8. package/lib/apps/cli/commands/start/studio.js +1 -1
  9. package/lib/apps/cli/internal/args/generate.args.d.ts +3 -0
  10. package/lib/apps/cli/internal/args/generate.args.js +10 -0
  11. package/lib/apps/cli/internal/base/BaseGeneratorCommand.d.ts +42 -0
  12. package/lib/apps/cli/internal/base/BaseGeneratorCommand.js +119 -0
  13. package/lib/apps/cli/internal/flags/generate/clients.flags.d.ts +16 -0
  14. package/lib/apps/cli/internal/flags/generate/clients.flags.js +8 -0
  15. package/lib/apps/cli/internal/flags/generate/fromTemplate.flags.d.ts +25 -1
  16. package/lib/apps/cli/internal/flags/generate/fromTemplate.flags.js +2 -58
  17. package/lib/apps/cli/internal/flags/generate/sharedFlags.d.ts +16 -0
  18. package/lib/apps/cli/internal/flags/generate/sharedFlags.js +57 -0
  19. package/lib/apps/cli/internal/flags/start/preview.flags.d.ts +1 -0
  20. package/lib/apps/cli/internal/flags/start/preview.flags.js +1 -0
  21. package/lib/apps/cli/internal/flags/start/studio.flags.d.ts +1 -0
  22. package/lib/apps/cli/internal/flags/start/studio.flags.js +1 -0
  23. package/lib/domains/models/Preview.d.ts +1 -1
  24. package/lib/domains/models/Preview.js +145 -132
  25. package/lib/domains/models/Studio.d.ts +1 -1
  26. package/lib/domains/models/Studio.js +115 -100
  27. package/lib/domains/models/generate/ClientLanguages.d.ts +12 -0
  28. package/lib/domains/models/generate/ClientLanguages.js +17 -0
  29. package/lib/domains/models/generate/Flags.d.ts +9 -0
  30. package/lib/domains/models/generate/Flags.js +2 -0
  31. package/lib/domains/services/generator.service.d.ts +1 -0
  32. package/lib/domains/services/generator.service.js +5 -2
  33. package/lib/utils/generate/flags.d.ts +2 -0
  34. package/lib/utils/generate/flags.js +14 -0
  35. package/lib/utils/generate/mapBaseUrl.d.ts +6 -0
  36. package/lib/utils/generate/mapBaseUrl.js +34 -0
  37. package/lib/utils/generate/parseParams.d.ts +3 -0
  38. package/lib/utils/generate/parseParams.js +58 -0
  39. package/lib/utils/generate/prompts.d.ts +4 -0
  40. package/lib/utils/generate/prompts.js +77 -0
  41. package/lib/utils/generate/registry.d.ts +2 -0
  42. package/lib/utils/generate/registry.js +30 -0
  43. package/lib/utils/{fileWatcher.d.ts → generate/watcher.d.ts} +3 -0
  44. package/lib/utils/{fileWatcher.js → generate/watcher.js} +75 -8
  45. package/oclif.manifest.json +167 -3
  46. package/package.json +7 -5
  47. package/scripts/generateTypesForGenerateCommand.js +40 -0
@@ -0,0 +1,6 @@
1
+ import { IMapBaseUrlToFlag } from '../../domains/models/generate/Flags';
2
+ export declare function getMapBaseUrlToFolderResolver(urlToFolder: IMapBaseUrlToFlag): {
3
+ order: number;
4
+ canRead(): boolean;
5
+ read(file: any): Promise<unknown>;
6
+ };
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getMapBaseUrlToFolderResolver = getMapBaseUrlToFolderResolver;
4
+ const tslib_1 = require("tslib");
5
+ const fs = tslib_1.__importStar(require("fs"));
6
+ function getMapBaseUrlToFolderResolver(urlToFolder) {
7
+ return {
8
+ order: 1,
9
+ canRead() {
10
+ return true;
11
+ },
12
+ read(file) {
13
+ const baseUrl = urlToFolder.url;
14
+ const baseDir = urlToFolder.folder;
15
+ return new Promise((resolve, reject) => {
16
+ let localpath = file.url;
17
+ localpath = localpath.replace(baseUrl, baseDir);
18
+ try {
19
+ fs.readFile(localpath, (err, data) => {
20
+ if (err) {
21
+ reject(`Error opening file "${localpath}"`);
22
+ }
23
+ else {
24
+ resolve(data);
25
+ }
26
+ });
27
+ }
28
+ catch (err) {
29
+ reject(`Error opening file "${localpath}"`);
30
+ }
31
+ });
32
+ }
33
+ };
34
+ }
@@ -0,0 +1,3 @@
1
+ export declare function paramParser(inputs?: string[]): Record<string, any>;
2
+ export declare function disableHooksParser(inputs?: string[]): Record<string, any>;
3
+ export declare function mapBaseURLParser(input?: string): any;
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.paramParser = paramParser;
4
+ exports.disableHooksParser = disableHooksParser;
5
+ exports.mapBaseURLParser = mapBaseURLParser;
6
+ const tslib_1 = require("tslib");
7
+ const path_1 = tslib_1.__importDefault(require("path"));
8
+ function paramParser(inputs) {
9
+ if (!inputs) {
10
+ return {};
11
+ }
12
+ const params = {};
13
+ for (const input of inputs) {
14
+ if (!input.includes('=')) {
15
+ throw new Error(`Invalid param ${input}. It must be in the format of --param name1=value1 name2=value2 `);
16
+ }
17
+ const [paramName, paramValue] = input.split(/=(.+)/, 2);
18
+ params[String(paramName)] = paramValue;
19
+ }
20
+ return params;
21
+ }
22
+ function disableHooksParser(inputs) {
23
+ if (!inputs) {
24
+ return {};
25
+ }
26
+ const disableHooks = {};
27
+ for (const input of inputs) {
28
+ const [hookType, hookNames] = input.split(/=/);
29
+ if (!hookType) {
30
+ throw new Error('Invalid --disable-hook flag. It must be in the format of: --disable-hook <hookType> or --disable-hook <hookType>=<hookName1>,<hookName2>,...');
31
+ }
32
+ if (hookNames) {
33
+ disableHooks[String(hookType)] = hookNames.split(',');
34
+ }
35
+ else {
36
+ disableHooks[String(hookType)] = true;
37
+ }
38
+ }
39
+ return disableHooks;
40
+ }
41
+ function mapBaseURLParser(input) {
42
+ if (!input) {
43
+ return;
44
+ }
45
+ const mapBaseURLToFolder = {};
46
+ const re = /(.*):(.*)/g; // NOSONAR
47
+ let mapping = [];
48
+ if ((mapping = re.exec(input)) === null || mapping.length !== 3) {
49
+ throw new Error('Invalid --map-base-url flag. A mapping <url>:<folder> with delimiter : expected.');
50
+ }
51
+ mapBaseURLToFolder.url = mapping[1].replace(/\/$/, '');
52
+ mapBaseURLToFolder.folder = path_1.default.resolve(mapping[2]);
53
+ const isURL = /^https?:/;
54
+ if (!isURL.test(mapBaseURLToFolder.url.toLowerCase())) {
55
+ throw new Error('Invalid --map-base-url flag. The mapping <url>:<folder> requires a valid http/https url and valid folder with delimiter `:`.');
56
+ }
57
+ return mapBaseURLToFolder;
58
+ }
@@ -0,0 +1,4 @@
1
+ export declare function promptForAsyncAPIPath(): Promise<string>;
2
+ export declare function promptForLanguage(defaultLanguage: string): Promise<string>;
3
+ export declare function promptForTemplate(): Promise<string>;
4
+ export declare function promptForOutputDir(): Promise<string>;
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.promptForAsyncAPIPath = promptForAsyncAPIPath;
4
+ exports.promptForLanguage = promptForLanguage;
5
+ exports.promptForTemplate = promptForTemplate;
6
+ exports.promptForOutputDir = promptForOutputDir;
7
+ const tslib_1 = require("tslib");
8
+ const fs_1 = tslib_1.__importDefault(require("fs"));
9
+ const prompts_1 = require("@clack/prompts");
10
+ const OPERATION_CANCELLED_ERROR = 'Operation cancelled';
11
+ function promptForAsyncAPIPath() {
12
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
13
+ const asyncapi = yield (0, prompts_1.text)({
14
+ message: 'Please provide the path to the AsyncAPI document',
15
+ placeholder: 'asyncapi.yaml',
16
+ defaultValue: 'asyncapi.yaml',
17
+ validate(value) {
18
+ if (!value) {
19
+ return 'The path to the AsyncAPI document is required';
20
+ }
21
+ else if (!fs_1.default.existsSync(value)) {
22
+ return 'The file does not exist';
23
+ }
24
+ }
25
+ });
26
+ if ((0, prompts_1.isCancel)(asyncapi)) {
27
+ throw new Error(OPERATION_CANCELLED_ERROR);
28
+ }
29
+ return asyncapi;
30
+ });
31
+ }
32
+ function promptForLanguage(defaultLanguage) {
33
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
34
+ const language = yield (0, prompts_1.text)({
35
+ message: 'Please provide the language of the generated client',
36
+ placeholder: defaultLanguage,
37
+ defaultValue: defaultLanguage,
38
+ });
39
+ if ((0, prompts_1.isCancel)(language)) {
40
+ throw new Error(OPERATION_CANCELLED_ERROR);
41
+ }
42
+ return language;
43
+ });
44
+ }
45
+ function promptForTemplate() {
46
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
47
+ const template = yield (0, prompts_1.text)({
48
+ message: 'Please provide the name of the generator template',
49
+ placeholder: '@asyncapi/html-template',
50
+ defaultValue: '@asyncapi/html-template',
51
+ });
52
+ if ((0, prompts_1.isCancel)(template)) {
53
+ throw new Error(OPERATION_CANCELLED_ERROR);
54
+ }
55
+ return template;
56
+ });
57
+ }
58
+ function promptForOutputDir() {
59
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
60
+ const output = yield (0, prompts_1.text)({
61
+ message: 'Please provide the output directory',
62
+ placeholder: './docs',
63
+ validate(value) {
64
+ if (!value) {
65
+ return 'The output directory is required';
66
+ }
67
+ else if (typeof value !== 'string') {
68
+ return 'The output directory must be a string';
69
+ }
70
+ }
71
+ });
72
+ if ((0, prompts_1.isCancel)(output)) {
73
+ throw new Error(OPERATION_CANCELLED_ERROR);
74
+ }
75
+ return output;
76
+ });
77
+ }
@@ -0,0 +1,2 @@
1
+ export declare function registryURLParser(input?: string): void;
2
+ export declare function registryValidation(registryUrl?: string, registryAuth?: string, registryToken?: string): Promise<void>;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registryURLParser = registryURLParser;
4
+ exports.registryValidation = registryValidation;
5
+ const tslib_1 = require("tslib");
6
+ function registryURLParser(input) {
7
+ if (!input) {
8
+ return;
9
+ }
10
+ const isURL = /^https?:/;
11
+ if (!isURL.test(input.toLowerCase())) {
12
+ throw new Error('Invalid --registry-url flag. The param requires a valid http/https url.');
13
+ }
14
+ }
15
+ function registryValidation(registryUrl, registryAuth, registryToken) {
16
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
17
+ if (!registryUrl) {
18
+ return;
19
+ }
20
+ try {
21
+ const response = yield fetch(registryUrl);
22
+ if (response.status === 401 && !registryAuth && !registryToken) {
23
+ throw new Error('You Need to pass either registryAuth in username:password encoded in Base64 or need to pass registryToken');
24
+ }
25
+ }
26
+ catch (error) {
27
+ throw new Error(`Can't fetch registryURL: ${registryUrl}`);
28
+ }
29
+ });
30
+ }
@@ -46,3 +46,6 @@ export declare class Watcher {
46
46
  */
47
47
  closeWatcher(path: string): void;
48
48
  }
49
+ export declare function runWatchMode(thisArg: any, asyncapi: string, template: string, output: string, generatorClass: any, // ✅ passed in
50
+ watchHandler: (changedFiles: Record<string, any>) => Promise<void>): Promise<void>;
51
+ export declare function watcherHandler(thisArg: any, asyncapi: string, template: string, output: string, options: Record<string, any>, genOption: any, interactive: boolean): (changedFiles: Record<string, any>) => Promise<void>;
@@ -2,12 +2,18 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Watcher = void 0;
4
4
  exports.isLocalTemplate = isLocalTemplate;
5
+ exports.runWatchMode = runWatchMode;
6
+ exports.watcherHandler = watcherHandler;
5
7
  const tslib_1 = require("tslib");
6
8
  // eslint-disable security/detect-object-injection
7
9
  const fs = tslib_1.__importStar(require("fs"));
8
10
  const util_1 = require("util");
9
11
  const chokidar_1 = tslib_1.__importDefault(require("chokidar"));
10
12
  const lstat = (0, util_1.promisify)(fs.lstat);
13
+ const path_1 = tslib_1.__importDefault(require("path"));
14
+ const picocolors_1 = require("picocolors");
15
+ const SpecificationFile_1 = require("../../domains/models/SpecificationFile");
16
+ const generator_error_1 = require("../../errors/generator-error");
11
17
  function isLocalTemplate(templatePath) {
12
18
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
13
19
  const stats = yield lstat(templatePath);
@@ -39,10 +45,7 @@ class Watcher {
39
45
  * @param {*} errorCallback Calback to call when it is no longer possible to watch a file.
40
46
  */
41
47
  initiateWatchOnPath(path, changeCallback, errorCallback) {
42
- const watcher = chokidar_1.default.watch(path, {
43
- ignoreInitial: true,
44
- ignored: this.ignorePaths,
45
- });
48
+ const watcher = chokidar_1.default.watch(path, { ignoreInitial: true, ignored: this.ignorePaths });
46
49
  watcher.on('all', (eventType, changedPath) => this.fileChanged(path, changedPath, eventType, changeCallback, errorCallback));
47
50
  this.watchers[String(path)] = watcher;
48
51
  }
@@ -70,10 +73,7 @@ class Watcher {
70
73
  try {
71
74
  if (fs.existsSync(listenerPath)) {
72
75
  const newEventType = this.convertEventType(eventType);
73
- this.filesChanged[String(changedPath)] = {
74
- eventType: newEventType,
75
- path: changedPath,
76
- };
76
+ this.filesChanged[String(changedPath)] = { eventType: newEventType, path: changedPath };
77
77
  // Since multiple changes can occur at the same time, lets wait a bit before processing.
78
78
  if (this.fsWait) {
79
79
  return;
@@ -161,3 +161,70 @@ class Watcher {
161
161
  }
162
162
  }
163
163
  exports.Watcher = Watcher;
164
+ function runWatchMode(thisArg, asyncapi, template, output, generatorClass, // ✅ passed in
165
+ watchHandler) {
166
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
167
+ const specification = yield (0, SpecificationFile_1.load)(asyncapi);
168
+ const watchDir = path_1.default.resolve(template);
169
+ const outputPath = path_1.default.resolve(watchDir, output);
170
+ const transpiledTemplatePath = path_1.default.resolve(watchDir, generatorClass.TRANSPILED_TEMPLATE_LOCATION); // ✅ use dynamic class
171
+ const ignorePaths = [outputPath, transpiledTemplatePath];
172
+ const specificationFile = specification.getFilePath();
173
+ // Template name is needed as it is not always a part of the cli command
174
+ // There is a use case that you run generator from a root of the template with `./` path
175
+ let templateName = '';
176
+ try {
177
+ // eslint-disable-next-line
178
+ templateName = require(path_1.default.resolve(watchDir, 'package.json')).name;
179
+ }
180
+ catch (_) {
181
+ // intentional
182
+ }
183
+ let watcher;
184
+ if (specificationFile) {
185
+ thisArg.log(`[WATCHER] Watching for changes in the template directory ${(0, picocolors_1.magenta)(watchDir)} and in the AsyncAPI file ${(0, picocolors_1.magenta)(specificationFile)}`);
186
+ watcher = new Watcher([specificationFile, watchDir], ignorePaths);
187
+ }
188
+ else {
189
+ thisArg.log(`[WATCHER] Watching for changes in the template directory ${(0, picocolors_1.magenta)(watchDir)}`);
190
+ watcher = new Watcher(watchDir, ignorePaths);
191
+ }
192
+ if (!(yield thisArg.isLocalTemplate(path_1.default.resolve(generatorClass.DEFAULT_TEMPLATES_DIR, templateName)))) {
193
+ thisArg.warn(`WARNING: ${template} is a remote template. Changes may be lost on subsequent installations.`);
194
+ }
195
+ yield watcher.watch(watchHandler, (paths) => {
196
+ thisArg.error(`[WATCHER] Could not find the file path ${paths}, are you sure it still exists? If it has been deleted or moved please rerun the generator.`, {
197
+ exit: 1,
198
+ });
199
+ });
200
+ });
201
+ }
202
+ function watcherHandler(thisArg, asyncapi, template, output, options, genOption, interactive) {
203
+ return (changedFiles) => tslib_1.__awaiter(this, void 0, void 0, function* () {
204
+ console.clear();
205
+ console.log('[WATCHER] Change detected');
206
+ for (const [, value] of Object.entries(changedFiles)) {
207
+ let eventText;
208
+ switch (value.eventType) {
209
+ case 'changed':
210
+ eventText = (0, picocolors_1.green)(value.eventType);
211
+ break;
212
+ case 'removed':
213
+ eventText = (0, picocolors_1.red)(value.eventType);
214
+ break;
215
+ case 'renamed':
216
+ eventText = (0, picocolors_1.yellow)(value.eventType);
217
+ break;
218
+ default:
219
+ eventText = (0, picocolors_1.yellow)(value.eventType);
220
+ }
221
+ thisArg.log(`\t${(0, picocolors_1.magenta)(value.path)} was ${eventText}`);
222
+ }
223
+ try {
224
+ yield thisArg.generate(asyncapi, template, output, options, genOption, interactive);
225
+ }
226
+ catch (err) {
227
+ throw new generator_error_1.GeneratorError(err);
228
+ }
229
+ });
230
+ }
@@ -750,6 +750,158 @@
750
750
  "versions.js"
751
751
  ]
752
752
  },
753
+ "generate:client": {
754
+ "aliases": [],
755
+ "args": {
756
+ "language": {
757
+ "description": "The language you want the client generated for. Available target languages: dart, java, javascript, python",
758
+ "name": "language",
759
+ "required": true
760
+ },
761
+ "asyncapi": {
762
+ "description": "- Local path, url or context-name pointing to AsyncAPI file",
763
+ "name": "asyncapi",
764
+ "required": false
765
+ }
766
+ },
767
+ "description": "Generates clients baked-in AsyncAPI Generator. Available for: dart, java, javascript, python. If some language is not supported or you want to improve existing client, join us at https://github.com/asyncapi/generator",
768
+ "examples": [
769
+ "asyncapi generate client javascript asyncapi.yaml --param version=1.0.0 singleFile=true --output ./docs --force-write"
770
+ ],
771
+ "flags": {
772
+ "help": {
773
+ "char": "h",
774
+ "description": "Show CLI help.",
775
+ "name": "help",
776
+ "allowNo": false,
777
+ "type": "boolean"
778
+ },
779
+ "disable-hook": {
780
+ "char": "d",
781
+ "description": "Disable a specific hook type or hooks from a given hook type",
782
+ "name": "disable-hook",
783
+ "hasDynamicHelp": false,
784
+ "multiple": true,
785
+ "type": "option"
786
+ },
787
+ "no-interactive": {
788
+ "description": "Disable interactive mode and run with the provided flags.",
789
+ "name": "no-interactive",
790
+ "allowNo": false,
791
+ "type": "boolean"
792
+ },
793
+ "install": {
794
+ "char": "i",
795
+ "description": "Installs the template and its dependencies (defaults to false)",
796
+ "name": "install",
797
+ "allowNo": false,
798
+ "type": "boolean"
799
+ },
800
+ "debug": {
801
+ "description": "Enable more specific errors in the console",
802
+ "name": "debug",
803
+ "allowNo": false,
804
+ "type": "boolean"
805
+ },
806
+ "no-overwrite": {
807
+ "char": "n",
808
+ "description": "Glob or path of the file(s) to skip when regenerating",
809
+ "name": "no-overwrite",
810
+ "hasDynamicHelp": false,
811
+ "multiple": true,
812
+ "type": "option"
813
+ },
814
+ "output": {
815
+ "char": "o",
816
+ "description": "Directory where to put the generated files (defaults to current directory)",
817
+ "name": "output",
818
+ "hasDynamicHelp": false,
819
+ "multiple": false,
820
+ "type": "option"
821
+ },
822
+ "force-write": {
823
+ "description": "Force writing of the generated files to given directory even if it is a git repo with unstaged files or not empty dir (defaults to false)",
824
+ "name": "force-write",
825
+ "allowNo": false,
826
+ "type": "boolean"
827
+ },
828
+ "watch": {
829
+ "char": "w",
830
+ "description": "Watches the template directory and the AsyncAPI document, and re-generate the files when changes occur. Ignores the output directory.",
831
+ "name": "watch",
832
+ "allowNo": false,
833
+ "type": "boolean"
834
+ },
835
+ "param": {
836
+ "char": "p",
837
+ "description": "Additional param to pass to templates",
838
+ "name": "param",
839
+ "hasDynamicHelp": false,
840
+ "multiple": true,
841
+ "type": "option"
842
+ },
843
+ "map-base-url": {
844
+ "description": "Maps all schema references from base url to local folder",
845
+ "name": "map-base-url",
846
+ "hasDynamicHelp": false,
847
+ "multiple": false,
848
+ "type": "option"
849
+ },
850
+ "registry-url": {
851
+ "description": "Specifies the URL of the private registry for fetching templates and dependencies",
852
+ "name": "registry-url",
853
+ "default": "https://registry.npmjs.org",
854
+ "hasDynamicHelp": false,
855
+ "multiple": false,
856
+ "type": "option"
857
+ },
858
+ "registry-auth": {
859
+ "description": "The registry username and password encoded with base64, formatted as username:password",
860
+ "name": "registry-auth",
861
+ "hasDynamicHelp": false,
862
+ "multiple": false,
863
+ "type": "option"
864
+ },
865
+ "registry-token": {
866
+ "description": "The npm registry authentication token, that can be passed instead of base64 encoded username and password",
867
+ "name": "registry-token",
868
+ "hasDynamicHelp": false,
869
+ "multiple": false,
870
+ "type": "option"
871
+ },
872
+ "proxyHost": {
873
+ "description": "Name of the ProxyHost",
874
+ "name": "proxyHost",
875
+ "required": false,
876
+ "hasDynamicHelp": false,
877
+ "multiple": false,
878
+ "type": "option"
879
+ },
880
+ "proxyPort": {
881
+ "description": "Port number number for the proxyHost.",
882
+ "name": "proxyPort",
883
+ "required": false,
884
+ "hasDynamicHelp": false,
885
+ "multiple": false,
886
+ "type": "option"
887
+ }
888
+ },
889
+ "hasDynamicHelp": false,
890
+ "hiddenAliases": [],
891
+ "id": "generate:client",
892
+ "pluginAlias": "@asyncapi/cli",
893
+ "pluginName": "@asyncapi/cli",
894
+ "pluginType": "core",
895
+ "isESM": false,
896
+ "relativePath": [
897
+ "lib",
898
+ "apps",
899
+ "cli",
900
+ "commands",
901
+ "generate",
902
+ "client.js"
903
+ ]
904
+ },
753
905
  "generate:fromTemplate": {
754
906
  "aliases": [],
755
907
  "args": {
@@ -787,7 +939,6 @@
787
939
  "no-interactive": {
788
940
  "description": "Disable interactive mode and run with the provided flags.",
789
941
  "name": "no-interactive",
790
- "required": false,
791
942
  "allowNo": false,
792
943
  "type": "boolean"
793
944
  },
@@ -899,7 +1050,6 @@
899
1050
  "pluginAlias": "@asyncapi/cli",
900
1051
  "pluginName": "@asyncapi/cli",
901
1052
  "pluginType": "core",
902
- "strict": true,
903
1053
  "isESM": false,
904
1054
  "relativePath": [
905
1055
  "lib",
@@ -1609,6 +1759,13 @@
1609
1759
  "name": "suppressLogs",
1610
1760
  "allowNo": false,
1611
1761
  "type": "boolean"
1762
+ },
1763
+ "noBrowser": {
1764
+ "char": "B",
1765
+ "description": "Pass this to not open browser automatically upon running the command",
1766
+ "name": "noBrowser",
1767
+ "allowNo": false,
1768
+ "type": "boolean"
1612
1769
  }
1613
1770
  },
1614
1771
  "hasDynamicHelp": false,
@@ -1669,6 +1826,13 @@
1669
1826
  "required": false,
1670
1827
  "allowNo": false,
1671
1828
  "type": "boolean"
1829
+ },
1830
+ "noBrowser": {
1831
+ "char": "B",
1832
+ "description": "Pass this to not open browser automatically upon running the command",
1833
+ "name": "noBrowser",
1834
+ "allowNo": false,
1835
+ "type": "boolean"
1672
1836
  }
1673
1837
  },
1674
1838
  "hasDynamicHelp": false,
@@ -1978,5 +2142,5 @@
1978
2142
  ]
1979
2143
  }
1980
2144
  },
1981
- "version": "3.4.2"
2145
+ "version": "3.5.1"
1982
2146
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@asyncapi/cli",
3
3
  "description": "All in one CLI for all AsyncAPI tools",
4
- "version": "3.4.2",
4
+ "version": "3.5.1",
5
5
  "author": "@asyncapi",
6
6
  "bin": {
7
7
  "asyncapi": "./bin/run_bin"
@@ -18,7 +18,7 @@
18
18
  "@asyncapi/optimizer": "^1.0.4",
19
19
  "@asyncapi/parser": "^3.3.0",
20
20
  "@asyncapi/problem": "^1.0.0",
21
- "@asyncapi/protobuf-schema-parser": "^3.5.1",
21
+ "@asyncapi/protobuf-schema-parser": "^3.6.0",
22
22
  "@asyncapi/raml-dt-schema-parser": "^4.0.24",
23
23
  "@asyncapi/studio": "^0.24.2",
24
24
  "@changesets/changelog-git": "^0.2.0",
@@ -37,7 +37,7 @@
37
37
  "express": "^4.17.1",
38
38
  "fast-levenshtein": "^3.0.0",
39
39
  "fs-extra": "^11.1.0",
40
- "generator-v2": "npm:@asyncapi/generator@2.4.1",
40
+ "generator-v2": "npm:@asyncapi/generator@2.8.3",
41
41
  "helmet": "^8.1.0",
42
42
  "https-proxy-agent": "^7.0.6",
43
43
  "inquirer": "^8.2.0",
@@ -92,6 +92,7 @@
92
92
  "mocha": "^10.2.0",
93
93
  "nodemon": "^3.1.10",
94
94
  "nyc": "^15.1.0",
95
+ "puppeteer": "^24.17.0",
95
96
  "rimraf": "^3.0.2",
96
97
  "simple-git": "^3.16.0",
97
98
  "supertest": "^7.1.4",
@@ -160,7 +161,7 @@
160
161
  },
161
162
  "repository": "asyncapi/cli",
162
163
  "scripts": {
163
- "build": "rimraf lib && node scripts/fetch-asyncapi-example.js && tsc && tsc-alias --project tsconfig.json && oclif manifest && echo \"Build Completed\"",
164
+ "build": "rimraf lib && node scripts/fetch-asyncapi-example.js && npm run generate:languages && tsc && tsc-alias --project tsconfig.json && oclif manifest && echo \"Build Completed\"",
164
165
  "bump:github-action": "cd github-action/lib/ && node bump-action-version.js",
165
166
  "bump:version": "npx -p @changesets/cli@2.27.7 changeset version && npm run bump:github-action",
166
167
  "dev": "tsc --watch",
@@ -170,6 +171,7 @@
170
171
  "generate:assets": "npm run generate:readme:toc && npm run generate:commands",
171
172
  "generate:commands": "npm run generate:readme:create && npm run generate:readme:commands && node ./scripts/updateUsageDocs.js && rimraf ./scripts/README.md",
172
173
  "generate:readme:toc": "markdown-toc -i README.md",
174
+ "generate:languages": "node scripts/generateTypesForGenerateCommand.js",
173
175
  "prepare": "lefthook install",
174
176
  "lint": "eslint --max-warnings 5 --config .eslintrc .",
175
177
  "lint:fix": "eslint --max-warnings 5 --config .eslintrc . --fix",
@@ -197,7 +199,7 @@
197
199
  "api:prod": "npm run api:build && cross-env NODE_ENV=production PORT=80 node lib/apps/api/server.js",
198
200
  "api:docker": "docker run -it -p 80:80 asyncapi/server-api",
199
201
  "api:build:docker": "docker build -t asyncapi/server-api -f ./src/apps/api/Dockerfile .",
200
- "api:build": "rimraf lib && tsc && tsc-alias --project tsconfig.json",
202
+ "api:build": "rimraf lib && npm run generate:languages && tsc && tsc-alias --project tsconfig.json",
201
203
  "api:test": ""
202
204
  },
203
205
  "types": "lib/index.d.ts"
@@ -0,0 +1,40 @@
1
+ const { writeFile } = require('fs/promises');
2
+ const path = require('path');
3
+ const { listBakedInTemplates } = require('generator-v2');
4
+
5
+ async function generateClientLanguages() {
6
+ const bakedInClients = listBakedInTemplates({ type: 'client' });
7
+
8
+ const targets = Array.from(new Set(bakedInClients.map(t => t.target))).sort();
9
+
10
+ const enumEntries = targets
11
+ .map(t => ` ${capitalize(t)} = '${t}',`)
12
+ .join('\n');
13
+
14
+ const fileContent = `// Auto-generated. Do not edit manually.
15
+ export enum AvailableLanguage {
16
+ ${enumEntries}
17
+ }
18
+
19
+ export const availableLanguages = [${targets.map(t => `'${t}'`).join(', ')}] as const;
20
+ export type AvailableLanguageType = typeof availableLanguages[number];
21
+
22
+ /**
23
+ * Returns the first available language as the default option.
24
+ */
25
+ export const getDefaultLanguage = (): AvailableLanguageType => availableLanguages[0];
26
+ `;
27
+
28
+ const outputPath = path.join(__dirname, '../src/domains/models/generate/ClientLanguages.ts');
29
+ await writeFile(outputPath, fileContent);
30
+
31
+ console.log('✅ ClientLanguages.ts generated');
32
+ }
33
+
34
+ function capitalize(str) {
35
+ return str.charAt(0).toUpperCase() + str.slice(1);
36
+ }
37
+
38
+ generateClientLanguages().catch(err => {
39
+ throw new Error(`Failed to generate ClientLanguages.ts: ${err.message}`);
40
+ });