@asyncapi/cli 2.15.0 → 2.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -12,6 +12,7 @@ CLI to work with your AsyncAPI files. Currently under development, we are workin
12
12
 
13
13
  - [Installation](#installation)
14
14
  - [Usage](#usage)
15
+ - [Github Action](#github-action)
15
16
  - [Contributing](#contributing)
16
17
  * [Set up development environment](#set-up-development-environment)
17
18
  * [Command Structure and Patterns](#command-structure-and-patterns)
@@ -25,6 +26,9 @@ Learn how to install the AsyncAPI CLI by following the instructions in the [inst
25
26
  ## Usage
26
27
  The [usage guide](/docs/usage.md) provides information about different ways to use the CLI.
27
28
 
29
+ ## Github Action
30
+
31
+ The AsyncAPI CLI can be used as a GitHub Action. You can find more information in the [GitHub Action guide](https://www.asyncapi.com/docs/tools/cli/github-action).
28
32
 
29
33
  ## Contributing
30
34
 
@@ -6,6 +6,7 @@ const base_1 = tslib_1.__importDefault(require("../../core/base"));
6
6
  const fs_1 = require("fs");
7
7
  const os_1 = require("os");
8
8
  const analytics_flags_1 = require("../../core/flags/config/analytics.flags");
9
+ const picocolors_1 = require("picocolors");
9
10
  const { readFile, writeFile } = fs_1.promises;
10
11
  class Analytics extends base_1.default {
11
12
  run() {
@@ -25,7 +26,7 @@ class Analytics extends base_1.default {
25
26
  this.metricsMetadata.analytics_enabled = flags.enable;
26
27
  }
27
28
  else if (!flags.status) {
28
- this.log('\nPlease append the "--disable" flag to the command in case you prefer to disable analytics, or use the "--enable" flag if you want to enable analytics back again. In case you do not know the analytics current status, then you can append the "--status" flag to be aware of it.\n');
29
+ this.log(`\nPlease append the ${(0, picocolors_1.blueBright)('--disable')} flag to the command if you prefer to disable analytics, or use the ${(0, picocolors_1.blueBright)('--enable')} flag if you want to enable analytics again. To check the current analytics status, use the ${(0, picocolors_1.blueBright)('--status')} flag.\n`);
29
30
  return;
30
31
  }
31
32
  yield writeFile(analyticsConfigFile, JSON.stringify(analyticsConfigFileContent), { encoding: 'utf8' });
@@ -34,7 +35,7 @@ class Analytics extends base_1.default {
34
35
  this.log('\nAnalytics are enabled.\n');
35
36
  }
36
37
  else {
37
- this.log('\nAnalytics are disabled. Please append the "--enable" flag to the command in case you prefer to enable analytics.\n');
38
+ this.log(`\n${(0, picocolors_1.redBright)('Analytics are disabled.')} To enable analytics, use the ${(0, picocolors_1.blueBright)('--enable')} flag.\n`);
38
39
  }
39
40
  this.metricsMetadata.analytics_status_checked = flags.status;
40
41
  }
@@ -42,13 +43,13 @@ class Analytics extends base_1.default {
42
43
  catch (e) {
43
44
  switch (e.code) {
44
45
  case 'ENOENT':
45
- this.error(`Unable to access the analytics configuration file. We tried to access the ".asyncapi-analytics" file in in the path "${analyticsConfigFile}" but the file could not be found.`);
46
+ this.error(`Unable to access the analytics configuration file. We tried to access the ${(0, picocolors_1.blueBright)('.asyncapi-analytics')} file in the path "${(0, picocolors_1.blueBright)(analyticsConfigFile)}" but the file could not be found.`);
46
47
  break;
47
48
  case 'EEXIST':
48
- this.error(`Unable to update the analytics configuration file. We tried to update your ".asyncapi-analytics" file in the path "${analyticsConfigFile}" but the file does not exist.`);
49
+ this.error(`Unable to update the analytics configuration file. We tried to update your ".asyncapi-analytics" file in the path "${(0, picocolors_1.blueBright)(analyticsConfigFile)}" but the file does not exist.`);
49
50
  break;
50
51
  default:
51
- this.error(`Unable to change your analytics configuration. Please check the following message for further info about the error:\n\n${e}`);
52
+ this.error(`Unable to change your analytics configuration. Please check the following message for further info about the error:\n\n${(0, picocolors_1.redBright)(e)}`);
52
53
  }
53
54
  }
54
55
  });
@@ -6,6 +6,7 @@ const base_1 = tslib_1.__importDefault(require("../../../core/base"));
6
6
  const Context_1 = require("../../../core/models/Context");
7
7
  const context_error_1 = require("../../../core/errors/context-error");
8
8
  const context_flags_1 = require("../../../core/flags/config/context.flags");
9
+ const picocolors_1 = require("picocolors");
9
10
  class ContextAdd extends base_1.default {
10
11
  run() {
11
12
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
@@ -15,16 +16,15 @@ class ContextAdd extends base_1.default {
15
16
  const setAsCurrent = flags['set-current'];
16
17
  try {
17
18
  yield (0, Context_1.addContext)(contextName, specFilePath);
18
- this.log(`Added context "${contextName}".\n\nYou can set it as your current context: asyncapi config context use ${contextName}\nYou can use this context when needed by passing ${contextName} as a parameter: asyncapi validate ${contextName}`);
19
+ this.log(`🎉 Context ${(0, picocolors_1.blueBright)(contextName)} added successfully!\nYou can set it as your current context:\n ${(0, picocolors_1.blueBright)('asyncapi')} ${(0, picocolors_1.blueBright)('config')} ${(0, picocolors_1.blueBright)('context')} ${(0, picocolors_1.blueBright)('use')} ${(0, picocolors_1.blueBright)(contextName)}\nYou can use this context when needed by passing ${(0, picocolors_1.blueBright)(contextName)} as a parameter:\n ${(0, picocolors_1.blueBright)('asyncapi')} ${(0, picocolors_1.blueBright)('validate')} ${(0, picocolors_1.blueBright)(contextName)}`);
19
20
  if (setAsCurrent) {
20
21
  yield (0, Context_1.setCurrentContext)(contextName);
21
- this.log(`The newly added context "${contextName}", is set as your current context!`);
22
+ this.log(`\nThe newly added context, ${(0, picocolors_1.blueBright)(contextName)}, is set as your current context!`);
22
23
  }
23
24
  }
24
25
  catch (e) {
25
26
  if (e instanceof (context_error_1.MissingContextFileError || context_error_1.ContextFileWrongFormatError)) {
26
- this.log('You have no context file configured. Run "asyncapi config context init" to initialize it.');
27
- return;
27
+ this.error(`Unable to add context. You have no context file configured.\nRun ${(0, picocolors_1.blueBright)('asyncapi config context init')} to initialize it.`);
28
28
  }
29
29
  throw e;
30
30
  }
@@ -5,6 +5,7 @@ const base_1 = tslib_1.__importDefault(require("../../../core/base"));
5
5
  const Context_1 = require("../../../core/models/Context");
6
6
  const context_error_1 = require("../../../core/errors/context-error");
7
7
  const global_flags_1 = require("../../../core/flags/global.flags");
8
+ const picocolors_1 = require("picocolors");
8
9
  class ContextCurrent extends base_1.default {
9
10
  run() {
10
11
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
@@ -14,22 +15,19 @@ class ContextCurrent extends base_1.default {
14
15
  }
15
16
  catch (e) {
16
17
  if (e instanceof (context_error_1.MissingContextFileError || context_error_1.ContextFileWrongFormatError)) {
17
- this.log('You have no context file configured. Run "asyncapi config context init" to initialize it.');
18
- return;
18
+ this.error(`Unable to show current context. You have no context file configured.\nRun ${(0, picocolors_1.blueBright)('asyncapi config context init')} to initialize it.`);
19
19
  }
20
20
  else if (e instanceof context_error_1.ContextFileEmptyError) {
21
- this.log(`Context file "${Context_1.CONTEXT_FILE_PATH}" is empty.`);
22
- return;
21
+ this.error(`Context file ${(0, picocolors_1.blueBright)(Context_1.CONTEXT_FILE_PATH)} is empty.`);
23
22
  }
24
23
  else if (e instanceof context_error_1.ContextNotFoundError ||
25
24
  (fileContent && !fileContent.current)) {
26
- this.log('No context is set as current. Run "asyncapi config context" to see all available options.');
27
- return;
25
+ this.error(`No context is set as current.\nRun ${(0, picocolors_1.blueBright)('asyncapi config context')} to see all available options.`);
28
26
  }
29
27
  throw e;
30
28
  }
31
29
  if (fileContent) {
32
- this.log(`${fileContent.current}: ${fileContent.context}`);
30
+ this.log(`${(0, picocolors_1.blueBright)(fileContent.current)}: ${fileContent.context}`);
33
31
  }
34
32
  });
35
33
  }
@@ -6,6 +6,7 @@ const base_1 = tslib_1.__importDefault(require("../../../core/base"));
6
6
  const Context_1 = require("../../../core/models/Context");
7
7
  const context_error_1 = require("../../../core/errors/context-error");
8
8
  const global_flags_1 = require("../../../core/flags/global.flags");
9
+ const picocolors_1 = require("picocolors");
9
10
  class ContextEdit extends base_1.default {
10
11
  run() {
11
12
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
@@ -14,16 +15,14 @@ class ContextEdit extends base_1.default {
14
15
  const newSpecFilePath = args['new-spec-file-path'];
15
16
  try {
16
17
  yield (0, Context_1.editContext)(contextName, newSpecFilePath);
17
- this.log(`Edited context "${contextName}".\n\nYou can set it as your current context: asyncapi config context use ${contextName}\nYou can use this context when needed by passing ${contextName} as a parameter: asyncapi validate ${contextName}`);
18
+ this.log(`🎉 Context ${(0, picocolors_1.blueBright)(contextName)} edited successfully!\nYou can set it as your current context:\n ${(0, picocolors_1.blueBright)('asyncapi')} ${(0, picocolors_1.blueBright)('config')} ${(0, picocolors_1.blueBright)('context')} ${(0, picocolors_1.blueBright)('use')} ${(0, picocolors_1.blueBright)(contextName)}\nYou can use this context when needed by passing ${(0, picocolors_1.blueBright)(contextName)} as a parameter:\n ${(0, picocolors_1.blueBright)('asyncapi')} ${(0, picocolors_1.blueBright)('validate')} ${(0, picocolors_1.blueBright)(contextName)}`);
18
19
  }
19
20
  catch (e) {
20
21
  if (e instanceof (context_error_1.MissingContextFileError || context_error_1.ContextFileWrongFormatError)) {
21
- this.log('You have no context file configured. Run "asyncapi config context init" to initialize it.');
22
- return;
22
+ this.error(`Unable to edit context. You have no context file configured.\nRun ${(0, picocolors_1.blueBright)('asyncapi config context init')} to initialize it.`);
23
23
  }
24
24
  else if (e instanceof context_error_1.ContextFileEmptyError) {
25
- this.log(`Context file "${Context_1.CONTEXT_FILE_PATH}" is empty.`);
26
- return;
25
+ this.error(`Context file ${(0, picocolors_1.blueBright)(Context_1.CONTEXT_FILE_PATH)} is empty.`);
27
26
  }
28
27
  throw e;
29
28
  }
@@ -5,13 +5,14 @@ const core_1 = require("@oclif/core");
5
5
  const base_1 = tslib_1.__importDefault(require("../../../core/base"));
6
6
  const Context_1 = require("../../../core/models/Context");
7
7
  const global_flags_1 = require("../../../core/flags/global.flags");
8
+ const picocolors_1 = require("picocolors");
8
9
  class ContextInit extends base_1.default {
9
10
  run() {
10
11
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
11
12
  const { args } = yield this.parse(ContextInit);
12
13
  const contextFilePath = args['context-file-path'];
13
14
  const contextWritePath = yield (0, Context_1.initContext)(contextFilePath);
14
- this.log(`Initialized context ${contextWritePath}`);
15
+ this.log(`🎉 Context initialized at ${(0, picocolors_1.blueBright)(contextWritePath)}`);
15
16
  });
16
17
  }
17
18
  }
@@ -19,9 +20,9 @@ exports.default = ContextInit;
19
20
  ContextInit.description = 'Initialize context';
20
21
  ContextInit.flags = (0, global_flags_1.helpFlag)();
21
22
  ContextInit.contextFilePathMessage = `Specify directory in which context file should be created:
22
- - current directory : asyncapi config context init . (default)
23
- - root of current repository : asyncapi config context init ./
24
- - user's home directory : asyncapi config context init ~`;
23
+ - current directory : ${(0, picocolors_1.blueBright)('asyncapi config context init .')}(default)
24
+ - root of current repository : ${(0, picocolors_1.blueBright)('asyncapi config context init ./ ')}
25
+ - user's home directory : ${(0, picocolors_1.blueBright)('asyncapi config context init ~`')}`;
25
26
  ContextInit.args = {
26
27
  'context-file-path': core_1.Args.string({ description: `${ContextInit.contextFilePathMessage}`, required: false })
27
28
  };
@@ -5,24 +5,25 @@ const base_1 = tslib_1.__importDefault(require("../../../core/base"));
5
5
  const Context_1 = require("../../../core/models/Context");
6
6
  const context_error_1 = require("../../../core/errors/context-error");
7
7
  const global_flags_1 = require("../../../core/flags/global.flags");
8
+ const picocolors_1 = require("picocolors");
8
9
  class ContextList extends base_1.default {
9
10
  run() {
10
11
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
11
12
  try {
12
13
  const fileContent = yield (0, Context_1.loadContextFile)();
13
14
  if (yield (0, Context_1.isContextFileEmpty)(fileContent)) {
14
- this.log(`Context file "${Context_1.CONTEXT_FILE_PATH}" is empty.`);
15
+ this.log(`Context file ${(0, picocolors_1.blueBright)(Context_1.CONTEXT_FILE_PATH)} is empty.`);
15
16
  return;
16
17
  }
17
18
  if (fileContent) {
18
19
  for (const [contextName, filePath] of Object.entries(fileContent.store)) {
19
- this.log(`${contextName}: ${filePath}`);
20
+ this.log(`${(0, picocolors_1.blueBright)(contextName)}: ${filePath}`);
20
21
  }
21
22
  }
22
23
  }
23
24
  catch (e) {
24
25
  if (e instanceof (context_error_1.MissingContextFileError || context_error_1.ContextFileWrongFormatError)) {
25
- this.log('You have no context file configured. Run "asyncapi config context init" to initialize it.');
26
+ this.log(`Unable to list contexts. You have no context file configured.\nRun ${(0, picocolors_1.blueBright)('asyncapi config context init')} to initialize it.\n`);
26
27
  return;
27
28
  }
28
29
  throw e;
@@ -6,6 +6,7 @@ const base_1 = tslib_1.__importDefault(require("../../../core/base"));
6
6
  const Context_1 = require("../../../core/models/Context");
7
7
  const context_error_1 = require("../../../core/errors/context-error");
8
8
  const global_flags_1 = require("../../../core/flags/global.flags");
9
+ const picocolors_1 = require("picocolors");
9
10
  class ContextRemove extends base_1.default {
10
11
  run() {
11
12
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
@@ -13,16 +14,14 @@ class ContextRemove extends base_1.default {
13
14
  const contextName = args['context-name'];
14
15
  try {
15
16
  yield (0, Context_1.removeContext)(contextName);
16
- this.log(`${contextName} successfully deleted`);
17
+ this.log(`Context ${(0, picocolors_1.blueBright)(contextName)} removed successfully!\n`);
17
18
  }
18
19
  catch (e) {
19
20
  if (e instanceof (context_error_1.MissingContextFileError || context_error_1.ContextFileWrongFormatError)) {
20
- this.log('You have no context file configured. Run "asyncapi config context init" to initialize it.');
21
- return;
21
+ this.error(`Unable to remove context. You have no context file configured.\nRun ${(0, picocolors_1.blueBright)('asyncapi config context init')} to initialize it.`);
22
22
  }
23
23
  else if (e instanceof context_error_1.ContextFileEmptyError) {
24
- this.log(`Context file "${Context_1.CONTEXT_FILE_PATH}" is empty.`);
25
- return;
24
+ this.error(`Context file ${(0, picocolors_1.blueBright)(Context_1.CONTEXT_FILE_PATH)} is empty.`);
26
25
  }
27
26
  throw e;
28
27
  }
@@ -6,6 +6,7 @@ const base_1 = tslib_1.__importDefault(require("../../../core/base"));
6
6
  const Context_1 = require("../../../core/models/Context");
7
7
  const context_error_1 = require("../../../core/errors/context-error");
8
8
  const global_flags_1 = require("../../../core/flags/global.flags");
9
+ const picocolors_1 = require("picocolors");
9
10
  class ContextUse extends base_1.default {
10
11
  run() {
11
12
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
@@ -13,15 +14,14 @@ class ContextUse extends base_1.default {
13
14
  const contextName = args['context-name'];
14
15
  try {
15
16
  yield (0, Context_1.setCurrentContext)(contextName);
16
- this.log(`${contextName} is set as current`);
17
+ this.log(`Context ${(0, picocolors_1.blueBright)(contextName)} is now set as current.`);
17
18
  }
18
19
  catch (e) {
19
20
  if (e instanceof (context_error_1.MissingContextFileError || context_error_1.ContextFileWrongFormatError)) {
20
- this.log('You have no context file configured. Run "asyncapi config context init" to initialize it.');
21
- return;
21
+ this.error(`Unable to set the current context. You have no context file configured.\nRun ${(0, picocolors_1.blueBright)('asyncapi config context init')} to initialize it.`);
22
22
  }
23
23
  else if (e instanceof context_error_1.ContextFileEmptyError) {
24
- this.log(`Context file "${Context_1.CONTEXT_FILE_PATH}" is empty.`);
24
+ this.error(`Context file ${(0, picocolors_1.blueBright)(Context_1.CONTEXT_FILE_PATH)} is empty.`);
25
25
  return;
26
26
  }
27
27
  throw e;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  const base_1 = tslib_1.__importDefault(require("../../core/base"));
5
5
  const global_flags_1 = require("../../core/flags/global.flags");
6
+ const picocolors_1 = require("picocolors");
6
7
  class Versions extends base_1.default {
7
8
  run() {
8
9
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
@@ -29,7 +30,7 @@ class Versions extends base_1.default {
29
30
  }
30
31
  }
31
32
  // Showing information available with `--version` flag.
32
- this.log(this.config.userAgent);
33
+ this.log((0, picocolors_1.gray)(`\n${this.config.userAgent}\n`));
33
34
  // Iteration through the array containing all dependencies '@asyncapi/*'
34
35
  // along with their versions.
35
36
  for (let i = 0; i < dependencies.length; i++) {
@@ -47,7 +48,7 @@ class Versions extends base_1.default {
47
48
  this.log(` └${dependency}\n`);
48
49
  }
49
50
  }
50
- this.log(`Repository: ${this.config.pjson.homepage}`);
51
+ this.log(`Repository: ${(0, picocolors_1.blueBright)(this.config.pjson.homepage)}`);
51
52
  });
52
53
  }
53
54
  }
@@ -109,6 +109,7 @@ class NewFile extends base_1.default {
109
109
  fileName = fileName || DEFAULT_ASYNCAPI_FILE_NAME;
110
110
  selectedTemplate = selectedTemplate || DEFAULT_ASYNCAPI_TEMPLATE;
111
111
  yield this.createAsyncapiFile(fileName, selectedTemplate);
112
+ fileName = fileName.includes('.') ? fileName : `${fileName}.yaml`;
112
113
  if (openStudio) {
113
114
  (0, Studio_1.start)(fileName, flags.port || Studio_1.DEFAULT_PORT);
114
115
  }
@@ -155,5 +156,5 @@ NewFile.description = 'Creates a new asyncapi file';
155
156
  NewFile.flags = (0, file_flags_1.fileFlags)(getExamplesFlagDescription());
156
157
  NewFile.examples = [
157
158
  'asyncapi new\t - start creation of a file in interactive mode',
158
- 'asyncapi new --file-name=my-asyncapi.yml --example=default-example.yml --no-tty\t - create a new file with a specific name, using one of the examples and without interactive mode'
159
+ 'asyncapi new --file-name=my-asyncapi.yaml --example=default-example.yaml --no-tty\t - create a new file with a specific name, using one of the examples and without interactive mode'
159
160
  ];
@@ -6,5 +6,8 @@ export default class StartStudio extends Command {
6
6
  file: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
7
7
  port: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
8
8
  };
9
+ static readonly args: {
10
+ 'spec-file': import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
11
+ };
9
12
  run(): Promise<void>;
10
13
  }
@@ -5,13 +5,35 @@ const base_1 = tslib_1.__importDefault(require("../../core/base"));
5
5
  const Studio_1 = require("../../core/models/Studio");
6
6
  const SpecificationFile_1 = require("../../core/models/SpecificationFile");
7
7
  const studio_flags_1 = require("../../core/flags/start/studio.flags");
8
+ const core_1 = require("@oclif/core");
8
9
  class StartStudio extends base_1.default {
9
10
  run() {
11
+ var _a;
10
12
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
11
- const { flags } = yield this.parse(StartStudio);
12
- const filePath = flags.file || (yield (0, SpecificationFile_1.load)()).getFilePath();
13
+ const { args, flags } = yield this.parse(StartStudio);
14
+ if (flags.file) {
15
+ this.warn('The file flag has been removed and is being replaced by the argument spec-file. Please pass the filename directly like `asyncapi start studio asyncapi.yml`');
16
+ }
17
+ let filePath = (_a = args['spec-file']) !== null && _a !== void 0 ? _a : flags.file;
13
18
  const port = flags.port;
14
- this.specFile = yield (0, SpecificationFile_1.load)(filePath);
19
+ if (!filePath) {
20
+ try {
21
+ filePath = ((yield (0, SpecificationFile_1.load)()).getFilePath());
22
+ this.log(`Loaded specification from: ${filePath}`);
23
+ }
24
+ catch (error) {
25
+ filePath = '';
26
+ this.error('No file specified.');
27
+ }
28
+ }
29
+ try {
30
+ this.specFile = yield (0, SpecificationFile_1.load)(filePath);
31
+ }
32
+ catch (error) {
33
+ if (filePath) {
34
+ this.error(error);
35
+ }
36
+ }
15
37
  this.metricsMetadata.port = port;
16
38
  (0, Studio_1.start)(filePath, port);
17
39
  });
@@ -20,3 +42,6 @@ class StartStudio extends base_1.default {
20
42
  exports.default = StartStudio;
21
43
  StartStudio.description = 'starts a new local instance of Studio';
22
44
  StartStudio.flags = (0, studio_flags_1.studioFlags)();
45
+ StartStudio.args = {
46
+ 'spec-file': core_1.Args.string({ description: 'spec path, url, or context-name', required: false }),
47
+ };
package/lib/core/base.js CHANGED
@@ -43,6 +43,10 @@ class default_1 extends core_1.Command {
43
43
  return yield _super.catch.call(this, err);
44
44
  }
45
45
  catch (e) {
46
+ if (e.message.includes('EEXIT: 0')) {
47
+ process.exitCode = 0;
48
+ return;
49
+ }
46
50
  if (e instanceof Error) {
47
51
  this.logToStderr(`${e.name}: ${e.message}`);
48
52
  process.exitCode = 1;
@@ -5,7 +5,7 @@ const core_1 = require("@oclif/core");
5
5
  const studioFlags = () => {
6
6
  return {
7
7
  help: core_1.Flags.help({ char: 'h' }),
8
- file: core_1.Flags.string({ char: 'f', description: 'path to the AsyncAPI file to link with Studio' }),
8
+ file: core_1.Flags.string({ char: 'f', description: 'path to the AsyncAPI file to link with Studio', deprecated: true }),
9
9
  port: core_1.Flags.integer({ char: 'p', description: 'port in which to start Studio' }),
10
10
  };
11
11
  };
@@ -20,30 +20,32 @@ function isValidFilePath(filePath) {
20
20
  return (0, fs_1.existsSync)(filePath);
21
21
  }
22
22
  function start(filePath, port = exports.DEFAULT_PORT) {
23
- if (!isValidFilePath(filePath)) {
23
+ if (filePath && !isValidFilePath(filePath)) {
24
24
  throw new specification_file_1.SpecificationFileNotFound(filePath);
25
25
  }
26
- chokidar_1.default.watch(filePath).on('all', (event, path) => {
27
- switch (event) {
28
- case 'add':
29
- case 'change':
30
- getFileContent(path).then((code) => {
26
+ if (filePath) {
27
+ chokidar_1.default.watch(filePath).on('all', (event, path) => {
28
+ switch (event) {
29
+ case 'add':
30
+ case 'change':
31
+ getFileContent(path).then((code) => {
32
+ messageQueue.push(JSON.stringify({
33
+ type: 'file:changed',
34
+ code,
35
+ }));
36
+ sendQueuedMessages();
37
+ });
38
+ break;
39
+ case 'unlink':
31
40
  messageQueue.push(JSON.stringify({
32
- type: 'file:changed',
33
- code,
41
+ type: 'file:deleted',
42
+ filePath,
34
43
  }));
35
44
  sendQueuedMessages();
36
- });
37
- break;
38
- case 'unlink':
39
- messageQueue.push(JSON.stringify({
40
- type: 'file:deleted',
41
- filePath,
42
- }));
43
- sendQueuedMessages();
44
- break;
45
- }
46
- });
45
+ break;
46
+ }
47
+ });
48
+ }
47
49
  const server = (0, http_1.createServer)((request, response) => {
48
50
  //not all CLI users use npm. Some package managers put dependencies in different weird places
49
51
  //this is why we need to first figure out where exactly is the index.html located
@@ -67,17 +69,26 @@ function start(filePath, port = exports.DEFAULT_PORT) {
67
69
  const wsServer = new ws_1.WebSocketServer({ noServer: true });
68
70
  wsServer.on('connection', (socket) => {
69
71
  sockets.push(socket);
70
- getFileContent(filePath).then((code) => {
72
+ if (filePath) {
73
+ getFileContent(filePath).then((code) => {
74
+ messageQueue.push(JSON.stringify({
75
+ type: 'file:loaded',
76
+ code,
77
+ }));
78
+ sendQueuedMessages();
79
+ });
80
+ }
81
+ else {
71
82
  messageQueue.push(JSON.stringify({
72
83
  type: 'file:loaded',
73
- code,
84
+ code: '',
74
85
  }));
75
86
  sendQueuedMessages();
76
- });
87
+ }
77
88
  socket.on('message', (event) => {
78
89
  try {
79
90
  const json = JSON.parse(event);
80
- if (json.type === 'file:update') {
91
+ if (filePath && json.type === 'file:update') {
81
92
  saveFileContent(filePath, json.code);
82
93
  }
83
94
  else {
@@ -95,9 +106,15 @@ function start(filePath, port = exports.DEFAULT_PORT) {
95
106
  });
96
107
  server.listen(port, () => {
97
108
  const url = `http://localhost:${port}?liveServer=${port}&studio-version=${package_json_1.version}`;
98
- console.log(`Studio is now running at ${url}.`);
99
- console.log(`You can open this URL in your web browser, and if needed, press ${(0, picocolors_1.gray)('Ctrl + C')} to stop the process.`);
100
- console.log(`Watching changes on file ${filePath}`);
109
+ console.log(`🎉 Connected to Live Server running at ${(0, picocolors_1.blueBright)(url)}.`);
110
+ console.log(`🌐 Open this URL in your web browser: ${(0, picocolors_1.blueBright)(url)}`);
111
+ console.log(`🛑 If needed, press ${(0, picocolors_1.redBright)('Ctrl + C')} to stop the process.`);
112
+ if (filePath) {
113
+ console.log(`👁️ Watching changes on file ${(0, picocolors_1.blueBright)(filePath)}`);
114
+ }
115
+ else {
116
+ console.warn('Warning: No file was provided, and we couldn\'t find a default file (like "asyncapi.yaml" or "asyncapi.json") in the current folder. Starting Studio with a blank workspace.');
117
+ }
101
118
  (0, open_1.default)(url);
102
119
  });
103
120
  }
@@ -1210,7 +1210,7 @@
1210
1210
  "description": "Creates a new asyncapi file",
1211
1211
  "examples": [
1212
1212
  "asyncapi new\t - start creation of a file in interactive mode",
1213
- "asyncapi new --file-name=my-asyncapi.yml --example=default-example.yml --no-tty\t - create a new file with a specific name, using one of the examples and without interactive mode"
1213
+ "asyncapi new --file-name=my-asyncapi.yaml --example=default-example.yaml --no-tty\t - create a new file with a specific name, using one of the examples and without interactive mode"
1214
1214
  ],
1215
1215
  "flags": {
1216
1216
  "help": {
@@ -1340,7 +1340,7 @@
1340
1340
  "description": "Creates a new asyncapi file",
1341
1341
  "examples": [
1342
1342
  "asyncapi new\t - start creation of a file in interactive mode",
1343
- "asyncapi new --file-name=my-asyncapi.yml --example=default-example.yml --no-tty\t - create a new file with a specific name, using one of the examples and without interactive mode"
1343
+ "asyncapi new --file-name=my-asyncapi.yaml --example=default-example.yaml --no-tty\t - create a new file with a specific name, using one of the examples and without interactive mode"
1344
1344
  ],
1345
1345
  "flags": {
1346
1346
  "help": {
@@ -1494,7 +1494,13 @@
1494
1494
  },
1495
1495
  "start:studio": {
1496
1496
  "aliases": [],
1497
- "args": {},
1497
+ "args": {
1498
+ "spec-file": {
1499
+ "description": "spec path, url, or context-name",
1500
+ "name": "spec-file",
1501
+ "required": false
1502
+ }
1503
+ },
1498
1504
  "description": "starts a new local instance of Studio",
1499
1505
  "flags": {
1500
1506
  "help": {
@@ -1506,6 +1512,7 @@
1506
1512
  },
1507
1513
  "file": {
1508
1514
  "char": "f",
1515
+ "deprecated": true,
1509
1516
  "description": "path to the AsyncAPI file to link with Studio",
1510
1517
  "name": "file",
1511
1518
  "hasDynamicHelp": false,
@@ -1678,7 +1685,7 @@
1678
1685
  "aliases": [],
1679
1686
  "args": {
1680
1687
  "context-file-path": {
1681
- "description": "Specify directory in which context file should be created:\n - current directory : asyncapi config context init . (default)\n - root of current repository : asyncapi config context init ./\n - user's home directory : asyncapi config context init ~",
1688
+ "description": "Specify directory in which context file should be created:\n - current directory : \u001b[94masyncapi config context init .\u001b[39m(default)\n - root of current repository : \u001b[94masyncapi config context init ./ \u001b[39m\n - user's home directory : \u001b[94masyncapi config context init ~`\u001b[39m",
1682
1689
  "name": "context-file-path",
1683
1690
  "required": false
1684
1691
  }
@@ -1700,7 +1707,7 @@
1700
1707
  "pluginName": "@asyncapi/cli",
1701
1708
  "pluginType": "core",
1702
1709
  "strict": true,
1703
- "contextFilePathMessage": "Specify directory in which context file should be created:\n - current directory : asyncapi config context init . (default)\n - root of current repository : asyncapi config context init ./\n - user's home directory : asyncapi config context init ~",
1710
+ "contextFilePathMessage": "Specify directory in which context file should be created:\n - current directory : \u001b[94masyncapi config context init .\u001b[39m(default)\n - root of current repository : \u001b[94masyncapi config context init ./ \u001b[39m\n - user's home directory : \u001b[94masyncapi config context init ~`\u001b[39m",
1704
1711
  "isESM": false,
1705
1712
  "relativePath": [
1706
1713
  "lib",
@@ -1810,5 +1817,5 @@
1810
1817
  ]
1811
1818
  }
1812
1819
  },
1813
- "version": "2.15.0"
1820
+ "version": "2.16.1"
1814
1821
  }
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": "2.15.0",
4
+ "version": "2.16.1",
5
5
  "author": "@asyncapi",
6
6
  "bin": {
7
7
  "asyncapi": "./bin/run_bin"