Use the API Luke (#3825)

This commit is contained in:
Peter Hedenskog 2023-05-03 09:31:54 +02:00 committed by GitHub
parent ed87e6222d
commit 0bfbdba69c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 639 additions and 41 deletions

View File

@ -5,8 +5,100 @@
import { writeFileSync } from 'node:fs';
import { execSync } from 'node:child_process';
import { platform } from 'node:os';
import { resolve } from 'node:path';
import { readFileSync } from 'node:fs';
import merge from 'lodash.merge';
import ora from 'ora';
import { parseCommandLine } from '../lib/cli/cli.js';
import { run } from '../lib/sitespeed.js';
import { addTest, waitAndGetResult, get } from '../lib/api/send.js';
async function api(options) {
const action = options.api.action ?? 'addAndGetResult';
if (action === 'get' && !options.api.id) {
process.exitCode = 1;
console.log('Missing test id --api.id');
process.exit();
}
const hostname = options.api.hostname;
let apiOptions = options.explicitOptions;
// Delete the hostname to make sure the server do not end in
// a forever loop
delete apiOptions.api.hostname;
/*
// Add support for running multi tests
if (options.multi) {
const scripting = await readFileSync(
new URL(resolve(process.cwd(), options._[0]), import.meta.url)
);
}
*/
if (options.config) {
const config = JSON.parse(
await readFileSync(
new URL(resolve(process.cwd(), options.config), import.meta.url)
)
);
apiOptions = merge(options.explicitOptions, config);
delete apiOptions.config;
}
if (action === 'add' || action === 'addAndGetResult') {
const spinner = ora({
text: `Send test to ${hostname}`,
isSilent: options.api.silent
}).start();
try {
const data = await addTest(hostname, apiOptions, spinner);
const testId = JSON.parse(data).id;
spinner.color = 'yellow';
spinner.text = `Added test with id ${testId}`;
if (action === 'add') {
spinner.succeed(`Added test with id ${testId}`);
console.log(testId);
process.exit();
} else if (action === 'addAndGetResult') {
const result = await waitAndGetResult(
testId,
hostname,
apiOptions,
spinner
);
spinner.succeed(`Got test result with id ${testId}`);
if (options.api.json) {
console.log(JSON.stringify(result));
} else {
console.log(result.result);
}
}
} catch (error) {
spinner.fail(error.message);
process.exitCode = 1;
process.exit();
}
} else if (action === 'get') {
try {
const result = await get(options.api.id, hostname, apiOptions);
if (options.api.json) {
console.log(JSON.stringify(result));
} else {
console.log(result);
}
} catch (error) {
process.exitCode = 1;
console.log(error);
}
}
}
async function start() {
let parsed = await parseCommandLine();
@ -17,45 +109,49 @@ async function start() {
parsed.options.urlsMetaData = parsed.urlsMetaData;
let options = parsed.options;
process.exitCode = 1;
try {
const result = await run(options);
// This can be used as an option to get hold of where the data is stored
// for third parties
if (options.storeResult == 'true') {
writeFileSync('result.json', JSON.stringify(result));
}
if (result.errors.length > 0) {
throw new Error('Errors while running:\n' + result.errors.join('\n'));
}
if ((options.open || options.o) && platform() === 'darwin') {
execSync('open ' + result.localPath + '/index.html');
} else if ((options.open || options.o) && platform() === 'linux') {
execSync('xdg-open ' + result.localPath + '/index.html');
}
if (
parsed.options.budget &&
Object.keys(result.budgetResult.failing).length > 0
) {
process.exitCode = 1;
budgetFailing = true;
}
if (
!budgetFailing ||
(parsed.options.budget && parsed.options.budget.suppressExitCode)
) {
process.exitCode = 0;
}
} catch (error) {
if (options.api && options.api.hostname) {
api(options);
} else {
process.exitCode = 1;
console.log(error);
} finally {
process.exit();
try {
const result = await run(options);
// This can be used as an option to get hold of where the data is stored
// for third parties
if (options.storeResult == 'true') {
writeFileSync('result.json', JSON.stringify(result));
}
if (result.errors.length > 0) {
throw new Error('Errors while running:\n' + result.errors.join('\n'));
}
if ((options.open || options.o) && platform() === 'darwin') {
execSync('open ' + result.localPath + '/index.html');
} else if ((options.open || options.o) && platform() === 'linux') {
execSync('xdg-open ' + result.localPath + '/index.html');
}
if (
parsed.options.budget &&
Object.keys(result.budgetResult.failing).length > 0
) {
process.exitCode = 1;
budgetFailing = true;
}
if (
!budgetFailing ||
(parsed.options.budget && parsed.options.budget.suppressExitCode)
) {
process.exitCode = 0;
}
} catch (error) {
process.exitCode = 1;
console.log(error);
} finally {
process.exit();
}
}
}

93
lib/api/send.js Normal file
View File

@ -0,0 +1,93 @@
import http from 'node:http';
import https from 'node:https';
const delay = ms => new Promise(res => setTimeout(res, ms));
export async function addTest(hostname, options, spinner) {
const port = options.api.port ?? 3000;
const postData = options;
const postOptions = {
hostname: hostname,
port: port,
path: '/api/add',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(JSON.stringify(postData))
}
};
return new Promise((resolve, reject) => {
// not perfect but maybe work for us
const library = options.api.port === 443 ? https : http;
const request = library.request(postOptions, res => {
if (res.statusCode === 200) {
res.setEncoding('utf8');
let body = '';
res.on('data', chunk => (body += chunk));
res.on('end', () => resolve(body));
} else {
spinner.text = `Got ${res.statusCode} from the API: ${res.statusMessage}`;
spinner.color = 'red';
const e = new Error(
`Got ${res.statusCode} from the API: ${res.statusMessage}`
);
reject(e);
}
});
request.on('error', error => {
spinner.text = `Got ${error.toString()} from the API`;
spinner.color = 'red';
reject(error);
});
request.write(JSON.stringify(postData));
request.end();
});
}
export async function waitAndGetResult(testId, hostname, options, spinner) {
do {
await delay(2000);
const response = await get(testId, hostname, options);
spinner.text = response.message;
if (response.status === 'completed') {
return response;
}
// eslint-disable-next-line no-constant-condition
} while (true);
}
export async function get(testId, hostname, options) {
return new Promise((resolve, reject) => {
const port = options.api.port ?? 3000;
const library = port === 443 ? https : http;
const url = `${port === 443 ? 'https' : 'http'}://${hostname}${
port != 80 && port != 443 ? `:${port}` : ''
}/api/status/${testId}`;
library
.get(url, res => {
let data = [];
if (res.statusCode != 200) {
return reject(
new Error(
`Got response code ${res.statusCode} from the API: ${res.statusMessage}`
)
);
}
res.on('data', chunk => {
data.push(chunk);
});
res.on('end', () => {
return resolve(JSON.parse(Buffer.concat(data).toString()));
});
})
.on('error', () => {
return reject();
});
});
}

View File

@ -1092,6 +1092,21 @@ export async function parseCommandLine() {
'The wait time before you start the real testing after your pre-cache request.'
})
/*
API options
*/
.option('api.key', {
describe: 'The API key to use',
group: 'API'
})
.option('api.hostname', {
describe: 'The hostname of the server hosting the API',
group: 'API'
})
.option('api.serverName', {
describe: 'The serverName that will run the actual test',
group: 'API'
})
/*
Crawler options
*/
.option('crawler.depth', {
@ -1797,6 +1812,38 @@ export async function parseCommandLine() {
'Instead of using the local copy of the hosting database, you can use the latest version through the Green Web Foundation API. This means sitespeed.io will make HTTP GET to the the hosting info.',
group: 'Sustainable'
});
parsed
.option('api.type', {
describe: 'The type of API call you want to do: S',
default: 'addAndGetResult',
choices: ['add', 'addAndGetResult', 'get'],
group: 'API'
})
.option('api.hostname', {
describe: 'The hostname of the API server.',
group: 'API'
})
.option('api.silent', {
describe:
'Set to true if you do not want to log anything from the comunication',
default: false,
group: 'API'
})
.option('api.port', {
describe: 'The port for the API',
port: 3000,
group: 'API'
})
.option('api.id', {
describe:
'The id of the test. You it when you want to get the test result.',
group: 'API'
})
.option('api.json', {
describe: 'Output the result as JSON.',
group: 'API'
});
parsed
.option('mobile', {
describe:

367
npm-shrinkwrap.json generated
View File

@ -45,6 +45,7 @@
"markdown": "0.5.0",
"node-scp": "0.0.22",
"node-slack": "0.0.7",
"ora": "6.3.0",
"os-name": "5.1.0",
"p-limit": "4.0.0",
"pug": "3.0.2",
@ -1809,6 +1810,58 @@
"file-uri-to-path": "1.0.0"
}
},
"node_modules/bl": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz",
"integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==",
"dependencies": {
"buffer": "^6.0.3",
"inherits": "^2.0.4",
"readable-stream": "^3.4.0"
}
},
"node_modules/bl/node_modules/buffer": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.2.1"
}
},
"node_modules/bl/node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/blueimp-md5": {
"version": "2.19.0",
"resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz",
@ -2272,6 +2325,31 @@
"node": ">=0.10"
}
},
"node_modules/cli-cursor": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz",
"integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==",
"dependencies": {
"restore-cursor": "^4.0.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/cli-spinners": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.8.0.tgz",
"integrity": "sha512-/eG5sJcvEIwxcdYM86k5tPwn0MUzkX5YY3eImTGpJOZgVe4SdTMY14vQpcxgBzJ0wXwAYrS8E+c3uHeK4JNyzQ==",
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/cli-truncate": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz",
@ -2364,6 +2442,14 @@
"node": ">=8"
}
},
"node_modules/clone": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
"integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
"engines": {
"node": ">=0.8"
}
},
"node_modules/coach-core": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/coach-core/-/coach-core-7.1.3.tgz",
@ -2696,6 +2782,17 @@
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
"dev": true
},
"node_modules/defaults": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
"integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
"dependencies": {
"clone": "^1.0.2"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/deferred": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/deferred/-/deferred-0.7.1.tgz",
@ -4976,6 +5073,17 @@
"node": ">=0.10.0"
}
},
"node_modules/is-interactive": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz",
"integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-map": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
@ -5150,7 +5258,6 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz",
"integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==",
"dev": true,
"engines": {
"node": ">=12"
},
@ -5883,6 +5990,32 @@
"resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz",
"integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg="
},
"node_modules/log-symbols": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz",
"integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==",
"dependencies": {
"chalk": "^5.0.0",
"is-unicode-supported": "^1.1.0"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/log-symbols/node_modules/chalk": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz",
"integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==",
"engines": {
"node": "^12.17.0 || ^14.13 || >=16.0.0"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
@ -6505,6 +6638,64 @@
"node": ">= 0.8.0"
}
},
"node_modules/ora": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/ora/-/ora-6.3.0.tgz",
"integrity": "sha512-1/D8uRFY0ay2kgBpmAwmSA404w4OoPVhHMqRqtjvrcK/dnzcEZxMJ+V4DUbyICu8IIVRclHcOf5wlD1tMY4GUQ==",
"dependencies": {
"chalk": "^5.0.0",
"cli-cursor": "^4.0.0",
"cli-spinners": "^2.6.1",
"is-interactive": "^2.0.0",
"is-unicode-supported": "^1.1.0",
"log-symbols": "^5.1.0",
"stdin-discarder": "^0.1.0",
"strip-ansi": "^7.0.1",
"wcwidth": "^1.0.1"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/ora/node_modules/ansi-regex": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/ora/node_modules/chalk": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz",
"integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==",
"engines": {
"node": "^12.17.0 || ^14.13 || >=16.0.0"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/ora/node_modules/strip-ansi": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz",
"integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==",
"dependencies": {
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/os-homedir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
@ -7658,6 +7849,21 @@
"node": ">=4"
}
},
"node_modules/restore-cursor": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz",
"integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==",
"dependencies": {
"onetime": "^5.1.0",
"signal-exit": "^3.0.2"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/resumer": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz",
@ -8200,6 +8406,20 @@
"node": ">=8"
}
},
"node_modules/stdin-discarder": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.1.0.tgz",
"integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==",
"dependencies": {
"bl": "^5.0.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/stop-iteration-iterator": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz",
@ -8931,6 +9151,14 @@
}
]
},
"node_modules/wcwidth": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
"integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
"dependencies": {
"defaults": "^1.0.3"
}
},
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
@ -10601,6 +10829,32 @@
"file-uri-to-path": "1.0.0"
}
},
"bl": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz",
"integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==",
"requires": {
"buffer": "^6.0.3",
"inherits": "^2.0.4",
"readable-stream": "^3.4.0"
},
"dependencies": {
"buffer": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
"requires": {
"base64-js": "^1.3.1",
"ieee754": "^1.2.1"
}
},
"ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
}
}
},
"blueimp-md5": {
"version": "2.19.0",
"resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz",
@ -10946,6 +11200,19 @@
"timers-ext": "^0.1.7"
}
},
"cli-cursor": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz",
"integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==",
"requires": {
"restore-cursor": "^4.0.0"
}
},
"cli-spinners": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.8.0.tgz",
"integrity": "sha512-/eG5sJcvEIwxcdYM86k5tPwn0MUzkX5YY3eImTGpJOZgVe4SdTMY14vQpcxgBzJ0wXwAYrS8E+c3uHeK4JNyzQ=="
},
"cli-truncate": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz",
@ -11009,6 +11276,11 @@
}
}
},
"clone": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
"integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg=="
},
"coach-core": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/coach-core/-/coach-core-7.1.3.tgz",
@ -11290,6 +11562,14 @@
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
"dev": true
},
"defaults": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
"integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
"requires": {
"clone": "^1.0.2"
}
},
"deferred": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/deferred/-/deferred-0.7.1.tgz",
@ -12981,6 +13261,11 @@
"is-extglob": "^2.1.1"
}
},
"is-interactive": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz",
"integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ=="
},
"is-map": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
@ -13091,8 +13376,7 @@
"is-unicode-supported": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz",
"integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==",
"dev": true
"integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="
},
"is-weakmap": {
"version": "2.0.1",
@ -13728,6 +14012,22 @@
"resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz",
"integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg="
},
"log-symbols": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz",
"integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==",
"requires": {
"chalk": "^5.0.0",
"is-unicode-supported": "^1.1.0"
},
"dependencies": {
"chalk": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz",
"integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA=="
}
}
},
"lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
@ -14182,6 +14482,42 @@
"word-wrap": "^1.2.3"
}
},
"ora": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/ora/-/ora-6.3.0.tgz",
"integrity": "sha512-1/D8uRFY0ay2kgBpmAwmSA404w4OoPVhHMqRqtjvrcK/dnzcEZxMJ+V4DUbyICu8IIVRclHcOf5wlD1tMY4GUQ==",
"requires": {
"chalk": "^5.0.0",
"cli-cursor": "^4.0.0",
"cli-spinners": "^2.6.1",
"is-interactive": "^2.0.0",
"is-unicode-supported": "^1.1.0",
"log-symbols": "^5.1.0",
"stdin-discarder": "^0.1.0",
"strip-ansi": "^7.0.1",
"wcwidth": "^1.0.1"
},
"dependencies": {
"ansi-regex": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA=="
},
"chalk": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz",
"integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA=="
},
"strip-ansi": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz",
"integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==",
"requires": {
"ansi-regex": "^6.0.1"
}
}
}
},
"os-homedir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
@ -15082,6 +15418,15 @@
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
"dev": true
},
"restore-cursor": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz",
"integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==",
"requires": {
"onetime": "^5.1.0",
"signal-exit": "^3.0.2"
}
},
"resumer": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz",
@ -15477,6 +15822,14 @@
}
}
},
"stdin-discarder": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.1.0.tgz",
"integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==",
"requires": {
"bl": "^5.0.0"
}
},
"stop-iteration-iterator": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz",
@ -16039,6 +16392,14 @@
"resolved": "https://registry.npmjs.org/wappalyzer-core/-/wappalyzer-core-6.6.0.tgz",
"integrity": "sha512-pdod7Zg1GwVJBSjMSmV8kiFfPhzUcRbjQeQo4Alcfu7p7epGYggP9xdBSY8o1PlJOvmW/FMQH5AEd7Scxb0wUA=="
},
"wcwidth": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
"integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
"requires": {
"defaults": "^1.0.3"
}
},
"webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",

View File

@ -113,6 +113,7 @@
"markdown": "0.5.0",
"node-scp": "0.0.22",
"node-slack": "0.0.7",
"ora": "6.3.0",
"os-name": "5.1.0",
"p-limit": "4.0.0",
"pug": "3.0.2",