bump-cli 2.5.0 → 2.7.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 +19 -9
- package/lib/api/error.js +1 -1
- package/lib/args.js +1 -1
- package/lib/commands/deploy.d.ts +10 -6
- package/lib/commands/deploy.js +126 -50
- package/lib/commands/diff.d.ts +9 -8
- package/lib/commands/diff.js +16 -12
- package/lib/commands/preview.js +8 -8
- package/lib/core/definition_directory.d.ts +20 -0
- package/lib/core/definition_directory.js +138 -0
- package/lib/core/deploy.d.ts +14 -0
- package/lib/core/deploy.js +71 -0
- package/lib/core/utils/file.d.ts +12 -0
- package/lib/core/utils/file.js +32 -0
- package/lib/core/utils/prompts.d.ts +1 -0
- package/lib/core/utils/prompts.js +21 -0
- package/lib/definition.d.ts +5 -1
- package/lib/definition.js +3 -1
- package/lib/flags.d.ts +4 -1
- package/lib/flags.js +23 -3
- package/oclif.manifest.json +1 -1
- package/package.json +14 -7
package/README.md
CHANGED
|
@@ -47,16 +47,16 @@ $ bump --help
|
|
|
47
47
|
The Bump CLI is used to interact with your API documentation hosted on Bump by using the API of developers.bump.sh
|
|
48
48
|
|
|
49
49
|
VERSION
|
|
50
|
-
bump-cli/2.
|
|
50
|
+
bump-cli/2.5.0 linux-x64 node-v16.14.0
|
|
51
51
|
|
|
52
52
|
USAGE
|
|
53
53
|
$ bump [COMMAND]
|
|
54
54
|
|
|
55
55
|
COMMANDS
|
|
56
|
-
deploy
|
|
57
|
-
diff Get a
|
|
58
|
-
help
|
|
59
|
-
preview
|
|
56
|
+
deploy Create a new version of your documentation from the given file or URL.
|
|
57
|
+
diff Get a comparison diff with your documentation from the given file or URL.
|
|
58
|
+
help Display help for bump.
|
|
59
|
+
preview Create a documentation preview from the given file or URL.
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
Please check the [Bump CLI help page](https://help.bump.sh/bump-cli) for more CLI usage details.
|
|
@@ -92,12 +92,24 @@ Deploy the definition file as the current version of the documentation with the
|
|
|
92
92
|
$ bump deploy path/to/your/file.yml --doc DOC_ID_OR_SLUG --token DOC_TOKEN
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
+
Deploy the definition file to the `staging` branch of the documentation:
|
|
96
|
+
|
|
97
|
+
```sh-session
|
|
98
|
+
$ bump deploy path/to/your/file.yml --doc DOC_ID_OR_SLUG --token DOC_TOKEN --branch staging
|
|
99
|
+
```
|
|
100
|
+
|
|
95
101
|
If you already have a hub in your [Bump.sh](https://bump.sh) account, you can automatically create a documentation inside it and deploy to it with:
|
|
96
102
|
|
|
97
103
|
```sh-session
|
|
98
104
|
$ bump deploy path/to/your/file.yml --auto-create --doc DOC_SLUG --hub HUB_ID_OR_SLUG --token HUB_TOKEN
|
|
99
105
|
```
|
|
100
106
|
|
|
107
|
+
Within a Hub, you can also deploy a whole directory containing multiple API definitions in a single command:
|
|
108
|
+
|
|
109
|
+
```sh-session
|
|
110
|
+
$ bump deploy path/to/your/apis/ --auto-create --hub HUB_ID_OR_SLUG --token HUB_TOKEN
|
|
111
|
+
```
|
|
112
|
+
|
|
101
113
|
Simulate a deployment of your definition file to make sure it is valid with the `--dry-run` flag, it is particularly useful in a Continuous Integration environment running a test deployment outside your main branch:
|
|
102
114
|
|
|
103
115
|
```sh-session
|
|
@@ -136,7 +148,7 @@ _Note: You can also test this feature in our dedicated web application at <https
|
|
|
136
148
|
|
|
137
149
|
#### Authenticated diffs attached to your Bump documentation
|
|
138
150
|
|
|
139
|
-
From a Bump documentation, the `diff` command will retrieve a
|
|
151
|
+
From a Bump documentation, the `diff` command will retrieve a comparison changelog between your existing documentation and the given file or URL:
|
|
140
152
|
|
|
141
153
|
```sh-session
|
|
142
154
|
$ bump diff path/to/your/file.yml --doc DOC_ID_OR_SLUG --token DOC_TOKEN
|
|
@@ -146,7 +158,7 @@ Updated: POST /validations
|
|
|
146
158
|
Body attribute modified: documentation
|
|
147
159
|
```
|
|
148
160
|
|
|
149
|
-
If you want to compare two unpublished versions of your definition file, the `diff` command can retrieve a
|
|
161
|
+
If you want to compare two unpublished versions of your definition file, the `diff` command can retrieve a comparison changelog between two given file or URL, “as simple as `git diff`”:
|
|
150
162
|
|
|
151
163
|
```sh-session
|
|
152
164
|
$ bump diff path/to/your/file.yml path/to/your/next-file.yml --doc <doc_slug> --token <your_doc_token>
|
|
@@ -156,8 +168,6 @@ Updated: POST /versions
|
|
|
156
168
|
Body attribute added: previous_version_id
|
|
157
169
|
```
|
|
158
170
|
|
|
159
|
-
_Note: you can use the `--open` flag to open the visual diff URL in your browser directly._
|
|
160
|
-
|
|
161
171
|
Please check `bump diff --help` for full usage details.
|
|
162
172
|
|
|
163
173
|
## Development
|
package/lib/api/error.js
CHANGED
|
@@ -39,7 +39,7 @@ class APIError extends errors_1.CLIError {
|
|
|
39
39
|
return [
|
|
40
40
|
[
|
|
41
41
|
genericMessage,
|
|
42
|
-
`
|
|
42
|
+
`In a hub context you might want to try the ${chalk_1.default.dim('--auto-create')} flag.\nOtherwise, please check the given ${chalk_1.default.dim('--documentation')}, ${chalk_1.default.dim('--token')} or ${chalk_1.default.dim('--hub')} flags`,
|
|
43
43
|
],
|
|
44
44
|
104,
|
|
45
45
|
];
|
package/lib/args.js
CHANGED
|
@@ -4,7 +4,7 @@ exports.otherFileArg = exports.fileArg = void 0;
|
|
|
4
4
|
const fileArg = {
|
|
5
5
|
name: 'FILE',
|
|
6
6
|
required: true,
|
|
7
|
-
description: 'Path or URL to your API documentation file. OpenAPI (2.0 to 3.1.0) and AsyncAPI (2.x) specifications are currently supported.',
|
|
7
|
+
description: 'Path or URL to your API documentation file. OpenAPI (2.0 to 3.1.0) and AsyncAPI (2.x) specifications are currently supported.\nPath can also be a directory when deploying to a Hub.',
|
|
8
8
|
};
|
|
9
9
|
exports.fileArg = fileArg;
|
|
10
10
|
const otherFileArg = {
|
package/lib/commands/deploy.d.ts
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import Command from '../command';
|
|
2
|
-
import * as
|
|
2
|
+
import * as flagsBuilder from '../flags';
|
|
3
3
|
export default class Deploy extends Command {
|
|
4
4
|
static description: string;
|
|
5
5
|
static examples: string[];
|
|
6
6
|
static flags: {
|
|
7
7
|
help: import("@oclif/parser/lib/flags").IBooleanFlag<void>;
|
|
8
|
-
doc:
|
|
9
|
-
'doc-name':
|
|
10
|
-
hub:
|
|
11
|
-
branch:
|
|
12
|
-
token:
|
|
8
|
+
doc: flagsBuilder.IOptionFlag<string | undefined>;
|
|
9
|
+
'doc-name': flagsBuilder.IOptionFlag<string | undefined>;
|
|
10
|
+
hub: flagsBuilder.IOptionFlag<string | undefined>;
|
|
11
|
+
branch: flagsBuilder.IOptionFlag<string | undefined>;
|
|
12
|
+
token: flagsBuilder.IOptionFlag<string | undefined>;
|
|
13
13
|
'auto-create': import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
|
|
14
|
+
interactive: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
|
|
15
|
+
'filename-pattern': flagsBuilder.IOptionFlag<string | undefined>;
|
|
14
16
|
'dry-run': import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
|
|
15
17
|
};
|
|
16
18
|
static args: {
|
|
@@ -19,4 +21,6 @@ export default class Deploy extends Command {
|
|
|
19
21
|
description: string;
|
|
20
22
|
}[];
|
|
21
23
|
run(): Promise<void>;
|
|
24
|
+
private deployDirectory;
|
|
25
|
+
private deploySingleFile;
|
|
22
26
|
}
|
package/lib/commands/deploy.js
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
|
-
const
|
|
4
|
+
const chalk_1 = (0, tslib_1.__importDefault)(require("chalk"));
|
|
5
|
+
const fs_1 = require("fs");
|
|
6
|
+
const errors_1 = require("@oclif/parser/lib/errors");
|
|
7
|
+
const errors_2 = require("@oclif/errors");
|
|
5
8
|
const command_1 = (0, tslib_1.__importDefault)(require("../command"));
|
|
6
|
-
const
|
|
9
|
+
const flagsBuilder = (0, tslib_1.__importStar)(require("../flags"));
|
|
10
|
+
const definition_directory_1 = require("../core/definition_directory");
|
|
11
|
+
const deploy_1 = require("../core/deploy");
|
|
12
|
+
const prompts_1 = require("../core/utils/prompts");
|
|
7
13
|
const args_1 = require("../args");
|
|
8
14
|
const cli_1 = require("../cli");
|
|
15
|
+
const definition_1 = require("../definition");
|
|
9
16
|
class Deploy extends command_1.default {
|
|
10
17
|
/*
|
|
11
18
|
Oclif doesn't type parsed args & flags correctly and especially
|
|
@@ -15,73 +22,142 @@ class Deploy extends command_1.default {
|
|
|
15
22
|
*/
|
|
16
23
|
async run() {
|
|
17
24
|
const { args, flags } = this.parse(Deploy);
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
25
|
+
const [dryRun, documentation, token, hub, autoCreate, interactive, filenamePattern, documentationName, branch,] = [
|
|
26
|
+
flags['dry-run'],
|
|
27
|
+
flags.doc,
|
|
28
|
+
/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */
|
|
29
|
+
flags.token,
|
|
30
|
+
flags.hub,
|
|
31
|
+
flags['auto-create'],
|
|
32
|
+
flags.interactive,
|
|
33
|
+
/* Flags.filenamePattern has a default value, so it's always defined. But
|
|
34
|
+
* oclif types doesn't detect it */
|
|
35
|
+
/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */
|
|
36
|
+
flags['filename-pattern'],
|
|
37
|
+
flags['doc-name'],
|
|
38
|
+
flags.branch,
|
|
39
|
+
];
|
|
40
|
+
const file = await (0, fs_1.statSync)(args.FILE);
|
|
41
|
+
if (file.isDirectory()) {
|
|
42
|
+
if (hub) {
|
|
43
|
+
await this.deployDirectory(args.FILE, dryRun, token, hub, autoCreate, interactive, filenamePattern, documentationName, branch);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
throw new errors_1.RequiredFlagError({ flag: Deploy.flags.hub, parse: {} });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
if (documentation) {
|
|
51
|
+
const api = await definition_1.API.load(args.FILE);
|
|
52
|
+
this.d(`${args.FILE} looks like an ${api.specName} spec version ${api.version}`);
|
|
53
|
+
await this.deploySingleFile(api, dryRun, documentation, token, hub, autoCreate, documentationName, branch);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
throw new errors_1.RequiredFlagError({ flag: Deploy.flags.doc, parse: {} });
|
|
57
|
+
}
|
|
51
58
|
}
|
|
52
59
|
return;
|
|
53
60
|
}
|
|
61
|
+
async deployDirectory(dir, dryRun, token, hub, autoCreate, interactive, filenamePattern, documentationName, branch) {
|
|
62
|
+
const definitionDirectory = new definition_directory_1.DefinitionDirectory(dir, filenamePattern);
|
|
63
|
+
const action = dryRun ? 'validate' : 'deploy';
|
|
64
|
+
await definitionDirectory.readDefinitions();
|
|
65
|
+
// In “interactive” mode we ask the user if he wants to add more
|
|
66
|
+
// definitions to deploy. He is thus presented a form to select
|
|
67
|
+
// some files from the target directory.
|
|
68
|
+
if (interactive) {
|
|
69
|
+
let confirm = true;
|
|
70
|
+
if (definitionDirectory.definitionsExists()) {
|
|
71
|
+
await (0, prompts_1.confirm)('Do you want to add more files to deploy?').catch(() => {
|
|
72
|
+
confirm = false;
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
if (confirm) {
|
|
76
|
+
await definitionDirectory.interactiveSelection();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (definitionDirectory.definitionsExists()) {
|
|
80
|
+
cli_1.cli.info(chalk_1.default.underline(`Let's ${action} those documentations to your ${hub} hub on Bump.sh`));
|
|
81
|
+
await definitionDirectory.sequentialMap(async (definition) => {
|
|
82
|
+
if (interactive) {
|
|
83
|
+
await definitionDirectory.renameToConvention(definition);
|
|
84
|
+
}
|
|
85
|
+
await this.deploySingleFile(definition.definition, dryRun, definition.slug, token, hub, autoCreate, definition.slug || documentationName, branch);
|
|
86
|
+
return definition;
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
throw new errors_2.CLIError(`No documentations found in ${dir}.\nYou should check the ${chalk_1.default.dim('--filename-pattern')} flag to select your files from your naming convention.\nIf you don't have a naming convention we can help naming your API definition files:\nTry the ${chalk_1.default.dim('--interactive')} flag for that.`);
|
|
91
|
+
}
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
async deploySingleFile(api, dryRun, documentation, token, hub, autoCreate, documentationName, branch) {
|
|
95
|
+
const action = dryRun ? 'validate' : 'deploy';
|
|
96
|
+
cli_1.cli.action.start(`Let's ${action} a new version to your ${documentation} documentation on Bump.sh`);
|
|
97
|
+
const response = await new deploy_1.Deploy(this.config).run(api, dryRun, documentation, token, hub, autoCreate, documentationName, branch);
|
|
98
|
+
if (dryRun) {
|
|
99
|
+
await cli_1.cli.styledSuccess('Definition is valid');
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
if (response) {
|
|
103
|
+
await cli_1.cli.styledSuccess(`Your new documentation version will soon be ready at ${response.doc_public_url}`);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
await cli_1.cli.warn('Your documentation has not changed');
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
cli_1.cli.action.stop();
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
54
112
|
}
|
|
55
113
|
exports.default = Deploy;
|
|
56
|
-
Deploy.description = '
|
|
114
|
+
Deploy.description = 'Create a new version of your documentation from the given file or URL.';
|
|
57
115
|
Deploy.examples = [
|
|
58
|
-
`Deploy a new version of an existing documentation
|
|
116
|
+
`Deploy a new version of ${chalk_1.default.underline('an existing documentation')}
|
|
59
117
|
|
|
60
|
-
$ bump deploy FILE --doc <your_doc_id_or_slug> --token <your_doc_token>
|
|
118
|
+
${chalk_1.default.dim('$ bump deploy FILE --doc <your_doc_id_or_slug> --token <your_doc_token>')}
|
|
61
119
|
* Let's deploy a new documentation version on Bump... done
|
|
62
120
|
* Your new documentation version will soon be ready
|
|
63
121
|
`,
|
|
64
|
-
`Deploy a new version of an existing documentation attached to a hub
|
|
122
|
+
`Deploy a new version of ${chalk_1.default.underline('an existing documentation attached to a hub')}
|
|
65
123
|
|
|
66
|
-
$ bump deploy FILE --doc <doc_slug> --hub <your_hub_id_or_slug> --token <your_doc_token>
|
|
124
|
+
${chalk_1.default.dim('$ bump deploy FILE --doc <doc_slug> --hub <your_hub_id_or_slug> --token <your_doc_token>')}
|
|
67
125
|
* Let's deploy a new documentation version on Bump... done
|
|
68
126
|
* Your new documentation version will soon be ready
|
|
69
127
|
`,
|
|
70
|
-
`
|
|
128
|
+
`Deploy a whole directory of ${chalk_1.default.underline('API definitions files to a hub')}
|
|
129
|
+
|
|
130
|
+
${chalk_1.default.dim('$ bump deploy DIR --filename-pattern *-{slug}-api --hub <hub_slug> --token <hub_token>')}
|
|
131
|
+
We've found 2 valid API definitions to deploy
|
|
132
|
+
└─ DIR
|
|
133
|
+
└─ source-my-service-api.yml (OpenAPI spec version 3.1.0)
|
|
134
|
+
└─ source-my-jobs-service-api.yml (AsyncAPI spec version 2.6.0)
|
|
135
|
+
|
|
136
|
+
Let's deploy those documentations to your <hub_slug> hub on Bump.sh
|
|
137
|
+
|
|
138
|
+
* Your new documentation version will soon be ready
|
|
139
|
+
Let's deploy a new version to your my-service documentation on Bump.sh... done
|
|
140
|
+
|
|
141
|
+
* Your new documentation version will soon be ready
|
|
142
|
+
Let's deploy a new version to your my-jobs-service documentation on Bump.sh... done
|
|
143
|
+
`,
|
|
144
|
+
`${chalk_1.default.underline('Validate a new documentation version')} before deploying it
|
|
71
145
|
|
|
72
|
-
$ bump deploy FILE --dry-run --doc <doc_slug> --token <your_doc_token>
|
|
146
|
+
${chalk_1.default.dim('$ bump deploy FILE --dry-run --doc <doc_slug> --token <your_doc_token>')}
|
|
73
147
|
* Let's validate a new documentation version on Bump... done
|
|
74
148
|
* Definition is valid
|
|
75
149
|
`,
|
|
76
150
|
];
|
|
77
151
|
Deploy.flags = {
|
|
78
|
-
help:
|
|
79
|
-
doc:
|
|
80
|
-
'doc-name':
|
|
81
|
-
hub:
|
|
82
|
-
branch:
|
|
83
|
-
token:
|
|
84
|
-
'auto-create':
|
|
85
|
-
|
|
152
|
+
help: flagsBuilder.help({ char: 'h' }),
|
|
153
|
+
doc: flagsBuilder.doc(),
|
|
154
|
+
'doc-name': flagsBuilder.docName(),
|
|
155
|
+
hub: flagsBuilder.hub(),
|
|
156
|
+
branch: flagsBuilder.branch(),
|
|
157
|
+
token: flagsBuilder.token(),
|
|
158
|
+
'auto-create': flagsBuilder.autoCreate(),
|
|
159
|
+
interactive: flagsBuilder.interactive(),
|
|
160
|
+
'filename-pattern': flagsBuilder.filenamePattern(),
|
|
161
|
+
'dry-run': flagsBuilder.dryRun(),
|
|
86
162
|
};
|
|
87
163
|
Deploy.args = [args_1.fileArg];
|
package/lib/commands/diff.d.ts
CHANGED
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
import Command from '../command';
|
|
2
|
-
import * as
|
|
2
|
+
import * as flagsBuilder from '../flags';
|
|
3
3
|
import { DiffResponse } from '../api/models';
|
|
4
4
|
export default class Diff extends Command {
|
|
5
5
|
static description: string;
|
|
6
6
|
static examples: string[];
|
|
7
7
|
static flags: {
|
|
8
8
|
help: import("@oclif/parser/lib/flags").IBooleanFlag<void>;
|
|
9
|
-
doc:
|
|
10
|
-
hub:
|
|
11
|
-
branch:
|
|
12
|
-
token:
|
|
9
|
+
doc: flagsBuilder.IOptionFlag<string | undefined>;
|
|
10
|
+
hub: flagsBuilder.IOptionFlag<string | undefined>;
|
|
11
|
+
branch: flagsBuilder.IOptionFlag<string | undefined>;
|
|
12
|
+
token: flagsBuilder.IOptionFlag<string | undefined>;
|
|
13
13
|
open: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
'fail-on-breaking': import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
|
|
15
|
+
format: flagsBuilder.IOptionFlag<string | undefined>;
|
|
16
|
+
expires: flagsBuilder.IOptionFlag<string | undefined>;
|
|
16
17
|
};
|
|
17
18
|
static args: {
|
|
18
19
|
name: string;
|
|
19
20
|
description: string;
|
|
20
21
|
}[];
|
|
21
22
|
run(): Promise<void>;
|
|
22
|
-
displayCompareResult(result: DiffResponse, format: string, open: boolean): Promise<void>;
|
|
23
|
+
displayCompareResult(result: DiffResponse, format: string, open: boolean, failOnBreaking: boolean): Promise<void>;
|
|
23
24
|
}
|
package/lib/commands/diff.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
const errors_1 = require("@oclif/errors");
|
|
5
5
|
const command_1 = (0, tslib_1.__importDefault)(require("../command"));
|
|
6
|
-
const
|
|
6
|
+
const flagsBuilder = (0, tslib_1.__importStar)(require("../flags"));
|
|
7
7
|
const diff_1 = require("../core/diff");
|
|
8
8
|
const args_1 = require("../args");
|
|
9
9
|
const cli_1 = require("../cli");
|
|
@@ -41,14 +41,14 @@ class Diff extends command_1.default {
|
|
|
41
41
|
const diff = await new diff_1.Diff(this.config).run(args.FILE, args.FILE2, documentation, hub, branch, token, format, expires);
|
|
42
42
|
cli_1.cli.action.stop();
|
|
43
43
|
if (diff) {
|
|
44
|
-
await this.displayCompareResult(diff, format, flags.open);
|
|
44
|
+
await this.displayCompareResult(diff, format, flags.open, flags['fail-on-breaking']);
|
|
45
45
|
}
|
|
46
46
|
else {
|
|
47
47
|
await cli_1.cli.log('No changes detected.');
|
|
48
48
|
}
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
51
|
-
async displayCompareResult(result, format, open) {
|
|
51
|
+
async displayCompareResult(result, format, open, failOnBreaking) {
|
|
52
52
|
if (format == 'text' && result.text) {
|
|
53
53
|
await cli_1.cli.log(result.text);
|
|
54
54
|
}
|
|
@@ -67,10 +67,13 @@ class Diff extends command_1.default {
|
|
|
67
67
|
if (open && result.public_url) {
|
|
68
68
|
await cli_1.cli.open(result.public_url);
|
|
69
69
|
}
|
|
70
|
+
if (failOnBreaking && result.breaking) {
|
|
71
|
+
this.exit(1);
|
|
72
|
+
}
|
|
70
73
|
}
|
|
71
74
|
}
|
|
72
75
|
exports.default = Diff;
|
|
73
|
-
Diff.description = 'Get a
|
|
76
|
+
Diff.description = 'Get a comparison diff with your documentation from the given file or URL.';
|
|
74
77
|
Diff.examples = [
|
|
75
78
|
`Compare a potential new version with the currently published one:
|
|
76
79
|
|
|
@@ -103,13 +106,14 @@ Diff.examples = [
|
|
|
103
106
|
`,
|
|
104
107
|
];
|
|
105
108
|
Diff.flags = {
|
|
106
|
-
help:
|
|
107
|
-
doc:
|
|
108
|
-
hub:
|
|
109
|
-
branch:
|
|
110
|
-
token:
|
|
111
|
-
open:
|
|
112
|
-
|
|
113
|
-
|
|
109
|
+
help: flagsBuilder.help({ char: 'h' }),
|
|
110
|
+
doc: flagsBuilder.doc(),
|
|
111
|
+
hub: flagsBuilder.hub(),
|
|
112
|
+
branch: flagsBuilder.branch(),
|
|
113
|
+
token: flagsBuilder.token({ required: false }),
|
|
114
|
+
open: flagsBuilder.open({ description: 'Open the visual diff in your browser' }),
|
|
115
|
+
'fail-on-breaking': flagsBuilder.failOnBreaking(),
|
|
116
|
+
format: flagsBuilder.format(),
|
|
117
|
+
expires: flagsBuilder.expires(),
|
|
114
118
|
};
|
|
115
119
|
Diff.args = [args_1.fileArg, args_1.otherFileArg];
|
package/lib/commands/preview.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
const definition_1 = require("../definition");
|
|
5
5
|
const command_1 = (0, tslib_1.__importDefault)(require("../command"));
|
|
6
|
-
const
|
|
6
|
+
const flagsBuilder = (0, tslib_1.__importStar)(require("../flags"));
|
|
7
7
|
const args_1 = require("../args");
|
|
8
8
|
const cli_1 = require("../cli");
|
|
9
9
|
const fs_1 = require("fs");
|
|
@@ -11,12 +11,10 @@ const async_mutex_1 = require("async-mutex");
|
|
|
11
11
|
class Preview extends command_1.default {
|
|
12
12
|
async run() {
|
|
13
13
|
const { args, flags } = this.parse(Preview);
|
|
14
|
+
await this.preview(args.FILE, flags.open);
|
|
14
15
|
if (flags.live) {
|
|
15
16
|
await this.waitForChanges(args.FILE, flags.open);
|
|
16
17
|
}
|
|
17
|
-
else {
|
|
18
|
-
await this.preview(args.FILE, flags.open);
|
|
19
|
-
}
|
|
20
18
|
return;
|
|
21
19
|
}
|
|
22
20
|
async preview(file, open = false, currentPreview = undefined) {
|
|
@@ -68,17 +66,19 @@ class Preview extends command_1.default {
|
|
|
68
66
|
}
|
|
69
67
|
}
|
|
70
68
|
exports.default = Preview;
|
|
71
|
-
Preview.description = '
|
|
69
|
+
Preview.description = 'Create a documentation preview from the given file or URL.';
|
|
72
70
|
Preview.examples = [
|
|
73
71
|
`$ bump preview FILE
|
|
74
72
|
* Your preview is visible at: https://bump.sh/preview/45807371-9a32-48a7-b6e4-1cb7088b5b9b
|
|
75
73
|
`,
|
|
76
74
|
];
|
|
77
75
|
Preview.flags = {
|
|
78
|
-
help:
|
|
79
|
-
live:
|
|
76
|
+
help: flagsBuilder.help({ char: 'h' }),
|
|
77
|
+
live: flagsBuilder.live({
|
|
80
78
|
description: 'Generate a preview each time you save the given file',
|
|
81
79
|
}),
|
|
82
|
-
open:
|
|
80
|
+
open: flagsBuilder.open({
|
|
81
|
+
description: 'Open the generated preview URL in your browser',
|
|
82
|
+
}),
|
|
83
83
|
};
|
|
84
84
|
Preview.args = [args_1.fileArg];
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { API } from '../definition';
|
|
2
|
+
export declare type DefinitionConfig = {
|
|
3
|
+
definition: API;
|
|
4
|
+
file: string;
|
|
5
|
+
slug: string;
|
|
6
|
+
};
|
|
7
|
+
export declare class DefinitionDirectory {
|
|
8
|
+
protected readonly path: string;
|
|
9
|
+
protected readonly definitions: DefinitionConfig[];
|
|
10
|
+
protected readonly filenamePattern: RegExp;
|
|
11
|
+
protected readonly humanFilenamePattern: string;
|
|
12
|
+
protected buildNewFilename: (slug: string) => string;
|
|
13
|
+
constructor(directory: string, filenamePattern: string);
|
|
14
|
+
readDefinitions(): Promise<DefinitionConfig[]>;
|
|
15
|
+
definitionsExists(): boolean;
|
|
16
|
+
sequentialMap(callback: (definition: DefinitionConfig) => Promise<DefinitionConfig>): Promise<void>;
|
|
17
|
+
renameToConvention(documentation: DefinitionConfig): Promise<void>;
|
|
18
|
+
interactiveSelection(): Promise<DefinitionConfig[]>;
|
|
19
|
+
d(formatter: any, ...args: any[]): void;
|
|
20
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DefinitionDirectory = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const chalk_1 = (0, tslib_1.__importDefault)(require("chalk"));
|
|
6
|
+
const debug_1 = (0, tslib_1.__importDefault)(require("debug"));
|
|
7
|
+
const fs_1 = require("fs");
|
|
8
|
+
const node_path_1 = require("node:path");
|
|
9
|
+
const p = (0, tslib_1.__importStar)(require("@clack/prompts"));
|
|
10
|
+
const errors_1 = require("@oclif/errors");
|
|
11
|
+
const cli_1 = require("../cli");
|
|
12
|
+
const definition_1 = require("../definition");
|
|
13
|
+
const file_1 = require("./utils/file");
|
|
14
|
+
const prompts_1 = require("../core/utils/prompts");
|
|
15
|
+
class DefinitionDirectory {
|
|
16
|
+
constructor(directory, filenamePattern) {
|
|
17
|
+
this.path = (0, node_path_1.resolve)(directory);
|
|
18
|
+
this.definitions = [];
|
|
19
|
+
// Transform basic patterns '*' or '{text}' into a real RegExp
|
|
20
|
+
this.filenamePattern = new RegExp('^' + filenamePattern.replace('*', '.*?').replace(/{.*?}/, '(?<slug>.+?)') + '$');
|
|
21
|
+
this.buildNewFilename = (slug) => filenamePattern.replace('*', '').replace(/{.*?}/, slug);
|
|
22
|
+
this.humanFilenamePattern = filenamePattern.replace(/{(.*?)}/, `${chalk_1.default.inverse('{$1}')}`);
|
|
23
|
+
}
|
|
24
|
+
async readDefinitions() {
|
|
25
|
+
var e_1, _a;
|
|
26
|
+
try {
|
|
27
|
+
for (var _b = (0, tslib_1.__asyncValues)(file_1.File.listValidConventionFiles(this.path, this.filenamePattern)), _c; _c = await _b.next(), !_c.done;) {
|
|
28
|
+
const { value, filename } = _c.value;
|
|
29
|
+
const file = (0, node_path_1.join)(this.path, value);
|
|
30
|
+
/* We already check the filenamePattern match inside the
|
|
31
|
+
`File.listValidConventionFiles` method so we are sure the group
|
|
32
|
+
matched exists. */
|
|
33
|
+
/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */
|
|
34
|
+
const slug = filename.match(this.filenamePattern).groups.slug;
|
|
35
|
+
const definition = await definition_1.API.load(file);
|
|
36
|
+
this.definitions.push({
|
|
37
|
+
file,
|
|
38
|
+
definition,
|
|
39
|
+
slug,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
44
|
+
finally {
|
|
45
|
+
try {
|
|
46
|
+
if (_c && !_c.done && (_a = _b.return)) await _a.call(_b);
|
|
47
|
+
}
|
|
48
|
+
finally { if (e_1) throw e_1.error; }
|
|
49
|
+
}
|
|
50
|
+
if (this.definitions.length) {
|
|
51
|
+
cli_1.cli.info(chalk_1.default.underline(`We've found ${this.definitions.length} valid API definitions to deploy`));
|
|
52
|
+
const subtree = cli_1.cli.tree();
|
|
53
|
+
this.definitions.forEach(({ file, definition }) => subtree.insert(`${(0, node_path_1.basename)(file)} (${definition.specName} spec version ${definition.version})`));
|
|
54
|
+
const tree = cli_1.cli.tree();
|
|
55
|
+
tree.insert(this.path, subtree);
|
|
56
|
+
tree.display();
|
|
57
|
+
cli_1.cli.info('');
|
|
58
|
+
}
|
|
59
|
+
return this.definitions;
|
|
60
|
+
}
|
|
61
|
+
definitionsExists() {
|
|
62
|
+
return !!this.definitions.length;
|
|
63
|
+
}
|
|
64
|
+
async sequentialMap(callback) {
|
|
65
|
+
for (const definition of this.definitions) {
|
|
66
|
+
await callback(definition);
|
|
67
|
+
}
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
async renameToConvention(documentation) {
|
|
71
|
+
const { file, slug } = documentation;
|
|
72
|
+
if ((0, node_path_1.basename)(file, (0, node_path_1.extname)(file)).match(this.filenamePattern))
|
|
73
|
+
return;
|
|
74
|
+
// Default convention is defined in the flags.ts file for the
|
|
75
|
+
// 'filenamePattern' flag.
|
|
76
|
+
const newFilename = this.buildNewFilename(slug);
|
|
77
|
+
const newFile = `${(0, node_path_1.dirname)(file)}/${newFilename}${(0, node_path_1.extname)(file)}`;
|
|
78
|
+
let confirm = true;
|
|
79
|
+
await (0, prompts_1.confirm)(`Do you want to rename ${file} to ${newFile} (for later deployments)?`).catch(() => {
|
|
80
|
+
confirm = false;
|
|
81
|
+
});
|
|
82
|
+
if (confirm) {
|
|
83
|
+
await (0, fs_1.rename)(file, newFile, (err) => {
|
|
84
|
+
if (err)
|
|
85
|
+
throw err;
|
|
86
|
+
cli_1.cli.styledSuccess(`Renamed ${file} to ${newFile}.`);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
async interactiveSelection() {
|
|
92
|
+
p.intro(`This interactive form will help you rename your API contrat files to follow the expected naming convention.\n${chalk_1.default.gray('│ ')}Once finished, the selected files will be deployed to Bump.sh.\n${chalk_1.default.gray('│ ')}\n${chalk_1.default.gray('│ ')}File naming convention: ${this.humanFilenamePattern}${chalk_1.default.dim('.[json|yml|yaml]')}\n`);
|
|
93
|
+
const fileOptions = file_1.File.listInvalidConventionFiles(this.path, this.filenamePattern);
|
|
94
|
+
if (!fileOptions.length) {
|
|
95
|
+
throw new errors_1.CLIError(`No JSON or YAML files needing a rename were found in ${this.path}.\nAre you sure you need the ${chalk_1.default.dim('--interactive')} flag?`);
|
|
96
|
+
}
|
|
97
|
+
let shouldContinue = true;
|
|
98
|
+
while (shouldContinue) {
|
|
99
|
+
const filePrompt = {
|
|
100
|
+
fileName: () => p.select({
|
|
101
|
+
message: `Which file do you want to deploy from ${chalk_1.default.dim(this.path)}?`,
|
|
102
|
+
options: fileOptions,
|
|
103
|
+
}),
|
|
104
|
+
};
|
|
105
|
+
const groupPrompt = {
|
|
106
|
+
/* Results type should be taken from the previous prompts
|
|
107
|
+
* defined with clack/prompt */
|
|
108
|
+
slug: ({ results }) => p.text({
|
|
109
|
+
message: `What is the ${chalk_1.default.inverse('documentation slug')} for this ${chalk_1.default.dim(results.fileName)} file?`,
|
|
110
|
+
}),
|
|
111
|
+
};
|
|
112
|
+
const prompt = await p.group(Object.assign(Object.assign(Object.assign({}, filePrompt), groupPrompt), { shouldContinue: () => p.confirm({ message: 'Do you want to select another file?' }) }), {
|
|
113
|
+
onCancel: () => {
|
|
114
|
+
p.cancel('Deploy cancelled.');
|
|
115
|
+
process.exit(0);
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
const file = (0, node_path_1.join)(this.path, prompt.fileName);
|
|
119
|
+
const definition = await definition_1.API.load(file);
|
|
120
|
+
this.d(`${file} looks like an ${definition.specName} spec version ${definition.version}`);
|
|
121
|
+
this.definitions.push({
|
|
122
|
+
file,
|
|
123
|
+
definition,
|
|
124
|
+
slug: prompt.slug,
|
|
125
|
+
});
|
|
126
|
+
shouldContinue = prompt.shouldContinue;
|
|
127
|
+
}
|
|
128
|
+
p.outro(`You're all set. Your deployments will start soon.`);
|
|
129
|
+
return this.definitions;
|
|
130
|
+
}
|
|
131
|
+
// Function signature type taken from @types/debug
|
|
132
|
+
// Debugger(formatter: any, ...args: any[]): void;
|
|
133
|
+
/* eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any */
|
|
134
|
+
d(formatter, ...args) {
|
|
135
|
+
return (0, debug_1.default)(`bump-cli:core:interactive`)(formatter, ...args);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
exports.DefinitionDirectory = DefinitionDirectory;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as Config from '@oclif/config';
|
|
2
|
+
import { API } from '../definition';
|
|
3
|
+
import { BumpApi } from '../api';
|
|
4
|
+
import { VersionRequest, VersionResponse } from '../api/models';
|
|
5
|
+
export declare class Deploy {
|
|
6
|
+
_bump: BumpApi;
|
|
7
|
+
_config: Config.IConfig;
|
|
8
|
+
constructor(config: Config.IConfig);
|
|
9
|
+
run(api: API, dryRun: boolean, documentation: string, token: string, hub: string | undefined, autoCreate: boolean, documentationName: string | undefined, branch: string | undefined): Promise<VersionResponse | undefined>;
|
|
10
|
+
get bumpClient(): BumpApi;
|
|
11
|
+
createVersion(request: VersionRequest, token: string): Promise<VersionResponse | undefined>;
|
|
12
|
+
validateVersion(version: VersionRequest, token: string): Promise<undefined>;
|
|
13
|
+
d(formatter: any, ...args: any[]): void;
|
|
14
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Deploy = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const debug_1 = (0, tslib_1.__importDefault)(require("debug"));
|
|
6
|
+
const api_1 = require("../api");
|
|
7
|
+
class Deploy {
|
|
8
|
+
constructor(config) {
|
|
9
|
+
this._config = config;
|
|
10
|
+
}
|
|
11
|
+
async run(api, dryRun, documentation, token, hub, autoCreate, documentationName, branch) {
|
|
12
|
+
let version = undefined;
|
|
13
|
+
const [definition, references] = api.extractDefinition();
|
|
14
|
+
const request = {
|
|
15
|
+
documentation,
|
|
16
|
+
hub,
|
|
17
|
+
documentation_name: documentationName,
|
|
18
|
+
auto_create_documentation: autoCreate && !dryRun,
|
|
19
|
+
definition,
|
|
20
|
+
references,
|
|
21
|
+
branch_name: branch,
|
|
22
|
+
};
|
|
23
|
+
if (dryRun) {
|
|
24
|
+
await this.validateVersion(request, token);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
version = await this.createVersion(request, token);
|
|
28
|
+
}
|
|
29
|
+
return version;
|
|
30
|
+
}
|
|
31
|
+
get bumpClient() {
|
|
32
|
+
if (!this._bump)
|
|
33
|
+
this._bump = new api_1.BumpApi(this._config);
|
|
34
|
+
return this._bump;
|
|
35
|
+
}
|
|
36
|
+
async createVersion(request, token) {
|
|
37
|
+
const response = await this.bumpClient.postVersion(request, token);
|
|
38
|
+
let version = undefined;
|
|
39
|
+
switch (response.status) {
|
|
40
|
+
case 204:
|
|
41
|
+
break;
|
|
42
|
+
case 201:
|
|
43
|
+
version = response.data
|
|
44
|
+
? response.data
|
|
45
|
+
: { id: '', doc_public_url: 'https://bump.sh' };
|
|
46
|
+
break;
|
|
47
|
+
default:
|
|
48
|
+
this.d(`API status response was ${response.status}. Expected 201 or 204.`);
|
|
49
|
+
throw new Error('Unexpected server response. Please contact support at https://bump.sh if this error persists');
|
|
50
|
+
}
|
|
51
|
+
return version;
|
|
52
|
+
}
|
|
53
|
+
async validateVersion(version, token) {
|
|
54
|
+
const response = await this.bumpClient.postValidation(version, token);
|
|
55
|
+
switch (response.status) {
|
|
56
|
+
case 200:
|
|
57
|
+
break;
|
|
58
|
+
default:
|
|
59
|
+
this.d(`API status response was ${response.status}. Expected 200.`);
|
|
60
|
+
throw new Error('Unexpected server response. Please contact support at https://bump.sh if this error persists');
|
|
61
|
+
}
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
// Function signature type taken from @types/debug
|
|
65
|
+
// Debugger(formatter: any, ...args: any[]): void;
|
|
66
|
+
/* eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any */
|
|
67
|
+
d(formatter, ...args) {
|
|
68
|
+
return (0, debug_1.default)(`bump-cli:core:deploy`)(formatter, ...args);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
exports.Deploy = Deploy;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
declare type FileDescription = {
|
|
2
|
+
value: string;
|
|
3
|
+
label: string;
|
|
4
|
+
filename: string;
|
|
5
|
+
};
|
|
6
|
+
export declare class File {
|
|
7
|
+
protected static readonly supportedFormats: string[];
|
|
8
|
+
static listValidConventionFiles(path: string, regex: RegExp): FileDescription[];
|
|
9
|
+
static listInvalidConventionFiles(path: string, regex: RegExp): FileDescription[];
|
|
10
|
+
private static listValidFormatFiles;
|
|
11
|
+
}
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.File = void 0;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
class File {
|
|
7
|
+
static listValidConventionFiles(path, regex) {
|
|
8
|
+
return File.listValidFormatFiles(path).filter(({ filename }) => {
|
|
9
|
+
return filename.match(regex);
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
static listInvalidConventionFiles(path, regex) {
|
|
13
|
+
return File.listValidFormatFiles(path).filter(({ filename }) => {
|
|
14
|
+
return !filename.match(regex);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
static listValidFormatFiles(path) {
|
|
18
|
+
return (0, fs_1.readdirSync)(path)
|
|
19
|
+
.filter((file) => {
|
|
20
|
+
return File.supportedFormats.includes((0, path_1.extname)(file));
|
|
21
|
+
})
|
|
22
|
+
.map((file) => {
|
|
23
|
+
return {
|
|
24
|
+
value: file,
|
|
25
|
+
label: (0, path_1.basename)(file),
|
|
26
|
+
filename: (0, path_1.basename)(file, (0, path_1.extname)(file)),
|
|
27
|
+
};
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.File = File;
|
|
32
|
+
File.supportedFormats = ['.yml', '.yaml', '.json'];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const confirm: (message?: string) => Promise<void>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.confirm = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const errors_1 = require("@oclif/errors");
|
|
6
|
+
const p = (0, tslib_1.__importStar)(require("@clack/prompts"));
|
|
7
|
+
const confirm = async (message = 'Continue?') => {
|
|
8
|
+
const prompt = await p.group({
|
|
9
|
+
shouldContinue: () => p.confirm({ message: message }),
|
|
10
|
+
}, {
|
|
11
|
+
onCancel: () => {
|
|
12
|
+
p.cancel('Cancelled.');
|
|
13
|
+
process.exit(0);
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
if (!prompt.shouldContinue) {
|
|
17
|
+
throw new errors_1.CLIError(`Cancelled`);
|
|
18
|
+
}
|
|
19
|
+
return;
|
|
20
|
+
};
|
|
21
|
+
exports.confirm = confirm;
|
package/lib/definition.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import $RefParser from '@apidevtools/json-schema-ref-parser';
|
|
2
2
|
import { JSONSchema4Object, JSONSchema6Object } from 'json-schema';
|
|
3
|
+
declare class SupportedFormat {
|
|
4
|
+
static readonly openapi: Record<string, SpecSchema>;
|
|
5
|
+
static readonly asyncapi: Record<string, SpecSchema>;
|
|
6
|
+
}
|
|
3
7
|
declare class API {
|
|
4
8
|
readonly location: string;
|
|
5
9
|
readonly rawDefinition: string;
|
|
@@ -34,4 +38,4 @@ declare type AsyncAPI = JSONSchema4Object & {
|
|
|
34
38
|
readonly asyncapi: string;
|
|
35
39
|
readonly info: string;
|
|
36
40
|
};
|
|
37
|
-
export { API };
|
|
41
|
+
export { API, SupportedFormat };
|
package/lib/definition.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.API = void 0;
|
|
3
|
+
exports.SupportedFormat = exports.API = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const errors_1 = require("@oclif/errors");
|
|
6
6
|
const json_schema_ref_parser_1 = (0, tslib_1.__importDefault)(require("@apidevtools/json-schema-ref-parser"));
|
|
@@ -9,6 +9,7 @@ const specs_1 = (0, tslib_1.__importDefault)(require("@asyncapi/specs"));
|
|
|
9
9
|
const path_1 = (0, tslib_1.__importDefault)(require("path"));
|
|
10
10
|
class SupportedFormat {
|
|
11
11
|
}
|
|
12
|
+
exports.SupportedFormat = SupportedFormat;
|
|
12
13
|
SupportedFormat.openapi = {
|
|
13
14
|
'2.0': require('oas-schemas/schemas/v2.0/schema.json'),
|
|
14
15
|
'3.0': require('oas-schemas/schemas/v3.0/schema.json'),
|
|
@@ -21,6 +22,7 @@ SupportedFormat.asyncapi = {
|
|
|
21
22
|
'2.3': specs_1.default['2.3.0'],
|
|
22
23
|
'2.4': specs_1.default['2.4.0'],
|
|
23
24
|
'2.5': specs_1.default['2.5.0'],
|
|
25
|
+
'2.6': specs_1.default['2.6.0'],
|
|
24
26
|
};
|
|
25
27
|
class UnsupportedFormat extends errors_1.CLIError {
|
|
26
28
|
constructor(message = '') {
|
package/lib/flags.d.ts
CHANGED
|
@@ -4,12 +4,15 @@ export * from '@oclif/command/lib/flags';
|
|
|
4
4
|
declare const doc: flags.Definition<string>;
|
|
5
5
|
declare const docName: flags.Definition<string>;
|
|
6
6
|
declare const hub: flags.Definition<string>;
|
|
7
|
+
declare const filenamePattern: flags.Definition<string>;
|
|
7
8
|
declare const branch: flags.Definition<string>;
|
|
8
9
|
declare const token: flags.Definition<string>;
|
|
9
10
|
declare const autoCreate: (options?: {}) => Parser.flags.IBooleanFlag<boolean>;
|
|
11
|
+
declare const interactive: (options?: {}) => Parser.flags.IBooleanFlag<boolean>;
|
|
10
12
|
declare const dryRun: (options?: {}) => Parser.flags.IBooleanFlag<boolean>;
|
|
11
13
|
declare const open: (options?: {}) => Parser.flags.IBooleanFlag<boolean>;
|
|
14
|
+
declare const failOnBreaking: (options?: {}) => Parser.flags.IBooleanFlag<boolean>;
|
|
12
15
|
declare const live: (options?: {}) => Parser.flags.IBooleanFlag<boolean>;
|
|
13
16
|
declare const format: flags.Definition<string>;
|
|
14
17
|
declare const expires: flags.Definition<string>;
|
|
15
|
-
export { doc, docName, hub, branch, token, autoCreate, dryRun, open, live, format, expires, };
|
|
18
|
+
export { doc, docName, hub, branch, token, autoCreate, interactive, filenamePattern, dryRun, open, failOnBreaking, live, format, expires, };
|
package/lib/flags.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.expires = exports.format = exports.live = exports.open = exports.dryRun = exports.autoCreate = exports.token = exports.branch = exports.hub = exports.docName = exports.doc = void 0;
|
|
3
|
+
exports.expires = exports.format = exports.live = exports.failOnBreaking = exports.open = exports.dryRun = exports.filenamePattern = exports.interactive = exports.autoCreate = exports.token = exports.branch = exports.hub = exports.docName = exports.doc = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const command_1 = require("@oclif/command");
|
|
6
6
|
// Re-export oclif flags https://oclif.io/docs/flags
|
|
7
7
|
(0, tslib_1.__exportStar)(require("@oclif/command/lib/flags"), exports);
|
|
8
|
-
// Custom flags for
|
|
8
|
+
// Custom flags for bump-cli
|
|
9
9
|
const doc = command_1.flags.build({
|
|
10
10
|
char: 'd',
|
|
11
|
-
required: true,
|
|
12
11
|
description: 'Documentation public id or slug. Can be provided via BUMP_ID environment variable',
|
|
13
12
|
default: () => {
|
|
14
13
|
const envDoc = process.env.BUMP_ID;
|
|
@@ -35,6 +34,11 @@ const hub = command_1.flags.build({
|
|
|
35
34
|
},
|
|
36
35
|
});
|
|
37
36
|
exports.hub = hub;
|
|
37
|
+
const filenamePattern = command_1.flags.build({
|
|
38
|
+
description: `Pattern to extract the documentation slug from filenames when deploying a DIRECTORY. Pattern uses only '*' and '{slug}' as special characters to extract the slug from a filename without extension. Used with --hub flag only.`,
|
|
39
|
+
default: '{slug}-api',
|
|
40
|
+
});
|
|
41
|
+
exports.filenamePattern = filenamePattern;
|
|
38
42
|
const branch = command_1.flags.build({
|
|
39
43
|
char: 'B',
|
|
40
44
|
description: 'Branch name. Can be provided via BUMP_BRANCH_NAME environment variable',
|
|
@@ -60,6 +64,10 @@ const autoCreate = (options = {}) => {
|
|
|
60
64
|
return command_1.flags.boolean(Object.assign({ description: 'Automatically create the documentation if needed (only available with a --hub flag). Documentation name can be provided with --doc-name flag. Default: false', dependsOn: ['hub'] }, options));
|
|
61
65
|
};
|
|
62
66
|
exports.autoCreate = autoCreate;
|
|
67
|
+
const interactive = (options = {}) => {
|
|
68
|
+
return command_1.flags.boolean(Object.assign({ description: "Interactively create a configuration file to deploy a Hub (only available with a --hub flag). This will start an interactive process if you don't have a CLI configuration file. Default: false", dependsOn: ['hub'] }, options));
|
|
69
|
+
};
|
|
70
|
+
exports.interactive = interactive;
|
|
63
71
|
const dryRun = (options = {}) => {
|
|
64
72
|
return command_1.flags.boolean(Object.assign({ description: 'Validate a new documentation version. Does everything a normal deploy would do except publishing the new version. Useful in automated environments such as test platforms or continuous integration. Default: false' }, options));
|
|
65
73
|
};
|
|
@@ -68,6 +76,18 @@ const open = (options = {}) => {
|
|
|
68
76
|
return command_1.flags.boolean(Object.assign({ char: 'o', default: false }, options));
|
|
69
77
|
};
|
|
70
78
|
exports.open = open;
|
|
79
|
+
const failOnBreaking = (options = {}) => {
|
|
80
|
+
return command_1.flags.boolean(Object.assign({ char: 'F', description: 'Fail when diff contains a breaking change', default: () => {
|
|
81
|
+
const envCi = process.env.CI;
|
|
82
|
+
if (envCi) {
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
} }, options));
|
|
89
|
+
};
|
|
90
|
+
exports.failOnBreaking = failOnBreaking;
|
|
71
91
|
const live = (options = {}) => {
|
|
72
92
|
return command_1.flags.boolean(Object.assign({ char: 'l', default: false }, options));
|
|
73
93
|
};
|
package/oclif.manifest.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"2.
|
|
1
|
+
{"version":"2.7.0","commands":{"deploy":{"id":"deploy","description":"Create a new version of your documentation from the given file or URL.","pluginName":"bump-cli","pluginType":"core","aliases":[],"examples":["Deploy a new version of an existing documentation\n\n$ bump deploy FILE --doc <your_doc_id_or_slug> --token <your_doc_token>\n* Let's deploy a new documentation version on Bump... done\n* Your new documentation version will soon be ready\n","Deploy a new version of an existing documentation attached to a hub\n\n$ bump deploy FILE --doc <doc_slug> --hub <your_hub_id_or_slug> --token <your_doc_token>\n* Let's deploy a new documentation version on Bump... done\n* Your new documentation version will soon be ready\n","Deploy a whole directory of API definitions files to a hub\n\n$ bump deploy DIR --filename-pattern *-{slug}-api --hub <hub_slug> --token <hub_token>\nWe've found 2 valid API definitions to deploy\n└─ DIR\n └─ source-my-service-api.yml (OpenAPI spec version 3.1.0)\n └─ source-my-jobs-service-api.yml (AsyncAPI spec version 2.6.0)\n\nLet's deploy those documentations to your <hub_slug> hub on Bump.sh\n\n* Your new documentation version will soon be ready\nLet's deploy a new version to your my-service documentation on Bump.sh... done\n\n* Your new documentation version will soon be ready\nLet's deploy a new version to your my-jobs-service documentation on Bump.sh... done\n","Validate a new documentation version before deploying it\n\n$ bump deploy FILE --dry-run --doc <doc_slug> --token <your_doc_token>\n* Let's validate a new documentation version on Bump... done\n* Definition is valid\n"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"doc":{"name":"doc","type":"option","char":"d","description":"Documentation public id or slug. Can be provided via BUMP_ID environment variable"},"doc-name":{"name":"doc-name","type":"option","char":"n","description":"Documentation name. Used with --auto-create flag."},"hub":{"name":"hub","type":"option","char":"b","description":"Hub id or slug. Can be provided via BUMP_HUB_ID environment variable"},"branch":{"name":"branch","type":"option","char":"B","description":"Branch name. Can be provided via BUMP_BRANCH_NAME environment variable"},"token":{"name":"token","type":"option","char":"t","description":"Documentation or Hub token. Can be provided via BUMP_TOKEN environment variable","required":true,"default":"99f52837852249b328c0a00249f846a3"},"auto-create":{"name":"auto-create","type":"boolean","description":"Automatically create the documentation if needed (only available with a --hub flag). Documentation name can be provided with --doc-name flag. Default: false","allowNo":false},"interactive":{"name":"interactive","type":"boolean","description":"Interactively create a configuration file to deploy a Hub (only available with a --hub flag). This will start an interactive process if you don't have a CLI configuration file. Default: false","allowNo":false},"filename-pattern":{"name":"filename-pattern","type":"option","description":"Pattern to extract the documentation slug from filenames when deploying a DIRECTORY. Pattern uses only '*' and '{slug}' as special characters to extract the slug from a filename without extension. Used with --hub flag only.","default":"{slug}-api"},"dry-run":{"name":"dry-run","type":"boolean","description":"Validate a new documentation version. Does everything a normal deploy would do except publishing the new version. Useful in automated environments such as test platforms or continuous integration. Default: false","allowNo":false}},"args":[{"name":"FILE","description":"Path or URL to your API documentation file. OpenAPI (2.0 to 3.1.0) and AsyncAPI (2.x) specifications are currently supported.\nPath can also be a directory when deploying to a Hub.","required":true}]},"diff":{"id":"diff","description":"Get a comparison diff with your documentation from the given file or URL.","pluginName":"bump-cli","pluginType":"core","aliases":[],"examples":["Compare a potential new version with the currently published one:\n\n $ bump diff FILE --doc <your_doc_id_or_slug> --token <your_doc_token>\n * Comparing the given definition file with the currently deployed one... done\n Removed: GET /compare\n Added: GET /versions/{versionId}\n","Store the diff in a dedicated file:\n\n $ bump diff FILE --doc <doc_slug> --token <doc_token> > /tmp/my-saved-diff\n * Comparing the given definition file with the currently deployed one... done\n\n $ cat /tmp/my-saved-diff\n Removed: GET /compare\n Added: GET /versions/{versionId}\n","In case of a non modified definition FILE compared to your existing documentation, no changes are output:\n\n $ bump diff FILE --doc <doc_slug> --token <your_doc_token>\n * Comparing the given definition file with the currently deployed one... done\n › Warning: Your documentation has not changed\n","Compare two different input files or URL independently to the one published on bump.sh\n\n $ bump diff FILE FILE2 --doc <doc_slug> --token <your_doc_token>\n * Comparing the two given definition files... done\n Updated: POST /versions\n Body attribute added: previous_version_id\n"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"doc":{"name":"doc","type":"option","char":"d","description":"Documentation public id or slug. Can be provided via BUMP_ID environment variable"},"hub":{"name":"hub","type":"option","char":"b","description":"Hub id or slug. Can be provided via BUMP_HUB_ID environment variable"},"branch":{"name":"branch","type":"option","char":"B","description":"Branch name. Can be provided via BUMP_BRANCH_NAME environment variable"},"token":{"name":"token","type":"option","char":"t","description":"Documentation or Hub token. Can be provided via BUMP_TOKEN environment variable","required":false,"default":"99f52837852249b328c0a00249f846a3"},"open":{"name":"open","type":"boolean","char":"o","description":"Open the visual diff in your browser","allowNo":false},"fail-on-breaking":{"name":"fail-on-breaking","type":"boolean","char":"F","description":"Fail when diff contains a breaking change","allowNo":false},"format":{"name":"format","type":"option","char":"f","description":"Format in which to provide the diff result","options":["text","markdown","json","html"],"default":"text"},"expires":{"name":"expires","type":"option","char":"e","description":"Specify a longer expiration date for public diffs (defaults to 1 day). Use iso8601 format to provide a date, or you can use `--expires 'never'` to keep the result live indefinitely."}},"args":[{"name":"FILE","description":"Path or URL to your API documentation file. OpenAPI (2.0 to 3.1.0) and AsyncAPI (2.x) specifications are currently supported.\nPath can also be a directory when deploying to a Hub.","required":true},{"name":"FILE2","description":"Path or URL to a second API documentation file to compute its diff"}]},"preview":{"id":"preview","description":"Create a documentation preview from the given file or URL.","pluginName":"bump-cli","pluginType":"core","aliases":[],"examples":["$ bump preview FILE\n* Your preview is visible at: https://bump.sh/preview/45807371-9a32-48a7-b6e4-1cb7088b5b9b\n"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"live":{"name":"live","type":"boolean","char":"l","description":"Generate a preview each time you save the given file","allowNo":false},"open":{"name":"open","type":"boolean","char":"o","description":"Open the generated preview URL in your browser","allowNo":false}},"args":[{"name":"FILE","description":"Path or URL to your API documentation file. OpenAPI (2.0 to 3.1.0) and AsyncAPI (2.x) specifications are currently supported.\nPath can also be a directory when deploying to a Hub.","required":true}]}}}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bump-cli",
|
|
3
3
|
"description": "The Bump CLI is used to interact with your API documentation hosted on Bump by using the API of developers.bump.sh",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.7.0",
|
|
5
5
|
"author": "Paul Bonaud <paulr@bump.sh>",
|
|
6
6
|
"bin": {
|
|
7
7
|
"bump": "./bin/run"
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
"@types/debug": "^4.1.5",
|
|
14
14
|
"@types/mocha": "^10.0.0",
|
|
15
15
|
"@types/node": "^18.11.18",
|
|
16
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
17
|
-
"@typescript-eslint/parser": "^
|
|
16
|
+
"@typescript-eslint/eslint-plugin": "^5.21.0",
|
|
17
|
+
"@typescript-eslint/parser": "^5.21.0",
|
|
18
18
|
"chai": "^4.3.4",
|
|
19
19
|
"cross-spawn": "^7.0.3",
|
|
20
20
|
"eslint": "^7.24.0",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"sinon": "^14.0.0",
|
|
30
30
|
"stdout-stderr": "^0.1.13",
|
|
31
31
|
"ts-node": "^10.0.0",
|
|
32
|
-
"typescript": "
|
|
32
|
+
"typescript": "4.5.5"
|
|
33
33
|
},
|
|
34
34
|
"engines": {
|
|
35
35
|
"node": ">=14.0.0"
|
|
@@ -55,8 +55,13 @@
|
|
|
55
55
|
"commands": "./lib/commands",
|
|
56
56
|
"bin": "bump",
|
|
57
57
|
"plugins": [
|
|
58
|
-
"@oclif/plugin-help"
|
|
59
|
-
|
|
58
|
+
"@oclif/plugin-help",
|
|
59
|
+
"@oclif/plugin-warn-if-update-available"
|
|
60
|
+
],
|
|
61
|
+
"warn-if-update-available": {
|
|
62
|
+
"timeoutInDays": 30,
|
|
63
|
+
"message": "<%= config.name %> update available from <%= chalk.greenBright(config.version) %> to <%= chalk.greenBright(latest) %>. Please upgrade with <%= chalk.underline.dim(`npm update ${config.name}`) %>."
|
|
64
|
+
}
|
|
60
65
|
},
|
|
61
66
|
"repository": "bump-sh/cli",
|
|
62
67
|
"scripts": {
|
|
@@ -78,10 +83,12 @@
|
|
|
78
83
|
"dependencies": {
|
|
79
84
|
"@apidevtools/json-schema-ref-parser": "^9.0.7",
|
|
80
85
|
"@asyncapi/specs": "^4.0.1",
|
|
86
|
+
"@clack/prompts": "^0.6.3",
|
|
81
87
|
"@oclif/command": "^1.8.16",
|
|
82
88
|
"@oclif/config": "^1.17.0",
|
|
83
|
-
"@oclif/core": "
|
|
89
|
+
"@oclif/core": "1.20.4",
|
|
84
90
|
"@oclif/plugin-help": "^5.1.10",
|
|
91
|
+
"@oclif/plugin-warn-if-update-available": "^2.0.36",
|
|
85
92
|
"async-mutex": "^0.4.0",
|
|
86
93
|
"axios": "^0.27.2",
|
|
87
94
|
"debug": "^4.3.1",
|