@asyncapi/cli 0.13.0 β 0.14.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.
- package/README.md +33 -1
- package/lib/commands/diff.d.ts +1 -0
- package/lib/commands/diff.js +15 -0
- package/lib/commands/validate.d.ts +1 -0
- package/lib/commands/validate.js +9 -17
- package/lib/errors/context-error.d.ts +1 -0
- package/lib/errors/context-error.js +9 -3
- package/lib/errors/specification-file.d.ts +5 -0
- package/lib/errors/specification-file.js +27 -1
- package/lib/errors/validation-error.js +11 -1
- package/lib/flags.d.ts +1 -0
- package/lib/flags.js +8 -0
- package/lib/globals.d.ts +10 -0
- package/lib/globals.js +44 -0
- package/lib/models/SpecificationFile.d.ts +7 -1
- package/lib/models/SpecificationFile.js +39 -10
- package/oclif.manifest.json +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -69,8 +69,9 @@ USAGE
|
|
|
69
69
|
|
|
70
70
|
COMMANDS
|
|
71
71
|
config access configs
|
|
72
|
-
|
|
72
|
+
diff find diff between two asyncapi files
|
|
73
73
|
new creates a new asyncapi file
|
|
74
|
+
start starts a new local instance of Studio
|
|
74
75
|
validate validate asyncapi file
|
|
75
76
|
```
|
|
76
77
|
|
|
@@ -92,3 +93,34 @@ UX developed for the CLI should be compliant with [Command Line Interface Guidel
|
|
|
92
93
|
### Command Structure and Patterns
|
|
93
94
|
|
|
94
95
|
We are following `verb + noun` and `namespace + noun + [verb]` pattern for making our commands and arguments. For example `asyncapi validate <spec-file-path>` and `asyncapi config context add <context-name> <spec-file-path>`.
|
|
96
|
+
|
|
97
|
+
## Contributors
|
|
98
|
+
|
|
99
|
+
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
|
100
|
+
|
|
101
|
+
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
|
102
|
+
<!-- prettier-ignore-start -->
|
|
103
|
+
<!-- markdownlint-disable -->
|
|
104
|
+
<table>
|
|
105
|
+
<tr>
|
|
106
|
+
<td align="center"><a href="https://github.com/jotamusik"><img src="https://avatars.githubusercontent.com/u/14940638?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jorge Aguiar MartΓn</b></sub></a><br /><a href="https://github.com/asyncapi/cli/commits?author=jotamusik" title="Code">π»</a> <a href="#ideas-jotamusik" title="Ideas, Planning, & Feedback">π€</a> <a href="https://github.com/asyncapi/cli/commits?author=jotamusik" title="Tests">β οΈ</a> <a href="https://github.com/asyncapi/cli/commits?author=jotamusik" title="Documentation">π</a></td>
|
|
107
|
+
<td align="center"><a href="https://www.brainfart.dev/"><img src="https://avatars.githubusercontent.com/u/6995927?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lukasz Gornicki</b></sub></a><br /><a href="#ideas-derberg" title="Ideas, Planning, & Feedback">π€</a> <a href="https://github.com/asyncapi/cli/commits?author=derberg" title="Code">π»</a> <a href="https://github.com/asyncapi/cli/pulls?q=is%3Apr+reviewed-by%3Aderberg" title="Reviewed Pull Requests">π</a> <a href="#maintenance-derberg" title="Maintenance">π§</a></td>
|
|
108
|
+
<td align="center"><a href="https://souvik.vercel.app/"><img src="https://avatars.githubusercontent.com/u/41781438?v=4?s=100" width="100px;" alt=""/><br /><sub><b>souvik</b></sub></a><br /><a href="https://github.com/asyncapi/cli/commits?author=Souvikns" title="Code">π»</a> <a href="#ideas-Souvikns" title="Ideas, Planning, & Feedback">π€</a> <a href="https://github.com/asyncapi/cli/commits?author=Souvikns" title="Tests">β οΈ</a> <a href="https://github.com/asyncapi/cli/pulls?q=is%3Apr+reviewed-by%3ASouvikns" title="Reviewed Pull Requests">π</a> <a href="#maintenance-Souvikns" title="Maintenance">π§</a> <a href="https://github.com/asyncapi/cli/commits?author=Souvikns" title="Documentation">π</a></td>
|
|
109
|
+
<td align="center"><a href="https://boyney.io/"><img src="https://avatars.githubusercontent.com/u/3268013?v=4?s=100" width="100px;" alt=""/><br /><sub><b>David Boyne</b></sub></a><br /><a href="https://github.com/asyncapi/cli/commits?author=boyney123" title="Code">π»</a> <a href="#ideas-boyney123" title="Ideas, Planning, & Feedback">π€</a> <a href="#maintenance-boyney123" title="Maintenance">π§</a></td>
|
|
110
|
+
<td align="center"><a href="http://www.fmvilas.com/"><img src="https://avatars.githubusercontent.com/u/242119?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Fran MΓ©ndez</b></sub></a><br /><a href="https://github.com/asyncapi/cli/commits?author=fmvilas" title="Code">π»</a> <a href="#ideas-fmvilas" title="Ideas, Planning, & Feedback">π€</a> <a href="https://github.com/asyncapi/cli/pulls?q=is%3Apr+reviewed-by%3Afmvilas" title="Reviewed Pull Requests">π</a></td>
|
|
111
|
+
<td align="center"><a href="https://github.com/magicmatatjahu"><img src="https://avatars.githubusercontent.com/u/20404945?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Maciej UrbaΕczyk</b></sub></a><br /><a href="https://github.com/asyncapi/cli/pulls?q=is%3Apr+reviewed-by%3Amagicmatatjahu" title="Reviewed Pull Requests">π</a> <a href="#maintenance-magicmatatjahu" title="Maintenance">π§</a> <a href="#ideas-magicmatatjahu" title="Ideas, Planning, & Feedback">π€</a></td>
|
|
112
|
+
<td align="center"><a href="https://aayushsahu.com/"><img src="https://avatars.githubusercontent.com/u/54525741?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Aayush Kumar Sahu</b></sub></a><br /><a href="https://github.com/asyncapi/cli/commits?author=aayushmau5" title="Code">π»</a> <a href="https://github.com/asyncapi/cli/commits?author=aayushmau5" title="Tests">β οΈ</a></td>
|
|
113
|
+
</tr>
|
|
114
|
+
<tr>
|
|
115
|
+
<td align="center"><a href="https://github.com/mihirterna"><img src="https://avatars.githubusercontent.com/u/31316452?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mihir Kulkarni</b></sub></a><br /><a href="https://github.com/asyncapi/cli/commits?author=mihirterna" title="Code">π»</a></td>
|
|
116
|
+
<td align="center"><a href="https://imabp.github.io/resume/"><img src="https://avatars.githubusercontent.com/u/53480076?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Abir</b></sub></a><br /><a href="https://github.com/asyncapi/cli/commits?author=imabp" title="Tests">β οΈ</a></td>
|
|
117
|
+
<td align="center"><a href="https://github.com/peter-rr"><img src="https://avatars.githubusercontent.com/u/81691177?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Peter Ramos</b></sub></a><br /><a href="https://github.com/asyncapi/cli/commits?author=peter-rr" title="Code">π»</a></td>
|
|
118
|
+
</tr>
|
|
119
|
+
</table>
|
|
120
|
+
|
|
121
|
+
<!-- markdownlint-restore -->
|
|
122
|
+
<!-- prettier-ignore-end -->
|
|
123
|
+
|
|
124
|
+
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
|
125
|
+
|
|
126
|
+
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
package/lib/commands/diff.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export default class Diff extends Command {
|
|
|
8
8
|
format: flags.IOptionFlag<string>;
|
|
9
9
|
type: flags.IOptionFlag<string>;
|
|
10
10
|
overrides: flags.IOptionFlag<string | undefined>;
|
|
11
|
+
watch: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
|
|
11
12
|
};
|
|
12
13
|
static args: {
|
|
13
14
|
name: string;
|
package/lib/commands/diff.js
CHANGED
|
@@ -11,6 +11,8 @@ const base_1 = tslib_1.__importDefault(require("../base"));
|
|
|
11
11
|
const validation_error_1 = require("../errors/validation-error");
|
|
12
12
|
const specification_file_1 = require("../errors/specification-file");
|
|
13
13
|
const diff_error_1 = require("../errors/diff-error");
|
|
14
|
+
const globals_1 = require("../globals");
|
|
15
|
+
const flags_1 = require("../flags");
|
|
14
16
|
const { readFile } = fs_1.promises;
|
|
15
17
|
class Diff extends base_1.default {
|
|
16
18
|
async run() {
|
|
@@ -20,9 +22,11 @@ class Diff extends base_1.default {
|
|
|
20
22
|
const outputFormat = flags['format'];
|
|
21
23
|
const outputType = flags['type'];
|
|
22
24
|
const overrideFilePath = flags['overrides'];
|
|
25
|
+
const watchMode = flags['watch'];
|
|
23
26
|
let firstDocument, secondDocument;
|
|
24
27
|
try {
|
|
25
28
|
firstDocument = await SpecificationFile_1.load(firstDocumentPath);
|
|
29
|
+
enableWatch(watchMode, { spec: firstDocument, handler: this, handlerName: 'diff', docVersion: 'old', label: 'DIFF_OLD' });
|
|
26
30
|
}
|
|
27
31
|
catch (err) {
|
|
28
32
|
if (err instanceof specification_file_1.SpecificationFileNotFound) {
|
|
@@ -37,6 +41,7 @@ class Diff extends base_1.default {
|
|
|
37
41
|
}
|
|
38
42
|
try {
|
|
39
43
|
secondDocument = await SpecificationFile_1.load(secondDocumentPath);
|
|
44
|
+
enableWatch(watchMode, { spec: secondDocument, handler: this, handlerName: 'diff', docVersion: 'new', label: 'DIFF_NEW' });
|
|
40
45
|
}
|
|
41
46
|
catch (err) {
|
|
42
47
|
if (err instanceof specification_file_1.SpecificationFileNotFound) {
|
|
@@ -116,6 +121,7 @@ Diff.flags = {
|
|
|
116
121
|
char: 'o',
|
|
117
122
|
description: 'path to JSON file containing the override properties',
|
|
118
123
|
}),
|
|
124
|
+
watch: flags_1.watchFlag
|
|
119
125
|
};
|
|
120
126
|
Diff.args = [
|
|
121
127
|
{
|
|
@@ -149,3 +155,12 @@ async function readOverrideFile(path) {
|
|
|
149
155
|
throw new diff_error_1.DiffOverrideJSONError();
|
|
150
156
|
}
|
|
151
157
|
}
|
|
158
|
+
/**
|
|
159
|
+
* function to enable watchmode.
|
|
160
|
+
* The function is abstracted here, to avoid eslint cognitive complexity error.
|
|
161
|
+
*/
|
|
162
|
+
const enableWatch = (status, watcher) => {
|
|
163
|
+
if (status) {
|
|
164
|
+
globals_1.specWatcher(watcher);
|
|
165
|
+
}
|
|
166
|
+
};
|
package/lib/commands/validate.js
CHANGED
|
@@ -6,25 +6,16 @@ const parser = tslib_1.__importStar(require("@asyncapi/parser"));
|
|
|
6
6
|
const base_1 = tslib_1.__importDefault(require("../base"));
|
|
7
7
|
const validation_error_1 = require("../errors/validation-error");
|
|
8
8
|
const SpecificationFile_1 = require("../models/SpecificationFile");
|
|
9
|
-
const
|
|
9
|
+
const globals_1 = require("../globals");
|
|
10
|
+
const flags_1 = require("../flags");
|
|
10
11
|
class Validate extends base_1.default {
|
|
11
12
|
async run() {
|
|
12
|
-
const { args } = this.parse(Validate);
|
|
13
|
+
const { args, flags } = this.parse(Validate); // NOSONAR
|
|
13
14
|
const filePath = args['spec-file'];
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
catch (err) {
|
|
19
|
-
if (err instanceof specification_file_1.SpecificationFileNotFound) {
|
|
20
|
-
this.error(new validation_error_1.ValidationError({
|
|
21
|
-
type: 'invalid-file',
|
|
22
|
-
filepath: filePath
|
|
23
|
-
}));
|
|
24
|
-
}
|
|
25
|
-
else {
|
|
26
|
-
this.error(err);
|
|
27
|
-
}
|
|
15
|
+
const watchMode = flags['watch'];
|
|
16
|
+
const specFile = await SpecificationFile_1.load(filePath);
|
|
17
|
+
if (watchMode) {
|
|
18
|
+
globals_1.specWatcher({ spec: specFile, handler: this, handlerName: 'validate' });
|
|
28
19
|
}
|
|
29
20
|
try {
|
|
30
21
|
if (specFile.getFilePath()) {
|
|
@@ -47,7 +38,8 @@ class Validate extends base_1.default {
|
|
|
47
38
|
exports.default = Validate;
|
|
48
39
|
Validate.description = 'validate asyncapi file';
|
|
49
40
|
Validate.flags = {
|
|
50
|
-
help: command_1.flags.help({ char: 'h' })
|
|
41
|
+
help: command_1.flags.help({ char: 'h' }),
|
|
42
|
+
watch: flags_1.watchFlag
|
|
51
43
|
};
|
|
52
44
|
Validate.args = [
|
|
53
45
|
{ name: 'spec-file', description: 'spec path, url, or context-name', required: false },
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export declare const NO_CONTEXTS_SAVED = "Specify what AsyncAPI file to be used.\nThese are your options to specify in the CLI what AsyncAPI file should be used:\n - You can provide a path to the AsyncAPI file: asyncapi <command> path/to/file/asyncapi\n - You can also pass a saved context that points to your AsyncAPI file: asyncapi <command> context-name\n - In case you did not specify a context that you want to use, the CLI checks if there is a default context and uses it. To set default context run: asyncapi context use mycontext\n - In case you did not provide any reference to AsyncAPI file and there is no default context, the CLI detects if in your current working directory you have files like asyncapi.json, asyncapi.yaml, asyncapi.yml. Just rename your file accordingly.\n";
|
|
1
2
|
declare class ContextError extends Error {
|
|
2
3
|
constructor();
|
|
3
4
|
}
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ContextNotFound = exports.MissingCurrentContextError = exports.MissingContextFileError = void 0;
|
|
4
|
-
const NO_CONTEXTS_SAVED = 'No contexts saved yet, run asyncapi --help to learn more';
|
|
3
|
+
exports.ContextNotFound = exports.MissingCurrentContextError = exports.MissingContextFileError = exports.NO_CONTEXTS_SAVED = void 0;
|
|
5
4
|
const CONTEXT_NOT_FOUND = (contextName) => `Context "${contextName}" does not exists.`;
|
|
6
5
|
const MISSING_CURRENT_CONTEXT = 'No context is set as current, please set a current context.';
|
|
6
|
+
exports.NO_CONTEXTS_SAVED = `Specify what AsyncAPI file to be used.
|
|
7
|
+
These are your options to specify in the CLI what AsyncAPI file should be used:
|
|
8
|
+
- You can provide a path to the AsyncAPI file: asyncapi <command> path/to/file/asyncapi
|
|
9
|
+
- You can also pass a saved context that points to your AsyncAPI file: asyncapi <command> context-name
|
|
10
|
+
- In case you did not specify a context that you want to use, the CLI checks if there is a default context and uses it. To set default context run: asyncapi context use mycontext
|
|
11
|
+
- In case you did not provide any reference to AsyncAPI file and there is no default context, the CLI detects if in your current working directory you have files like asyncapi.json, asyncapi.yaml, asyncapi.yml. Just rename your file accordingly.
|
|
12
|
+
`;
|
|
7
13
|
class ContextError extends Error {
|
|
8
14
|
constructor() {
|
|
9
15
|
super();
|
|
@@ -13,7 +19,7 @@ class ContextError extends Error {
|
|
|
13
19
|
class MissingContextFileError extends ContextError {
|
|
14
20
|
constructor() {
|
|
15
21
|
super();
|
|
16
|
-
this.message = NO_CONTEXTS_SAVED;
|
|
22
|
+
this.message = exports.NO_CONTEXTS_SAVED;
|
|
17
23
|
}
|
|
18
24
|
}
|
|
19
25
|
exports.MissingContextFileError = MissingContextFileError;
|
|
@@ -7,4 +7,9 @@ export declare class SpecificationFileNotFound extends SpecificationFileError {
|
|
|
7
7
|
export declare class SpecificationURLNotFound extends SpecificationFileError {
|
|
8
8
|
constructor(URL: string);
|
|
9
9
|
}
|
|
10
|
+
declare type From = 'file' | 'url' | 'context';
|
|
11
|
+
export declare class ErrorLoadingSpec extends Error {
|
|
12
|
+
private readonly errorMessages;
|
|
13
|
+
constructor(from?: From, param?: string);
|
|
14
|
+
}
|
|
10
15
|
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SpecificationURLNotFound = exports.SpecificationFileNotFound = void 0;
|
|
3
|
+
exports.ErrorLoadingSpec = exports.SpecificationURLNotFound = exports.SpecificationFileNotFound = void 0;
|
|
4
|
+
const context_error_1 = require("./context-error");
|
|
4
5
|
class SpecificationFileError extends Error {
|
|
5
6
|
constructor() {
|
|
6
7
|
super();
|
|
@@ -26,3 +27,28 @@ class SpecificationURLNotFound extends SpecificationFileError {
|
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
exports.SpecificationURLNotFound = SpecificationURLNotFound;
|
|
30
|
+
class ErrorLoadingSpec extends Error {
|
|
31
|
+
constructor(from, param) {
|
|
32
|
+
super();
|
|
33
|
+
this.errorMessages = {
|
|
34
|
+
default: context_error_1.NO_CONTEXTS_SAVED
|
|
35
|
+
};
|
|
36
|
+
if (from === 'file') {
|
|
37
|
+
this.name = 'error loading AsyncAPI document from file';
|
|
38
|
+
this.message = `${param} is an invalid file path`;
|
|
39
|
+
}
|
|
40
|
+
if (from === 'url') {
|
|
41
|
+
this.name = 'error loading AsyncAPI docuement from url';
|
|
42
|
+
this.message = `${param} is an invalid url`;
|
|
43
|
+
}
|
|
44
|
+
if (from === 'context') {
|
|
45
|
+
this.name = 'error loading AsyncAPI document from context';
|
|
46
|
+
this.message = `${param} is an invalid context name`;
|
|
47
|
+
}
|
|
48
|
+
if (!from) {
|
|
49
|
+
this.name = 'error locating AsyncAPI document';
|
|
50
|
+
this.message = this.errorMessages.default;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.ErrorLoadingSpec = ErrorLoadingSpec;
|
|
@@ -27,11 +27,21 @@ class ValidationError extends Error {
|
|
|
27
27
|
for (const e of err.validationErrors) {
|
|
28
28
|
const errorHasTitle = !!e.title;
|
|
29
29
|
const errorHasLocation = !!e.location;
|
|
30
|
-
|
|
30
|
+
/*
|
|
31
|
+
* All the conditions below are needed since validationErrors (from ParserError) come from Parser JS library,
|
|
32
|
+
* so we cannot assure that all the fields or properties are always provided in the error. There might be cases
|
|
33
|
+
* that even title is not provided.
|
|
34
|
+
*/
|
|
35
|
+
if (errorHasTitle && errorHasLocation) {
|
|
31
36
|
errorsInfo.push(`${e.title} ${e.location.startLine}:${e.location.startColumn}`);
|
|
37
|
+
continue;
|
|
32
38
|
}
|
|
33
39
|
if (errorHasTitle) {
|
|
34
40
|
errorsInfo.push(`${e.title}`);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (errorHasLocation) {
|
|
44
|
+
errorsInfo.push(`${e.location.startLine}:${e.location.startColumn}`);
|
|
35
45
|
}
|
|
36
46
|
}
|
|
37
47
|
}
|
package/lib/flags.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const watchFlag: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
|
package/lib/flags.js
ADDED
package/lib/globals.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import Command from './base';
|
|
2
|
+
import { Specification } from './models/SpecificationFile';
|
|
3
|
+
export declare type specWatcherParams = {
|
|
4
|
+
spec: Specification;
|
|
5
|
+
handler: Command;
|
|
6
|
+
handlerName: string;
|
|
7
|
+
label?: string;
|
|
8
|
+
docVersion?: 'old' | 'new';
|
|
9
|
+
};
|
|
10
|
+
export declare const specWatcher: (params: specWatcherParams) => void;
|
package/lib/globals.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.specWatcher = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const chokidar_1 = tslib_1.__importDefault(require("chokidar"));
|
|
6
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
7
|
+
const GreenLog = chalk_1.default.hex('#00FF00');
|
|
8
|
+
const OrangeLog = chalk_1.default.hex('#FFA500');
|
|
9
|
+
const CHOKIDAR_CONFIG = {
|
|
10
|
+
// awaitWriteFinish: true // Used for large size specification files.
|
|
11
|
+
};
|
|
12
|
+
const WATCH_MESSAGES = {
|
|
13
|
+
logOnStart: (filePath) => console.log(GreenLog(`Watching AsyncAPI file at ${filePath}\n`)),
|
|
14
|
+
logOnChange: (handlerName) => console.log(OrangeLog(`Change detected, running ${handlerName}\n`)),
|
|
15
|
+
logOnAutoDisable: (docVersion = '') => console.log(OrangeLog(`Watch mode for ${docVersion || 'AsyncAPI'} file was not enabled.`), OrangeLog('\nINFO: Watch works only with files from local file system\n'))
|
|
16
|
+
};
|
|
17
|
+
const CHOKIDAR_INSTANCE_STORE = new Map();
|
|
18
|
+
exports.specWatcher = (params) => {
|
|
19
|
+
if (!params.spec.getFilePath()) {
|
|
20
|
+
return WATCH_MESSAGES.logOnAutoDisable(params.docVersion);
|
|
21
|
+
}
|
|
22
|
+
if (CHOKIDAR_INSTANCE_STORE.get(params.label || '_default')) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const filePath = params.spec.getFilePath();
|
|
26
|
+
try {
|
|
27
|
+
WATCH_MESSAGES.logOnStart(filePath);
|
|
28
|
+
chokidar_1.default
|
|
29
|
+
.watch(filePath, CHOKIDAR_CONFIG)
|
|
30
|
+
.on('change', async () => {
|
|
31
|
+
WATCH_MESSAGES.logOnChange(params.handlerName);
|
|
32
|
+
try {
|
|
33
|
+
await params.handler.run();
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
await params.handler.catch(err);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
CHOKIDAR_INSTANCE_STORE.set(params.label || '_default', true);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
console.log(error);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
@@ -18,7 +18,13 @@ export default class SpecificationFile {
|
|
|
18
18
|
getPath(): string;
|
|
19
19
|
read(): Promise<string>;
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
interface LoadType {
|
|
22
|
+
file?: boolean;
|
|
23
|
+
url?: boolean;
|
|
24
|
+
context?: boolean;
|
|
25
|
+
}
|
|
26
|
+
export declare function load(filePathOrContextName?: string, loadType?: LoadType): Promise<Specification>;
|
|
22
27
|
export declare function nameType(name: string): Promise<string>;
|
|
23
28
|
export declare function isURL(urlpath: string): Promise<boolean>;
|
|
24
29
|
export declare function fileExists(name: string): Promise<boolean>;
|
|
30
|
+
export {};
|
|
@@ -7,6 +7,7 @@ const path = tslib_1.__importStar(require("path"));
|
|
|
7
7
|
const node_fetch_1 = tslib_1.__importDefault(require("node-fetch"));
|
|
8
8
|
const Context_1 = require("./Context");
|
|
9
9
|
const specification_file_1 = require("../errors/specification-file");
|
|
10
|
+
const context_error_1 = require("../errors/context-error");
|
|
10
11
|
const { readFile, lstat } = fs_1.promises;
|
|
11
12
|
const allowedFileNames = [
|
|
12
13
|
'asyncapi.json',
|
|
@@ -32,15 +33,25 @@ class Specification {
|
|
|
32
33
|
return this.fileURL;
|
|
33
34
|
}
|
|
34
35
|
static async fromFile(filepath) {
|
|
35
|
-
|
|
36
|
+
let spec;
|
|
37
|
+
try {
|
|
38
|
+
spec = await readFile(filepath, { encoding: 'utf8' });
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
throw new specification_file_1.ErrorLoadingSpec('file', filepath);
|
|
42
|
+
}
|
|
43
|
+
return new Specification(spec, { filepath });
|
|
36
44
|
}
|
|
37
45
|
static async fromURL(URLpath) {
|
|
38
46
|
let response;
|
|
39
47
|
try {
|
|
40
48
|
response = await node_fetch_1.default(URLpath, { method: 'GET' });
|
|
49
|
+
if (!response.ok) {
|
|
50
|
+
throw new specification_file_1.ErrorLoadingSpec('url', URLpath);
|
|
51
|
+
}
|
|
41
52
|
}
|
|
42
53
|
catch (error) {
|
|
43
|
-
throw new specification_file_1.
|
|
54
|
+
throw new specification_file_1.ErrorLoadingSpec('url', URLpath);
|
|
44
55
|
}
|
|
45
56
|
return new Specification(await (response === null || response === void 0 ? void 0 : response.text()), { fileURL: URLpath });
|
|
46
57
|
}
|
|
@@ -58,8 +69,18 @@ class SpecificationFile {
|
|
|
58
69
|
}
|
|
59
70
|
}
|
|
60
71
|
exports.default = SpecificationFile;
|
|
61
|
-
|
|
72
|
+
/* eslint-disable sonarjs/cognitive-complexity */
|
|
73
|
+
async function load(filePathOrContextName, loadType) {
|
|
62
74
|
if (filePathOrContextName) {
|
|
75
|
+
if (loadType === null || loadType === void 0 ? void 0 : loadType.file) {
|
|
76
|
+
return Specification.fromFile(filePathOrContextName);
|
|
77
|
+
}
|
|
78
|
+
if (loadType === null || loadType === void 0 ? void 0 : loadType.context) {
|
|
79
|
+
return loadFromContext(filePathOrContextName);
|
|
80
|
+
}
|
|
81
|
+
if (loadType === null || loadType === void 0 ? void 0 : loadType.url) {
|
|
82
|
+
return Specification.fromURL(filePathOrContextName);
|
|
83
|
+
}
|
|
63
84
|
const type = await nameType(filePathOrContextName);
|
|
64
85
|
if (type === TYPE_CONTEXT_NAME) {
|
|
65
86
|
return loadFromContext(filePathOrContextName);
|
|
@@ -78,11 +99,11 @@ async function load(filePathOrContextName) {
|
|
|
78
99
|
if (autoDetectedSpecFile) {
|
|
79
100
|
return Specification.fromFile(autoDetectedSpecFile);
|
|
80
101
|
}
|
|
81
|
-
if (
|
|
82
|
-
throw
|
|
102
|
+
if (e instanceof context_error_1.MissingContextFileError) {
|
|
103
|
+
throw new specification_file_1.ErrorLoadingSpec();
|
|
83
104
|
}
|
|
105
|
+
throw e;
|
|
84
106
|
}
|
|
85
|
-
throw new specification_file_1.SpecificationFileNotFound();
|
|
86
107
|
}
|
|
87
108
|
exports.load = load;
|
|
88
109
|
async function nameType(name) {
|
|
@@ -118,16 +139,24 @@ async function fileExists(name) {
|
|
|
118
139
|
if ((await lstat(name)).isFile()) {
|
|
119
140
|
return true;
|
|
120
141
|
}
|
|
121
|
-
throw new specification_file_1.
|
|
142
|
+
throw new specification_file_1.ErrorLoadingSpec('file', name);
|
|
122
143
|
}
|
|
123
144
|
catch (e) {
|
|
124
|
-
throw new specification_file_1.
|
|
145
|
+
throw new specification_file_1.ErrorLoadingSpec('file', name);
|
|
125
146
|
}
|
|
126
147
|
}
|
|
127
148
|
exports.fileExists = fileExists;
|
|
128
149
|
async function loadFromContext(contextName) {
|
|
129
|
-
|
|
130
|
-
|
|
150
|
+
try {
|
|
151
|
+
const context = await Context_1.loadContext(contextName);
|
|
152
|
+
return Specification.fromFile(context);
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
if (error instanceof context_error_1.MissingContextFileError) {
|
|
156
|
+
throw new specification_file_1.ErrorLoadingSpec();
|
|
157
|
+
}
|
|
158
|
+
throw error;
|
|
159
|
+
}
|
|
131
160
|
}
|
|
132
161
|
async function detectSpecFile() {
|
|
133
162
|
const existingFileNames = await Promise.all(allowedFileNames.map(async (filename) => {
|
package/oclif.manifest.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"0.
|
|
1
|
+
{"version":"0.14.0","commands":{"config":{"id":"config","description":"access configs","pluginName":"@asyncapi/cli","pluginType":"core","aliases":[],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"diff":{"id":"diff","description":"find diff between two asyncapi files","pluginName":"@asyncapi/cli","pluginType":"core","aliases":[],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"format":{"name":"format","type":"option","char":"f","description":"format of the output","options":["json"],"default":"json"},"type":{"name":"type","type":"option","char":"t","description":"type of the output","options":["breaking","non-breaking","unclassified","all"],"default":"all"},"overrides":{"name":"overrides","type":"option","char":"o","description":"path to JSON file containing the override properties"},"watch":{"name":"watch","type":"boolean","char":"w","description":"Enable watch mode","allowNo":false}},"args":[{"name":"old","description":"old spec path, URL or context-name","required":true},{"name":"new","description":"new spec path, URL or context-name","required":true}]},"new":{"id":"new","description":"creates a new asyncapi file","pluginName":"@asyncapi/cli","pluginType":"core","aliases":[],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"file-name":{"name":"file-name","type":"option","char":"n","description":"name of the file"},"example":{"name":"example","type":"option","char":"e","description":"name of the example to use"},"studio":{"name":"studio","type":"boolean","char":"s","description":"open in Studio","allowNo":false},"port":{"name":"port","type":"option","char":"p","description":"port in which to start Studio"},"no-tty":{"name":"no-tty","type":"boolean","description":"do not use an interactive terminal","allowNo":false}},"args":[]},"start":{"id":"start","description":"starts a new local instance of Studio","pluginName":"@asyncapi/cli","pluginType":"core","aliases":[],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"validate":{"id":"validate","description":"validate asyncapi file","pluginName":"@asyncapi/cli","pluginType":"core","aliases":[],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"watch":{"name":"watch","type":"boolean","char":"w","description":"Enable watch mode","allowNo":false}},"args":[{"name":"spec-file","description":"spec path, url, or context-name","required":false}]},"config:context":{"id":"config:context","pluginName":"@asyncapi/cli","pluginType":"core","aliases":[],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"start:studio":{"id":"start:studio","description":"starts a new local instance of Studio","pluginName":"@asyncapi/cli","pluginType":"core","aliases":[],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"file":{"name":"file","type":"option","char":"f","description":"path to the AsyncAPI file to link with Studio"},"port":{"name":"port","type":"option","char":"p","description":"port in which to start Studio"}},"args":[]},"config:context:add":{"id":"config:context:add","description":"Add or modify a context in the store","pluginName":"@asyncapi/cli","pluginType":"core","aliases":[],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[{"name":"context-name","description":"context name","required":true},{"name":"spec-file-path","description":"file path of the spec file","required":true}]},"config:context:current":{"id":"config:context:current","description":"Shows the current context that is being used","pluginName":"@asyncapi/cli","pluginType":"core","aliases":[],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"config:context:list":{"id":"config:context:list","description":"List all the stored context in the store","pluginName":"@asyncapi/cli","pluginType":"core","aliases":[],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"config:context:remove":{"id":"config:context:remove","description":"Delete a context from the store","pluginName":"@asyncapi/cli","pluginType":"core","aliases":[],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[{"name":"context-name","description":"Name of the context to delete","required":true}]},"config:context:use":{"id":"config:context:use","description":"Set a context as current","pluginName":"@asyncapi/cli","pluginType":"core","aliases":[],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[{"name":"context-name","description":"name of the saved context","required":true}]}}}
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@asyncapi/cli",
|
|
3
3
|
"description": "All in one CLI for all AsyncAPI tools",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.14.0",
|
|
5
5
|
"author": "@asyncapi",
|
|
6
6
|
"bin": {
|
|
7
7
|
"asyncapi": "./bin/run"
|
|
8
8
|
},
|
|
9
9
|
"bugs": "https://github.com/asyncapi/cli/issues",
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@asyncapi/diff": "^0.
|
|
11
|
+
"@asyncapi/diff": "^0.3.0",
|
|
12
12
|
"@asyncapi/parser": "^1.14.0",
|
|
13
13
|
"@asyncapi/studio": "^0.9.0",
|
|
14
14
|
"@fmvilas/oclif-plugin-spaced-commands": "^1.0.4",
|