bump-cli 2.10.0 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -16,7 +16,7 @@ Using [OpenAPI](https://github.com/OAI/OpenAPI-Specification) (v3.x and v2.0) or
16
16
  - Validate an API document before publishing to your documentation.
17
17
  - [Publish an API document](#the-deploy-command) to your Bump.sh documentation or hubs.
18
18
  - [Compare two API documents](#the-diff-command) to generate a human-readable diff from your API definition.
19
- Under the hood, it uses the API of [developers.bump.sh](https://developers.bump.sh). And is built with the [`oclif`](https://oclif.io) framework in Typescript.
19
+ Under the hood, it uses the workspace API of [developers.bump.sh](https://developers.bump.sh/doc/workspace/). And is built with the [`oclif`](https://oclif.io) framework in Typescript.
20
20
 
21
21
  Using [Flower](https://docs.bump.sh/help/mcp-servers/specification-support/flower-support/) or [Arazzo](https://docs.bump.sh/arazzo/v1.0/), you can:
22
22
 
@@ -83,7 +83,7 @@ npx bump --help
83
83
 
84
84
  ### Can I install Bump.sh CLI without using NodeJS?
85
85
 
86
- Unfortunately, at the moment we only support the Node environment. However, you can download a standalone package directly from the [latest Github release](https://github.com/bump-sh/cli/releases) assets which you can run as a standalone binary. Or you can push your documentation using [our API](https://developers.bump.sh/) (advanced usage only).
86
+ Unfortunately, at the moment we only support the Node environment. However, you can download a standalone package directly from the [latest Github release](https://github.com/bump-sh/cli/releases) assets which you can run as a standalone binary. Or you can push your documentation using [our API](https://developers.bump.sh/doc/workspace/) (advanced usage only).
87
87
 
88
88
  ## Usage
89
89
 
@@ -202,9 +202,6 @@ bump deploy path/to/flower-or-arazzo-document.yml --mcp-server my-mcp-server-id-
202
202
  More details about the MCP server feature are available on [this
203
203
  dedicated help section](https://docs.bump.sh/help/mcp-servers/).
204
204
 
205
- This feature is currently in closed beta.
206
- Request an early access at hello@bump.sh
207
-
208
205
  ### The `diff` command
209
206
 
210
207
  Using the `diff` command can help to spot differences between the local API
@@ -284,7 +281,7 @@ bump preview path/to/file.json
284
281
  You can also preview a document available via a URL:
285
282
 
286
283
  ```shell
287
- bump preview https://developers.bump.sh/source.yaml
284
+ bump preview https://developers.bump.sh/doc/workspace/source.yaml
288
285
  ```
289
286
 
290
287
  #### Live preview
@@ -384,7 +381,7 @@ For example to generate a preview:
384
381
  > Your preview is visible at: https://bump.sh/preview/42
385
382
  ```
386
383
 
387
- Please note that even if CLI is running locally, by default requests are sent to [Bump.sh API](https://developers.bump.sh/).
384
+ Please note that even if CLI is running locally, by default requests are sent to [Bump.sh API](https://developers.bump.sh/doc/workspace/).
388
385
 
389
386
  If you have a local version of the Bump.sh API, you can run CLI 100% in local environment
390
387
  by setting the environment variable `BUMP_HOST`:
package/dist/api/index.js CHANGED
@@ -12,7 +12,7 @@ class BumpApi {
12
12
  headers: this.authorizationHeader(token),
13
13
  });
14
14
  postDiff = (body) => this.client.post('/diffs', body);
15
- postMCPServerDeploy = (mcpServerIdOrSlug, body, token) => this.client.post(`/mcp_servers/${mcpServerIdOrSlug}/deploy`, body, {
15
+ postMCPServerDeploy = (mcpServerIdOrSlug, body, token) => this.client.post(`/mcp-servers/${mcpServerIdOrSlug}/deploy`, body, {
16
16
  headers: this.authorizationHeader(token),
17
17
  });
18
18
  postPreview = (body) => this.client.post('/previews', body);
@@ -34,6 +34,7 @@ export interface VersionRequest {
34
34
  unpublished?: boolean;
35
35
  }
36
36
  export interface VersionResponse {
37
+ doc_name: string;
37
38
  doc_public_url?: string;
38
39
  id: string;
39
40
  }
@@ -75,4 +76,5 @@ export interface WorkflowVersionRequest {
75
76
  export interface WorkflowVersionResponse {
76
77
  id: string;
77
78
  mcp_server_id: string;
79
+ mcp_server_name: string;
78
80
  }
@@ -110,23 +110,25 @@ ${chalk.dim('$ bump deploy FILE --mcp-server <your_mcp_server_id_or_slug> --toke
110
110
  async deploySingleFile(api, dryRun, documentation, token, hub, autoCreate, documentationName, branch, overlay, temporary) {
111
111
  ux.action.status = `...a new version to your ${documentation} documentation`;
112
112
  const response = await new CoreDeploy(this.bump).run(api, dryRun, documentation, token, hub, autoCreate, documentationName, branch, overlay, temporary);
113
+ const docName = response?.doc_name || documentation;
113
114
  if (dryRun) {
114
115
  ux.stdout(ux.colorize('green', 'Definition is valid'));
115
116
  }
116
117
  else if (response) {
117
- process.stdout.write(ux.colorize('green', `Your ${documentation} documentation...`));
118
+ process.stdout.write(ux.colorize('green', `Your ${docName} documentation...`));
118
119
  ux.stdout(ux.colorize('green', `has received a new ${temporary ? 'preview' : 'deployment'} which will soon be ready at:`));
119
120
  ux.stdout(ux.colorize('underline', response.doc_public_url));
120
121
  }
121
122
  else {
122
- ux.warn(`Your ${documentation} documentation has not changed`);
123
+ ux.warn(`Your ${docName} documentation has not changed`);
123
124
  }
124
125
  }
125
126
  async deploySingleWorkflowFile(workflowDefinition, mcpServer, token) {
126
127
  ux.action.status = `...a new workflow definition to your ${mcpServer} MCP server`;
127
128
  const response = await new CoreWorkflowDeploy(this.bump).run(workflowDefinition, mcpServer, token);
129
+ const mcpServerName = response?.mcp_server_name || mcpServer;
128
130
  if (response) {
129
- process.stdout.write(ux.colorize('green', `Your ${mcpServer} MCP server...`));
131
+ process.stdout.write(ux.colorize('green', `Your ${mcpServerName} MCP server...`));
130
132
  ux.stdout(ux.colorize('green', `has received a new workflow definition which will soon be ready.`));
131
133
  }
132
134
  else {
@@ -1,6 +1,9 @@
1
1
  import { Config } from '@oclif/core';
2
2
  import { BumpApi } from '../api/index.js';
3
3
  import { DiffResponse, VersionResponse, WithDiff } from '../api/models.js';
4
+ export interface DiffResult extends DiffResponse {
5
+ doc_name?: string;
6
+ }
4
7
  export declare class Diff {
5
8
  static readonly TIMEOUT = 120;
6
9
  private _bump;
@@ -11,14 +14,14 @@ export declare class Diff {
11
14
  createDiff(file1: string, file2: string, expires: string | undefined, overlays1?: string[] | undefined, overlays2?: string[] | undefined): Promise<DiffResponse | undefined>;
12
15
  createVersion(file: string, documentation: string, token: string, hub: string | undefined, branch_name: string | undefined, previous_version_id?: string | undefined, overlays?: string[] | undefined): Promise<VersionResponse | undefined>;
13
16
  d(formatter: any, ...args: any[]): void;
14
- extractDiff(versionWithDiff: VersionResponse & WithDiff): DiffResponse;
17
+ extractDiff(versionWithDiff: VersionResponse & WithDiff): DiffResult;
15
18
  isVersion(result: DiffResponse | VersionResponse): result is VersionResponse;
16
19
  isVersionWithDiff(result: DiffResponse | (VersionResponse & WithDiff)): result is VersionResponse & WithDiff;
17
20
  pollingDelay(): Promise<void>;
18
- run(file1: string, file2: string | undefined, documentation: string | undefined, hub: string | undefined, branch: string | undefined, token: string | undefined, format: string, expires?: string | undefined, overlays1?: string[] | undefined, overlays2?: string[] | undefined): Promise<DiffResponse | undefined>;
19
- waitResult(result: DiffResponse | VersionResponse, token: string | undefined, opts: {
21
+ run(file1: string, file2: string | undefined, documentation: string | undefined, hub: string | undefined, branch: string | undefined, token: string | undefined, format: string, expires?: string | undefined, overlays1?: string[] | undefined, overlays2?: string[] | undefined): Promise<DiffResult | undefined>;
22
+ waitResult(apiResponse: DiffResponse | VersionResponse, token: string | undefined, opts: {
20
23
  format: string;
21
24
  timeout: number;
22
- }): Promise<DiffResponse>;
25
+ }): Promise<DiffResult>;
23
26
  private delay;
24
27
  }
package/dist/core/diff.js CHANGED
@@ -82,6 +82,7 @@ export class Diff {
82
82
  return {
83
83
  breaking: versionWithDiff.diff_breaking,
84
84
  details: versionWithDiff.diff_details,
85
+ doc_name: versionWithDiff.doc_name,
85
86
  id: versionWithDiff.id,
86
87
  markdown: versionWithDiff.diff_markdown,
87
88
  public_url: versionWithDiff.diff_public_url,
@@ -122,35 +123,34 @@ export class Diff {
122
123
  }
123
124
  return undefined;
124
125
  }
125
- async waitResult(result, token, opts) {
126
- const pollingResponse = await (this.isVersion(result) && token
127
- ? this.bumpClient.getVersion(result.id, token)
128
- : this.bumpClient.getDiff(result.id, opts.format));
126
+ async waitResult(apiResponse, token, opts) {
127
+ let diffResult = { id: apiResponse.id };
128
+ const pollingResponse = await (this.isVersion(apiResponse) && token
129
+ ? this.bumpClient.getVersion(apiResponse.id, token)
130
+ : this.bumpClient.getDiff(apiResponse.id, opts.format));
129
131
  if (opts.timeout <= 0) {
130
132
  throw new CLIError('We were unable to compute your documentation diff. Sorry about that. Please try again later. If the error persists, please contact support at https://bump.sh.');
131
133
  }
132
134
  switch (pollingResponse.status) {
133
135
  case 200: {
134
- let diff = pollingResponse.data;
135
- if (this.isVersionWithDiff(diff)) {
136
- diff = this.extractDiff(diff);
137
- }
136
+ const diff = pollingResponse.data;
137
+ diffResult = this.isVersionWithDiff(diff) ? this.extractDiff(diff) : diff;
138
138
  this.d('Received diff:');
139
- this.d(diff);
140
- return diff;
139
+ this.d(diffResult);
140
+ return diffResult;
141
141
  break;
142
142
  }
143
143
  case 202: {
144
144
  this.d('Waiting 1 sec before next poll');
145
145
  await this.pollingDelay();
146
- return this.waitResult(result, token, {
146
+ return this.waitResult(apiResponse, token, {
147
147
  format: opts.format,
148
148
  timeout: opts.timeout - 1,
149
149
  });
150
150
  break;
151
151
  }
152
152
  }
153
- return {};
153
+ return diffResult;
154
154
  }
155
155
  async delay(ms) {
156
156
  return new Promise((resolve) => {
@@ -4,6 +4,7 @@ export declare class Overlay {
4
4
  run(spec: APIDefinition, overlay: OpenAPIOverlay): APIDefinition;
5
5
  private executeAction;
6
6
  private humanName;
7
+ private mergeWithEnumDedup;
7
8
  private pathEntryToKey;
8
9
  private remove;
9
10
  private update;
@@ -98,6 +98,18 @@ export class Overlay {
98
98
  humanName(action) {
99
99
  return action.description ? `Action '${action.description}'` : 'Action';
100
100
  }
101
+ // Deep merge objects using a module (built-in spread operator is only shallow)
102
+ mergeWithEnumDedup(target, update) {
103
+ const merger = mergician({
104
+ afterEach(options) {
105
+ if (options.key === 'enum' && Array.isArray(options.mergeVal)) {
106
+ return [...new Set(options.mergeVal)];
107
+ }
108
+ },
109
+ appendArrays: true,
110
+ });
111
+ return merger(target, update);
112
+ }
101
113
  // The last path entry (e.g. "'price']" or '0]') contains a final
102
114
  // ']' so we need to remove it AND we need to replace single quotes
103
115
  // to double quotes AND FINALLY parse the element to transform the
@@ -118,13 +130,11 @@ export class Overlay {
118
130
  }
119
131
  update(spec, parent, update, property_or_index) {
120
132
  try {
121
- // Deep merge objects using a module (built-in spread operator is only shallow)
122
- const merger = mergician({ appendArrays: true, dedupArrays: true });
123
133
  if (property_or_index === '$') {
124
134
  // You can't actually merge an update on a root object
125
135
  // target with the jsonpathly lib, this is just us merging
126
136
  // the given update with the whole spec.
127
- spec = merger(spec, update);
137
+ spec = this.mergeWithEnumDedup(spec, update);
128
138
  }
129
139
  else if (property_or_index !== undefined) {
130
140
  const targetObject = parent[property_or_index];
@@ -132,7 +142,7 @@ export class Overlay {
132
142
  parent[property_or_index] =
133
143
  Array.isArray(targetObject) && Array.isArray(update)
134
144
  ? [...targetObject, ...update]
135
- : merger(targetObject, update);
145
+ : this.mergeWithEnumDedup(targetObject, update);
136
146
  }
137
147
  else {
138
148
  parent[property_or_index] = update;
@@ -2,6 +2,7 @@ import type { JSONSchema7 } from 'json-schema';
2
2
  declare const _default: {
3
3
  schemas: {
4
4
  '1.0': JSONSchema7;
5
+ '1.1': JSONSchema7;
5
6
  };
6
7
  };
7
8
  export default _default;
@@ -1,8 +1,10 @@
1
1
  // Spec definitions are copied from the official
2
2
  // spec repo https://spec.openapis.org/arazzo/
3
3
  import schemaV10 from './v1.0/schema.json' with { type: 'json' };
4
+ import schemaV11 from './v1.1/schema.json' with { type: 'json' };
4
5
  export default {
5
6
  schemas: {
6
7
  '1.0': schemaV10,
8
+ '1.1': schemaV11,
7
9
  },
8
10
  };