bump-cli 2.8.4 → 2.9.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 +12 -12
- package/bin/dev.cmd +3 -0
- package/bin/dev.js +6 -0
- package/bin/run.js +5 -0
- package/{lib → dist}/api/error.d.ts +6 -9
- package/dist/api/error.js +97 -0
- package/{lib → dist}/api/index.d.ts +13 -13
- package/dist/api/index.js +46 -0
- package/dist/api/models.js +1 -0
- package/{lib → dist}/api/vars.js +10 -14
- package/dist/args.d.ts +4 -0
- package/{lib → dist}/args.js +11 -15
- package/dist/base-command.d.ts +7 -0
- package/dist/base-command.js +18 -0
- package/dist/commands/deploy.d.ts +24 -0
- package/dist/commands/deploy.js +158 -0
- package/dist/commands/diff.d.ts +21 -0
- package/dist/commands/diff.js +110 -0
- package/dist/commands/overlay.d.ts +13 -0
- package/dist/commands/overlay.js +53 -0
- package/dist/commands/preview.d.ts +15 -0
- package/dist/commands/preview.js +83 -0
- package/{lib/core/definition_directory.d.ts → dist/core/definition-directory.d.ts} +10 -8
- package/dist/core/definition-directory.js +149 -0
- package/{lib → dist}/core/deploy.d.ts +7 -10
- package/{lib → dist}/core/deploy.js +39 -47
- package/{lib → dist}/core/diff.d.ts +12 -15
- package/{lib → dist}/core/diff.js +88 -98
- package/{lib → dist}/core/overlay.d.ts +2 -2
- package/{lib → dist}/core/overlay.js +36 -41
- package/{lib → dist}/core/utils/file.d.ts +4 -4
- package/dist/core/utils/file.js +36 -0
- package/dist/core/utils/prompts.d.ts +1 -0
- package/dist/core/utils/prompts.js +13 -0
- package/{lib → dist}/definition.d.ts +31 -30
- package/dist/definition.js +240 -0
- package/dist/flags.d.ts +48 -0
- package/dist/flags.js +120 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +15 -0
- package/oclif.manifest.json +283 -1
- package/package.json +65 -57
- package/bin/run +0 -5
- package/lib/api/error.js +0 -96
- package/lib/api/index.js +0 -64
- package/lib/api/models.js +0 -2
- package/lib/args.d.ts +0 -15
- package/lib/cli/index.d.ts +0 -31
- package/lib/cli/index.js +0 -14
- package/lib/cli/styled/success.d.ts +0 -1
- package/lib/cli/styled/success.js +0 -11
- package/lib/command.d.ts +0 -9
- package/lib/command.js +0 -31
- package/lib/commands/deploy.d.ts +0 -27
- package/lib/commands/deploy.js +0 -164
- package/lib/commands/diff.d.ts +0 -24
- package/lib/commands/diff.js +0 -119
- package/lib/commands/overlay.d.ts +0 -16
- package/lib/commands/overlay.js +0 -56
- package/lib/commands/preview.d.ts +0 -19
- package/lib/commands/preview.js +0 -83
- package/lib/core/definition_directory.js +0 -138
- package/lib/core/utils/file.js +0 -41
- package/lib/core/utils/prompts.d.ts +0 -1
- package/lib/core/utils/prompts.js +0 -21
- package/lib/definition.js +0 -218
- package/lib/flags.d.ts +0 -20
- package/lib/flags.js +0 -116
- package/lib/index.d.ts +0 -7
- package/lib/index.js +0 -14
- package/{lib → dist}/api/models.d.ts +20 -20
- package/{lib → dist}/api/vars.d.ts +3 -3
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Bump CLI
|
|
2
2
|
|
|
3
3
|
<p align="center">
|
|
4
|
-
<img width="20%" src="https://bump.sh/icon-default-large.png" />
|
|
4
|
+
<img width="20%" src="https://bump.sh/icon-default-maskable-large.png" />
|
|
5
5
|
</p>
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
@@ -32,7 +32,7 @@ Under the hood, it uses the API of [developers.bump.sh](https://developers.bump.
|
|
|
32
32
|
|
|
33
33
|
## Installation
|
|
34
34
|
|
|
35
|
-
The Bump.sh CLI is a node package currently distributed via NPM. This means you must have the Node
|
|
35
|
+
The Bump.sh CLI is a node package currently distributed via NPM. This means you must have the Node v20+ interpreter installed on your computer or CI servers.
|
|
36
36
|
|
|
37
37
|
_If you are looking to use Bump.sh in a continuous integration environment you might be interested by [our Github Action](https://github.com/marketplace/actions/api-documentation-on-bump)._
|
|
38
38
|
|
|
@@ -257,7 +257,7 @@ Please check `bump preview --help` for more usage details
|
|
|
257
257
|
|
|
258
258
|
> This feature implements the [OpenAPI Overlay specification](https://github.com/OAI/Overlay-Specification). It is possible to apply an Overlay to any kind of document, be it an OpenAPI or AsyncAPI definition file.
|
|
259
259
|
|
|
260
|
-
The Overlay specification of OpenAPI makes it possible to modify the content of an API definition file by adding a layer on top of it. That layer helps add, remove, or change some or all of the content of the original definition.
|
|
260
|
+
The Overlay specification of OpenAPI makes it possible to modify the content of an API definition file by adding a layer on top of it. That layer helps add, remove, or change some or all of the content of the original definition.
|
|
261
261
|
|
|
262
262
|
Technically, the `bump overlay` command will output a modified version of the `[DEFINITION_FILE]` (an OpenAPI or AsyncAPI document) by applying the operations described in the `[OVERLAY_FILE]` Overlay file to the original API document.
|
|
263
263
|
|
|
@@ -270,34 +270,34 @@ bump overlay api-document.yaml overlay-file.yaml > api-overlayed-document.yaml
|
|
|
270
270
|
_Note: you can also apply the overlay during the [`bump deploy` command]((#bump-deploy-file)) with the new `--overlay` flag:_
|
|
271
271
|
|
|
272
272
|
```shell
|
|
273
|
-
bump deploy api-document.yaml --doc my-doc --token my-token --overlay overlay-file.yaml
|
|
273
|
+
bump deploy api-document.yaml --doc my-doc --token my-token --overlay overlay-file.yaml
|
|
274
274
|
```
|
|
275
275
|
|
|
276
276
|
## Development
|
|
277
277
|
|
|
278
|
-
Make sure to have Node.js (At least
|
|
278
|
+
Make sure to have Node.js (At least v20) installed on your machine.
|
|
279
279
|
|
|
280
280
|
- Install node dependencies with
|
|
281
|
-
|
|
281
|
+
|
|
282
282
|
```sh-session
|
|
283
283
|
npm install
|
|
284
284
|
```
|
|
285
|
-
|
|
285
|
+
|
|
286
286
|
- Compile the Typescript code
|
|
287
|
-
|
|
287
|
+
|
|
288
288
|
```sh-session
|
|
289
289
|
npm run build
|
|
290
290
|
npm run clean # to remove build artifacts
|
|
291
291
|
```
|
|
292
|
-
|
|
292
|
+
|
|
293
293
|
- Format the codebase to comply with the linter rules
|
|
294
|
-
|
|
294
|
+
|
|
295
295
|
```sh-session
|
|
296
296
|
npm run fmt
|
|
297
297
|
```
|
|
298
|
-
|
|
298
|
+
|
|
299
299
|
- Run the test suites
|
|
300
|
-
|
|
300
|
+
|
|
301
301
|
```sh-session
|
|
302
302
|
npm run test
|
|
303
303
|
npm run test-coverage # Run tests with coverage
|
package/bin/dev.cmd
ADDED
package/bin/dev.js
ADDED
package/bin/run.js
ADDED
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import { CLIError } from '@oclif/errors';
|
|
1
|
+
import { CLIError } from '@oclif/core/errors';
|
|
2
2
|
import { AxiosError } from 'axios';
|
|
3
|
-
import { InvalidDefinitionError } from './models';
|
|
4
|
-
|
|
3
|
+
import { InvalidDefinitionError } from './models.js';
|
|
4
|
+
type MessagesAndExitCode = [string[], number];
|
|
5
5
|
export default class APIError extends CLIError {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
constructor(httpError: AxiosError, info?: string[], exit?: number);
|
|
6
|
+
constructor(httpError?: AxiosError | undefined, info?: string[], exit?: number);
|
|
7
|
+
static humanAttributeError(attribute: string, messages: unknown): string[];
|
|
8
|
+
static invalidDefinition(error: InvalidDefinitionError): MessagesAndExitCode;
|
|
10
9
|
static is(error: Error): error is APIError;
|
|
11
10
|
static notFound(error: Error): MessagesAndExitCode;
|
|
12
|
-
static invalidDefinition(error: InvalidDefinitionError): MessagesAndExitCode;
|
|
13
|
-
static humanAttributeError(attribute: string, messages: unknown): string[];
|
|
14
11
|
static unauthenticated(): MessagesAndExitCode;
|
|
15
12
|
}
|
|
16
13
|
export {};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { CLIError } from '@oclif/core/errors';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import d from 'debug';
|
|
4
|
+
const debug = d('bump-cli:api-client');
|
|
5
|
+
export default class APIError extends CLIError {
|
|
6
|
+
constructor(httpError, info = [], exit = 100) {
|
|
7
|
+
const status = httpError?.response?.status;
|
|
8
|
+
debug(httpError);
|
|
9
|
+
if (httpError) {
|
|
10
|
+
switch (status) {
|
|
11
|
+
case 422: {
|
|
12
|
+
;
|
|
13
|
+
[info, exit] = APIError.invalidDefinition(httpError.response?.data);
|
|
14
|
+
break;
|
|
15
|
+
}
|
|
16
|
+
case 401: {
|
|
17
|
+
;
|
|
18
|
+
[info, exit] = APIError.unauthenticated();
|
|
19
|
+
break;
|
|
20
|
+
}
|
|
21
|
+
case 404:
|
|
22
|
+
case 400: {
|
|
23
|
+
;
|
|
24
|
+
[info, exit] = APIError.notFound(httpError.response?.data);
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (info.length > 0) {
|
|
29
|
+
super(info.join('\n'), { exit });
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
super(`Unhandled API error (status: ${status}) (error: ${httpError})`, { exit });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
super('Unhandled API error', { exit });
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
static humanAttributeError(attribute, messages) {
|
|
40
|
+
let info = [];
|
|
41
|
+
if (Array.isArray(messages)) {
|
|
42
|
+
const allMessages = messages
|
|
43
|
+
.map((message, idx) => {
|
|
44
|
+
if (message instanceof Object) {
|
|
45
|
+
return this.humanAttributeError(idx.toString(), message);
|
|
46
|
+
}
|
|
47
|
+
return message;
|
|
48
|
+
})
|
|
49
|
+
.join(', ');
|
|
50
|
+
info.push(`${chalk.underline(attribute)} ${allMessages}`);
|
|
51
|
+
}
|
|
52
|
+
else if (messages instanceof Object) {
|
|
53
|
+
for (const [child, childMessages] of Object.entries(messages)) {
|
|
54
|
+
const childErrors = this.humanAttributeError(`${attribute}.${child}`, childMessages);
|
|
55
|
+
info = [...info, ...childErrors];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else if (messages) {
|
|
59
|
+
info.push(`${chalk.underline(attribute)} ${messages}`);
|
|
60
|
+
}
|
|
61
|
+
return info;
|
|
62
|
+
}
|
|
63
|
+
static invalidDefinition(error) {
|
|
64
|
+
let info = [];
|
|
65
|
+
const genericMessage = error.message || 'Invalid definition file';
|
|
66
|
+
const exit = 122;
|
|
67
|
+
if (error && 'errors' in error) {
|
|
68
|
+
for (const [attr, message] of Object.entries(error.errors)) {
|
|
69
|
+
const humanErrors = APIError.humanAttributeError(attr, message);
|
|
70
|
+
info = [...info, ...humanErrors];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
info.push(genericMessage);
|
|
75
|
+
}
|
|
76
|
+
return [info, exit];
|
|
77
|
+
}
|
|
78
|
+
static is(error) {
|
|
79
|
+
return error instanceof CLIError && 'http' in error;
|
|
80
|
+
}
|
|
81
|
+
static notFound(error) {
|
|
82
|
+
const genericMessage = error.message || "It seems the documentation provided doesn't exist.";
|
|
83
|
+
return [
|
|
84
|
+
[
|
|
85
|
+
genericMessage,
|
|
86
|
+
`In a hub context you might want to try the ${chalk.dim('--auto-create')} flag.\nOtherwise, please check the given ${chalk.dim('--doc')}, ${chalk.dim('--token')} or ${chalk.dim('--hub')} flags`,
|
|
87
|
+
],
|
|
88
|
+
104,
|
|
89
|
+
];
|
|
90
|
+
}
|
|
91
|
+
static unauthenticated() {
|
|
92
|
+
return [
|
|
93
|
+
['You are not allowed to deploy to this documentation.', 'please check your --token flag or BUMP_TOKEN variable'],
|
|
94
|
+
101,
|
|
95
|
+
];
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Config } from '@oclif/core';
|
|
2
2
|
import { AxiosInstance, AxiosResponse } from 'axios';
|
|
3
|
-
import { PingResponse, PreviewRequest, PreviewResponse, VersionRequest, VersionResponse,
|
|
4
|
-
import APIError from './error';
|
|
3
|
+
import { DiffRequest, DiffResponse, PingResponse, PreviewRequest, PreviewResponse, VersionRequest, VersionResponse, WithDiff } from './models.js';
|
|
5
4
|
declare class BumpApi {
|
|
6
|
-
protected config: Config
|
|
5
|
+
protected config: Config;
|
|
7
6
|
protected readonly client: AxiosInstance;
|
|
8
|
-
|
|
7
|
+
getDiff: (diffId: string, format: string) => Promise<AxiosResponse<DiffResponse>>;
|
|
9
8
|
getPing: () => Promise<AxiosResponse<PingResponse>>;
|
|
10
9
|
getVersion: (versionId: string, token: string) => Promise<AxiosResponse<VersionResponse & WithDiff>>;
|
|
11
|
-
postPreview: (body?: PreviewRequest | undefined) => Promise<AxiosResponse<PreviewResponse>>;
|
|
12
|
-
putPreview: (versionId: string, body?: PreviewRequest | undefined) => Promise<AxiosResponse<PreviewResponse>>;
|
|
13
|
-
postVersion: (body: VersionRequest, token: string) => Promise<AxiosResponse<VersionResponse>>;
|
|
14
10
|
postDiff: (body: DiffRequest) => Promise<AxiosResponse<DiffResponse>>;
|
|
15
|
-
|
|
11
|
+
postPreview: (body?: PreviewRequest) => Promise<AxiosResponse<PreviewResponse>>;
|
|
16
12
|
postValidation: (body: VersionRequest, token: string) => Promise<AxiosResponse<void>>;
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
postVersion: (body: VersionRequest, token: string) => Promise<AxiosResponse<VersionResponse>>;
|
|
14
|
+
putPreview: (versionId: string, body?: PreviewRequest) => Promise<AxiosResponse<PreviewResponse>>;
|
|
19
15
|
private authorizationHeader;
|
|
16
|
+
private handleError;
|
|
17
|
+
private initializeResponseInterceptor;
|
|
18
|
+
constructor(config: Config);
|
|
20
19
|
}
|
|
21
|
-
export
|
|
22
|
-
export { BumpApi
|
|
20
|
+
export { default as APIError } from './error.js';
|
|
21
|
+
export { BumpApi };
|
|
22
|
+
export * from './models.js';
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import APIError from './error.js';
|
|
3
|
+
import { vars } from './vars.js';
|
|
4
|
+
class BumpApi {
|
|
5
|
+
config;
|
|
6
|
+
client;
|
|
7
|
+
getDiff = (diffId, format) => this.client.get(`/diffs/${diffId}`, {
|
|
8
|
+
params: { formats: [format] },
|
|
9
|
+
});
|
|
10
|
+
getPing = () => this.client.get('/ping');
|
|
11
|
+
getVersion = (versionId, token) => this.client.get(`/versions/${versionId}`, {
|
|
12
|
+
headers: this.authorizationHeader(token),
|
|
13
|
+
});
|
|
14
|
+
postDiff = (body) => this.client.post('/diffs', body);
|
|
15
|
+
postPreview = (body) => this.client.post('/previews', body);
|
|
16
|
+
postValidation = (body, token) => this.client.post('/validations', body, {
|
|
17
|
+
headers: this.authorizationHeader(token),
|
|
18
|
+
});
|
|
19
|
+
postVersion = (body, token) => this.client.post('/versions', body, {
|
|
20
|
+
headers: this.authorizationHeader(token),
|
|
21
|
+
});
|
|
22
|
+
putPreview = (versionId, body) => this.client.put(`/previews/${versionId}`, body);
|
|
23
|
+
authorizationHeader = (token) => ({
|
|
24
|
+
Authorization: `Basic ${Buffer.from(token).toString('base64')}`,
|
|
25
|
+
});
|
|
26
|
+
handleError = (error) => Promise.reject(new APIError(error));
|
|
27
|
+
initializeResponseInterceptor = () => {
|
|
28
|
+
this.client.interceptors.response.use((data) => data, this.handleError);
|
|
29
|
+
};
|
|
30
|
+
// Check https://oclif.io/docs/config for details about Config.IConfig
|
|
31
|
+
constructor(config) {
|
|
32
|
+
this.config = config;
|
|
33
|
+
const baseURL = `${vars.apiUrl}${vars.apiBasePath}`;
|
|
34
|
+
const headers = {
|
|
35
|
+
'User-Agent': vars.apiUserAgent(config.userAgent),
|
|
36
|
+
};
|
|
37
|
+
this.client = axios.create({
|
|
38
|
+
baseURL,
|
|
39
|
+
headers,
|
|
40
|
+
});
|
|
41
|
+
this.initializeResponseInterceptor();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export { default as APIError } from './error.js';
|
|
45
|
+
export { BumpApi };
|
|
46
|
+
export * from './models.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/{lib → dist}/api/vars.js
RENAMED
|
@@ -1,23 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
get
|
|
6
|
-
return this.
|
|
1
|
+
export class Vars {
|
|
2
|
+
get apiBasePath() {
|
|
3
|
+
return '/api/v1';
|
|
4
|
+
}
|
|
5
|
+
get apiUrl() {
|
|
6
|
+
return this.host.startsWith('http') ? this.host : `https://${this.host}`;
|
|
7
7
|
}
|
|
8
8
|
get envHost() {
|
|
9
9
|
return process.env.BUMP_HOST;
|
|
10
10
|
}
|
|
11
|
+
get host() {
|
|
12
|
+
return this.envHost || 'bump.sh';
|
|
13
|
+
}
|
|
11
14
|
apiUserAgent(base) {
|
|
12
15
|
const content = [base, process.env.BUMP_USER_AGENT].filter(Boolean);
|
|
13
16
|
return content.join(' ');
|
|
14
17
|
}
|
|
15
|
-
get apiUrl() {
|
|
16
|
-
return this.host.startsWith('http') ? this.host : `https://${this.host}`;
|
|
17
|
-
}
|
|
18
|
-
get apiBasePath() {
|
|
19
|
-
return '/api/v1';
|
|
20
|
-
}
|
|
21
18
|
}
|
|
22
|
-
|
|
23
|
-
exports.vars = new Vars();
|
|
19
|
+
export const vars = new Vars();
|
package/dist/args.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
declare const fileArg: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
2
|
+
declare const otherFileArg: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
3
|
+
declare const overlayFileArg: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
4
|
+
export { fileArg, otherFileArg, overlayFileArg };
|
package/{lib → dist}/args.js
RENAMED
|
@@ -1,20 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const fileArg = {
|
|
1
|
+
import { Args } from '@oclif/core';
|
|
2
|
+
const fileArg = Args.string({
|
|
3
|
+
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.',
|
|
5
4
|
name: 'FILE',
|
|
6
5
|
required: true,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
exports.fileArg = fileArg;
|
|
10
|
-
const otherFileArg = {
|
|
11
|
-
name: 'FILE2',
|
|
6
|
+
});
|
|
7
|
+
const otherFileArg = Args.string({
|
|
12
8
|
description: 'Path or URL to a second API documentation file to compute its diff',
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const overlayFileArg = {
|
|
9
|
+
name: 'FILE2',
|
|
10
|
+
});
|
|
11
|
+
const overlayFileArg = Args.string({
|
|
12
|
+
description: 'Path or URL to an overlay file',
|
|
16
13
|
name: 'OVERLAY_FILE',
|
|
17
14
|
required: true,
|
|
18
|
-
|
|
19
|
-
};
|
|
20
|
-
exports.overlayFileArg = overlayFileArg;
|
|
15
|
+
});
|
|
16
|
+
export { fileArg, otherFileArg, overlayFileArg };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import { BumpApi } from './api/index.js';
|
|
3
|
+
export declare abstract class BaseCommand<T extends typeof Command> extends Command {
|
|
4
|
+
protected _bump: BumpApi;
|
|
5
|
+
protected get bump(): BumpApi;
|
|
6
|
+
protected d(formatter: any, ...args: any[]): void;
|
|
7
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import debug from 'debug';
|
|
3
|
+
import { BumpApi } from './api/index.js';
|
|
4
|
+
/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
|
|
5
|
+
export class BaseCommand extends Command {
|
|
6
|
+
_bump;
|
|
7
|
+
get bump() {
|
|
8
|
+
if (!this._bump)
|
|
9
|
+
this._bump = new BumpApi(this.config);
|
|
10
|
+
return this._bump;
|
|
11
|
+
}
|
|
12
|
+
// Function signature type taken from @types/debug
|
|
13
|
+
// Debugger(formatter: any, ...args: any[]): void;
|
|
14
|
+
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
|
15
|
+
d(formatter, ...args) {
|
|
16
|
+
return debug(`bump-cli:command:${this.constructor.name.toLowerCase()}`)(formatter, ...args);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { BaseCommand } from '../base-command.js';
|
|
2
|
+
import { API } from '../definition.js';
|
|
3
|
+
export default class Deploy extends BaseCommand<typeof Deploy> {
|
|
4
|
+
static args: {
|
|
5
|
+
file: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
+
};
|
|
7
|
+
static description: string;
|
|
8
|
+
static examples: string[];
|
|
9
|
+
static flags: {
|
|
10
|
+
'auto-create': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
branch: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
doc: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
'doc-name': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
|
+
'filename-pattern': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
hub: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
|
+
interactive: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
18
|
+
overlay: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
|
+
token: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
20
|
+
};
|
|
21
|
+
protected deployDirectory(dir: string, dryRun: boolean, token: string, hub: string, autoCreate: boolean, interactive: boolean, filenamePattern: string, documentationName: string | undefined, branch: string | undefined): Promise<void>;
|
|
22
|
+
protected deploySingleFile(api: API, dryRun: boolean, documentation: string, token: string, hub: string | undefined, autoCreate: boolean, documentationName: string | undefined, branch: string | undefined, overlay?: string | undefined): Promise<void>;
|
|
23
|
+
run(): Promise<void>;
|
|
24
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { ux } from '@oclif/core';
|
|
2
|
+
import { CLIError } from '@oclif/core/errors';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { fileArg } from '../args.js';
|
|
5
|
+
import { BaseCommand } from '../base-command.js';
|
|
6
|
+
import { DefinitionDirectory } from '../core/definition-directory.js';
|
|
7
|
+
import { Deploy as CoreDeploy } from '../core/deploy.js';
|
|
8
|
+
import { isDir } from '../core/utils/file.js';
|
|
9
|
+
import { confirm as promptConfirm } from '../core/utils/prompts.js';
|
|
10
|
+
import { API } from '../definition.js';
|
|
11
|
+
import * as flagsBuilder from '../flags.js';
|
|
12
|
+
export default class Deploy extends BaseCommand {
|
|
13
|
+
static args = { file: fileArg };
|
|
14
|
+
static description = 'Create a new version of your documentation from the given file or URL.';
|
|
15
|
+
static examples = [
|
|
16
|
+
`Deploy a new version of ${chalk.underline('an existing documentation')}
|
|
17
|
+
|
|
18
|
+
${chalk.dim('$ bump deploy FILE --doc <your_doc_id_or_slug> --token <your_doc_token>')}
|
|
19
|
+
* Let's deploy on Bump.sh... done
|
|
20
|
+
* Your new documentation version will soon be ready
|
|
21
|
+
`,
|
|
22
|
+
`Deploy a new version of ${chalk.underline('an existing documentation attached to a hub')}
|
|
23
|
+
|
|
24
|
+
${chalk.dim('$ bump deploy FILE --doc <doc_slug> --hub <your_hub_id_or_slug> --token <your_doc_token>')}
|
|
25
|
+
* Let's deploy on Bump.sh... done
|
|
26
|
+
* Your new documentation version will soon be ready
|
|
27
|
+
`,
|
|
28
|
+
`Deploy a whole directory of ${chalk.underline('API definitions files to a hub')}
|
|
29
|
+
|
|
30
|
+
${chalk.dim('$ bump deploy DIR --filename-pattern *-{slug}-api --hub <hub_slug> --token <hub_token>')}
|
|
31
|
+
We've found 2 valid API definitions to deploy
|
|
32
|
+
└─ DIR
|
|
33
|
+
└─ source-my-service-api.yml (OpenAPI spec version 3.1.0)
|
|
34
|
+
└─ source-my-jobs-service-api.yml (AsyncAPI spec version 2.6.0)
|
|
35
|
+
|
|
36
|
+
Let's deploy those documentations to your <hub_slug> hub on Bump.sh
|
|
37
|
+
|
|
38
|
+
* Your new documentation version will soon be ready
|
|
39
|
+
Let's deploy a new version to your my-service documentation on Bump.sh... done
|
|
40
|
+
|
|
41
|
+
* Your new documentation version will soon be ready
|
|
42
|
+
Let's deploy a new version to your my-jobs-service documentation on Bump.sh... done
|
|
43
|
+
`,
|
|
44
|
+
`${chalk.underline('Validate a new documentation version')} before deploying it
|
|
45
|
+
|
|
46
|
+
${chalk.dim('$ bump deploy FILE --dry-run --doc <doc_slug> --token <your_doc_token>')}
|
|
47
|
+
* Let's validate on Bump.sh... done
|
|
48
|
+
* Definition is valid
|
|
49
|
+
`,
|
|
50
|
+
];
|
|
51
|
+
static flags = {
|
|
52
|
+
'auto-create': flagsBuilder.autoCreate(),
|
|
53
|
+
branch: flagsBuilder.branch(),
|
|
54
|
+
doc: flagsBuilder.doc(),
|
|
55
|
+
'doc-name': flagsBuilder.docName(),
|
|
56
|
+
'dry-run': flagsBuilder.dryRun(),
|
|
57
|
+
'filename-pattern': flagsBuilder.filenamePattern(),
|
|
58
|
+
hub: flagsBuilder.hub(),
|
|
59
|
+
interactive: flagsBuilder.interactive(),
|
|
60
|
+
overlay: flagsBuilder.overlay(),
|
|
61
|
+
token: flagsBuilder.token(),
|
|
62
|
+
};
|
|
63
|
+
async deployDirectory(dir, dryRun, token, hub, autoCreate, interactive, filenamePattern, documentationName, branch) {
|
|
64
|
+
const definitionDirectory = new DefinitionDirectory(dir, filenamePattern);
|
|
65
|
+
await definitionDirectory.readDefinitions();
|
|
66
|
+
await ux.action.pauseAsync(async () => {
|
|
67
|
+
definitionDirectory.stdoutDefinitions();
|
|
68
|
+
// In “interactive” mode we ask the user if he wants to add more
|
|
69
|
+
// definitions to deploy. He is thus presented a form to select
|
|
70
|
+
// some files from the target directory.
|
|
71
|
+
if (interactive) {
|
|
72
|
+
let confirm = true;
|
|
73
|
+
if (definitionDirectory.definitionsExists()) {
|
|
74
|
+
confirm = await promptConfirm('Do you want to add more files to deploy?');
|
|
75
|
+
}
|
|
76
|
+
if (confirm) {
|
|
77
|
+
await ux.action.pauseAsync(async () => {
|
|
78
|
+
await definitionDirectory.interactiveSelection();
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
if (definitionDirectory.definitionsExists()) {
|
|
84
|
+
await ux.action.pauseAsync(async () => {
|
|
85
|
+
definitionDirectory.stdoutDefinitions();
|
|
86
|
+
if (interactive) {
|
|
87
|
+
await definitionDirectory.sequentialMap(async (definition) => {
|
|
88
|
+
await definitionDirectory.renameToConvention(definition);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
ux.action.status = `...to your ${hub} hub on Bump.sh`;
|
|
93
|
+
await definitionDirectory.sequentialMap(async (definition) => {
|
|
94
|
+
await this.deploySingleFile(definition.definition, dryRun, definition.slug, token, hub, autoCreate, definition.slug || documentationName, branch);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
throw new CLIError(`No documentation found in ${dir} with the pattern '${filenamePattern}'.\nYou should check with the ${chalk.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.dim('--interactive')} flag for that.`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
async deploySingleFile(api, dryRun, documentation, token, hub, autoCreate, documentationName, branch, overlay) {
|
|
102
|
+
ux.action.status = `...a new version to your ${documentation} documentation`;
|
|
103
|
+
const response = await new CoreDeploy(this.bump).run(api, dryRun, documentation, token, hub, autoCreate, documentationName, branch, overlay);
|
|
104
|
+
if (dryRun) {
|
|
105
|
+
ux.stdout(ux.colorize('green', 'Definition is valid'));
|
|
106
|
+
}
|
|
107
|
+
else if (response) {
|
|
108
|
+
process.stdout.write(ux.colorize('green', `Your ${documentation} documentation...`));
|
|
109
|
+
ux.stdout(ux.colorize('green', `has received a new deployment which will soon be ready at:`));
|
|
110
|
+
ux.stdout(ux.colorize('underline', response.doc_public_url));
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
ux.warn(`Your ${documentation} documentation has not changed`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/*
|
|
117
|
+
Oclif doesn't type parsed args & flags correctly and especially
|
|
118
|
+
required-ness which is not known by the compiler, thus the use of
|
|
119
|
+
the non-null assertion '!' in this command.
|
|
120
|
+
See https://github.com/oclif/oclif/issues/301 for details
|
|
121
|
+
*/
|
|
122
|
+
async run() {
|
|
123
|
+
const { args, flags } = await this.parse(Deploy);
|
|
124
|
+
const [dryRun, documentation, token, hub, autoCreate, interactive, filenamePattern, documentationName, branch, overlay,] = [
|
|
125
|
+
flags['dry-run'],
|
|
126
|
+
flags.doc,
|
|
127
|
+
flags.token,
|
|
128
|
+
flags.hub,
|
|
129
|
+
flags['auto-create'],
|
|
130
|
+
flags.interactive,
|
|
131
|
+
/* Flags.filenamePattern has a default value, so it's always defined. But
|
|
132
|
+
* oclif types doesn't detect it */
|
|
133
|
+
flags['filename-pattern'],
|
|
134
|
+
flags['doc-name'],
|
|
135
|
+
flags.branch,
|
|
136
|
+
flags.overlay,
|
|
137
|
+
];
|
|
138
|
+
const action = dryRun ? 'validate' : 'deploy';
|
|
139
|
+
ux.action.start(`Let's ${action} on Bump.sh`);
|
|
140
|
+
if (isDir(args.file)) {
|
|
141
|
+
if (hub) {
|
|
142
|
+
await this.deployDirectory(args.file, dryRun, token, hub, autoCreate, interactive, filenamePattern, documentationName, branch);
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
throw new CLIError('Missing required flag --hub when deploying an entire directory');
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
else if (documentation) {
|
|
149
|
+
const api = await API.load(args.file);
|
|
150
|
+
this.d(`${args.file} looks like an ${api.specName} spec version ${api.version}`);
|
|
151
|
+
await this.deploySingleFile(api, dryRun, documentation, token, hub, autoCreate, documentationName, branch, overlay);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
throw new CLIError('Missing required flag --doc=<slug>');
|
|
155
|
+
}
|
|
156
|
+
ux.action.stop();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { DiffResponse } from '../api/models.js';
|
|
2
|
+
import { BaseCommand } from '../base-command.js';
|
|
3
|
+
export default class Diff extends BaseCommand<typeof Diff> {
|
|
4
|
+
static args: {
|
|
5
|
+
file: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
+
otherFile: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static description: string;
|
|
9
|
+
static examples: string[];
|
|
10
|
+
static flags: {
|
|
11
|
+
branch: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
doc: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
expires: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
'fail-on-breaking': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
|
+
format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
hub: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
|
+
token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
|
+
};
|
|
19
|
+
displayCompareResult(result: DiffResponse, format: string, failOnBreaking: boolean): Promise<void>;
|
|
20
|
+
run(): Promise<void>;
|
|
21
|
+
}
|