chore: revert 1.10.2 (#1468)

* Revert "fix: fix issues with https-agent-proxy for cli and openapi-core packages (#1461)"

This reverts commit 7ec5cfcd37.
This commit is contained in:
Andrew Tatomyr
2024-03-04 16:52:07 +02:00
committed by GitHub
parent 87a455ca83
commit f1a6f356ea
20 changed files with 102 additions and 275 deletions

View File

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

View File

@@ -78,30 +78,6 @@ 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 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=http://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 ## Next steps
- Set up [autocomplete for Redocly CLI](./guides/autocomplete.md). - Set up [autocomplete for Redocly CLI](./guides/autocomplete.md).

44
package-lock.json generated
View File

@@ -12945,7 +12945,6 @@
"dependencies": { "dependencies": {
"@redocly/ajv": "^8.11.0", "@redocly/ajv": "^8.11.0",
"colorette": "^1.2.0", "colorette": "^1.2.0",
"https-proxy-agent": "^7.0.4",
"js-levenshtein": "^1.1.6", "js-levenshtein": "^1.1.6",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"lodash.isequal": "^4.5.0", "lodash.isequal": "^4.5.0",
@@ -12968,29 +12967,6 @@
"node": ">=14.19.0", "node": ">=14.19.0",
"npm": ">=7.0.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": { "dependencies": {
@@ -15634,7 +15610,6 @@
"@types/node-fetch": "^2.5.7", "@types/node-fetch": "^2.5.7",
"@types/pluralize": "^0.0.29", "@types/pluralize": "^0.0.29",
"colorette": "^1.2.0", "colorette": "^1.2.0",
"https-proxy-agent": "^7.0.4",
"js-levenshtein": "^1.1.6", "js-levenshtein": "^1.1.6",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"lodash.isequal": "^4.5.0", "lodash.isequal": "^4.5.0",
@@ -15643,25 +15618,6 @@
"pluralize": "^8.0.0", "pluralize": "^8.0.0",
"typescript": "^5.2.2", "typescript": "^5.2.2",
"yaml-ast-parser": "0.0.43" "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": { "@sinclair/typebox": {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -18,8 +18,7 @@
"path": "path-browserify", "path": "path-browserify",
"os": false, "os": false,
"node-fetch": false, "node-fetch": false,
"colorette": false, "colorette": false
"https-proxy-agent": false
}, },
"homepage": "https://github.com/Redocly/redocly-cli", "homepage": "https://github.com/Redocly/redocly-cli",
"keywords": [ "keywords": [
@@ -37,7 +36,6 @@
"dependencies": { "dependencies": {
"@redocly/ajv": "^8.11.0", "@redocly/ajv": "^8.11.0",
"colorette": "^1.2.0", "colorette": "^1.2.0",
"https-proxy-agent": "^7.0.4",
"js-levenshtein": "^1.1.6", "js-levenshtein": "^1.1.6",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"lodash.isequal": "^4.5.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 { initRules } from './config/rules';
import { reportUnresolvedRef } from './rules/no-unresolved-refs'; import { reportUnresolvedRef } from './rules/no-unresolved-refs';
import { isPlainObject, isTruthy } from './utils'; import { isPlainObject, isTruthy } from './utils';
import { isRedoclyRegistryURL } from './redocly/domains'; import { isRedoclyRegistryURL } from './redocly';
import { RemoveUnusedComponents as RemoveUnusedComponentsOas2 } from './decorators/oas2/remove-unused-components'; import { RemoveUnusedComponents as RemoveUnusedComponentsOas2 } from './decorators/oas2/remove-unused-components';
import { RemoveUnusedComponents as RemoveUnusedComponentsOas3 } from './decorators/oas3/remove-unused-components'; import { RemoveUnusedComponents as RemoveUnusedComponentsOas3 } from './decorators/oas3/remove-unused-components';
import { ConfigTypes } from './types/redocly-yaml'; import { ConfigTypes } from './types/redocly-yaml';

View File

@@ -10,7 +10,7 @@ import {
Oas3RuleSet, Oas3RuleSet,
Async2RuleSet, Async2RuleSet,
} from '../oas-types'; } from '../oas-types';
import { isBrowser } from '../env'; import { isBrowser, env } from '../env';
import type { NodeType } from '../types'; import type { NodeType } from '../types';
import type { import type {
@@ -35,6 +35,25 @@ const IGNORE_BANNER =
`# This file instructs Redocly's linter to ignore the rules contained for specific parts of your API.\n` + `# 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`; `# 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 { function getIgnoreFilePath(configFile?: string): string | undefined {
if (configFile) { if (configFile) {
return doesYamlFileExist(configFile) return doesYamlFileExist(configFile)
@@ -45,6 +64,9 @@ function getIgnoreFilePath(configFile?: string): string | undefined {
} }
} }
export const DOMAINS = getDomains();
export const AVAILABLE_REGIONS = Object.keys(DOMAINS) as Region[];
export class StyleguideConfig { export class StyleguideConfig {
plugins: Plugin[]; plugins: Plugin[];
ignore: Record<string, Record<string, Set<string>>> = {}; ignore: Record<string, Record<string, Set<string>>> = {};

View File

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

View File

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

View File

@@ -1,11 +1,4 @@
export { export { BundleOutputFormat, readFileFromUrl, slash, doesYamlFileExist, isTruthy } from './utils';
BundleOutputFormat,
readFileFromUrl,
slash,
doesYamlFileExist,
isTruthy,
getProxyAgent,
} from './utils';
export { Oas3_1Types } from './types/oas3_1'; export { Oas3_1Types } from './types/oas3_1';
export { Oas3Types } from './types/oas3'; export { Oas3Types } from './types/oas3';
export { Oas2Types } from './types/oas2'; export { Oas2Types } from './types/oas2';
@@ -48,9 +41,7 @@ export {
ResolvedApi, ResolvedApi,
} from './config'; } from './config';
export { RedoclyClient } from './redocly'; export { RedoclyClient, isRedoclyRegistryURL } from './redocly';
export * from './redocly/domains';
export { export {
Source, Source,

View File

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

View File

@@ -1,48 +0,0 @@
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,19 +2,13 @@ import { existsSync, readFileSync, writeFileSync, unlinkSync } from 'fs';
import { resolve } from 'path'; import { resolve } from 'path';
import { homedir } from 'os'; import { homedir } from 'os';
import { RegistryApi } from './registry-api'; import { RegistryApi } from './registry-api';
import { DEFAULT_REGION, DOMAINS, AVAILABLE_REGIONS } from '../config/config';
import { env } from '../env'; import { env } from '../env';
import { RegionalToken, RegionalTokenWithValidity } from './redocly-client-types'; import { RegionalToken, RegionalTokenWithValidity } from './redocly-client-types';
import { isNotEmptyObject } from '../utils'; import { isNotEmptyObject } from '../utils';
import { colorize } from '../logger'; import { colorize } from '../logger';
import type { AccessTokens, Region } from '../config/types'; import type { AccessTokens, Region } from '../config/types';
import {
AVAILABLE_REGIONS,
DEFAULT_REGION,
DOMAINS,
getRedoclyDomain,
setRedoclyDomain,
} from './domains';
export const TOKEN_FILENAME = '.redocly-config.json'; export const TOKEN_FILENAME = '.redocly-config.json';
@@ -29,7 +23,7 @@ export class RedoclyClient {
this.loadTokens(); this.loadTokens();
this.domain = region ? DOMAINS[region] : env.REDOCLY_DOMAIN || DOMAINS[DEFAULT_REGION]; this.domain = region ? DOMAINS[region] : env.REDOCLY_DOMAIN || DOMAINS[DEFAULT_REGION];
setRedoclyDomain(this.domain); env.REDOCLY_DOMAIN = this.domain; // isRedoclyRegistryURL depends on the value to be set
this.registryApi = new RegistryApi(this.accessTokens, this.region); this.registryApi = new RegistryApi(this.accessTokens, this.region);
} }
@@ -42,9 +36,9 @@ export class RedoclyClient {
); );
} }
if (getRedoclyDomain()) { if (env.REDOCLY_DOMAIN) {
return (AVAILABLE_REGIONS.find( return (AVAILABLE_REGIONS.find(
(region) => DOMAINS[region as Region] === getRedoclyDomain() (region) => DOMAINS[region as Region] === env.REDOCLY_DOMAIN
) || DEFAULT_REGION) as Region; ) || DEFAULT_REGION) as Region;
} }
return region || DEFAULT_REGION; return region || DEFAULT_REGION;
@@ -102,7 +96,7 @@ export class RedoclyClient {
const allTokens = this.getAllTokens(); const allTokens = this.getAllTokens();
const verifiedTokens = await Promise.allSettled( const verifiedTokens = await Promise.allSettled(
allTokens.map(({ token }) => this.verifyToken(token)) allTokens.map(({ token, region }) => this.verifyToken(token, region))
); );
return allTokens return allTokens
@@ -126,7 +120,7 @@ export class RedoclyClient {
} }
try { try {
await this.verifyToken(accessToken); await this.verifyToken(accessToken, this.region);
return true; return true;
} catch (err) { } catch (err) {
@@ -144,16 +138,17 @@ export class RedoclyClient {
async verifyToken( async verifyToken(
accessToken: string, accessToken: string,
region: Region,
verbose: boolean = false verbose: boolean = false
): Promise<{ viewerId: string; organizations: string[] }> { ): Promise<{ viewerId: string; organizations: string[] }> {
return this.registryApi.authStatus(accessToken, verbose); return this.registryApi.authStatus(accessToken, region, verbose);
} }
async login(accessToken: string, verbose: boolean = false) { async login(accessToken: string, verbose: boolean = false) {
const credentialsPath = resolve(homedir(), TOKEN_FILENAME); const credentialsPath = resolve(homedir(), TOKEN_FILENAME);
try { try {
await this.verifyToken(accessToken, verbose); await this.verifyToken(accessToken, this.region, verbose);
} catch (err) { } catch (err) {
throw new Error('Authorization failed. Please check if you entered a valid API key.'); throw new Error('Authorization failed. Please check if you entered a valid API key.');
} }
@@ -175,3 +170,18 @@ 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, PushApiParams,
} from './registry-api-types'; } from './registry-api-types';
import type { AccessTokens, Region } from '../config/types'; import type { AccessTokens, Region } from '../config/types';
import { getProxyAgent, isNotEmptyObject } from '../utils'; import { DEFAULT_REGION, DOMAINS } from '../config/config';
import { getRedoclyDomain } from './domains'; import { isNotEmptyObject } from '../utils';
const version = require('../../package.json').version; const version = require('../../package.json').version;
@@ -18,8 +18,8 @@ export class RegistryApi {
return isNotEmptyObject(this.accessTokens) && this.accessTokens[this.region]; return isNotEmptyObject(this.accessTokens) && this.accessTokens[this.region];
} }
getBaseUrl() { getBaseUrl(region: Region = DEFAULT_REGION) {
return `https://api.${getRedoclyDomain()}/registry`; return `https://api.${DOMAINS[region]}/registry`;
} }
setAccessTokens(accessTokens: AccessTokens) { setAccessTokens(accessTokens: AccessTokens) {
@@ -27,7 +27,7 @@ export class RegistryApi {
return this; return this;
} }
private async request(path = '', options: RequestInit = {}) { private async request(path = '', options: RequestInit = {}, region?: Region) {
const currentCommand = const currentCommand =
typeof process !== 'undefined' ? process.env?.REDOCLY_CLI_COMMAND || '' : ''; typeof process !== 'undefined' ? process.env?.REDOCLY_CLI_COMMAND || '' : '';
const redoclyEnv = typeof process !== 'undefined' ? process.env?.REDOCLY_ENVIRONMENT || '' : ''; const redoclyEnv = typeof process !== 'undefined' ? process.env?.REDOCLY_ENVIRONMENT || '' : '';
@@ -42,8 +42,8 @@ export class RegistryApi {
} }
const response = await fetch( const response = await fetch(
`${this.getBaseUrl()}${path}`, `${this.getBaseUrl(region)}${path}`,
Object.assign({}, options, { headers, agent: getProxyAgent() }) Object.assign({}, options, { headers })
); );
if (response.status === 401) { if (response.status === 401) {
@@ -60,10 +60,11 @@ export class RegistryApi {
async authStatus( async authStatus(
accessToken: string, accessToken: string,
region: Region,
verbose = false verbose = false
): Promise<{ viewerId: string; organizations: string[] }> { ): Promise<{ viewerId: string; organizations: string[] }> {
try { try {
const response = await this.request('', { headers: { authorization: accessToken } }); const response = await this.request('', { headers: { authorization: accessToken } }, region);
return await response.json(); return await response.json();
} catch (error) { } catch (error) {
@@ -96,7 +97,8 @@ export class RegistryApi {
filename, filename,
isUpsert, isUpsert,
}), }),
} },
this.region
); );
if (response.ok) { if (response.ok) {
@@ -118,22 +120,26 @@ export class RegistryApi {
batchId, batchId,
batchSize, batchSize,
}: PushApiParams) { }: PushApiParams) {
const response = await this.request(`/${organizationId}/${name}/${version}`, { const response = await this.request(
method: 'PUT', `/${organizationId}/${name}/${version}`,
headers: { {
'content-type': 'application/json', method: 'PUT',
authorization: this.accessToken, headers: {
} as HeadersInit, 'content-type': 'application/json',
body: JSON.stringify({ authorization: this.accessToken,
rootFilePath, } as HeadersInit,
filePaths, body: JSON.stringify({
branch, rootFilePath,
isUpsert, filePaths,
isPublic, branch,
batchId, isUpsert,
batchSize, isPublic,
}), batchId,
}); batchSize,
}),
},
this.region
);
if (response.ok) { if (response.ok) {
return; return;

View File

@@ -5,10 +5,9 @@ import fetch from 'node-fetch';
import * as pluralize from 'pluralize'; import * as pluralize from 'pluralize';
import { parseYaml } from './js-yaml'; import { parseYaml } from './js-yaml';
import { UserContext } from './walk'; import { UserContext } from './walk';
import { HttpResolveConfig } from './config';
import { env } from './env'; import { env } from './env';
import { logger, colorize } from './logger'; import { logger, colorize } from './logger';
import { HttpResolveConfig } from './config';
import { HttpsProxyAgent } from 'https-proxy-agent';
export { parseYaml, stringifyYaml } from './js-yaml'; export { parseYaml, stringifyYaml } from './js-yaml';
@@ -275,8 +274,3 @@ export function nextTick() {
function getUpdatedFieldName(updatedField: string, updatedObject?: string) { function getUpdatedFieldName(updatedField: string, updatedObject?: string) {
return `${typeof updatedObject !== 'undefined' ? `${updatedObject}.` : ''}${updatedField}`; 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;
}