@aikidosec/ci-api-client 1.0.1 → 1.0.2
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/.editorconfig +18 -18
- package/.env +1 -1
- package/.prettierrc +10 -10
- package/CONTRIBUTING.md +30 -30
- package/LICENSE +21 -21
- package/README.md +80 -78
- package/RELEASING.md +26 -26
- package/lib/aikidoApi.d.ts +60 -60
- package/lib/aikidoApi.js +52 -52
- package/lib/commands/apiKey.d.ts +8 -8
- package/lib/commands/apiKey.js +20 -18
- package/lib/commands/scan.d.ts +36 -36
- package/lib/commands/scan.js +188 -188
- package/lib/commands/upload.d.ts +23 -23
- package/lib/commands/upload.js +94 -94
- package/lib/configuration.d.ts +4 -4
- package/lib/configuration.js +13 -13
- package/lib/index.d.ts +12 -12
- package/lib/index.js +31 -31
- package/lib/output.d.ts +7 -7
- package/lib/output.js +53 -53
- package/package.json +51 -51
- package/src/aikidoApi.ts +148 -148
- package/src/commands/apiKey.ts +33 -30
- package/src/commands/scan.ts +370 -370
- package/src/commands/upload.ts +184 -184
- package/src/configuration.ts +21 -21
- package/src/index.ts +64 -64
- package/src/output.ts +87 -87
- package/tsconfig.json +27 -27
package/lib/commands/upload.js
CHANGED
|
@@ -1,94 +1,94 @@
|
|
|
1
|
-
import { Option } from 'commander';
|
|
2
|
-
import { TUploadPayloadType, uploadCustomScanResult, } from '../aikidoApi.js';
|
|
3
|
-
import { getApiKey } from '../configuration.js';
|
|
4
|
-
import { outputError, outputHttpError, startSpinner, } from '../output.js';
|
|
5
|
-
import { readFile } from 'fs';
|
|
6
|
-
import { promisify } from 'util';
|
|
7
|
-
async function cli(options, command) {
|
|
8
|
-
const apiKey = getApiKey();
|
|
9
|
-
if (!apiKey) {
|
|
10
|
-
outputError('Please set an api key using: aikido-cli apikey <key>');
|
|
11
|
-
}
|
|
12
|
-
const { apiOptions, cliOptions } = await parseCliOptions(options);
|
|
13
|
-
let loader = startSpinner('Uploading custom scan');
|
|
14
|
-
const onUploadComplete = (result) => {
|
|
15
|
-
if (result.success === 1) {
|
|
16
|
-
loader?.succeed('Upload completed');
|
|
17
|
-
}
|
|
18
|
-
else {
|
|
19
|
-
loader?.fail('Upload failed, please verify your payload data and try again');
|
|
20
|
-
process.exit(10);
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
const onUploadFail = (error) => {
|
|
24
|
-
loader?.fail();
|
|
25
|
-
outputHttpError(error);
|
|
26
|
-
process.exit(1);
|
|
27
|
-
};
|
|
28
|
-
await upload({
|
|
29
|
-
data: apiOptions,
|
|
30
|
-
onUploadComplete,
|
|
31
|
-
onUploadFail,
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
export const upload = async ({ data, onUploadComplete, onUploadFail, }) => {
|
|
35
|
-
try {
|
|
36
|
-
const result = await uploadCustomScanResult(data);
|
|
37
|
-
onUploadComplete?.(result);
|
|
38
|
-
}
|
|
39
|
-
catch (error) {
|
|
40
|
-
onUploadFail?.(error);
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
const parseCliOptions = async (userCliOptions) => {
|
|
45
|
-
const apiOptions = {
|
|
46
|
-
repository_id: userCliOptions.repositoryId,
|
|
47
|
-
container_image_name: userCliOptions.containerImage ?? undefined,
|
|
48
|
-
payload_type: userCliOptions.type,
|
|
49
|
-
payload: '',
|
|
50
|
-
};
|
|
51
|
-
const cliOptions = {
|
|
52
|
-
payloadFile: userCliOptions.file,
|
|
53
|
-
payload: userCliOptions.payload,
|
|
54
|
-
};
|
|
55
|
-
if (userCliOptions.type == TUploadPayloadType.JsonSbom) {
|
|
56
|
-
if (userCliOptions.containerImage === undefined ||
|
|
57
|
-
userCliOptions.containerImage.trim() === '') {
|
|
58
|
-
outputError('Please provide a valid container image name with --container-image');
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
if (userCliOptions.file) {
|
|
62
|
-
try {
|
|
63
|
-
const data = await promisify(readFile)(userCliOptions.file, 'utf8');
|
|
64
|
-
apiOptions.payload = data;
|
|
65
|
-
}
|
|
66
|
-
catch (error) {
|
|
67
|
-
outputError('Cannot read file provided with --payloadFile, aborting');
|
|
68
|
-
process.exit(1);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
else if (cliOptions.payload?.trim() != '') {
|
|
72
|
-
apiOptions.payload = cliOptions.payload;
|
|
73
|
-
}
|
|
74
|
-
else {
|
|
75
|
-
outputError('No payload provided, aborting');
|
|
76
|
-
process.exit(1);
|
|
77
|
-
}
|
|
78
|
-
return { apiOptions, cliOptions };
|
|
79
|
-
};
|
|
80
|
-
const requiredOption = (option) => {
|
|
81
|
-
option.required = true;
|
|
82
|
-
return option;
|
|
83
|
-
};
|
|
84
|
-
export const cliSetup = (program) => program
|
|
85
|
-
.command('upload')
|
|
86
|
-
.option('-s, --scan-id <scanid>', 'Set the scan id')
|
|
87
|
-
.requiredOption('-r, --repository-id <repositoryid>', 'Set the repository id')
|
|
88
|
-
.option('-i, --container-image <container-image-name>', 'Set the container image name. ')
|
|
89
|
-
.addOption(requiredOption(new Option('-t, --type <type>', 'Set the provided payload type. Available options are: checkov, json-sbom').choices(['checkov', 'json-sbom'])))
|
|
90
|
-
.option('-f, --file <payloadFile>', 'Specify the payload file. The cli command wil read the file and use the contents as payload data.')
|
|
91
|
-
.option('-p, --payload <payload>', 'Set the payload')
|
|
92
|
-
.description('Upload a custom scan result.')
|
|
93
|
-
.action(cli);
|
|
94
|
-
export default { cli, cliSetup };
|
|
1
|
+
import { Option } from 'commander';
|
|
2
|
+
import { TUploadPayloadType, uploadCustomScanResult, } from '../aikidoApi.js';
|
|
3
|
+
import { getApiKey } from '../configuration.js';
|
|
4
|
+
import { outputError, outputHttpError, startSpinner, } from '../output.js';
|
|
5
|
+
import { readFile } from 'fs';
|
|
6
|
+
import { promisify } from 'util';
|
|
7
|
+
async function cli(options, command) {
|
|
8
|
+
const apiKey = getApiKey();
|
|
9
|
+
if (!apiKey) {
|
|
10
|
+
outputError('Please set an api key using: aikido-cli apikey <key>');
|
|
11
|
+
}
|
|
12
|
+
const { apiOptions, cliOptions } = await parseCliOptions(options);
|
|
13
|
+
let loader = startSpinner('Uploading custom scan');
|
|
14
|
+
const onUploadComplete = (result) => {
|
|
15
|
+
if (result.success === 1) {
|
|
16
|
+
loader?.succeed('Upload completed');
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
loader?.fail('Upload failed, please verify your payload data and try again');
|
|
20
|
+
process.exit(10);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const onUploadFail = (error) => {
|
|
24
|
+
loader?.fail();
|
|
25
|
+
outputHttpError(error);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
};
|
|
28
|
+
await upload({
|
|
29
|
+
data: apiOptions,
|
|
30
|
+
onUploadComplete,
|
|
31
|
+
onUploadFail,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
export const upload = async ({ data, onUploadComplete, onUploadFail, }) => {
|
|
35
|
+
try {
|
|
36
|
+
const result = await uploadCustomScanResult(data);
|
|
37
|
+
onUploadComplete?.(result);
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
onUploadFail?.(error);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
const parseCliOptions = async (userCliOptions) => {
|
|
45
|
+
const apiOptions = {
|
|
46
|
+
repository_id: userCliOptions.repositoryId,
|
|
47
|
+
container_image_name: userCliOptions.containerImage ?? undefined,
|
|
48
|
+
payload_type: userCliOptions.type,
|
|
49
|
+
payload: '',
|
|
50
|
+
};
|
|
51
|
+
const cliOptions = {
|
|
52
|
+
payloadFile: userCliOptions.file,
|
|
53
|
+
payload: userCliOptions.payload,
|
|
54
|
+
};
|
|
55
|
+
if (userCliOptions.type == TUploadPayloadType.JsonSbom) {
|
|
56
|
+
if (userCliOptions.containerImage === undefined ||
|
|
57
|
+
userCliOptions.containerImage.trim() === '') {
|
|
58
|
+
outputError('Please provide a valid container image name with --container-image');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (userCliOptions.file) {
|
|
62
|
+
try {
|
|
63
|
+
const data = await promisify(readFile)(userCliOptions.file, 'utf8');
|
|
64
|
+
apiOptions.payload = data;
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
outputError('Cannot read file provided with --payloadFile, aborting');
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else if (cliOptions.payload?.trim() != '') {
|
|
72
|
+
apiOptions.payload = cliOptions.payload;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
outputError('No payload provided, aborting');
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
return { apiOptions, cliOptions };
|
|
79
|
+
};
|
|
80
|
+
const requiredOption = (option) => {
|
|
81
|
+
option.required = true;
|
|
82
|
+
return option;
|
|
83
|
+
};
|
|
84
|
+
export const cliSetup = (program) => program
|
|
85
|
+
.command('upload')
|
|
86
|
+
.option('-s, --scan-id <scanid>', 'Set the scan id')
|
|
87
|
+
.requiredOption('-r, --repository-id <repositoryid>', 'Set the repository id')
|
|
88
|
+
.option('-i, --container-image <container-image-name>', 'Set the container image name. ')
|
|
89
|
+
.addOption(requiredOption(new Option('-t, --type <type>', 'Set the provided payload type. Available options are: checkov, json-sbom').choices(['checkov', 'json-sbom'])))
|
|
90
|
+
.option('-f, --file <payloadFile>', 'Specify the payload file. The cli command wil read the file and use the contents as payload data.')
|
|
91
|
+
.option('-p, --payload <payload>', 'Set the payload')
|
|
92
|
+
.description('Upload a custom scan result.')
|
|
93
|
+
.action(cli);
|
|
94
|
+
export default { cli, cliSetup };
|
package/lib/configuration.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Configstore from 'configstore';
|
|
2
|
-
export declare const getConfigStore: () => Configstore;
|
|
3
|
-
export declare const getApiKey: () => any;
|
|
4
|
-
export declare const setApiKey: (newApiKey: string) => void;
|
|
1
|
+
import Configstore from 'configstore';
|
|
2
|
+
export declare const getConfigStore: () => Configstore;
|
|
3
|
+
export declare const getApiKey: () => any;
|
|
4
|
+
export declare const setApiKey: (newApiKey: string) => void;
|
package/lib/configuration.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import Configstore from 'configstore';
|
|
2
|
-
import { program } from './index.js';
|
|
3
|
-
export const getConfigStore = () => {
|
|
4
|
-
return new Configstore(program.name());
|
|
5
|
-
};
|
|
6
|
-
export const getApiKey = () => {
|
|
7
|
-
return program.getOptionValue('apikey')
|
|
8
|
-
? program.getOptionValue('apikey')
|
|
9
|
-
: getConfigStore().get('apikey');
|
|
10
|
-
};
|
|
11
|
-
export const setApiKey = (newApiKey) => {
|
|
12
|
-
return getConfigStore().set('apikey', newApiKey);
|
|
13
|
-
};
|
|
1
|
+
import Configstore from 'configstore';
|
|
2
|
+
import { program } from './index.js';
|
|
3
|
+
export const getConfigStore = () => {
|
|
4
|
+
return new Configstore(program.name());
|
|
5
|
+
};
|
|
6
|
+
export const getApiKey = () => {
|
|
7
|
+
return program.getOptionValue('apikey')
|
|
8
|
+
? program.getOptionValue('apikey')
|
|
9
|
+
: getConfigStore().get('apikey');
|
|
10
|
+
};
|
|
11
|
+
export const setApiKey = (newApiKey) => {
|
|
12
|
+
return getConfigStore().set('apikey', newApiKey);
|
|
13
|
+
};
|
package/lib/index.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { Command } from 'commander';
|
|
3
|
-
export declare const program: Command;
|
|
4
|
-
declare global {
|
|
5
|
-
namespace NodeJS {
|
|
6
|
-
interface ProcessEnv {
|
|
7
|
-
[key: string]: any;
|
|
8
|
-
QUIET?: boolean;
|
|
9
|
-
CLI_DEBUG?: boolean | string;
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
}
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
export declare const program: Command;
|
|
4
|
+
declare global {
|
|
5
|
+
namespace NodeJS {
|
|
6
|
+
interface ProcessEnv {
|
|
7
|
+
[key: string]: any;
|
|
8
|
+
QUIET?: boolean;
|
|
9
|
+
CLI_DEBUG?: boolean | string;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
package/lib/index.js
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import { Command } from 'commander';
|
|
4
|
-
import dotenv from 'dotenv';
|
|
5
|
-
import apiKey from './commands/apiKey.js';
|
|
6
|
-
import scan from './commands/scan.js';
|
|
7
|
-
import upload from './commands/upload.js';
|
|
8
|
-
dotenv.config(process.env.NODE_ENV ? { path: `.env.${process.env.NODE_ENV}` } : {});
|
|
9
|
-
export const program = new Command();
|
|
10
|
-
program
|
|
11
|
-
.name('Aikido API Client')
|
|
12
|
-
.description('CLI api client to easily integrate the Aikido public CI API into custom deploy scripts')
|
|
13
|
-
.version('1.0.1');
|
|
14
|
-
apiKey.cliSetup(program);
|
|
15
|
-
scan.cliSetup(program);
|
|
16
|
-
upload.cliSetup(program);
|
|
17
|
-
program
|
|
18
|
-
.option('-q, --quiet', 'Disable console output when executing commands')
|
|
19
|
-
.on('option:quiet', function () {
|
|
20
|
-
process.env.QUIET = true;
|
|
21
|
-
});
|
|
22
|
-
program
|
|
23
|
-
.option('--debug', 'Add additional debug information to command output')
|
|
24
|
-
.on('option:debug', function () {
|
|
25
|
-
process.env.CLI_DEBUG = true;
|
|
26
|
-
});
|
|
27
|
-
program.option('--apikey <apikey>', 'Use a cli apikey instead of reading the key from the configuration');
|
|
28
|
-
program.configureOutput({
|
|
29
|
-
outputError: (str, write) => write(chalk.red(str)),
|
|
30
|
-
});
|
|
31
|
-
program.parse();
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import dotenv from 'dotenv';
|
|
5
|
+
import apiKey from './commands/apiKey.js';
|
|
6
|
+
import scan from './commands/scan.js';
|
|
7
|
+
import upload from './commands/upload.js';
|
|
8
|
+
dotenv.config(process.env.NODE_ENV ? { path: `.env.${process.env.NODE_ENV}` } : {});
|
|
9
|
+
export const program = new Command();
|
|
10
|
+
program
|
|
11
|
+
.name('Aikido API Client')
|
|
12
|
+
.description('CLI api client to easily integrate the Aikido public CI API into custom deploy scripts')
|
|
13
|
+
.version('1.0.1');
|
|
14
|
+
apiKey.cliSetup(program);
|
|
15
|
+
scan.cliSetup(program);
|
|
16
|
+
upload.cliSetup(program);
|
|
17
|
+
program
|
|
18
|
+
.option('-q, --quiet', 'Disable console output when executing commands')
|
|
19
|
+
.on('option:quiet', function () {
|
|
20
|
+
process.env.QUIET = true;
|
|
21
|
+
});
|
|
22
|
+
program
|
|
23
|
+
.option('--debug', 'Add additional debug information to command output')
|
|
24
|
+
.on('option:debug', function () {
|
|
25
|
+
process.env.CLI_DEBUG = true;
|
|
26
|
+
});
|
|
27
|
+
program.option('--apikey <apikey>', 'Use a cli apikey instead of reading the key from the configuration');
|
|
28
|
+
program.configureOutput({
|
|
29
|
+
outputError: (str, write) => write(chalk.red(str)),
|
|
30
|
+
});
|
|
31
|
+
program.parse();
|
package/lib/output.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Ora } from 'ora';
|
|
2
|
-
import { AxiosError } from 'axios';
|
|
3
|
-
export declare const outputLog: (message: string) => void;
|
|
4
|
-
export declare const outputDebug: (variable: any) => void;
|
|
5
|
-
export declare const outputError: (message: string, exitCode?: number) => void;
|
|
6
|
-
export declare const outputHttpError: (axiosError: AxiosError) => void;
|
|
7
|
-
export declare const startSpinner: (message: string) => Ora | null;
|
|
1
|
+
import { Ora } from 'ora';
|
|
2
|
+
import { AxiosError } from 'axios';
|
|
3
|
+
export declare const outputLog: (message: string) => void;
|
|
4
|
+
export declare const outputDebug: (variable: any) => void;
|
|
5
|
+
export declare const outputError: (message: string, exitCode?: number) => void;
|
|
6
|
+
export declare const outputHttpError: (axiosError: AxiosError) => void;
|
|
7
|
+
export declare const startSpinner: (message: string) => Ora | null;
|
package/lib/output.js
CHANGED
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
import ora from 'ora';
|
|
2
|
-
import { program } from './index.js';
|
|
3
|
-
import chalk from 'chalk';
|
|
4
|
-
export const outputLog = (message) => {
|
|
5
|
-
if (!process.env.QUIET) {
|
|
6
|
-
console.log(message);
|
|
7
|
-
}
|
|
8
|
-
};
|
|
9
|
-
export const outputDebug = (variable) => {
|
|
10
|
-
if (process.env.CLI_DEBUG == true || process.env.CLI_DEBUG == 'true') {
|
|
11
|
-
console.log(chalk.blue(typeof variable == 'object' ? JSON.stringify(variable) : variable));
|
|
12
|
-
}
|
|
13
|
-
};
|
|
14
|
-
export const outputError = (message, exitCode = 1) => {
|
|
15
|
-
program.error(message, {
|
|
16
|
-
exitCode,
|
|
17
|
-
});
|
|
18
|
-
};
|
|
19
|
-
export const outputHttpError = (axiosError) => {
|
|
20
|
-
if (axiosError.code === 'ECONNREFUSED') {
|
|
21
|
-
outputError(`Could not connect to Aikido API (${axiosError.message}). Please verify your network settings`);
|
|
22
|
-
}
|
|
23
|
-
else if (axiosError.response?.status &&
|
|
24
|
-
axiosError.response?.status === 401) {
|
|
25
|
-
outputError('Request failed. The provided api key is most likely no longer valid and has been rotated or revoked. Visit https://app.aikido.dev/settings/integrations/continuous-integration to generate a new key.');
|
|
26
|
-
}
|
|
27
|
-
else if (axiosError.response?.status &&
|
|
28
|
-
axiosError.response?.status === 403) {
|
|
29
|
-
outputError('Could not authenticate with the Aikido API. Please verify your Aikdio API key.');
|
|
30
|
-
}
|
|
31
|
-
else if (axiosError.response?.status &&
|
|
32
|
-
axiosError.response?.status === 500) {
|
|
33
|
-
outputError('Something went wrong contacting the Aikido API.');
|
|
34
|
-
}
|
|
35
|
-
const statusStr = axiosError.response?.status
|
|
36
|
-
? ` (${axiosError.response?.status})`
|
|
37
|
-
: '';
|
|
38
|
-
if (axiosError.response) {
|
|
39
|
-
outputDebug(axiosError.response?.status);
|
|
40
|
-
outputDebug(axiosError.response?.headers);
|
|
41
|
-
outputDebug(axiosError.response?.data);
|
|
42
|
-
}
|
|
43
|
-
outputError(`Something unexpected went wrong${statusStr}... Please contact us if this problem persists.`);
|
|
44
|
-
};
|
|
45
|
-
export const startSpinner = (message) => {
|
|
46
|
-
if (process.env.QUIET) {
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
const spinner = ora(message);
|
|
50
|
-
spinner.color = 'magenta';
|
|
51
|
-
spinner.start();
|
|
52
|
-
return spinner;
|
|
53
|
-
};
|
|
1
|
+
import ora from 'ora';
|
|
2
|
+
import { program } from './index.js';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
export const outputLog = (message) => {
|
|
5
|
+
if (!process.env.QUIET) {
|
|
6
|
+
console.log(message);
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
export const outputDebug = (variable) => {
|
|
10
|
+
if (process.env.CLI_DEBUG == true || process.env.CLI_DEBUG == 'true') {
|
|
11
|
+
console.log(chalk.blue(typeof variable == 'object' ? JSON.stringify(variable) : variable));
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
export const outputError = (message, exitCode = 1) => {
|
|
15
|
+
program.error(message, {
|
|
16
|
+
exitCode,
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
export const outputHttpError = (axiosError) => {
|
|
20
|
+
if (axiosError.code === 'ECONNREFUSED') {
|
|
21
|
+
outputError(`Could not connect to Aikido API (${axiosError.message}). Please verify your network settings`);
|
|
22
|
+
}
|
|
23
|
+
else if (axiosError.response?.status &&
|
|
24
|
+
axiosError.response?.status === 401) {
|
|
25
|
+
outputError('Request failed. The provided api key is most likely no longer valid and has been rotated or revoked. Visit https://app.aikido.dev/settings/integrations/continuous-integration to generate a new key.');
|
|
26
|
+
}
|
|
27
|
+
else if (axiosError.response?.status &&
|
|
28
|
+
axiosError.response?.status === 403) {
|
|
29
|
+
outputError('Could not authenticate with the Aikido API. Please verify your Aikdio API key.');
|
|
30
|
+
}
|
|
31
|
+
else if (axiosError.response?.status &&
|
|
32
|
+
axiosError.response?.status === 500) {
|
|
33
|
+
outputError('Something went wrong contacting the Aikido API.');
|
|
34
|
+
}
|
|
35
|
+
const statusStr = axiosError.response?.status
|
|
36
|
+
? ` (${axiosError.response?.status})`
|
|
37
|
+
: '';
|
|
38
|
+
if (axiosError.response) {
|
|
39
|
+
outputDebug(axiosError.response?.status);
|
|
40
|
+
outputDebug(axiosError.response?.headers);
|
|
41
|
+
outputDebug(axiosError.response?.data);
|
|
42
|
+
}
|
|
43
|
+
outputError(`Something unexpected went wrong${statusStr}... Please contact us if this problem persists.`);
|
|
44
|
+
};
|
|
45
|
+
export const startSpinner = (message) => {
|
|
46
|
+
if (process.env.QUIET) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
const spinner = ora(message);
|
|
50
|
+
spinner.color = 'magenta';
|
|
51
|
+
spinner.start();
|
|
52
|
+
return spinner;
|
|
53
|
+
};
|
package/package.json
CHANGED
|
@@ -1,51 +1,51 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@aikidosec/ci-api-client",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "CLI api client to easily integrate the Aikido public CI API into custom deploy scripts",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"author": "Bert Devriese <bert@builtinbruges.com>",
|
|
7
|
-
"private": false,
|
|
8
|
-
"type": "module",
|
|
9
|
-
"main": "lib/index.js",
|
|
10
|
-
"bin": {
|
|
11
|
-
"aikido-api-client": "./lib/index.js"
|
|
12
|
-
},
|
|
13
|
-
"repository": {
|
|
14
|
-
"type": "git",
|
|
15
|
-
"url": "https://github.com/AikidoSec/api-client.git"
|
|
16
|
-
},
|
|
17
|
-
"scripts": {
|
|
18
|
-
"start": "nodemon --watch 'src/**/*.ts' --esm --exec 'ts-node' src/index.ts",
|
|
19
|
-
"build": "tsc -p .",
|
|
20
|
-
"local": "yarn build && yarn global add file:$PWD; aikido-api-client",
|
|
21
|
-
"local-rm": "yarn global remove aikido-api-client",
|
|
22
|
-
"format": "prettier --write 'src/**/*.ts'",
|
|
23
|
-
"//": {
|
|
24
|
-
"refresh": "rm -rf ./node_modules ./yarn.lock && yarn"
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
"dependencies": {
|
|
28
|
-
"axios": "^1.4.0",
|
|
29
|
-
"chalk": "^5.3.0",
|
|
30
|
-
"commander": "^11.0.0",
|
|
31
|
-
"configstore": "^6.0.0",
|
|
32
|
-
"dotenv": "^16.3.1",
|
|
33
|
-
"ora": "^6.3.1"
|
|
34
|
-
},
|
|
35
|
-
"devDependencies": {
|
|
36
|
-
"@types/chalk": "^2.2.0",
|
|
37
|
-
"@types/commander": "^2.12.2",
|
|
38
|
-
"@types/configstore": "^6.0.0",
|
|
39
|
-
"@types/dotenv": "^8.2.0",
|
|
40
|
-
"@types/node": "^20.3.3",
|
|
41
|
-
"nodemon": "^2.0.22",
|
|
42
|
-
"prettier": "^2.8.8",
|
|
43
|
-
"ts-node": "^10.9.1",
|
|
44
|
-
"typescript": "^5.1.6"
|
|
45
|
-
},
|
|
46
|
-
"keywords": [
|
|
47
|
-
"aikido",
|
|
48
|
-
"security",
|
|
49
|
-
"cli"
|
|
50
|
-
]
|
|
51
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@aikidosec/ci-api-client",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "CLI api client to easily integrate the Aikido public CI API into custom deploy scripts",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Bert Devriese <bert@builtinbruges.com>",
|
|
7
|
+
"private": false,
|
|
8
|
+
"type": "module",
|
|
9
|
+
"main": "lib/index.js",
|
|
10
|
+
"bin": {
|
|
11
|
+
"aikido-api-client": "./lib/index.js"
|
|
12
|
+
},
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "https://github.com/AikidoSec/api-client.git"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"start": "nodemon --watch 'src/**/*.ts' --esm --exec 'ts-node' src/index.ts",
|
|
19
|
+
"build": "tsc -p .",
|
|
20
|
+
"local": "yarn build && yarn global add file:$PWD; aikido-api-client",
|
|
21
|
+
"local-rm": "yarn global remove aikido-api-client",
|
|
22
|
+
"format": "prettier --write 'src/**/*.ts'",
|
|
23
|
+
"//": {
|
|
24
|
+
"refresh": "rm -rf ./node_modules ./yarn.lock && yarn"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"axios": "^1.4.0",
|
|
29
|
+
"chalk": "^5.3.0",
|
|
30
|
+
"commander": "^11.0.0",
|
|
31
|
+
"configstore": "^6.0.0",
|
|
32
|
+
"dotenv": "^16.3.1",
|
|
33
|
+
"ora": "^6.3.1"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/chalk": "^2.2.0",
|
|
37
|
+
"@types/commander": "^2.12.2",
|
|
38
|
+
"@types/configstore": "^6.0.0",
|
|
39
|
+
"@types/dotenv": "^8.2.0",
|
|
40
|
+
"@types/node": "^20.3.3",
|
|
41
|
+
"nodemon": "^2.0.22",
|
|
42
|
+
"prettier": "^2.8.8",
|
|
43
|
+
"ts-node": "^10.9.1",
|
|
44
|
+
"typescript": "^5.1.6"
|
|
45
|
+
},
|
|
46
|
+
"keywords": [
|
|
47
|
+
"aikido",
|
|
48
|
+
"security",
|
|
49
|
+
"cli"
|
|
50
|
+
]
|
|
51
|
+
}
|