bump-cli 2.9.3 → 2.9.5

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
@@ -88,7 +88,7 @@ $ bump --help
88
88
  The Bump.sh CLI is used to interact with your API documentation hosted on Bump.sh by using the API of developers.bump.sh
89
89
 
90
90
  VERSION
91
- bump-cli/2.9.2 linux-x64 node-v20.18.1
91
+ bump-cli/2.9.3 linux-x64 node-v20.18.1
92
92
 
93
93
  USAGE
94
94
  $ bump [COMMAND]
@@ -325,12 +325,37 @@ Make sure to have Node.js (At least v20) installed on your machine.
325
325
  ```
326
326
 
327
327
  - Run the test suites
328
-
328
+
329
329
  ```shell
330
330
  npm run test
331
331
  npm run test-coverage # Run tests with coverage
332
332
  ```
333
333
 
334
+ ### Use package in local environment
335
+
336
+ You can run the package by executing the file `bin/run.js` locally:
337
+
338
+ ```shell
339
+ bin/run.js
340
+ ```
341
+
342
+ For example to generate a preview:
343
+
344
+ ```shell
345
+ ./bin/run.js preview path/to/file.json
346
+ > Your preview is visible at: https://bump.sh/preview/42
347
+ ```
348
+
349
+ Please note that even if CLI is running locally, by default requests are sent to [Bump.sh API](https://developers.bump.sh/).
350
+
351
+ If you have a local version of the Bump.sh API, you can run CLI 100% in local environment
352
+ by setting the environment variable `BUMP_HOST`:
353
+
354
+ ```shell
355
+ BUMP_HOST="http://localhost:3000" ./bin/run.js preview path/to/file.json
356
+ > Your preview is visible at: http://localhost:3000/preview/42
357
+ ```
358
+
334
359
  ## License
335
360
 
336
361
  The Bump CLI project is released under the [MIT License](http://opensource.org/licenses/MIT).
@@ -29,6 +29,7 @@ export interface VersionRequest {
29
29
  hub?: string;
30
30
  previous_version_id?: string;
31
31
  references?: Reference[];
32
+ temporary?: boolean;
32
33
  unpublished?: boolean;
33
34
  }
34
35
  export interface VersionResponse {
@@ -16,9 +16,10 @@ export default class Deploy extends BaseCommand<typeof Deploy> {
16
16
  hub: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
17
17
  interactive: import("@oclif/core/interfaces").BooleanFlag<boolean>;
18
18
  overlay: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
19
+ preview: import("@oclif/core/interfaces").BooleanFlag<boolean>;
19
20
  token: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
20
21
  };
21
22
  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
+ protected deploySingleFile(api: API, dryRun: boolean, documentation: string, token: string, hub: string | undefined, autoCreate: boolean, documentationName: string | undefined, branch: string | undefined, overlay?: string[] | undefined, temporary?: boolean | undefined): Promise<void>;
23
24
  run(): Promise<void>;
24
25
  }
@@ -58,6 +58,7 @@ ${chalk.dim('$ bump deploy FILE --dry-run --doc <doc_slug> --token <your_doc_tok
58
58
  hub: flagsBuilder.hub(),
59
59
  interactive: flagsBuilder.interactive(),
60
60
  overlay: flagsBuilder.overlay(),
61
+ preview: flagsBuilder.preview(),
61
62
  token: flagsBuilder.token(),
62
63
  };
63
64
  async deployDirectory(dir, dryRun, token, hub, autoCreate, interactive, filenamePattern, documentationName, branch) {
@@ -98,15 +99,15 @@ ${chalk.dim('$ bump deploy FILE --dry-run --doc <doc_slug> --token <your_doc_tok
98
99
  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
  }
100
101
  }
101
- async deploySingleFile(api, dryRun, documentation, token, hub, autoCreate, documentationName, branch, overlay) {
102
+ async deploySingleFile(api, dryRun, documentation, token, hub, autoCreate, documentationName, branch, overlay, temporary) {
102
103
  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
+ const response = await new CoreDeploy(this.bump).run(api, dryRun, documentation, token, hub, autoCreate, documentationName, branch, overlay, temporary);
104
105
  if (dryRun) {
105
106
  ux.stdout(ux.colorize('green', 'Definition is valid'));
106
107
  }
107
108
  else if (response) {
108
109
  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('green', `has received a new ${temporary ? 'preview' : 'deployment'} which will soon be ready at:`));
110
111
  ux.stdout(ux.colorize('underline', response.doc_public_url));
111
112
  }
112
113
  else {
@@ -121,7 +122,7 @@ ${chalk.dim('$ bump deploy FILE --dry-run --doc <doc_slug> --token <your_doc_tok
121
122
  */
122
123
  async run() {
123
124
  const { args, flags } = await this.parse(Deploy);
124
- const [dryRun, documentation, token, hub, autoCreate, interactive, filenamePattern, documentationName, branch, overlay,] = [
125
+ const [dryRun, documentation, token, hub, autoCreate, interactive, filenamePattern, documentationName, branch, overlay, temporary,] = [
125
126
  flags['dry-run'],
126
127
  flags.doc,
127
128
  flags.token,
@@ -134,8 +135,10 @@ ${chalk.dim('$ bump deploy FILE --dry-run --doc <doc_slug> --token <your_doc_tok
134
135
  flags['doc-name'],
135
136
  flags.branch,
136
137
  flags.overlay,
138
+ /* when --preview is provided, generate temporary version */
139
+ flags.preview,
137
140
  ];
138
- const action = dryRun ? 'validate' : 'deploy';
141
+ const action = dryRun ? 'validate' : temporary ? 'preview' : 'deploy';
139
142
  ux.action.start(`Let's ${action} on Bump.sh`);
140
143
  if (isDir(args.file)) {
141
144
  if (hub) {
@@ -148,7 +151,7 @@ ${chalk.dim('$ bump deploy FILE --dry-run --doc <doc_slug> --token <your_doc_tok
148
151
  else if (documentation) {
149
152
  const api = await API.load(args.file);
150
153
  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);
154
+ await this.deploySingleFile(api, dryRun, documentation, token, hub, autoCreate, documentationName, branch, overlay, temporary);
152
155
  }
153
156
  else {
154
157
  throw new CLIError('Missing required flag --doc=<slug>');
@@ -6,6 +6,6 @@ export declare class Deploy {
6
6
  constructor(bumpClient: BumpApi);
7
7
  protected createVersion(request: VersionRequest, token: string): Promise<VersionResponse | undefined>;
8
8
  d(formatter: any, ...args: any[]): void;
9
- run(api: API, dryRun: boolean, documentation: string, token: string, hub: string | undefined, autoCreate: boolean, documentationName: string | undefined, branch: string | undefined, overlay?: string[] | undefined): Promise<VersionResponse | undefined>;
9
+ run(api: API, dryRun: boolean, documentation: string, token: string, hub: string | undefined, autoCreate: boolean, documentationName: string | undefined, branch: string | undefined, overlay?: string[] | undefined, temporary?: boolean | false): Promise<VersionResponse | undefined>;
10
10
  validateVersion(version: VersionRequest, token: string): Promise<undefined>;
11
11
  }
@@ -26,7 +26,7 @@ export class Deploy {
26
26
  d(formatter, ...args) {
27
27
  return debug(`bump-cli:core:deploy`)(formatter, ...args);
28
28
  }
29
- async run(api, dryRun, documentation, token, hub, autoCreate, documentationName, branch, overlay) {
29
+ async run(api, dryRun, documentation, token, hub, autoCreate, documentationName, branch, overlay, temporary) {
30
30
  let version;
31
31
  if (overlay) {
32
32
  /* eslint-disable no-await-in-loop */
@@ -46,6 +46,7 @@ export class Deploy {
46
46
  documentation_name: documentationName,
47
47
  hub,
48
48
  references,
49
+ temporary,
49
50
  };
50
51
  if (dryRun) {
51
52
  await this.validateVersion(request, token);
package/dist/core/diff.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { Config } from '@oclif/core';
2
2
  import { CLIError } from '@oclif/core/errors';
3
3
  import debug from 'debug';
4
+ import { resolve } from 'node:path';
4
5
  import { BumpApi } from '../api/index.js';
5
6
  import { API } from '../definition.js';
6
7
  export class Diff {
@@ -99,7 +100,7 @@ export class Diff {
99
100
  }
100
101
  async run(file1, file2, documentation, hub, branch, token, format, expires) {
101
102
  if (!this._config)
102
- this._config = await Config.load('../../');
103
+ this._config = await Config.load(resolve(import.meta.dirname, './../../'));
103
104
  let diffVersion;
104
105
  if (file2 && (!documentation || !token)) {
105
106
  diffVersion = await this.createDiff(file1, file2, expires);
@@ -36,10 +36,27 @@ export class Overlay {
36
36
  process.stderr.write(`WARNING: Action target '${target}' has no matching elements\n`);
37
37
  continue;
38
38
  }
39
+ // When we execute a 'remove' action we need to be careful if
40
+ // the targets are elements of an array. Because the list of
41
+ // paths contains an index of each element.
42
+ //
43
+ // E.g.
44
+ // ["servers"][0]
45
+ // ["servers"][1]
46
+ // ["servers"][2]
47
+ //
48
+ // And if we remove elements starting from the 0, the array
49
+ // will be reindexed and thus the '2' index won't be valid
50
+ // anymore.
51
+ //
52
+ // Thus, in that case we revers the list of paths
53
+ if (action.remove) {
54
+ paths.reverse();
55
+ }
39
56
  for (const path of paths) {
40
57
  // The 'executeAction' will mutate the passed spec object in
41
58
  // place.
42
- this.executeAction(spec, action, path);
59
+ spec = this.executeAction(spec, action, path);
43
60
  }
44
61
  }
45
62
  }
@@ -71,14 +88,17 @@ export class Overlay {
71
88
  // Do the overlay action
72
89
  // Is it a remove?
73
90
  if (Object.hasOwn(action, 'remove')) {
91
+ this.d(`Executing 'remove' on target path: ${path}`);
74
92
  this.remove(parent, thingToActUpon);
75
93
  }
76
94
  else if (Object.hasOwn(action, 'update')) {
77
- this.update(spec, parent, action.update, thingToActUpon);
95
+ this.d(`Executing 'update' on target path: ${path}`);
96
+ spec = this.update(spec, parent, action.update, thingToActUpon);
78
97
  }
79
98
  else {
80
99
  process.stderr.write(`WARNING: ${this.humanName(action)} needs either a 'remove' or an 'update' property\n`);
81
100
  }
101
+ return spec;
82
102
  }
83
103
  humanName(action) {
84
104
  return action.description ? `Action '${action.description}'` : 'Action';
@@ -101,7 +121,7 @@ export class Overlay {
101
121
  // the given update with the whole spec.
102
122
  spec = merger(spec, update);
103
123
  }
104
- else if (property_or_index) {
124
+ else if (property_or_index !== undefined) {
105
125
  const targetObject = parent[property_or_index];
106
126
  if (typeof targetObject === 'object' && typeof update === 'object') {
107
127
  parent[property_or_index] =
@@ -117,5 +137,6 @@ export class Overlay {
117
137
  catch (error) {
118
138
  process.stderr.write(`Error applying overlay: ${error.message}\n`);
119
139
  }
140
+ return spec;
120
141
  }
121
142
  }
@@ -3,7 +3,7 @@ type FileDescription = {
3
3
  label: string;
4
4
  value: string;
5
5
  };
6
- export declare const isDir: (path: string) => boolean;
6
+ export declare const isDir: (path_or_url: string) => boolean;
7
7
  export declare class File {
8
8
  protected static readonly supportedFormats: string[];
9
9
  static listInvalidConventionFiles(path: string, regex: RegExp): FileDescription[];
@@ -1,8 +1,24 @@
1
+ import { CLIError } from '@oclif/core/errors';
1
2
  import { readdirSync, statSync } from 'node:fs';
2
3
  import { basename, extname } from 'node:path';
3
- export const isDir = (path) => {
4
+ export const isDir = (path_or_url) => {
5
+ if (isHttpUrl(path_or_url)) {
6
+ return false;
7
+ }
8
+ try {
9
+ return statSync(path_or_url).isDirectory();
10
+ }
11
+ catch (error) {
12
+ if (error instanceof Error) {
13
+ throw new CLIError(error);
14
+ }
15
+ return false;
16
+ }
17
+ };
18
+ const isHttpUrl = (path) => {
4
19
  try {
5
- return statSync(path).isDirectory();
20
+ const url = new URL(path);
21
+ return ['http:', 'https:'].includes(url.protocol);
6
22
  }
7
23
  catch {
8
24
  return false;
package/dist/flags.d.ts CHANGED
@@ -29,6 +29,7 @@ declare const dryRun: (opts?: Partial<Interfaces.BooleanFlag<boolean>>) => Inter
29
29
  declare const open: (opts?: Partial<Interfaces.BooleanFlag<boolean>>) => Interfaces.BooleanFlag<boolean>;
30
30
  declare const failOnBreaking: (opts?: Partial<Interfaces.BooleanFlag<boolean>>) => Interfaces.BooleanFlag<boolean>;
31
31
  declare const live: (opts?: Partial<Interfaces.BooleanFlag<boolean>>) => Interfaces.BooleanFlag<boolean>;
32
+ declare const preview: (opts?: Partial<Interfaces.BooleanFlag<boolean>>) => Interfaces.BooleanFlag<boolean>;
32
33
  declare const format: Interfaces.FlagDefinition<string, Interfaces.CustomOptions, {
33
34
  multiple: false;
34
35
  requiredOrDefaulted: true;
@@ -45,4 +46,4 @@ declare const overlay: Interfaces.FlagDefinition<string[], Interfaces.CustomOpti
45
46
  multiple: true;
46
47
  requiredOrDefaulted: false;
47
48
  }>;
48
- export { autoCreate, branch, doc, docName, dryRun, expires, failOnBreaking, filenamePattern, format, hub, interactive, live, open, out, overlay, token, };
49
+ export { autoCreate, branch, doc, docName, dryRun, expires, failOnBreaking, filenamePattern, format, hub, interactive, live, open, out, overlay, preview, token, };
package/dist/flags.js CHANGED
@@ -96,6 +96,14 @@ const live = (opts = {}) => {
96
96
  default: false,
97
97
  });
98
98
  };
99
+ const preview = (opts = {}) => {
100
+ return Flags.boolean({
101
+ ...opts,
102
+ char: 'p',
103
+ default: false,
104
+ description: 'Generate a preview in your API context. The resulting version is temporary and not visible by your documentation viewers.',
105
+ });
106
+ };
99
107
  const format = Flags.custom({
100
108
  char: 'f',
101
109
  default: 'text',
@@ -115,4 +123,4 @@ const overlay = Flags.custom({
115
123
  description: 'Path or URL of overlay file(s) to apply before deploying',
116
124
  multiple: true,
117
125
  });
118
- export { autoCreate, branch, doc, docName, dryRun, expires, failOnBreaking, filenamePattern, format, hub, interactive, live, open, out, overlay, token, };
126
+ export { autoCreate, branch, doc, docName, dryRun, expires, failOnBreaking, filenamePattern, format, hub, interactive, live, open, out, overlay, preview, token, };
@@ -92,6 +92,13 @@
92
92
  "multiple": true,
93
93
  "type": "option"
94
94
  },
95
+ "preview": {
96
+ "char": "p",
97
+ "description": "Generate a preview in your API context. The resulting version is temporary and not visible by your documentation viewers.",
98
+ "name": "preview",
99
+ "allowNo": false,
100
+ "type": "boolean"
101
+ },
95
102
  "token": {
96
103
  "char": "t",
97
104
  "description": "Documentation or Hub token. Can be provided via BUMP_TOKEN environment variable",
@@ -277,5 +284,5 @@
277
284
  "strict": true
278
285
  }
279
286
  },
280
- "version": "2.9.3"
287
+ "version": "2.9.5"
281
288
  }
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.sh by using the API of developers.bump.sh",
4
- "version": "2.9.3",
4
+ "version": "2.9.5",
5
5
  "author": "Paul Bonaud <paulr@bump.sh>",
6
6
  "bin": {
7
7
  "bump": "./bin/run.js"