mirror of
https://github.com/LukeHagar/redocly-cli.git
synced 2025-12-10 12:47:49 +00:00
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:
6
.changeset/tall-weeks-crash.md
Normal file
6
.changeset/tall-weeks-crash.md
Normal 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.
|
||||||
@@ -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
44
package-lock.json
generated
@@ -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": {
|
||||||
|
|||||||
@@ -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 }));
|
||||||
|
|||||||
@@ -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,
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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(),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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>>> = {};
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user