bump-cli 2.6.0 → 2.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -104,6 +104,12 @@ If you already have a hub in your [Bump.sh](https://bump.sh) account, you can au
104
104
  $ bump deploy path/to/your/file.yml --auto-create --doc DOC_SLUG --hub HUB_ID_OR_SLUG --token HUB_TOKEN
105
105
  ```
106
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
+
107
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:
108
114
 
109
115
  ```sh-session
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
- `Please check the given ${chalk_1.default.underline('--documentation')}, ${chalk_1.default.underline('--token')} or ${chalk_1.default.underline('--hub')} flags`,
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 = {
@@ -1,16 +1,18 @@
1
1
  import Command from '../command';
2
- import * as flags from '../flags';
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: flags.IOptionFlag<string | undefined>;
9
- 'doc-name': flags.IOptionFlag<string | undefined>;
10
- hub: flags.IOptionFlag<string | undefined>;
11
- branch: flags.IOptionFlag<string | undefined>;
12
- token: flags.IOptionFlag<string | undefined>;
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
  }
@@ -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 definition_1 = require("../definition");
4
+ const chalk_1 = (0, tslib_1.__importDefault)(require("chalk"));
5
+ const errors_1 = require("@oclif/parser/lib/errors");
6
+ const errors_2 = require("@oclif/errors");
5
7
  const command_1 = (0, tslib_1.__importDefault)(require("../command"));
6
- const flags = (0, tslib_1.__importStar)(require("../flags"));
8
+ const flagsBuilder = (0, tslib_1.__importStar)(require("../flags"));
9
+ const definition_directory_1 = require("../core/definition_directory");
10
+ const deploy_1 = require("../core/deploy");
11
+ const prompts_1 = require("../core/utils/prompts");
12
+ const file_1 = require("../core/utils/file");
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,141 @@ class Deploy extends command_1.default {
15
22
  */
16
23
  async run() {
17
24
  const { args, flags } = this.parse(Deploy);
18
- const api = await definition_1.API.load(args.FILE);
19
- const [definition, references] = api.extractDefinition();
20
- const action = flags['dry-run'] ? 'validate' : 'deploy';
21
- /* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */
22
- const [documentation, token] = [flags.doc, flags.token];
23
- this.d(`${args.FILE} looks like an ${api.specName} spec version ${api.version}`);
24
- cli_1.cli.action.start(`* Let's ${action} a new documentation version on Bump`);
25
- const request = {
26
- documentation,
27
- hub: flags.hub,
28
- documentation_name: flags['doc-name'],
29
- auto_create_documentation: flags['auto-create'] && !flags['dry-run'],
30
- definition,
31
- references,
32
- branch_name: flags.branch,
33
- };
34
- const response = flags['dry-run']
35
- ? await this.bump.postValidation(request, token)
36
- : await this.bump.postVersion(request, token);
37
- cli_1.cli.action.stop();
38
- switch (response.status) {
39
- case 200:
40
- cli_1.cli.styledSuccess('Definition is valid');
41
- break;
42
- case 201:
43
- const version = response.data
44
- ? response.data
45
- : { id: '', doc_public_url: 'https://bump.sh' };
46
- cli_1.cli.styledSuccess(`Your new documentation version will soon be ready at ${version.doc_public_url}`);
47
- break;
48
- case 204:
49
- this.warn('Your documentation has not changed');
50
- break;
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
+ if ((0, file_1.isDir)(args.FILE)) {
41
+ if (hub) {
42
+ await this.deployDirectory(args.FILE, dryRun, token, hub, autoCreate, interactive, filenamePattern, documentationName, branch);
43
+ }
44
+ else {
45
+ throw new errors_1.RequiredFlagError({ flag: Deploy.flags.hub, parse: {} });
46
+ }
47
+ }
48
+ else {
49
+ if (documentation) {
50
+ const api = await definition_1.API.load(args.FILE);
51
+ this.d(`${args.FILE} looks like an ${api.specName} spec version ${api.version}`);
52
+ await this.deploySingleFile(api, dryRun, documentation, token, hub, autoCreate, documentationName, branch);
53
+ }
54
+ else {
55
+ throw new errors_1.RequiredFlagError({ flag: Deploy.flags.doc, parse: {} });
56
+ }
51
57
  }
52
58
  return;
53
59
  }
60
+ async deployDirectory(dir, dryRun, token, hub, autoCreate, interactive, filenamePattern, documentationName, branch) {
61
+ const definitionDirectory = new definition_directory_1.DefinitionDirectory(dir, filenamePattern);
62
+ const action = dryRun ? 'validate' : 'deploy';
63
+ await definitionDirectory.readDefinitions();
64
+ // In “interactive” mode we ask the user if he wants to add more
65
+ // definitions to deploy. He is thus presented a form to select
66
+ // some files from the target directory.
67
+ if (interactive) {
68
+ let confirm = true;
69
+ if (definitionDirectory.definitionsExists()) {
70
+ await (0, prompts_1.confirm)('Do you want to add more files to deploy?').catch(() => {
71
+ confirm = false;
72
+ });
73
+ }
74
+ if (confirm) {
75
+ await definitionDirectory.interactiveSelection();
76
+ }
77
+ }
78
+ if (definitionDirectory.definitionsExists()) {
79
+ cli_1.cli.info(chalk_1.default.underline(`Let's ${action} those documentations to your ${hub} hub on Bump.sh`));
80
+ await definitionDirectory.sequentialMap(async (definition) => {
81
+ if (interactive) {
82
+ await definitionDirectory.renameToConvention(definition);
83
+ }
84
+ await this.deploySingleFile(definition.definition, dryRun, definition.slug, token, hub, autoCreate, definition.slug || documentationName, branch);
85
+ return definition;
86
+ });
87
+ }
88
+ else {
89
+ 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.`);
90
+ }
91
+ return;
92
+ }
93
+ async deploySingleFile(api, dryRun, documentation, token, hub, autoCreate, documentationName, branch) {
94
+ const action = dryRun ? 'validate' : 'deploy';
95
+ cli_1.cli.action.start(`Let's ${action} a new version to your ${documentation} documentation on Bump.sh`);
96
+ const response = await new deploy_1.Deploy(this.config).run(api, dryRun, documentation, token, hub, autoCreate, documentationName, branch);
97
+ if (dryRun) {
98
+ await cli_1.cli.styledSuccess('Definition is valid');
99
+ }
100
+ else {
101
+ if (response) {
102
+ await cli_1.cli.styledSuccess(`Your new documentation version will soon be ready at ${response.doc_public_url}`);
103
+ }
104
+ else {
105
+ await cli_1.cli.warn('Your documentation has not changed');
106
+ }
107
+ }
108
+ cli_1.cli.action.stop();
109
+ return;
110
+ }
54
111
  }
55
112
  exports.default = Deploy;
56
113
  Deploy.description = 'Create a new version of your documentation from the given file or URL.';
57
114
  Deploy.examples = [
58
- `Deploy a new version of an existing documentation
115
+ `Deploy a new version of ${chalk_1.default.underline('an existing documentation')}
59
116
 
60
- $ bump deploy FILE --doc <your_doc_id_or_slug> --token <your_doc_token>
117
+ ${chalk_1.default.dim('$ bump deploy FILE --doc <your_doc_id_or_slug> --token <your_doc_token>')}
61
118
  * Let's deploy a new documentation version on Bump... done
62
119
  * Your new documentation version will soon be ready
63
120
  `,
64
- `Deploy a new version of an existing documentation attached to a hub
121
+ `Deploy a new version of ${chalk_1.default.underline('an existing documentation attached to a hub')}
65
122
 
66
- $ bump deploy FILE --doc <doc_slug> --hub <your_hub_id_or_slug> --token <your_doc_token>
123
+ ${chalk_1.default.dim('$ bump deploy FILE --doc <doc_slug> --hub <your_hub_id_or_slug> --token <your_doc_token>')}
67
124
  * Let's deploy a new documentation version on Bump... done
68
125
  * Your new documentation version will soon be ready
69
126
  `,
70
- `Validate a new documentation version before deploying it
127
+ `Deploy a whole directory of ${chalk_1.default.underline('API definitions files to a hub')}
128
+
129
+ ${chalk_1.default.dim('$ bump deploy DIR --filename-pattern *-{slug}-api --hub <hub_slug> --token <hub_token>')}
130
+ We've found 2 valid API definitions to deploy
131
+ └─ DIR
132
+ └─ source-my-service-api.yml (OpenAPI spec version 3.1.0)
133
+ └─ source-my-jobs-service-api.yml (AsyncAPI spec version 2.6.0)
134
+
135
+ Let's deploy those documentations to your <hub_slug> hub on Bump.sh
136
+
137
+ * Your new documentation version will soon be ready
138
+ Let's deploy a new version to your my-service documentation on Bump.sh... done
139
+
140
+ * Your new documentation version will soon be ready
141
+ Let's deploy a new version to your my-jobs-service documentation on Bump.sh... done
142
+ `,
143
+ `${chalk_1.default.underline('Validate a new documentation version')} before deploying it
71
144
 
72
- $ bump deploy FILE --dry-run --doc <doc_slug> --token <your_doc_token>
145
+ ${chalk_1.default.dim('$ bump deploy FILE --dry-run --doc <doc_slug> --token <your_doc_token>')}
73
146
  * Let's validate a new documentation version on Bump... done
74
147
  * Definition is valid
75
148
  `,
76
149
  ];
77
150
  Deploy.flags = {
78
- help: flags.help({ char: 'h' }),
79
- doc: flags.doc(),
80
- 'doc-name': flags.docName(),
81
- hub: flags.hub(),
82
- branch: flags.branch(),
83
- token: flags.token(),
84
- 'auto-create': flags.autoCreate(),
85
- 'dry-run': flags.dryRun(),
151
+ help: flagsBuilder.help({ char: 'h' }),
152
+ doc: flagsBuilder.doc(),
153
+ 'doc-name': flagsBuilder.docName(),
154
+ hub: flagsBuilder.hub(),
155
+ branch: flagsBuilder.branch(),
156
+ token: flagsBuilder.token(),
157
+ 'auto-create': flagsBuilder.autoCreate(),
158
+ interactive: flagsBuilder.interactive(),
159
+ 'filename-pattern': flagsBuilder.filenamePattern(),
160
+ 'dry-run': flagsBuilder.dryRun(),
86
161
  };
87
162
  Deploy.args = [args_1.fileArg];
@@ -1,19 +1,19 @@
1
1
  import Command from '../command';
2
- import * as flags from '../flags';
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: flags.IOptionFlag<string | undefined>;
10
- hub: flags.IOptionFlag<string | undefined>;
11
- branch: flags.IOptionFlag<string | undefined>;
12
- token: flags.IOptionFlag<string | undefined>;
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
14
  'fail-on-breaking': import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
15
- format: flags.IOptionFlag<string | undefined>;
16
- expires: flags.IOptionFlag<string | undefined>;
15
+ format: flagsBuilder.IOptionFlag<string | undefined>;
16
+ expires: flagsBuilder.IOptionFlag<string | undefined>;
17
17
  };
18
18
  static args: {
19
19
  name: string;
@@ -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 flags = (0, tslib_1.__importStar)(require("../flags"));
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");
@@ -106,14 +106,14 @@ Diff.examples = [
106
106
  `,
107
107
  ];
108
108
  Diff.flags = {
109
- help: flags.help({ char: 'h' }),
110
- doc: flags.doc({ required: false }),
111
- hub: flags.hub(),
112
- branch: flags.branch(),
113
- token: flags.token({ required: false }),
114
- open: flags.open({ description: 'Open the visual diff in your browser' }),
115
- 'fail-on-breaking': flags.failOnBreaking(),
116
- format: flags.format(),
117
- expires: flags.expires(),
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(),
118
118
  };
119
119
  Diff.args = [args_1.fileArg, args_1.otherFileArg];
@@ -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 flags = (0, tslib_1.__importStar)(require("../flags"));
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) {
@@ -75,10 +73,12 @@ Preview.examples = [
75
73
  `,
76
74
  ];
77
75
  Preview.flags = {
78
- help: flags.help({ char: 'h' }),
79
- live: flags.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: flags.open({ description: 'Open the generated preview URL in your browser' }),
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,13 @@
1
+ declare type FileDescription = {
2
+ value: string;
3
+ label: string;
4
+ filename: string;
5
+ };
6
+ export declare const isDir: (path: string) => boolean;
7
+ export declare class File {
8
+ protected static readonly supportedFormats: string[];
9
+ static listValidConventionFiles(path: string, regex: RegExp): FileDescription[];
10
+ static listInvalidConventionFiles(path: string, regex: RegExp): FileDescription[];
11
+ private static listValidFormatFiles;
12
+ }
13
+ export {};
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.File = exports.isDir = void 0;
4
+ const fs_1 = require("fs");
5
+ const path_1 = require("path");
6
+ const isDir = (path) => {
7
+ try {
8
+ return (0, fs_1.statSync)(path).isDirectory();
9
+ }
10
+ catch (e) {
11
+ return false;
12
+ }
13
+ };
14
+ exports.isDir = isDir;
15
+ class File {
16
+ static listValidConventionFiles(path, regex) {
17
+ return File.listValidFormatFiles(path).filter(({ filename }) => {
18
+ return filename.match(regex);
19
+ });
20
+ }
21
+ static listInvalidConventionFiles(path, regex) {
22
+ return File.listValidFormatFiles(path).filter(({ filename }) => {
23
+ return !filename.match(regex);
24
+ });
25
+ }
26
+ static listValidFormatFiles(path) {
27
+ return (0, fs_1.readdirSync)(path)
28
+ .filter((file) => {
29
+ return File.supportedFormats.includes((0, path_1.extname)(file));
30
+ })
31
+ .map((file) => {
32
+ return {
33
+ value: file,
34
+ label: (0, path_1.basename)(file),
35
+ filename: (0, path_1.basename)(file, (0, path_1.extname)(file)),
36
+ };
37
+ });
38
+ }
39
+ }
40
+ exports.File = File;
41
+ 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;
@@ -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'),
package/lib/flags.d.ts CHANGED
@@ -4,13 +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>;
12
14
  declare const failOnBreaking: (options?: {}) => Parser.flags.IBooleanFlag<boolean>;
13
15
  declare const live: (options?: {}) => Parser.flags.IBooleanFlag<boolean>;
14
16
  declare const format: flags.Definition<string>;
15
17
  declare const expires: flags.Definition<string>;
16
- export { doc, docName, hub, branch, token, autoCreate, dryRun, open, failOnBreaking, 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.failOnBreaking = 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 bum-cli
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
  };
@@ -1 +1 @@
1
- {"version":"2.6.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","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","required":true},"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},"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},"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.","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","required":false},"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},"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.","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.","required":true}]}}}
1
+ {"version":"2.7.1","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},"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},"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.6.0",
4
+ "version": "2.7.1",
5
5
  "author": "Paul Bonaud <paulr@bump.sh>",
6
6
  "bin": {
7
7
  "bump": "./bin/run"
@@ -13,11 +13,11 @@
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": "^4.21.0",
17
- "@typescript-eslint/parser": "^4.21.0",
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
- "eslint": "^7.24.0",
20
+ "eslint": "^8.45.0",
21
21
  "eslint-config-prettier": "^8.1.0",
22
22
  "eslint-plugin-prettier": "^4.0.0",
23
23
  "globby": "^11.0.3",
@@ -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": "^4.3.3"
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": {
@@ -68,7 +73,7 @@
68
73
  "postpack": "rm -f oclif.manifest.json",
69
74
  "prepack": "rm -rf lib && npm run build && oclif-dev manifest && oclif-dev readme",
70
75
  "pretest": "npm run clean && npm run build && npm run lint",
71
- "publish": "np --no-release-draft",
76
+ "release": "np --no-release-draft",
72
77
  "test": "mocha \"test/**/*.test.ts\"",
73
78
  "test-coverage": "nyc npm run test",
74
79
  "test-integration": "node ./test/integration.js",
@@ -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": "^1.3.3",
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",