bump-cli 2.8.4 → 2.9.0-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 +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 +281 -1
- package/package.json +64 -56
- 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
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { ux } from '@oclif/core';
|
|
2
|
+
import { CLIError } from '@oclif/core/errors';
|
|
3
|
+
import { fileArg, otherFileArg } from '../args.js';
|
|
4
|
+
import { BaseCommand } from '../base-command.js';
|
|
5
|
+
import { Diff as CoreDiff } from '../core/diff.js';
|
|
6
|
+
import * as flagsBuilder from '../flags.js';
|
|
7
|
+
export default class Diff extends BaseCommand {
|
|
8
|
+
static args = {
|
|
9
|
+
file: fileArg,
|
|
10
|
+
otherFile: otherFileArg,
|
|
11
|
+
};
|
|
12
|
+
static description = 'Get a comparison diff with your documentation from the given file or URL.';
|
|
13
|
+
static examples = [
|
|
14
|
+
`Compare a potential new version with the currently published one:
|
|
15
|
+
|
|
16
|
+
$ bump diff FILE --doc <your_doc_id_or_slug> --token <your_doc_token>
|
|
17
|
+
* Comparing the given definition file with the currently deployed one... done
|
|
18
|
+
Removed: GET /compare
|
|
19
|
+
Added: GET /versions/{versionId}
|
|
20
|
+
`,
|
|
21
|
+
`Store the diff in a dedicated file:
|
|
22
|
+
|
|
23
|
+
$ bump diff FILE --doc <doc_slug> --token <doc_token> > /tmp/my-saved-diff
|
|
24
|
+
* Comparing the given definition file with the currently deployed one... done
|
|
25
|
+
|
|
26
|
+
$ cat /tmp/my-saved-diff
|
|
27
|
+
Removed: GET /compare
|
|
28
|
+
Added: GET /versions/{versionId}
|
|
29
|
+
`,
|
|
30
|
+
`In case of a non modified definition FILE compared to your existing documentation, no changes are output:
|
|
31
|
+
|
|
32
|
+
$ bump diff FILE --doc <doc_slug> --token <your_doc_token>
|
|
33
|
+
* Comparing the given definition file with the currently deployed one... done
|
|
34
|
+
› Warning: Your documentation has not changed
|
|
35
|
+
`,
|
|
36
|
+
`Compare two different input files or URL independently to the one published on bump.sh
|
|
37
|
+
|
|
38
|
+
$ bump diff FILE FILE2 --doc <doc_slug> --token <your_doc_token>
|
|
39
|
+
* Comparing the two given definition files... done
|
|
40
|
+
Updated: POST /versions
|
|
41
|
+
Body attribute added: previous_version_id
|
|
42
|
+
`,
|
|
43
|
+
];
|
|
44
|
+
static flags = {
|
|
45
|
+
branch: flagsBuilder.branch(),
|
|
46
|
+
doc: flagsBuilder.doc(),
|
|
47
|
+
expires: flagsBuilder.expires(),
|
|
48
|
+
'fail-on-breaking': flagsBuilder.failOnBreaking(),
|
|
49
|
+
format: flagsBuilder.format(),
|
|
50
|
+
hub: flagsBuilder.hub(),
|
|
51
|
+
token: flagsBuilder.token({ required: false }),
|
|
52
|
+
};
|
|
53
|
+
async displayCompareResult(result, format, failOnBreaking) {
|
|
54
|
+
if (format === 'text' && result.text) {
|
|
55
|
+
ux.stdout(result.text);
|
|
56
|
+
}
|
|
57
|
+
else if (format === 'markdown' && result.markdown) {
|
|
58
|
+
ux.stdout(result.markdown);
|
|
59
|
+
}
|
|
60
|
+
else if (format === 'json' && result.details) {
|
|
61
|
+
ux.stdout(JSON.stringify(result.details, null, 2));
|
|
62
|
+
}
|
|
63
|
+
else if (format === 'html' && result.html) {
|
|
64
|
+
ux.stdout(result.html);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
ux.stdout('No structural changes detected.');
|
|
68
|
+
}
|
|
69
|
+
if (failOnBreaking && result.breaking) {
|
|
70
|
+
this.exit(1);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/*
|
|
74
|
+
Oclif doesn't type parsed args & flags correctly and especially
|
|
75
|
+
required-ness which is not known by the compiler, thus the use of
|
|
76
|
+
the non-null assertion '!' in this command.
|
|
77
|
+
See https://github.com/oclif/oclif/issues/301 for details
|
|
78
|
+
*/
|
|
79
|
+
async run() {
|
|
80
|
+
const { args, flags } = await this.parse(Diff);
|
|
81
|
+
const [documentation, hub, branch, token, format, expires] = [
|
|
82
|
+
flags.doc,
|
|
83
|
+
flags.hub,
|
|
84
|
+
flags.branch,
|
|
85
|
+
flags.token,
|
|
86
|
+
flags.format,
|
|
87
|
+
flags.expires,
|
|
88
|
+
];
|
|
89
|
+
if (format === 'text') {
|
|
90
|
+
if (args.otherFile) {
|
|
91
|
+
ux.action.start('* Comparing the two given definition files');
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
ux.action.start('* Comparing the given definition file with the currently deployed one');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (!args.otherFile && (!documentation || !token)) {
|
|
98
|
+
throw new CLIError('Please provide a second file argument or login with an existing token');
|
|
99
|
+
}
|
|
100
|
+
ux.action.status = '...diff on Bump.sh in progress';
|
|
101
|
+
const diff = await new CoreDiff(this.bump).run(args.file, args.otherFile, documentation, hub, branch, token, format, expires);
|
|
102
|
+
ux.action.stop();
|
|
103
|
+
if (diff) {
|
|
104
|
+
await this.displayCompareResult(diff, format, flags['fail-on-breaking']);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
ux.stdout('No changes detected.');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BaseCommand } from '../base-command.js';
|
|
2
|
+
export default class Overlay extends BaseCommand<typeof Overlay> {
|
|
3
|
+
static args: {
|
|
4
|
+
file: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
5
|
+
overlay: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
+
};
|
|
7
|
+
static description: string;
|
|
8
|
+
static examples: string[];
|
|
9
|
+
static flags: {
|
|
10
|
+
out: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
};
|
|
12
|
+
run(): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { ux } from '@oclif/core';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { existsSync } from 'node:fs';
|
|
4
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
5
|
+
import { dirname } from 'node:path';
|
|
6
|
+
import { fileArg, overlayFileArg } from '../args.js';
|
|
7
|
+
import { BaseCommand } from '../base-command.js';
|
|
8
|
+
import { confirm as promptConfirm } from '../core/utils/prompts.js';
|
|
9
|
+
import { API } from '../definition.js';
|
|
10
|
+
import * as flagsBuilder from '../flags.js';
|
|
11
|
+
export default class Overlay extends BaseCommand {
|
|
12
|
+
static args = {
|
|
13
|
+
file: fileArg,
|
|
14
|
+
overlay: overlayFileArg,
|
|
15
|
+
};
|
|
16
|
+
static description = 'Apply an OpenAPI specified overlay to your API definition.';
|
|
17
|
+
static examples = [
|
|
18
|
+
`Apply the OVERLAY_FILE to the existing DEFINITION_FILE. The resulting
|
|
19
|
+
definition is output on stdout meaning you can redirect it to a new
|
|
20
|
+
file.
|
|
21
|
+
|
|
22
|
+
${chalk.dim('$ bump overlay DEFINITION_FILE OVERLAY_FILE > destination/file.json')}
|
|
23
|
+
* Let's apply the overlay to the main definition... done
|
|
24
|
+
`,
|
|
25
|
+
];
|
|
26
|
+
static flags = {
|
|
27
|
+
out: flagsBuilder.out(),
|
|
28
|
+
};
|
|
29
|
+
async run() {
|
|
30
|
+
const { args, flags } = await this.parse(Overlay);
|
|
31
|
+
const outputPath = flags.out;
|
|
32
|
+
ux.action.start("* Let's apply the overlay to the main definition");
|
|
33
|
+
ux.action.status = '...loading definition file';
|
|
34
|
+
const api = await API.load(args.file);
|
|
35
|
+
ux.action.status = '...applying overlay';
|
|
36
|
+
await api.applyOverlay(args.overlay);
|
|
37
|
+
const [overlayedDefinition] = api.extractDefinition(outputPath);
|
|
38
|
+
ux.action.stop();
|
|
39
|
+
if (outputPath) {
|
|
40
|
+
await mkdir(dirname(outputPath), { recursive: true });
|
|
41
|
+
let confirm = true;
|
|
42
|
+
if (existsSync(outputPath)) {
|
|
43
|
+
confirm = await promptConfirm(`Do you want to override the existing destination file? (${outputPath})`);
|
|
44
|
+
}
|
|
45
|
+
if (confirm) {
|
|
46
|
+
await writeFile(outputPath, overlayedDefinition);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
ux.stdout(overlayedDefinition);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BaseCommand } from '../base-command.js';
|
|
2
|
+
export default class Preview extends BaseCommand<typeof Preview> {
|
|
3
|
+
static args: {
|
|
4
|
+
file: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
5
|
+
};
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {
|
|
9
|
+
live: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
open: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
};
|
|
12
|
+
run(): Promise<void>;
|
|
13
|
+
private preview;
|
|
14
|
+
private waitForChanges;
|
|
15
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { ux } from '@oclif/core';
|
|
2
|
+
import { Mutex } from 'async-mutex';
|
|
3
|
+
import { watch } from 'node:fs';
|
|
4
|
+
import { default as openBrowser } from 'open';
|
|
5
|
+
import { fileArg } from '../args.js';
|
|
6
|
+
import { BaseCommand } from '../base-command.js';
|
|
7
|
+
import { API } from '../definition.js';
|
|
8
|
+
import * as flagsBuilder from '../flags.js';
|
|
9
|
+
export default class Preview extends BaseCommand {
|
|
10
|
+
static args = {
|
|
11
|
+
file: fileArg,
|
|
12
|
+
};
|
|
13
|
+
static description = 'Create a documentation preview from the given file or URL.';
|
|
14
|
+
static examples = [
|
|
15
|
+
`$ <%= config.bin %> <%= command.id %> FILE
|
|
16
|
+
* Your preview is visible at: https://bump.sh/preview/45807371-9a32-48a7-b6e4-1cb7088b5b9b
|
|
17
|
+
`,
|
|
18
|
+
];
|
|
19
|
+
static flags = {
|
|
20
|
+
live: flagsBuilder.live({
|
|
21
|
+
description: 'Generate a preview each time you save the given file',
|
|
22
|
+
}),
|
|
23
|
+
open: flagsBuilder.open({
|
|
24
|
+
description: 'Open the generated preview URL in your browser',
|
|
25
|
+
}),
|
|
26
|
+
};
|
|
27
|
+
async run() {
|
|
28
|
+
const { args, flags } = await this.parse(Preview);
|
|
29
|
+
ux.action.start("* Let's render a preview on Bump.sh");
|
|
30
|
+
const currentPreview = await this.preview(args.file, flags.open);
|
|
31
|
+
if (flags.live) {
|
|
32
|
+
await this.waitForChanges(args.file, currentPreview);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
ux.action.stop();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
async preview(file, open = false, currentPreview = undefined) {
|
|
39
|
+
const api = await API.load(file);
|
|
40
|
+
const [definition, references] = api.extractDefinition();
|
|
41
|
+
this.d(`${file} looks like an ${api.specName} spec version ${api.version}`);
|
|
42
|
+
const request = {
|
|
43
|
+
definition,
|
|
44
|
+
references,
|
|
45
|
+
};
|
|
46
|
+
ux.action.status = '...in progress';
|
|
47
|
+
const response = currentPreview
|
|
48
|
+
? await this.bump.putPreview(currentPreview.id, request)
|
|
49
|
+
: await this.bump.postPreview(request);
|
|
50
|
+
if (!currentPreview) {
|
|
51
|
+
ux.action.status = '...done';
|
|
52
|
+
ux.stdout(ux.colorize('green', `Your preview is visible at: ${response.data.public_url} (Expires at ${response.data.expires_at})`));
|
|
53
|
+
}
|
|
54
|
+
if (open && response.data.public_url) {
|
|
55
|
+
await openBrowser(response.data.public_url);
|
|
56
|
+
}
|
|
57
|
+
return response.data;
|
|
58
|
+
}
|
|
59
|
+
async waitForChanges(file, preview) {
|
|
60
|
+
const mutex = new Mutex();
|
|
61
|
+
let currentPreview = preview;
|
|
62
|
+
ux.action.status = `Waiting for changes on file ${file}...`;
|
|
63
|
+
watch(file, async () => {
|
|
64
|
+
if (!mutex.isLocked()) {
|
|
65
|
+
const release = await mutex.acquire();
|
|
66
|
+
this.preview(file, false, currentPreview)
|
|
67
|
+
.then((preview) => {
|
|
68
|
+
currentPreview = preview;
|
|
69
|
+
ux.stdout(ux.colorize('green', ` ↳ has been updated (Expires at ${preview.expires_at})`));
|
|
70
|
+
ux.action.status = `Waiting for changes on file ${file}`;
|
|
71
|
+
})
|
|
72
|
+
.catch((error) => {
|
|
73
|
+
this.warn(error);
|
|
74
|
+
})
|
|
75
|
+
.finally(() => {
|
|
76
|
+
setTimeout(() => {
|
|
77
|
+
release();
|
|
78
|
+
}, 1000); // Prevent previewing faster than once per second
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -1,20 +1,22 @@
|
|
|
1
|
-
import { API } from '../definition';
|
|
2
|
-
export
|
|
1
|
+
import { API } from '../definition.js';
|
|
2
|
+
export type DefinitionConfig = {
|
|
3
3
|
definition: API;
|
|
4
4
|
file: string;
|
|
5
5
|
slug: string;
|
|
6
6
|
};
|
|
7
7
|
export declare class DefinitionDirectory {
|
|
8
|
-
protected
|
|
8
|
+
protected buildNewFilename: (slug: string) => string;
|
|
9
9
|
protected readonly definitions: DefinitionConfig[];
|
|
10
10
|
protected readonly filenamePattern: RegExp;
|
|
11
11
|
protected readonly humanFilenamePattern: string;
|
|
12
|
-
protected
|
|
12
|
+
protected readonly path: string;
|
|
13
13
|
constructor(directory: string, filenamePattern: string);
|
|
14
|
-
|
|
14
|
+
d(formatter: any, ...args: any[]): void;
|
|
15
15
|
definitionsExists(): boolean;
|
|
16
|
-
sequentialMap(callback: (definition: DefinitionConfig) => Promise<DefinitionConfig>): Promise<void>;
|
|
17
|
-
renameToConvention(documentation: DefinitionConfig): Promise<void>;
|
|
18
16
|
interactiveSelection(): Promise<DefinitionConfig[]>;
|
|
19
|
-
|
|
17
|
+
map(callback: (definition: DefinitionConfig) => Promise<DefinitionConfig>): Promise<DefinitionConfig[]>;
|
|
18
|
+
readDefinitions(): Promise<DefinitionConfig[]>;
|
|
19
|
+
renameToConvention(documentation: DefinitionConfig): Promise<void>;
|
|
20
|
+
sequentialMap(callback: (definition: DefinitionConfig) => Promise<void>): Promise<DefinitionConfig[]>;
|
|
21
|
+
stdoutDefinitions(): void;
|
|
20
22
|
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import * as p from '@clack/prompts';
|
|
2
|
+
import { ux } from '@oclif/core';
|
|
3
|
+
import { CLIError, ExitError } from '@oclif/core/errors';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import debug from 'debug';
|
|
6
|
+
import { rename } from 'node:fs';
|
|
7
|
+
import { basename, dirname, extname, join, resolve } from 'node:path';
|
|
8
|
+
import { confirm as promptConfirm } from '../core/utils/prompts.js';
|
|
9
|
+
import { API } from '../definition.js';
|
|
10
|
+
import { File } from './utils/file.js';
|
|
11
|
+
export class DefinitionDirectory {
|
|
12
|
+
buildNewFilename;
|
|
13
|
+
definitions;
|
|
14
|
+
filenamePattern;
|
|
15
|
+
humanFilenamePattern;
|
|
16
|
+
path;
|
|
17
|
+
constructor(directory, filenamePattern) {
|
|
18
|
+
this.path = resolve(directory);
|
|
19
|
+
this.definitions = [];
|
|
20
|
+
// // Transform basic patterns '*' or '{text}' into a real RegExp
|
|
21
|
+
this.filenamePattern = new RegExp('^' + filenamePattern.replace('*', '.*?').replace(/{.*?}/, '(?<slug>.+?)') + '$');
|
|
22
|
+
this.buildNewFilename = (slug) => filenamePattern.replace('*', '').replace(/{.*?}/, slug);
|
|
23
|
+
this.humanFilenamePattern = filenamePattern.replace(/{(.*?)}/, `${chalk.inverse('{$1}')}`);
|
|
24
|
+
}
|
|
25
|
+
// Function signature type taken from @types/debug
|
|
26
|
+
// Debugger(formatter: any, ...args: any[]): void;
|
|
27
|
+
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
|
28
|
+
d(formatter, ...args) {
|
|
29
|
+
return debug(`bump-cli:core:interactive`)(formatter, ...args);
|
|
30
|
+
}
|
|
31
|
+
definitionsExists() {
|
|
32
|
+
return this.definitions.length > 0;
|
|
33
|
+
}
|
|
34
|
+
async interactiveSelection() {
|
|
35
|
+
p.intro(`This interactive form will help you rename your API contrat files to follow the expected naming convention.\n${chalk.gray('│ ')}Once finished, the selected files will be deployed to Bump.sh.\n${chalk.gray('│ ')}\n${chalk.gray('│ ')}File naming convention: ${this.humanFilenamePattern}${chalk.dim('.[json|yml|yaml]')}\n`);
|
|
36
|
+
let fileOptions = File.listInvalidConventionFiles(this.path, this.filenamePattern);
|
|
37
|
+
if (fileOptions.length === 0) {
|
|
38
|
+
throw new CLIError(`No JSON or YAML files needing a rename were found in ${this.path}.\nAre you sure you need the ${chalk.dim('--interactive')} flag?`);
|
|
39
|
+
}
|
|
40
|
+
let shouldContinue = true;
|
|
41
|
+
while (shouldContinue) {
|
|
42
|
+
fileOptions = fileOptions.filter(({ label }) => {
|
|
43
|
+
// keep file only if it's NOT already present in the directory
|
|
44
|
+
return (this.definitions.findIndex(({ file }) => {
|
|
45
|
+
return basename(file) === label;
|
|
46
|
+
}) === -1);
|
|
47
|
+
});
|
|
48
|
+
const filePrompt = {
|
|
49
|
+
fileName: () => p.select({
|
|
50
|
+
message: `Which file do you want to deploy from ${chalk.dim(this.path)}?`,
|
|
51
|
+
options: fileOptions,
|
|
52
|
+
}),
|
|
53
|
+
};
|
|
54
|
+
const groupPrompt = {
|
|
55
|
+
/* Results type should be taken from the previous prompts
|
|
56
|
+
* defined with clack/prompt */
|
|
57
|
+
slug: ({ results }) => p.text({
|
|
58
|
+
message: `What is the ${chalk.inverse('documentation slug')} for this ${chalk.dim(results.fileName)} file?`,
|
|
59
|
+
}),
|
|
60
|
+
};
|
|
61
|
+
// eslint-disable-next-line no-await-in-loop
|
|
62
|
+
const prompt = await p.group({
|
|
63
|
+
...filePrompt,
|
|
64
|
+
...groupPrompt,
|
|
65
|
+
shouldContinue: () => p.confirm({ message: 'Do you want to select another file?' }),
|
|
66
|
+
}, {
|
|
67
|
+
onCancel() {
|
|
68
|
+
p.cancel('Deploy cancelled.');
|
|
69
|
+
throw new ExitError(1);
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
const file = join(this.path, prompt.fileName);
|
|
73
|
+
// eslint-disable-next-line no-await-in-loop
|
|
74
|
+
const definition = await API.load(file);
|
|
75
|
+
this.d(`${file} looks like an ${definition.specName} spec version ${definition.version}`);
|
|
76
|
+
this.definitions.push({
|
|
77
|
+
definition,
|
|
78
|
+
file,
|
|
79
|
+
slug: prompt.slug,
|
|
80
|
+
});
|
|
81
|
+
shouldContinue = prompt.shouldContinue;
|
|
82
|
+
}
|
|
83
|
+
p.outro(`You're all set. Your deployments will start soon.`);
|
|
84
|
+
return this.definitions;
|
|
85
|
+
}
|
|
86
|
+
async map(callback) {
|
|
87
|
+
return Promise.all(this.definitions.map((definition) => callback(definition)));
|
|
88
|
+
}
|
|
89
|
+
async readDefinitions() {
|
|
90
|
+
for await (const { filename, value } of File.listValidConventionFiles(this.path, this.filenamePattern)) {
|
|
91
|
+
const file = join(this.path, value);
|
|
92
|
+
/* We already check the filenamePattern match inside the
|
|
93
|
+
`File.listValidConventionFiles` method so we are sure the group
|
|
94
|
+
matched exists. */
|
|
95
|
+
const slug = filename.match(this.filenamePattern).groups.slug;
|
|
96
|
+
const definition = await API.load(file);
|
|
97
|
+
this.definitions.push({
|
|
98
|
+
definition,
|
|
99
|
+
file,
|
|
100
|
+
slug,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
return this.definitions;
|
|
104
|
+
}
|
|
105
|
+
async renameToConvention(documentation) {
|
|
106
|
+
const { file, slug } = documentation;
|
|
107
|
+
if (this.filenamePattern.test(basename(file, extname(file))))
|
|
108
|
+
return;
|
|
109
|
+
// Default convention is defined in the flags.ts file for the
|
|
110
|
+
// 'filenamePattern' flag.
|
|
111
|
+
const newFilename = this.buildNewFilename(slug);
|
|
112
|
+
const newFile = `${dirname(file)}/${newFilename}${extname(file)}`;
|
|
113
|
+
const confirm = await promptConfirm(`Do you want to rename ${file} to ${newFile} (for later deployments)?`);
|
|
114
|
+
if (confirm) {
|
|
115
|
+
await rename(file, newFile, (err) => {
|
|
116
|
+
if (err)
|
|
117
|
+
throw err;
|
|
118
|
+
ux.stdout(ux.colorize('green', `Renamed ${file} to ${newFile}.`));
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
async sequentialMap(callback) {
|
|
123
|
+
for (const definition of this.definitions) {
|
|
124
|
+
// We explicitly need a sequential run of promises, so the await
|
|
125
|
+
// in loop is needed.
|
|
126
|
+
/* eslint-disable-next-line no-await-in-loop */
|
|
127
|
+
await callback(definition);
|
|
128
|
+
}
|
|
129
|
+
return this.definitions;
|
|
130
|
+
}
|
|
131
|
+
stdoutDefinitions() {
|
|
132
|
+
if (this.definitions.length > 0) {
|
|
133
|
+
ux.stdout(chalk.underline(`We've found ${this.definitions.length} valid API definitions to deploy`));
|
|
134
|
+
ux.stdout(`└─ ${this.path}`);
|
|
135
|
+
let iterations = this.definitions.length;
|
|
136
|
+
for (const { definition, file } of this.definitions) {
|
|
137
|
+
const filename = `${basename(file)} (${definition.specName} spec version ${definition.version})`;
|
|
138
|
+
iterations -= 1;
|
|
139
|
+
if (iterations) {
|
|
140
|
+
ux.stdout(` ├─ ${filename}`);
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
ux.stdout(` └─ ${filename}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
ux.stdout('');
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { VersionRequest, VersionResponse } from '../api/models';
|
|
1
|
+
import { BumpApi } from '../api/index.js';
|
|
2
|
+
import { VersionRequest, VersionResponse } from '../api/models.js';
|
|
3
|
+
import { API } from '../definition.js';
|
|
5
4
|
export declare class Deploy {
|
|
6
|
-
_bump
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
private _bump;
|
|
6
|
+
constructor(bumpClient: BumpApi);
|
|
7
|
+
protected createVersion(request: VersionRequest, token: string): Promise<VersionResponse | undefined>;
|
|
8
|
+
d(formatter: any, ...args: any[]): void;
|
|
9
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>;
|
|
10
|
-
get bumpClient(): BumpApi;
|
|
11
|
-
createVersion(request: VersionRequest, token: string): Promise<VersionResponse | undefined>;
|
|
12
10
|
validateVersion(version: VersionRequest, token: string): Promise<undefined>;
|
|
13
|
-
d(formatter: any, ...args: any[]): void;
|
|
14
11
|
}
|
|
@@ -1,27 +1,45 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import debug from 'debug';
|
|
2
|
+
export class Deploy {
|
|
3
|
+
_bump;
|
|
4
|
+
constructor(bumpClient) {
|
|
5
|
+
this._bump = bumpClient;
|
|
6
|
+
}
|
|
7
|
+
async createVersion(request, token) {
|
|
8
|
+
const response = await this._bump.postVersion(request, token);
|
|
9
|
+
let version;
|
|
10
|
+
switch (response.status) {
|
|
11
|
+
case 204: {
|
|
12
|
+
break;
|
|
13
|
+
}
|
|
14
|
+
case 201: {
|
|
15
|
+
version = response.data ?? { doc_public_url: 'https://bump.sh', id: '' };
|
|
16
|
+
break;
|
|
17
|
+
}
|
|
18
|
+
default: {
|
|
19
|
+
this.d(`API status response was ${response.status}. Expected 201 or 204.`);
|
|
20
|
+
throw new Error('Unexpected server response. Please contact support at https://bump.sh if this error persists');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return version;
|
|
24
|
+
}
|
|
25
|
+
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
|
26
|
+
d(formatter, ...args) {
|
|
27
|
+
return debug(`bump-cli:core:deploy`)(formatter, ...args);
|
|
10
28
|
}
|
|
11
29
|
async run(api, dryRun, documentation, token, hub, autoCreate, documentationName, branch, overlay) {
|
|
12
|
-
let version
|
|
30
|
+
let version;
|
|
13
31
|
if (overlay) {
|
|
14
32
|
await api.applyOverlay(overlay);
|
|
15
33
|
}
|
|
16
34
|
const [definition, references] = api.extractDefinition();
|
|
17
35
|
const request = {
|
|
18
|
-
documentation,
|
|
19
|
-
hub,
|
|
20
|
-
documentation_name: documentationName,
|
|
21
36
|
auto_create_documentation: autoCreate && !dryRun,
|
|
37
|
+
branch_name: branch,
|
|
22
38
|
definition,
|
|
39
|
+
documentation,
|
|
40
|
+
documentation_name: documentationName,
|
|
41
|
+
hub,
|
|
23
42
|
references,
|
|
24
|
-
branch_name: branch,
|
|
25
43
|
};
|
|
26
44
|
if (dryRun) {
|
|
27
45
|
await this.validateVersion(request, token);
|
|
@@ -31,44 +49,18 @@ class Deploy {
|
|
|
31
49
|
}
|
|
32
50
|
return version;
|
|
33
51
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
this._bump = new api_1.BumpApi(this._config);
|
|
37
|
-
return this._bump;
|
|
38
|
-
}
|
|
39
|
-
async createVersion(request, token) {
|
|
40
|
-
const response = await this.bumpClient.postVersion(request, token);
|
|
41
|
-
let version = undefined;
|
|
42
|
-
switch (response.status) {
|
|
43
|
-
case 204:
|
|
44
|
-
break;
|
|
45
|
-
case 201:
|
|
46
|
-
version = response.data
|
|
47
|
-
? response.data
|
|
48
|
-
: { id: '', doc_public_url: 'https://bump.sh' };
|
|
49
|
-
break;
|
|
50
|
-
default:
|
|
51
|
-
this.d(`API status response was ${response.status}. Expected 201 or 204.`);
|
|
52
|
-
throw new Error('Unexpected server response. Please contact support at https://bump.sh if this error persists');
|
|
53
|
-
}
|
|
54
|
-
return version;
|
|
55
|
-
}
|
|
52
|
+
// Function signature type taken from @types/debug
|
|
53
|
+
// Debugger(formatter: any, ...args: any[]): void;
|
|
56
54
|
async validateVersion(version, token) {
|
|
57
|
-
const response = await this.
|
|
55
|
+
const response = await this._bump.postValidation(version, token);
|
|
58
56
|
switch (response.status) {
|
|
59
|
-
case 200:
|
|
57
|
+
case 200: {
|
|
60
58
|
break;
|
|
61
|
-
|
|
59
|
+
}
|
|
60
|
+
default: {
|
|
62
61
|
this.d(`API status response was ${response.status}. Expected 200.`);
|
|
63
62
|
throw new Error('Unexpected server response. Please contact support at https://bump.sh if this error persists');
|
|
63
|
+
}
|
|
64
64
|
}
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
// Function signature type taken from @types/debug
|
|
68
|
-
// Debugger(formatter: any, ...args: any[]): void;
|
|
69
|
-
/* eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any */
|
|
70
|
-
d(formatter, ...args) {
|
|
71
|
-
return (0, debug_1.default)(`bump-cli:core:deploy`)(formatter, ...args);
|
|
72
65
|
}
|
|
73
66
|
}
|
|
74
|
-
exports.Deploy = Deploy;
|
|
@@ -1,24 +1,21 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import { VersionResponse, WithDiff, DiffResponse } from '../api/models';
|
|
1
|
+
import { BumpApi } from '../api/index.js';
|
|
2
|
+
import { DiffResponse, VersionResponse, WithDiff } from '../api/models.js';
|
|
4
3
|
export declare class Diff {
|
|
5
4
|
static readonly TIMEOUT = 120;
|
|
6
|
-
_bump
|
|
7
|
-
|
|
8
|
-
constructor(config: Config.IConfig);
|
|
9
|
-
run(file1: string, file2: string | undefined, documentation: string | undefined, hub: string | undefined, branch: string | undefined, token: string | undefined, format: string, expires: string | undefined): Promise<DiffResponse | undefined>;
|
|
10
|
-
get bumpClient(): BumpApi;
|
|
5
|
+
private _bump;
|
|
6
|
+
constructor(bumpClient: BumpApi);
|
|
11
7
|
get pollingPeriod(): number;
|
|
12
8
|
createDiff(file1: string, file2: string, expires: string | undefined): Promise<DiffResponse | undefined>;
|
|
13
9
|
createVersion(file: string, documentation: string, token: string, hub: string | undefined, branch_name: string | undefined, previous_version_id?: string | undefined): Promise<VersionResponse | undefined>;
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
d(formatter: any, ...args: any[]): void;
|
|
11
|
+
extractDiff(versionWithDiff: VersionResponse & WithDiff): DiffResponse;
|
|
12
|
+
isVersion(result: DiffResponse | VersionResponse): result is VersionResponse;
|
|
13
|
+
isVersionWithDiff(result: DiffResponse | (VersionResponse & WithDiff)): result is VersionResponse & WithDiff;
|
|
14
|
+
pollingDelay(): Promise<void>;
|
|
15
|
+
run(file1: string, file2: string | undefined, documentation: string | undefined, hub: string | undefined, branch: string | undefined, token: string | undefined, format: string, expires: string | undefined): Promise<DiffResponse | undefined>;
|
|
16
|
+
waitResult(result: DiffResponse | VersionResponse, token: string | undefined, opts: {
|
|
16
17
|
format: string;
|
|
18
|
+
timeout: number;
|
|
17
19
|
}): Promise<DiffResponse>;
|
|
18
|
-
pollingDelay(): Promise<void>;
|
|
19
20
|
private delay;
|
|
20
|
-
d(formatter: any, ...args: any[]): void;
|
|
21
|
-
isVersion(result: VersionResponse | DiffResponse): result is VersionResponse;
|
|
22
|
-
isVersionWithDiff(result: (VersionResponse & WithDiff) | DiffResponse): result is VersionResponse & WithDiff;
|
|
23
|
-
extractDiff(versionWithDiff: VersionResponse & WithDiff): DiffResponse;
|
|
24
21
|
}
|