0
Fork 0
mirror of https://github.com/verdaccio/verdaccio.git synced 2024-12-16 21:56:25 -05:00

chore: extend lint rules to root

This commit is contained in:
Juan Picado @jotadeveloper 2020-08-13 23:36:23 +02:00 committed by Juan Picado
parent e61bd6c78f
commit 9ed932e589
41 changed files with 84 additions and 160 deletions

View file

@ -109,7 +109,6 @@
"@typescript-eslint/ban-ts-ignore": 0, "@typescript-eslint/ban-ts-ignore": 0,
"@typescript-eslint/no-var-requires": 0, "@typescript-eslint/no-var-requires": 0,
"@typescript-eslint/no-inferrable-types": 0, "@typescript-eslint/no-inferrable-types": 0,
"@typescript-eslint/interface-name-prefix": 0,
"@typescript-eslint/no-empty-function": 0, "@typescript-eslint/no-empty-function": 0,
"@typescript-eslint/no-this-alias": 0, "@typescript-eslint/no-this-alias": 0,
"@typescript-eslint/no-use-before-define": 0, "@typescript-eslint/no-use-before-define": 0,

2
debug/bootstrap.js vendored
View file

@ -1,6 +1,6 @@
// this file aims to help local debugging with hot transpilation // this file aims to help local debugging with hot transpilation
// it requires BABEL_ENV=registry set as env variable // it requires BABEL_ENV=registry set as env variable
require('@babel/register')({ require('@babel/register')({
extensions: [".ts", ".js"] extensions: ['.ts', '.js'],
}); });
require('../packages/cli/src/index'); require('../packages/cli/src/index');

View file

@ -5,11 +5,6 @@ module.exports = {
}, },
verbose: false, verbose: false,
collectCoverage: true, collectCoverage: true,
collectCoverageFrom: [ collectCoverageFrom: ['src/**/*.ts', '!**/node_modules/**', '!**/partials/**', '!**/fixture/**'],
"src/**/*.ts",
"!**/node_modules/**",
"!**/partials/**",
"!**/fixture/**",
],
coveragePathIgnorePatterns: ['node_modules', 'fixtures'], coveragePathIgnorePatterns: ['node_modules', 'fixtures'],
}; };

View file

@ -101,7 +101,7 @@
"clean": "pnpm recursive run clean", "clean": "pnpm recursive run clean",
"build": "pnpm recursive run build", "build": "pnpm recursive run build",
"docker": "docker build -t verdaccio/verdaccio:local . --no-cache", "docker": "docker build -t verdaccio/verdaccio:local . --no-cache",
"lint": "eslint \"packages/**/@(src|tests|test)/**\"", "lint": "eslint . --ext .js,.ts,.tsx,.jsx",
"test": "pnpm recursive test", "test": "pnpm recursive test",
"test:e2e:cli": "cross-env NODE_ENV=test jest --config ./test/e2e-cli/jest.config.e2e.cli.js --passWithNoTests", "test:e2e:cli": "cross-env NODE_ENV=test jest --config ./test/e2e-cli/jest.config.e2e.cli.js --passWithNoTests",
"website:lint": "cd website && yarn lint", "website:lint": "cd website && yarn lint",

View file

@ -1,19 +1,19 @@
const setup = jest.fn(); const setup = jest.fn();
const logger = { const logger = {
child: jest.fn(() => ({ child: jest.fn(() => ({
debug: jest.fn(), debug: jest.fn(),
trace: jest.fn(), trace: jest.fn(),
warn: jest.fn(), warn: jest.fn(),
info: jest.fn(), info: jest.fn(),
error: jest.fn(), error: jest.fn(),
fatal: jest.fn(), fatal: jest.fn(),
})), })),
debug: jest.fn(), debug: jest.fn(),
trace: jest.fn(), trace: jest.fn(),
warn: jest.fn(), warn: jest.fn(),
info: jest.fn(), info: jest.fn(),
error: jest.fn(), error: jest.fn(),
fatal: jest.fn(), fatal: jest.fn(),
}; };
export { setup, logger } export { setup, logger };

View file

@ -1,4 +1,4 @@
import { Logger, RemoteUser } from "@verdaccio/types"; import { Logger, RemoteUser } from '@verdaccio/types';
declare global { declare global {
namespace Express { namespace Express {

View file

@ -1,4 +1,3 @@
const config = require('../../jest/config'); const config = require('../../jest/config');
module.exports = Object.assign({}, config, {}); module.exports = Object.assign({}, config, {});

View file

@ -1,4 +1,3 @@
const config = require('../../jest/config'); const config = require('../../jest/config');
module.exports = Object.assign({}, config, {}); module.exports = Object.assign({}, config, {});

View file

@ -3,4 +3,3 @@ const config = require('../../jest/config');
module.exports = Object.assign({}, config, { module.exports = Object.assign({}, config, {
verbose: true, verbose: true,
}); });

View file

@ -1,6 +1,5 @@
const config = require('../../jest/config'); const config = require('../../jest/config');
module.exports = Object.assign({}, config, { module.exports = Object.assign({}, config, {
collectCoverage: true collectCoverage: true,
}); });

View file

@ -1,7 +1,7 @@
// <reference types="node" /> // <reference types="node" />
import { Logger, RemoteUser } from "@verdaccio/types"; import * as http from 'http';
import * as http from "http"; import { Logger, RemoteUser } from '@verdaccio/types';
declare global { declare global {
namespace Express { namespace Express {

View file

@ -1,6 +1,5 @@
const config = require('../../jest/config'); const config = require('../../jest/config');
module.exports = Object.assign({}, config, { module.exports = Object.assign({}, config, {
collectCoverage: true collectCoverage: true,
}); });

View file

@ -1,6 +1,5 @@
const config = require('../../jest/config'); const config = require('../../jest/config');
module.exports = Object.assign({}, config, { module.exports = Object.assign({}, config, {
collectCoverage: true collectCoverage: true,
}); });

View file

@ -1,6 +1,5 @@
const config = require('../../jest/config'); const config = require('../../jest/config');
module.exports = Object.assign({}, config, { module.exports = Object.assign({}, config, {
collectCoverage: true collectCoverage: true,
}); });

View file

@ -1,6 +1,5 @@
const config = require('../../jest/config'); const config = require('../../jest/config');
module.exports = Object.assign({}, config, { module.exports = Object.assign({}, config, {
setupFilesAfterEnv: ['./jest.setup.js'] setupFilesAfterEnv: ['./jest.setup.js'],
}); });

View file

@ -1,4 +1,4 @@
import { Logger, RemoteUser } from "@verdaccio/types"; import { Logger, RemoteUser } from '@verdaccio/types';
declare global { declare global {
namespace Express { namespace Express {

View file

@ -2,6 +2,5 @@ const config = require('../../jest/config');
module.exports = Object.assign({}, config, { module.exports = Object.assign({}, config, {
// FIXME: coverage fails here // FIXME: coverage fails here
collectCoverage: true collectCoverage: true,
}); });

View file

@ -1,4 +1,4 @@
import { Logger, RemoteUser } from "@verdaccio/types"; import { Logger, RemoteUser } from '@verdaccio/types';
declare global { declare global {
namespace Express { namespace Express {

View file

@ -17,13 +17,13 @@ import {
Package, Package,
IPluginStorageFilter, IPluginStorageFilter,
Author, Author,
AuthPluginPackage, AuthPluginPackage,
Token, Token,
ITokenActions, ITokenActions,
TokenFilter TokenFilter,
} from '@verdaccio/types'; } from '@verdaccio/types';
import lunrMutable from 'lunr-mutable-indexes'; import lunrMutable from 'lunr-mutable-indexes';
import {NextFunction, Request, Response} from 'express'; import { NextFunction, Request, Response } from 'express';
export type StringValue = verdaccio$StringValue; export type StringValue = verdaccio$StringValue;
@ -42,13 +42,13 @@ export interface LegacyPackageList {
export type PackageAccessAddOn = PackageAccess & { export type PackageAccessAddOn = PackageAccess & {
// FIXME: should be published on @verdaccio/types // FIXME: should be published on @verdaccio/types
unpublish?: string[]; unpublish?: string[];
} };
export type MatchedPackage = PackageAccess | void; export type MatchedPackage = PackageAccess | void;
export type JWTPayload = RemoteUser & { export type JWTPayload = RemoteUser & {
password?: string; password?: string;
} };
export interface AESPayload { export interface AESPayload {
user: string; user: string;
@ -92,10 +92,10 @@ export interface Profile {
fullname: string; fullname: string;
} }
export type $RequestExtend = Request & {remote_user?: any; log: Logger} export type $RequestExtend = Request & { remote_user?: any; log: Logger };
export type $ResponseExtend = Response & {cookies?: any} export type $ResponseExtend = Response & { cookies?: any };
export type $NextFunctionVer = NextFunction & any; export type $NextFunctionVer = NextFunction & any;
export type $SidebarPackage = Package & {latest: any} export type $SidebarPackage = Package & { latest: any };
export interface IAuthWebUI { export interface IAuthWebUI {
jwtEncrypt(user: RemoteUser, signOptions: JWTSignOptions): Promise<string>; jwtEncrypt(user: RemoteUser, signOptions: JWTSignOptions): Promise<string>;
@ -194,4 +194,3 @@ export interface Styles {
} }
export type AuthorAvatar = Author & { avatar?: string }; export type AuthorAvatar = Author & { avatar?: string };

View file

@ -1,6 +1,6 @@
// this file aims to help local debugging with hot transpilation // this file aims to help local debugging with hot transpilation
// it requires BABEL_ENV=registry set as env variable // it requires BABEL_ENV=registry set as env variable
require('@babel/register')({ require('@babel/register')({
extensions: [".ts"] extensions: ['.ts'],
}); });
require('@verdaccio/cli'); require('@verdaccio/cli');

View file

@ -10,7 +10,7 @@ module.exports = {
// Some unit tests rely on data folders that look like packages. This confuses jest-hast-map // Some unit tests rely on data folders that look like packages. This confuses jest-hast-map
// when it tries to scan for package.json files. // when it tries to scan for package.json files.
transform: { transform: {
'^.+\\.[t|j]sx?$': 'babel-jest' '^.+\\.[t|j]sx?$': 'babel-jest',
}, },
modulePathIgnorePatterns: [ modulePathIgnorePatterns: [
'<rootDir>/test/unit/partials/mock-store/.*/package.json', '<rootDir>/test/unit/partials/mock-store/.*/package.json',
@ -28,14 +28,6 @@ module.exports = {
'<rootDir>/build', '<rootDir>/build',
'<rootDir>/.vscode/', '<rootDir>/.vscode/',
], ],
testPathIgnorePatterns: [ testPathIgnorePatterns: ['__snapshots__', '<rootDir>/build'],
'__snapshots__', coveragePathIgnorePatterns: ['node_modules', 'fixtures', '<rootDir>/src/api/debug', '<rootDir>/test'],
'<rootDir>/build',
],
coveragePathIgnorePatterns: [
'node_modules',
'fixtures',
'<rootDir>/src/api/debug',
'<rootDir>/test',
]
}; };

View file

@ -1,4 +1,3 @@
const config = require('../../jest/config'); const config = require('../../jest/config');
module.exports = Object.assign({}, config, {}); module.exports = Object.assign({}, config, {});

View file

@ -1,4 +1,4 @@
import { Logger, RemoteUser } from "@verdaccio/types"; import { Logger, RemoteUser } from '@verdaccio/types';
declare global { declare global {
namespace Express { namespace Express {

View file

@ -3,6 +3,6 @@
// this file aims to help local debugging with hot transpilation // this file aims to help local debugging with hot transpilation
// it requires BABEL_ENV=registry set as env variable // it requires BABEL_ENV=registry set as env variable
require('@babel/register')({ require('@babel/register')({
extensions: [".ts", ".js"] extensions: ['.ts', '.js'],
}); });
require('../src/lib/cli'); require('../src/lib/cli');

View file

@ -15,7 +15,7 @@ const octokit = new Octokit({
const [repoOwner, repoName] = process.env.GITHUB_REPOSITORY.split('/'); const [repoOwner, repoName] = process.env.GITHUB_REPOSITORY.split('/');
getStdin() getStdin()
.then(changelog => .then((changelog) =>
octokit.repos.createRelease({ octokit.repos.createRelease({
owner: repoOwner, owner: repoOwner,
repo: repoName, repo: repoName,
@ -24,7 +24,7 @@ getStdin()
draft: false, draft: false,
}) })
) )
.catch(err => { .catch((err) => {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.error(err); console.error(err);
process.exit(1); process.exit(1);

View file

@ -1,5 +1,6 @@
{ {
"rules": { "rules": {
"no-console": 0,
"@typescript-eslint/no-var-requires": 0, "@typescript-eslint/no-var-requires": 0,
"@typescript-eslint/explicit-member-accessibility": 0 "@typescript-eslint/explicit-member-accessibility": 0
} }

View file

@ -1,4 +1,4 @@
require('@babel/register')({ require('@babel/register')({
extensions: [".ts", ".js"] extensions: ['.ts', '.js'],
}); });
module.exports = require('./setup/test_environment'); module.exports = require('./setup/test_environment');

View file

@ -1,4 +1,4 @@
require('@babel/register')({ require('@babel/register')({
extensions: [".ts", ".js"] extensions: ['.ts', '.js'],
}); });
module.exports = require('./setup/setup'); module.exports = require('./setup/setup');

View file

@ -1,4 +1,4 @@
require('@babel/register')({ require('@babel/register')({
extensions: [".ts", ".js"] extensions: ['.ts', '.js'],
}); });
module.exports = require('./setup/teardown'); module.exports = require('./setup/teardown');

View file

@ -8,5 +8,5 @@ module.exports = {
testEnvironment: './env_babel.js', testEnvironment: './env_babel.js',
globalSetup: './env_setup.js', globalSetup: './env_setup.js',
globalTeardown: './env_teardown.js', globalTeardown: './env_teardown.js',
testRegex: '(/test/e2e.*\\.spec)\\.ts' testRegex: '(/test/e2e.*\\.spec)\\.ts',
}; };

View file

@ -1,5 +1,5 @@
module.exports = function() { module.exports = function () {
const message = "this is a basic project"; const message = 'this is a basic project';
console.log(message); console.log(message);
return message; return message;

View file

@ -1,5 +1,5 @@
module.exports = function() { module.exports = function () {
const message = "this is a scoped basic project"; const message = 'this is a scoped basic project';
console.log(message); console.log(message);
return message; return message;

View file

@ -1,44 +1,27 @@
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import os from 'os'; import os from 'os';
import { green } from 'kleur';
import { spawn } from 'child_process'; import { spawn } from 'child_process';
import { yellow } from 'kleur';
import { npm } from '../utils/process'; import { npm } from '../utils/process';
import * as __global from '../utils/global.js'; import * as __global from '../utils/global.js';
module.exports = async () => { module.exports = async () => {
const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), 'verdaccio-cli-e2e-')); const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), 'verdaccio-cli-e2e-'));
const tempConfigFile = path.join(tempRoot, 'verdaccio.yaml');
__global.addItem('dir-root', tempRoot); __global.addItem('dir-root', tempRoot);
console.log(green(`Global temp root folder: ${tempRoot}`)); console.log(yellow(`Add temp root folder: ${tempRoot}`));
fs.copyFileSync(path.join(__dirname, '../config/_bootstrap_verdaccio.yaml'), tempConfigFile); fs.copyFileSync(path.join(__dirname, '../config/_bootstrap_verdaccio.yaml'), path.join(tempRoot, 'verdaccio.yaml'));
console.log(green(`global temp root conf: ${tempConfigFile}`));
// @ts-ignore // @ts-ignore
global.__namespace = __global; global.__namespace = __global;
console.log(`current directory: ${process.cwd()}`); console.log(`current directory: ${process.cwd()}`);
const rootVerdaccio = path.resolve('./bin/verdaccio');
console.log(green(`verdaccio root path: ${rootVerdaccio}`));
// @ts-ignore // @ts-ignore
global.registryProcess = spawn('node', [path.resolve('./bin/verdaccio'), '-c', './verdaccio.yaml'], { global.registryProcess = spawn(
cwd: tempRoot, 'node',
// stdio: 'pipe' [require.resolve('verdaccio/bin/verdaccio'), '-c', './verdaccio.yaml'],
}); // @ts-ignore
{ cwd: tempRoot, silence: true }
// @ts-ignore );
global.registryProcess.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
// @ts-ignore
global.registryProcess.stderr.on('data', (data) => {
console.log(`stderr: ${data}`);
});
// @ts-ignore
global.registryProcess.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});
// publish current build version on local registry // publish current build version on local registry
await npm('publish', '--registry', 'http://localhost:4873', '--verbose'); await npm('publish', '--registry', 'http://localhost:4873');
}; };

View file

@ -1,7 +1,7 @@
const fs = require('fs');
import os from 'os'; import os from 'os';
import path from 'path'; import path from 'path';
import NodeEnvironment from 'jest-environment-node'; import NodeEnvironment from 'jest-environment-node';
const fs = require('fs');
const __global = require('../utils/global'); const __global = require('../utils/global');
class E2ECliTestEnvironment extends NodeEnvironment { class E2ECliTestEnvironment extends NodeEnvironment {

View file

@ -1,14 +1,5 @@
import { silentNpm } from '../../utils/process'; import { silentNpm } from '../../utils/process';
export function installVerdaccio(verdaccioInstall) { export function installVerdaccio(verdaccioInstall) {
return silentNpm( return silentNpm('install', '--prefix', verdaccioInstall, 'verdaccio', '--registry', 'http://localhost:4873', '--no-package-lock');
'install',
'--prefix',
verdaccioInstall,
'verdaccio',
'--registry',
'http://localhost:4873',
'--no-package-lock',
'--verbose'
);
} }

View file

@ -3,6 +3,7 @@ import { runVerdaccio } from '../../utils/process';
import { installVerdaccio } from '../__partials/npm_commands'; import { installVerdaccio } from '../__partials/npm_commands';
describe('verdaccio info', () => { describe('verdaccio info', () => {
jest.setTimeout(90000);
// @ts-ignore // @ts-ignore
const tempRootFolder = global.__namespace.getItem('dir-root'); const tempRootFolder = global.__namespace.getItem('dir-root');
const verdaccioInstall = path.join(tempRootFolder, 'verdaccio-root-info'); const verdaccioInstall = path.join(tempRootFolder, 'verdaccio-root-info');
@ -10,21 +11,16 @@ describe('verdaccio info', () => {
beforeAll(async () => { beforeAll(async () => {
await installVerdaccio(verdaccioInstall); await installVerdaccio(verdaccioInstall);
}, 30000); });
test('should run verdaccio info command', async () => { test('should run verdaccio info command', async () => {
const pathVerdaccioModule = require.resolve('verdaccio/bin/verdaccio', { const pathVerdaccioModule = require.resolve('verdaccio/bin/verdaccio', {
paths: [verdaccioInstall] paths: [verdaccioInstall],
}); });
const hasMatch = await runVerdaccio( const hasMatch = await runVerdaccio(pathVerdaccioModule, verdaccioInstall, ['--info'], /Environment/);
pathVerdaccioModule,
verdaccioInstall,
['--info'],
/Environment/
);
expect(hasMatch.ok).toBeTruthy(); expect(hasMatch.ok).toBeTruthy();
}, 20000); });
afterAll(() => { afterAll(() => {
registryProcess.kill(); registryProcess.kill();

View file

@ -21,13 +21,10 @@ describe('npm install', () => {
test('should match the listing port and load metadata', async () => { test('should match the listing port and load metadata', async () => {
const pathVerdaccioModule = require.resolve('verdaccio/bin/verdaccio', { const pathVerdaccioModule = require.resolve('verdaccio/bin/verdaccio', {
paths: [verdaccioInstall] paths: [verdaccioInstall],
}); });
registryProcess = await spawnRegistry(pathVerdaccioModule, ['-c', configPath, '-l', port], { registryProcess = await spawnRegistry(pathVerdaccioModule, ['-c', configPath, '-l', port], { cwd: verdaccioInstall, silent: true });
cwd: verdaccioInstall,
silent: false
});
const body = await callRegistry(`http://localhost:${port}/verdaccio`); const body = await callRegistry(`http://localhost:${port}/verdaccio`);
const parsedBody = JSON.parse(body); const parsedBody = JSON.parse(body);

View file

@ -23,39 +23,25 @@ describe('npm install', () => {
// @ts-ignore // @ts-ignore
global.__namespace = __global; global.__namespace = __global;
const pathVerdaccioModule = require.resolve('verdaccio/bin/verdaccio', { const pathVerdaccioModule = require.resolve('verdaccio/bin/verdaccio', {
paths: [verdaccioInstall] paths: [verdaccioInstall],
});
registryProcess = await spawnRegistry(pathVerdaccioModule, ['-c', configPath, '-l', port], {
cwd: verdaccioInstall,
silent: true
}); });
registryProcess = await spawnRegistry(pathVerdaccioModule, ['-c', configPath, '-l', port], { cwd: verdaccioInstall, silent: true });
}); });
test('should match on npm info verdaccio', async () => { test('should match on npm info verdaccio', async () => {
// FIXME: not the best match, looking for a better way to match the terminal output // FIXME: not the best match, looking for a better way to match the terminal output
const output = await execAndWaitForOutputToMatch( const output = await execAndWaitForOutputToMatch('npm', ['info', 'verdaccio', '--registry'], /A lightweight private npm proxy registry/);
'npm',
['info', 'verdaccio', '--registry'],
/A lightweight private npm proxy registry/
);
expect(output.ok).toBeTruthy(); expect(output.ok).toBeTruthy();
}); });
test('should install jquery', async () => { test('should install jquery', async () => {
const testCwd = path.join(tempRootFolder, '_jquery_'); const testCwd = path.join(tempRootFolder, '_jquery_');
await execAndWaitForOutputToMatch( await execAndWaitForOutputToMatch('npm', ['install', '--prefix', testCwd, 'jquery', '--registry', `http://localhost:${port}`], /''/, {
'npm', cwd: verdaccioInstall,
['install', '--prefix', testCwd, 'jquery', '--registry', `http://localhost:${port}`], });
/''/,
{
cwd: verdaccioInstall
}
);
const exist = await expectFileToExist( const exist = await expectFileToExist(path.join(testCwd, 'node_modules', 'jquery', 'package.json'));
path.join(testCwd, 'node_modules', 'jquery', 'package.json')
);
expect(exist).toBeTruthy(); expect(exist).toBeTruthy();
}); });

View file

@ -1,14 +1,14 @@
const namespace = Object.create(null); const namespace = Object.create(null);
exports.addItem = function(name, value) { exports.addItem = function (name, value) {
namespace[name] = value; namespace[name] = value;
} };
exports.getItem = function(name) { exports.getItem = function (name) {
console.log("get-item", name, namespace); console.log('get-item', name, namespace);
if (!(name in namespace)) { if (!(name in namespace)) {
throw new Error("The item ".concat(name, " does exist in the namespace")); throw new Error('The item '.concat(name, ' does exist in the namespace'));
} }
return namespace[name]; return namespace[name];
} };

View file

@ -12,7 +12,7 @@ export async function _exec(options, cmd, args) {
console.log(`ENV: ${JSON.stringify(env)}`); console.log(`ENV: ${JSON.stringify(env)}`);
const spawnOptions = { const spawnOptions = {
cwd, cwd,
...(env ? { env } : {}) ...(env ? { env } : {}),
}; };
if (process.platform.startsWith('win')) { if (process.platform.startsWith('win')) {
@ -76,12 +76,7 @@ export async function _exec(options, cmd, args) {
}); });
} }
export function execAndWaitForOutputToMatch( export function execAndWaitForOutputToMatch(cmd: string, args: string[], match: RegExp, spawnOptions: SpawnOptions = {}): any {
cmd: string,
args: string[],
match: RegExp,
spawnOptions: SpawnOptions = {}
): any {
return _exec({ waitForMatch: match, ...spawnOptions, silence: true }, cmd, args); return _exec({ waitForMatch: match, ...spawnOptions, silence: true }, cmd, args);
} }

View file

@ -5,7 +5,7 @@ export function callRegistry(url: string): Promise<string> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let options = { let options = {
url: url, url: url,
headers: { Accept: 'application/json' } headers: { Accept: 'application/json' },
}; };
// @ts-ignore // @ts-ignore
request(options, (error: any, response: IncomingMessage, body: string) => { request(options, (error: any, response: IncomingMessage, body: string) => {