@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 +4 -0
- package/lib/commands/config/analytics.js +6 -5
- package/lib/commands/config/context/add.js +4 -4
- package/lib/commands/config/context/current.js +5 -7
- package/lib/commands/config/context/edit.js +4 -5
- package/lib/commands/config/context/init.js +5 -4
- package/lib/commands/config/context/list.js +4 -3
- package/lib/commands/config/context/remove.js +4 -5
- package/lib/commands/config/context/use.js +4 -4
- package/lib/commands/config/versions.js +3 -2
- package/lib/commands/new/file.js +2 -1
- package/lib/commands/start/studio.d.ts +3 -0
- package/lib/commands/start/studio.js +28 -3
- package/lib/core/base.js +4 -0
- package/lib/core/flags/start/studio.flags.js +1 -1
- package/lib/core/models/Studio.js +43 -26
- package/oclif.manifest.json +13 -6
- package/package.json +1 -1
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(
|
|
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('
|
|
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
|
|
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(
|
|
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(
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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(
|
|
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.
|
|
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.
|
|
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(
|
|
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 .
|
|
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
|
|
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(
|
|
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(
|
|
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.
|
|
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.
|
|
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(
|
|
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.
|
|
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.
|
|
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
|
}
|
package/lib/commands/new/file.js
CHANGED
|
@@ -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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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:
|
|
33
|
-
|
|
41
|
+
type: 'file:deleted',
|
|
42
|
+
filePath,
|
|
34
43
|
}));
|
|
35
44
|
sendQueuedMessages();
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
-
|
|
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(
|
|
99
|
-
console.log(
|
|
100
|
-
console.log(
|
|
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
|
}
|
package/oclif.manifest.json
CHANGED
|
@@ -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.
|
|
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.
|
|
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 :
|
|
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 :
|
|
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.
|
|
1820
|
+
"version": "2.16.1"
|
|
1814
1821
|
}
|