fix: fix issues with https-agent-proxy for cli and openapi-core packages (#1493)

This commit is contained in:
Mateusz Lis
2024-06-18 07:53:02 +02:00
committed by GitHub
parent 5893961a45
commit 4c176991e4
20 changed files with 274 additions and 95 deletions

View File

@@ -0,0 +1,6 @@
---
"@redocly/openapi-core": minor
"@redocly/cli": minor
---
Users can run the CLI tool behind a proxy by using `HTTP_PROXY` or `HTTPS_PROXY` environment variables to configure the proxy settings.

View File

@@ -78,6 +78,30 @@ To give a Docker container access to your OpenAPI description files, you need to
docker run --rm -v $PWD:/spec redocly/cli lint openapi.yaml
```
## Run CLI behind a proxy
If you need to run the CLI tool behind a proxy, you can use the `HTTP_PROXY` and `HTTPS_PROXY` environment variables to configure the proxy settings. These environment variables are commonly used to specify the proxy server for HTTP and HTTPS traffic, respectively.
### Set up Proxy Environment Variables
Before running the CLI behind a proxy, make sure to set the appropriate proxy environment variables. Open a terminal and use the following commands:
```bash
# For HTTP proxy
export HTTP_PROXY=http://your-http-proxy-server:port
# For HTTPS proxy
export HTTPS_PROXY=https://your-https-proxy-server:port
```
### Use Environment Variables with CLI Commands
You can also directly include the proxy environment variables in the command itself. For example:
```bash
HTTPS_PROXY=https://your-https-proxy-server:port redocly lint --extends minimal openapi.yaml
```
## Next steps
- Set up [autocomplete for Redocly CLI](./guides/autocomplete.md).

44
package-lock.json generated
View File

@@ -13554,6 +13554,7 @@
"@redocly/ajv": "^8.11.0",
"@redocly/config": "^0.6.0",
"colorette": "^1.2.0",
"https-proxy-agent": "^7.0.4",
"js-levenshtein": "^1.1.6",
"js-yaml": "^4.1.0",
"lodash.isequal": "^4.5.0",
@@ -13576,6 +13577,29 @@
"node": ">=14.19.0",
"npm": ">=7.0.0"
}
},
"packages/core/node_modules/agent-base": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz",
"integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==",
"dependencies": {
"debug": "^4.3.4"
},
"engines": {
"node": ">= 14"
}
},
"packages/core/node_modules/https-proxy-agent": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz",
"integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==",
"dependencies": {
"agent-base": "^7.0.2",
"debug": "4"
},
"engines": {
"node": ">= 14"
}
}
},
"dependencies": {
@@ -16244,6 +16268,7 @@
"@types/node-fetch": "^2.5.7",
"@types/pluralize": "^0.0.29",
"colorette": "^1.2.0",
"https-proxy-agent": "^7.0.4",
"js-levenshtein": "^1.1.6",
"js-yaml": "^4.1.0",
"lodash.isequal": "^4.5.0",
@@ -16252,6 +16277,25 @@
"pluralize": "^8.0.0",
"typescript": "^5.2.2",
"yaml-ast-parser": "0.0.43"
},
"dependencies": {
"agent-base": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz",
"integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==",
"requires": {
"debug": "^4.3.4"
}
},
"https-proxy-agent": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz",
"integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==",
"requires": {
"agent-base": "^7.0.2",
"debug": "4"
}
}
}
},
"@sinclair/typebox": {

View File

@@ -21,6 +21,7 @@ export const __redoclyClient = {
export const RedoclyClient = jest.fn(() => __redoclyClient);
export const loadConfig = jest.fn(() => ConfigFixture);
export const getMergedConfig = jest.fn();
export const getProxyAgent = jest.fn();
export const lint = jest.fn();
export const bundle = jest.fn(() => ({ bundle: { parsed: null }, problems: null }));
export const getTotals = jest.fn(() => ({ errors: 0 }));

View File

@@ -42,6 +42,7 @@ describe('ApiClient', () => {
'Content-Type': 'application/json',
Authorization: `Bearer ${testToken}`,
},
signal: expect.any(Object),
}
);
@@ -122,6 +123,8 @@ describe('ApiClient', () => {
type: 'CICD',
autoMerge: true,
}),
signal: expect.any(Object),
agent: undefined,
}
);

View File

@@ -1,7 +1,7 @@
import fetchWithTimeout from '../../utils/fetch-with-timeout';
import fetch from 'node-fetch';
import * as FormData from 'form-data';
import { getProxyAgent } from '@redocly/openapi-core';
import type { Response } from 'node-fetch';
import type { ReadStream } from 'fs';
import type {
@@ -25,7 +25,7 @@ class RemotesApiClient {
}
async getDefaultBranch(organizationId: string, projectId: string) {
const response = await fetch(
const response = await fetchWithTimeout(
`${this.domain}/api/orgs/${organizationId}/projects/${projectId}/source`,
{
method: 'GET',
@@ -36,6 +36,10 @@ class RemotesApiClient {
}
);
if (!response) {
throw new Error(`Failed to get default branch.`);
}
try {
const source = await this.getParsedResponse<ProjectSourceResponse>(response);
@@ -53,7 +57,7 @@ class RemotesApiClient {
mountBranchName: string;
}
): Promise<UpsertRemoteResponse> {
const response = await fetch(
const response = await fetchWithTimeout(
`${this.domain}/api/orgs/${organizationId}/projects/${projectId}/remotes`,
{
method: 'POST',
@@ -70,6 +74,10 @@ class RemotesApiClient {
}
);
if (!response) {
throw new Error(`Failed to upsert.`);
}
try {
return await this.getParsedResponse<UpsertRemoteResponse>(response);
} catch (err) {
@@ -110,6 +118,7 @@ class RemotesApiClient {
Authorization: `Bearer ${this.apiKey}`,
},
body: formData,
agent: getProxyAgent(),
}
);
@@ -121,7 +130,7 @@ class RemotesApiClient {
}
async getRemotesList(organizationId: string, projectId: string, mountPath: string) {
const response = await fetch(
const response = await fetchWithTimeout(
`${this.domain}/api/orgs/${organizationId}/projects/${projectId}/remotes?filter=mountPath:/${mountPath}/`,
{
method: 'GET',
@@ -132,6 +141,10 @@ class RemotesApiClient {
}
);
if (!response) {
throw new Error(`Failed to get remotes list.`);
}
try {
return await this.getParsedResponse<ListRemotesResponse>(response);
} catch (err) {
@@ -160,7 +173,7 @@ class RemotesApiClient {
);
if (!response) {
throw new Error(`Failed to get push status: Time is up`);
throw new Error(`Failed to get push status.`);
}
try {

View File

@@ -14,6 +14,7 @@ import {
slash,
Region,
getMergedConfig,
getProxyAgent,
} from '@redocly/openapi-core';
import {
exitWithError,
@@ -62,8 +63,12 @@ export async function handlePush(argv: PushOptions, config: Config): Promise<voi
const client = new RedoclyClient(config.region);
const isAuthorized = await client.isAuthorizedWithRedoclyByRegion();
if (!isAuthorized) {
const clientToken = await promptClientToken(client.domain);
await client.login(clientToken);
try {
const clientToken = await promptClientToken(client.domain);
await client.login(clientToken);
} catch (e) {
exitWithError(e);
}
}
const startedAt = performance.now();
@@ -439,6 +444,7 @@ function uploadFileToS3(url: string, filePathOrBuffer: string | Buffer) {
typeof filePathOrBuffer === 'string'
? fs.statSync(filePathOrBuffer).size
: filePathOrBuffer.byteLength;
const readStream =
typeof filePathOrBuffer === 'string' ? fs.createReadStream(filePathOrBuffer) : filePathOrBuffer;
@@ -448,5 +454,6 @@ function uploadFileToS3(url: string, filePathOrBuffer: string | Buffer) {
'Content-Length': fileSizeInBytes.toString(),
},
body: readStream,
agent: getProxyAgent(),
});
}

View File

@@ -1,5 +1,6 @@
import nodeFetch from 'node-fetch';
import AbortController from 'abort-controller';
import { getProxyAgent } from '@redocly/openapi-core';
const TIMEOUT = 3000;
@@ -10,7 +11,11 @@ export default async (url: string, options = {}) => {
controller.abort();
}, TIMEOUT);
const res = await nodeFetch(url, { signal: controller.signal, ...options });
const res = await nodeFetch(url, {
signal: controller.signal,
...options,
agent: getProxyAgent(),
});
clearTimeout(timeout);
return res;
} catch (e) {

View File

@@ -18,7 +18,8 @@
"path": "path-browserify",
"os": false,
"node-fetch": false,
"colorette": false
"colorette": false,
"https-proxy-agent": false
},
"homepage": "https://github.com/Redocly/redocly-cli",
"keywords": [
@@ -37,6 +38,7 @@
"@redocly/ajv": "^8.11.0",
"@redocly/config": "^0.6.0",
"colorette": "^1.2.0",
"https-proxy-agent": "^7.0.4",
"js-levenshtein": "^1.1.6",
"js-yaml": "^4.1.0",
"lodash.isequal": "^4.5.0",

View File

@@ -14,7 +14,7 @@ import { isAbsoluteUrl, isRef, Location, refBaseName } from './ref-utils';
import { initRules } from './config/rules';
import { reportUnresolvedRef } from './rules/no-unresolved-refs';
import { isPlainObject, isTruthy } from './utils';
import { isRedoclyRegistryURL } from './redocly';
import { isRedoclyRegistryURL } from './redocly/domains';
import { RemoveUnusedComponents as RemoveUnusedComponentsOas2 } from './decorators/oas2/remove-unused-components';
import { RemoveUnusedComponents as RemoveUnusedComponentsOas3 } from './decorators/oas3/remove-unused-components';
import { ConfigTypes } from './types/redocly-yaml';

View File

@@ -10,7 +10,7 @@ import {
Oas3RuleSet,
Async2RuleSet,
} from '../oas-types';
import { isBrowser, env } from '../env';
import { isBrowser } from '../env';
import type { NodeType } from '../types';
import type {
@@ -35,25 +35,6 @@ const IGNORE_BANNER =
`# This file instructs Redocly's linter to ignore the rules contained for specific parts of your API.\n` +
`# See https://redoc.ly/docs/cli/ for more information.\n`;
export const DEFAULT_REGION = 'us';
function getDomains() {
const domains: { [region in Region]: string } = {
us: 'redocly.com',
eu: 'eu.redocly.com',
};
// FIXME: temporary fix for our lab environments
const domain = env.REDOCLY_DOMAIN;
if (domain?.endsWith('.redocly.host')) {
domains[domain.split('.')[0] as Region] = domain;
}
if (domain === 'redoc.online') {
domains[domain as Region] = domain;
}
return domains;
}
function getIgnoreFilePath(configFile?: string): string | undefined {
if (configFile) {
return doesYamlFileExist(configFile)
@@ -64,9 +45,6 @@ function getIgnoreFilePath(configFile?: string): string | undefined {
}
}
export const DOMAINS = getDomains();
export const AVAILABLE_REGIONS = Object.keys(DOMAINS) as Region[];
export class StyleguideConfig {
plugins: Plugin[];
ignore: Record<string, Record<string, Set<string>>> = {};

View File

@@ -3,7 +3,7 @@ import * as path from 'path';
import { RedoclyClient } from '../redocly';
import { isEmptyObject } from '../utils';
import { parseYaml } from '../js-yaml';
import { Config, DOMAINS } from './config';
import { Config } from './config';
import { ConfigValidationError, transformConfig } from './utils';
import { resolveConfig, resolveConfigFileAndRefs } from './config-resolvers';
import { bundleConfig } from '../bundle';
@@ -14,6 +14,7 @@ import type { Document } from '../resolve';
import type { RegionalToken, RegionalTokenWithValidity } from '../redocly/redocly-client-types';
import type { RawConfig, RawUniversalConfig, Region } from './types';
import type { ResolvedRefMap } from '../resolve';
import { DOMAINS } from '../redocly/domains';
async function addConfigMetadata({
rawConfig,

View File

@@ -1,5 +1,5 @@
import { UserContext } from '../../walk';
import { isRedoclyRegistryURL } from '../../redocly';
import { isRedoclyRegistryURL } from '../../redocly/domains';
import { Oas3Decorator, Oas2Decorator } from '../../visitors';

View File

@@ -4,6 +4,7 @@ export {
slash,
doesYamlFileExist,
isTruthy,
getProxyAgent,
pause,
} from './utils';
export { Oas3_1Types } from './types/oas3_1';
@@ -48,7 +49,9 @@ export {
ResolvedApi,
} from './config';
export { RedoclyClient, isRedoclyRegistryURL } from './redocly';
export { RedoclyClient } from './redocly';
export * from './redocly/domains';
export {
Source,

View File

@@ -0,0 +1,52 @@
import { RedoclyClient } from '../../index';
import { setRedoclyDomain, getRedoclyDomain, getDomains, AVAILABLE_REGIONS } from '../domains';
describe('domains', () => {
const REDOCLY_DOMAIN_US = 'redocly.com';
const TEST_DOMAIN = 'redoclyDomain.com';
const TEST_LAB_DOMAIN = 'lab.redocly.host';
const TEST_REDOC_ONLINE_DOMAIN = 'redoc.online';
afterEach(() => {
delete process.env.REDOCLY_DOMAIN;
setRedoclyDomain('');
});
it('should resolve the US domain by default', () => {
expect(getRedoclyDomain()).toBe(REDOCLY_DOMAIN_US);
});
it('should resolve the US and EU regions by default', () => {
expect(AVAILABLE_REGIONS).toStrictEqual(['us', 'eu']);
});
it('should resolve the specified domain if used with setter', () => {
setRedoclyDomain(TEST_DOMAIN);
expect(getRedoclyDomain()).toBe(TEST_DOMAIN);
});
it('should resolve the specified domain provided in environmental variable, after initializing RedoclyClient', () => {
process.env.REDOCLY_DOMAIN = TEST_DOMAIN;
const client = new RedoclyClient();
expect(getRedoclyDomain()).toBe(TEST_DOMAIN);
expect(client.domain).toBe(TEST_DOMAIN);
});
it('should return correct object when redocly domain is set to lab env', () => {
setRedoclyDomain(TEST_LAB_DOMAIN);
const domains = getDomains();
expect(domains).toEqual({ us: 'redocly.com', eu: 'eu.redocly.com', lab: 'lab.redocly.host' });
expect(getRedoclyDomain()).toBe(TEST_LAB_DOMAIN);
});
it('should return correct object when redocly domain is set to redoc.online env', () => {
setRedoclyDomain(TEST_REDOC_ONLINE_DOMAIN);
const domains = getDomains();
expect(domains).toEqual({
us: 'redocly.com',
eu: 'eu.redocly.com',
'redoc.online': 'redoc.online',
});
expect(getRedoclyDomain()).toBe(TEST_REDOC_ONLINE_DOMAIN);
});
});

View File

@@ -1,3 +1,4 @@
import { setRedoclyDomain } from '../domains';
import { RedoclyClient } from '../index';
jest.mock('node-fetch', () => ({
@@ -16,6 +17,7 @@ describe('RedoclyClient', () => {
afterEach(() => {
delete process.env.REDOCLY_DOMAIN;
setRedoclyDomain('');
});
it('should resolve the US domain by default', () => {
@@ -40,19 +42,19 @@ describe('RedoclyClient', () => {
});
it('should resolve domain by EU region prioritizing flag over env variable', () => {
process.env.REDOCLY_DOMAIN = testRedoclyDomain;
setRedoclyDomain(testRedoclyDomain);
const client = new RedoclyClient('eu');
expect(client.domain).toBe(REDOCLY_DOMAIN_EU);
});
it('should resolve domain by US region prioritizing flag over env variable', () => {
process.env.REDOCLY_DOMAIN = testRedoclyDomain;
setRedoclyDomain(testRedoclyDomain);
const client = new RedoclyClient('us');
expect(client.domain).toBe(REDOCLY_DOMAIN_US);
});
it('should resolve domain by US region when REDOCLY_DOMAIN consists EU domain', () => {
process.env.REDOCLY_DOMAIN = REDOCLY_DOMAIN_EU;
setRedoclyDomain(REDOCLY_DOMAIN_EU);
const client = new RedoclyClient();
expect(client.getRegion()).toBe('eu');
});

View File

@@ -0,0 +1,48 @@
import { Region } from '../config/types';
let redoclyDomain = 'redocly.com';
export const DEFAULT_REGION = 'us';
export const DOMAINS = getDomains();
export const AVAILABLE_REGIONS = Object.keys(DOMAINS) as Region[];
export function getDomains() {
const domains: { [region in Region]: string } = {
us: 'redocly.com',
eu: 'eu.redocly.com',
};
// FIXME: temporary fix for our lab environments
const domain = redoclyDomain;
if (domain?.endsWith('.redocly.host')) {
domains[domain.split('.')[0] as Region] = domain;
}
if (domain === 'redoc.online') {
domains[domain as Region] = domain;
}
return domains;
}
export function setRedoclyDomain(domain: string) {
redoclyDomain = domain;
}
export function getRedoclyDomain(): string {
return redoclyDomain;
}
export function isRedoclyRegistryURL(link: string): boolean {
const domain = getRedoclyDomain() || DOMAINS[DEFAULT_REGION];
const legacyDomain = domain === 'redocly.com' ? 'redoc.ly' : domain;
if (
!link.startsWith(`https://api.${domain}/registry/`) &&
!link.startsWith(`https://api.${legacyDomain}/registry/`)
) {
return false;
}
return true;
}

View File

@@ -2,13 +2,19 @@ import { existsSync, readFileSync, writeFileSync, unlinkSync } from 'fs';
import { resolve } from 'path';
import { homedir } from 'os';
import { RegistryApi } from './registry-api';
import { DEFAULT_REGION, DOMAINS, AVAILABLE_REGIONS } from '../config/config';
import { env } from '../env';
import { RegionalToken, RegionalTokenWithValidity } from './redocly-client-types';
import { isNotEmptyObject } from '../utils';
import { colorize } from '../logger';
import type { AccessTokens, Region } from '../config/types';
import {
AVAILABLE_REGIONS,
DEFAULT_REGION,
DOMAINS,
getRedoclyDomain,
setRedoclyDomain,
} from './domains';
export const TOKEN_FILENAME = '.redocly-config.json';
@@ -23,7 +29,7 @@ export class RedoclyClient {
this.loadTokens();
this.domain = region ? DOMAINS[region] : env.REDOCLY_DOMAIN || DOMAINS[DEFAULT_REGION];
env.REDOCLY_DOMAIN = this.domain; // isRedoclyRegistryURL depends on the value to be set
setRedoclyDomain(this.domain);
this.registryApi = new RegistryApi(this.accessTokens, this.region);
}
@@ -36,9 +42,9 @@ export class RedoclyClient {
);
}
if (env.REDOCLY_DOMAIN) {
if (getRedoclyDomain()) {
return (AVAILABLE_REGIONS.find(
(region) => DOMAINS[region as Region] === env.REDOCLY_DOMAIN
(region) => DOMAINS[region as Region] === getRedoclyDomain()
) || DEFAULT_REGION) as Region;
}
return region || DEFAULT_REGION;
@@ -96,7 +102,7 @@ export class RedoclyClient {
const allTokens = this.getAllTokens();
const verifiedTokens = await Promise.allSettled(
allTokens.map(({ token, region }) => this.verifyToken(token, region))
allTokens.map(({ token }) => this.verifyToken(token))
);
return allTokens
@@ -120,7 +126,7 @@ export class RedoclyClient {
}
try {
await this.verifyToken(accessToken, this.region);
await this.verifyToken(accessToken);
return true;
} catch (err) {
@@ -138,17 +144,16 @@ export class RedoclyClient {
async verifyToken(
accessToken: string,
region: Region,
verbose: boolean = false
): Promise<{ viewerId: string; organizations: string[] }> {
return this.registryApi.authStatus(accessToken, region, verbose);
return this.registryApi.authStatus(accessToken, verbose);
}
async login(accessToken: string, verbose: boolean = false) {
const credentialsPath = resolve(homedir(), TOKEN_FILENAME);
try {
await this.verifyToken(accessToken, this.region, verbose);
await this.verifyToken(accessToken, verbose);
} catch (err) {
throw new Error('Authorization failed. Please check if you entered a valid API key.');
}
@@ -170,18 +175,3 @@ export class RedoclyClient {
}
}
}
export function isRedoclyRegistryURL(link: string): boolean {
const domain = env.REDOCLY_DOMAIN || DOMAINS[DEFAULT_REGION];
const legacyDomain = domain === 'redocly.com' ? 'redoc.ly' : domain;
if (
!link.startsWith(`https://api.${domain}/registry/`) &&
!link.startsWith(`https://api.${legacyDomain}/registry/`)
) {
return false;
}
return true;
}

View File

@@ -6,8 +6,8 @@ import type {
PushApiParams,
} from './registry-api-types';
import type { AccessTokens, Region } from '../config/types';
import { DEFAULT_REGION, DOMAINS } from '../config/config';
import { isNotEmptyObject } from '../utils';
import { getProxyAgent, isNotEmptyObject } from '../utils';
import { getRedoclyDomain } from './domains';
const version = require('../../package.json').version;
@@ -18,8 +18,8 @@ export class RegistryApi {
return isNotEmptyObject(this.accessTokens) && this.accessTokens[this.region];
}
getBaseUrl(region: Region = DEFAULT_REGION) {
return `https://api.${DOMAINS[region]}/registry`;
getBaseUrl() {
return `https://api.${getRedoclyDomain()}/registry`;
}
setAccessTokens(accessTokens: AccessTokens) {
@@ -27,7 +27,7 @@ export class RegistryApi {
return this;
}
private async request(path = '', options: RequestInit = {}, region?: Region) {
private async request(path = '', options: RequestInit = {}) {
const currentCommand =
typeof process !== 'undefined' ? process.env?.REDOCLY_CLI_COMMAND || '' : '';
const redoclyEnv = typeof process !== 'undefined' ? process.env?.REDOCLY_ENVIRONMENT || '' : '';
@@ -42,8 +42,8 @@ export class RegistryApi {
}
const response = await fetch(
`${this.getBaseUrl(region)}${path}`,
Object.assign({}, options, { headers })
`${this.getBaseUrl()}${path}`,
Object.assign({}, options, { headers, agent: getProxyAgent() })
);
if (response.status === 401) {
@@ -60,11 +60,10 @@ export class RegistryApi {
async authStatus(
accessToken: string,
region: Region,
verbose = false
): Promise<{ viewerId: string; organizations: string[] }> {
try {
const response = await this.request('', { headers: { authorization: accessToken } }, region);
const response = await this.request('', { headers: { authorization: accessToken } });
return await response.json();
} catch (error) {
@@ -97,8 +96,7 @@ export class RegistryApi {
filename,
isUpsert,
}),
},
this.region
}
);
if (response.ok) {
@@ -120,26 +118,22 @@ export class RegistryApi {
batchId,
batchSize,
}: PushApiParams) {
const response = await this.request(
`/${organizationId}/${name}/${version}`,
{
method: 'PUT',
headers: {
'content-type': 'application/json',
authorization: this.accessToken,
} as HeadersInit,
body: JSON.stringify({
rootFilePath,
filePaths,
branch,
isUpsert,
isPublic,
batchId,
batchSize,
}),
},
this.region
);
const response = await this.request(`/${organizationId}/${name}/${version}`, {
method: 'PUT',
headers: {
'content-type': 'application/json',
authorization: this.accessToken,
} as HeadersInit,
body: JSON.stringify({
rootFilePath,
filePaths,
branch,
isUpsert,
isPublic,
batchId,
batchSize,
}),
});
if (response.ok) {
return;

View File

@@ -5,9 +5,10 @@ import fetch from 'node-fetch';
import * as pluralize from 'pluralize';
import { parseYaml } from './js-yaml';
import { UserContext } from './walk';
import { HttpResolveConfig } from './config';
import { env } from './env';
import { logger, colorize } from './logger';
import { HttpResolveConfig } from './config';
import { HttpsProxyAgent } from 'https-proxy-agent';
export { parseYaml, stringifyYaml } from './js-yaml';
@@ -278,3 +279,8 @@ export async function pause(ms: number): Promise<void> {
function getUpdatedFieldName(updatedField: string, updatedObject?: string) {
return `${typeof updatedObject !== 'undefined' ? `${updatedObject}.` : ''}${updatedField}`;
}
export function getProxyAgent() {
const proxy = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
return proxy ? new HttpsProxyAgent(proxy) : undefined;
}