@redocly/openapi-core 1.0.0-beta.68 → 1.0.0-beta.72
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/__tests__/lint.test.ts +1 -1
- package/__tests__/login.test.ts +17 -0
- package/lib/bundle.d.ts +4 -0
- package/lib/bundle.js +9 -3
- package/lib/config/all.js +2 -0
- package/lib/config/config.d.ts +10 -0
- package/lib/config/config.js +7 -1
- package/lib/config/load.js +17 -8
- package/lib/index.d.ts +2 -2
- package/lib/lint.js +2 -0
- package/lib/redocly/index.d.ts +26 -20
- package/lib/redocly/index.js +83 -214
- package/lib/redocly/registry-api-types.d.ts +28 -0
- package/lib/redocly/registry-api-types.js +2 -0
- package/lib/redocly/registry-api.d.ts +14 -0
- package/lib/redocly/registry-api.js +105 -0
- package/lib/rules/common/no-invalid-parameter-examples.d.ts +1 -0
- package/lib/rules/common/no-invalid-parameter-examples.js +25 -0
- package/lib/rules/common/no-invalid-schema-examples.d.ts +1 -0
- package/lib/rules/common/no-invalid-schema-examples.js +23 -0
- package/lib/rules/common/paths-kebab-case.js +1 -1
- package/lib/rules/common/registry-dependencies.js +4 -7
- package/lib/rules/oas2/index.d.ts +2 -0
- package/lib/rules/oas2/index.js +4 -0
- package/lib/rules/oas3/index.js +4 -0
- package/lib/rules/oas3/no-invalid-media-type-examples.js +5 -26
- package/lib/rules/utils.d.ts +3 -0
- package/lib/rules/utils.js +26 -1
- package/lib/typings/openapi.d.ts +3 -0
- package/lib/utils.d.ts +1 -0
- package/lib/utils.js +5 -1
- package/lib/walk.d.ts +2 -0
- package/lib/walk.js +7 -0
- package/package.json +1 -1
- package/src/bundle.ts +25 -3
- package/src/config/__tests__/load.test.ts +35 -0
- package/src/config/all.ts +2 -0
- package/src/config/config.ts +11 -0
- package/src/config/load.ts +20 -9
- package/src/index.ts +2 -8
- package/src/lint.ts +2 -0
- package/src/redocly/__tests__/redocly-client.test.ts +120 -0
- package/src/redocly/index.ts +101 -227
- package/src/redocly/registry-api-types.ts +31 -0
- package/src/redocly/registry-api.ts +110 -0
- package/src/rules/common/__tests__/paths-kebab-case.test.ts +23 -0
- package/src/rules/common/no-invalid-parameter-examples.ts +36 -0
- package/src/rules/common/no-invalid-schema-examples.ts +27 -0
- package/src/rules/common/paths-kebab-case.ts +1 -1
- package/src/rules/common/registry-dependencies.ts +6 -8
- package/src/rules/oas2/index.ts +4 -0
- package/src/rules/oas3/index.ts +4 -0
- package/src/rules/oas3/no-invalid-media-type-examples.ts +16 -36
- package/src/rules/utils.ts +43 -2
- package/src/typings/openapi.ts +4 -0
- package/src/utils.ts +5 -1
- package/src/walk.ts +10 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/lib/redocly/query.d.ts +0 -4
- package/lib/redocly/query.js +0 -44
- package/src/redocly/query.ts +0 -38
package/__tests__/lint.test.ts
CHANGED
|
@@ -2,7 +2,7 @@ import outdent from 'outdent';
|
|
|
2
2
|
import { detectOpenAPI } from '../src/oas-types';
|
|
3
3
|
import { parseYamlToDocument } from './utils';
|
|
4
4
|
|
|
5
|
-
describe
|
|
5
|
+
describe('lint', () => {
|
|
6
6
|
it('detect OpenAPI should throw an error when version is not string', () => {
|
|
7
7
|
|
|
8
8
|
const testDocument = parseYamlToDocument(
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { RedoclyClient } from '../src/redocly';
|
|
2
|
+
|
|
3
|
+
describe('login', () => {
|
|
4
|
+
it('should call login with setAccessTokens function', async () => {
|
|
5
|
+
const client = new RedoclyClient();
|
|
6
|
+
Object.defineProperty(client, 'registryApi', {
|
|
7
|
+
value: {
|
|
8
|
+
setAccessTokens: jest.fn(),
|
|
9
|
+
authStatus: jest.fn(() => true)
|
|
10
|
+
},
|
|
11
|
+
writable: true,
|
|
12
|
+
configurable: true
|
|
13
|
+
});
|
|
14
|
+
await client.login('token');
|
|
15
|
+
expect(client.registryApi.setAccessTokens).toHaveBeenCalled();
|
|
16
|
+
});
|
|
17
|
+
});
|
package/lib/bundle.d.ts
CHANGED
|
@@ -15,12 +15,14 @@ export declare function bundle(opts: {
|
|
|
15
15
|
config: Config;
|
|
16
16
|
dereference?: boolean;
|
|
17
17
|
base?: string;
|
|
18
|
+
skipRedoclyRegistryRefs?: boolean;
|
|
18
19
|
}): Promise<{
|
|
19
20
|
bundle: Document;
|
|
20
21
|
problems: import("./walk").NormalizedProblem[];
|
|
21
22
|
fileDependencies: Set<string>;
|
|
22
23
|
rootType: NormalizedNodeType;
|
|
23
24
|
refTypes: Map<string, NormalizedNodeType> | undefined;
|
|
25
|
+
visitorsData: Record<string, Record<string, unknown>>;
|
|
24
26
|
}>;
|
|
25
27
|
export declare function bundleDocument(opts: {
|
|
26
28
|
document: Document;
|
|
@@ -28,10 +30,12 @@ export declare function bundleDocument(opts: {
|
|
|
28
30
|
customTypes?: Record<string, NodeType>;
|
|
29
31
|
externalRefResolver: BaseResolver;
|
|
30
32
|
dereference?: boolean;
|
|
33
|
+
skipRedoclyRegistryRefs?: boolean;
|
|
31
34
|
}): Promise<{
|
|
32
35
|
bundle: Document;
|
|
33
36
|
problems: import("./walk").NormalizedProblem[];
|
|
34
37
|
fileDependencies: Set<string>;
|
|
35
38
|
rootType: NormalizedNodeType;
|
|
36
39
|
refTypes: Map<string, NormalizedNodeType> | undefined;
|
|
40
|
+
visitorsData: Record<string, Record<string, unknown>>;
|
|
37
41
|
}>;
|
package/lib/bundle.js
CHANGED
|
@@ -23,6 +23,7 @@ const ref_utils_1 = require("./ref-utils");
|
|
|
23
23
|
const rules_1 = require("./config/rules");
|
|
24
24
|
const no_unresolved_refs_1 = require("./rules/no-unresolved-refs");
|
|
25
25
|
const utils_1 = require("./utils");
|
|
26
|
+
const redocly_1 = require("./redocly");
|
|
26
27
|
var OasVersion;
|
|
27
28
|
(function (OasVersion) {
|
|
28
29
|
OasVersion["Version2"] = "oas2";
|
|
@@ -45,7 +46,7 @@ function bundle(opts) {
|
|
|
45
46
|
exports.bundle = bundle;
|
|
46
47
|
function bundleDocument(opts) {
|
|
47
48
|
return __awaiter(this, void 0, void 0, function* () {
|
|
48
|
-
const { document, config, customTypes, externalRefResolver, dereference = false } = opts;
|
|
49
|
+
const { document, config, customTypes, externalRefResolver, dereference = false, skipRedoclyRegistryRefs = false, } = opts;
|
|
49
50
|
const oasVersion = oas_types_1.detectOpenAPI(document.parsed);
|
|
50
51
|
const oasMajorVersion = oas_types_1.openAPIMajor(oasVersion);
|
|
51
52
|
const rules = config.getRulesForOasVersion(oasMajorVersion);
|
|
@@ -60,13 +61,14 @@ function bundleDocument(opts) {
|
|
|
60
61
|
problems: [],
|
|
61
62
|
oasVersion: oasVersion,
|
|
62
63
|
refTypes: new Map(),
|
|
64
|
+
visitorsData: {},
|
|
63
65
|
};
|
|
64
66
|
const bundleVisitor = visitors_1.normalizeVisitors([
|
|
65
67
|
...preprocessors,
|
|
66
68
|
{
|
|
67
69
|
severity: 'error',
|
|
68
70
|
ruleId: 'bundler',
|
|
69
|
-
visitor: makeBundleVisitor(oasMajorVersion, dereference, document),
|
|
71
|
+
visitor: makeBundleVisitor(oasMajorVersion, dereference, skipRedoclyRegistryRefs, document),
|
|
70
72
|
},
|
|
71
73
|
...decorators,
|
|
72
74
|
], types);
|
|
@@ -88,6 +90,7 @@ function bundleDocument(opts) {
|
|
|
88
90
|
fileDependencies: externalRefResolver.getFiles(),
|
|
89
91
|
rootType: types.DefinitionRoot,
|
|
90
92
|
refTypes: ctx.refTypes,
|
|
93
|
+
visitorsData: ctx.visitorsData,
|
|
91
94
|
};
|
|
92
95
|
});
|
|
93
96
|
}
|
|
@@ -131,7 +134,7 @@ function mapTypeToComponent(typeName, version) {
|
|
|
131
134
|
}
|
|
132
135
|
}
|
|
133
136
|
// function oas3Move
|
|
134
|
-
function makeBundleVisitor(version, dereference, rootDocument) {
|
|
137
|
+
function makeBundleVisitor(version, dereference, skipRedoclyRegistryRefs, rootDocument) {
|
|
135
138
|
let components;
|
|
136
139
|
const visitor = {
|
|
137
140
|
ref: {
|
|
@@ -146,6 +149,9 @@ function makeBundleVisitor(version, dereference, rootDocument) {
|
|
|
146
149
|
!dereference) {
|
|
147
150
|
return;
|
|
148
151
|
}
|
|
152
|
+
if (skipRedoclyRegistryRefs && redocly_1.isRedoclyRegistryURL(node.$ref)) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
149
155
|
const componentType = mapTypeToComponent(ctx.type.name, version);
|
|
150
156
|
if (!componentType) {
|
|
151
157
|
replaceRef(node, resolved, ctx);
|
package/lib/config/all.js
CHANGED
package/lib/config/config.d.ts
CHANGED
|
@@ -70,11 +70,20 @@ export declare type HttpResolveConfig = {
|
|
|
70
70
|
export declare type ResolveConfig = {
|
|
71
71
|
http: HttpResolveConfig;
|
|
72
72
|
};
|
|
73
|
+
export declare const DEFAULT_REGION = "us";
|
|
74
|
+
export declare type Region = 'us' | 'eu';
|
|
75
|
+
export declare type AccessTokens = {
|
|
76
|
+
[region in Region]?: string;
|
|
77
|
+
};
|
|
78
|
+
export declare const DOMAINS: {
|
|
79
|
+
[region in Region]: string;
|
|
80
|
+
};
|
|
73
81
|
export declare type RawConfig = {
|
|
74
82
|
referenceDocs?: any;
|
|
75
83
|
apiDefinitions?: Record<string, string>;
|
|
76
84
|
lint?: LintRawConfig;
|
|
77
85
|
resolve?: RawResolveConfig;
|
|
86
|
+
region?: Region;
|
|
78
87
|
};
|
|
79
88
|
export declare class LintConfig {
|
|
80
89
|
rawConfig: LintRawConfig;
|
|
@@ -126,5 +135,6 @@ export declare class Config {
|
|
|
126
135
|
lint: LintConfig;
|
|
127
136
|
resolve: ResolveConfig;
|
|
128
137
|
licenseKey?: string;
|
|
138
|
+
region?: Region;
|
|
129
139
|
constructor(rawConfig: RawConfig, configFile?: string | undefined);
|
|
130
140
|
}
|
package/lib/config/config.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Config = exports.LintConfig = exports.IGNORE_FILE = void 0;
|
|
3
|
+
exports.Config = exports.LintConfig = exports.DOMAINS = exports.DEFAULT_REGION = exports.IGNORE_FILE = void 0;
|
|
4
4
|
const fs = require("fs");
|
|
5
5
|
const path = require("path");
|
|
6
6
|
const path_1 = require("path");
|
|
@@ -12,6 +12,11 @@ const recommended_1 = require("./recommended");
|
|
|
12
12
|
exports.IGNORE_FILE = '.redocly.lint-ignore.yaml';
|
|
13
13
|
const IGNORE_BANNER = `# This file instructs Redocly's linter to ignore the rules contained for specific parts of your API.\n` +
|
|
14
14
|
`# See https://redoc.ly/docs/cli/ for more information.\n`;
|
|
15
|
+
exports.DEFAULT_REGION = 'us';
|
|
16
|
+
exports.DOMAINS = {
|
|
17
|
+
us: 'redoc.ly',
|
|
18
|
+
eu: 'eu.redocly.com',
|
|
19
|
+
};
|
|
15
20
|
class LintConfig {
|
|
16
21
|
constructor(rawConfig, configFile) {
|
|
17
22
|
this.rawConfig = rawConfig;
|
|
@@ -233,6 +238,7 @@ class Config {
|
|
|
233
238
|
customFetch: undefined,
|
|
234
239
|
},
|
|
235
240
|
};
|
|
241
|
+
this.region = rawConfig.region;
|
|
236
242
|
}
|
|
237
243
|
}
|
|
238
244
|
exports.Config = Config;
|
package/lib/config/load.js
CHANGED
|
@@ -35,20 +35,29 @@ function loadConfig(configPath, customExtends) {
|
|
|
35
35
|
rawConfig.lint.extends = customExtends;
|
|
36
36
|
}
|
|
37
37
|
const redoclyClient = new redocly_1.RedoclyClient();
|
|
38
|
-
|
|
38
|
+
const tokens = yield redoclyClient.getTokens();
|
|
39
|
+
if (tokens.length) {
|
|
39
40
|
if (!rawConfig.resolve)
|
|
40
41
|
rawConfig.resolve = {};
|
|
41
42
|
if (!rawConfig.resolve.http)
|
|
42
43
|
rawConfig.resolve.http = {};
|
|
43
|
-
rawConfig.resolve.http.headers = [
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
rawConfig.resolve.http.headers = [...((_a = rawConfig.resolve.http.headers) !== null && _a !== void 0 ? _a : [])];
|
|
45
|
+
for (const item of tokens) {
|
|
46
|
+
const domain = config_1.DOMAINS[item.region];
|
|
47
|
+
rawConfig.resolve.http.headers.push({
|
|
48
|
+
matches: `https://api.${domain}/registry/**`,
|
|
46
49
|
name: 'Authorization',
|
|
47
50
|
envVariable: undefined,
|
|
48
|
-
value:
|
|
49
|
-
},
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
value: item.token,
|
|
52
|
+
},
|
|
53
|
+
//support redocly.com domain for future compatibility
|
|
54
|
+
...(item.region === 'us' ? [{
|
|
55
|
+
matches: `https://api.redocly.com/registry/**`,
|
|
56
|
+
name: 'Authorization',
|
|
57
|
+
envVariable: undefined,
|
|
58
|
+
value: item.token,
|
|
59
|
+
}] : []));
|
|
60
|
+
}
|
|
52
61
|
}
|
|
53
62
|
return new config_1.Config(Object.assign(Object.assign({}, rawConfig), { lint: Object.assign(Object.assign({}, rawConfig === null || rawConfig === void 0 ? void 0 : rawConfig.lint), { plugins: [...(((_b = rawConfig === null || rawConfig === void 0 ? void 0 : rawConfig.lint) === null || _b === void 0 ? void 0 : _b.plugins) || []), builtIn_1.defaultPlugin] }) }), configPath);
|
|
54
63
|
});
|
package/lib/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export { Oas2Definition } from './typings/swagger';
|
|
|
8
8
|
export { StatsAccumulator, StatsName } from './typings/common';
|
|
9
9
|
export { normalizeTypes } from './types';
|
|
10
10
|
export { Stats } from './rules/other/stats';
|
|
11
|
-
export { Config, LintConfig, RawConfig, IGNORE_FILE } from './config/config';
|
|
11
|
+
export { Config, LintConfig, RawConfig, IGNORE_FILE, Region } from './config/config';
|
|
12
12
|
export { loadConfig } from './config/load';
|
|
13
13
|
export { RedoclyClient } from './redocly';
|
|
14
14
|
export { Source, BaseResolver, Document, resolveDocument, ResolveError, YamlParseError, makeDocumentFromString, } from './resolve';
|
|
@@ -19,5 +19,5 @@ export { normalizeVisitors } from './visitors';
|
|
|
19
19
|
export { WalkContext, walkDocument, NormalizedProblem, ProblemSeverity, LineColLocationObject, LocationObject, Loc, } from './walk';
|
|
20
20
|
export { getAstNodeByPointer, getLineColLocation } from './format/codeframes';
|
|
21
21
|
export { formatProblems, OutputFormat, getTotals, Totals } from './format/format';
|
|
22
|
-
export { lint, lint as validate, lintDocument, lintFromString, lintConfig
|
|
22
|
+
export { lint, lint as validate, lintDocument, lintFromString, lintConfig } from './lint';
|
|
23
23
|
export { bundle, bundleDocument } from './bundle';
|
package/lib/lint.js
CHANGED
|
@@ -51,6 +51,7 @@ function lintDocument(opts) {
|
|
|
51
51
|
const ctx = {
|
|
52
52
|
problems: [],
|
|
53
53
|
oasVersion: oasVersion,
|
|
54
|
+
visitorsData: {},
|
|
54
55
|
};
|
|
55
56
|
const preprocessors = rules_1.initRules(rules, config, 'preprocessors', oasVersion);
|
|
56
57
|
const regularRules = rules_1.initRules(rules, config, 'rules', oasVersion);
|
|
@@ -77,6 +78,7 @@ function lintConfig(opts) {
|
|
|
77
78
|
const ctx = {
|
|
78
79
|
problems: [],
|
|
79
80
|
oasVersion: oas_types_1.OasVersion.Version3_0,
|
|
81
|
+
visitorsData: {},
|
|
80
82
|
};
|
|
81
83
|
const config = new config_1.LintConfig({
|
|
82
84
|
plugins: [builtIn_1.defaultPlugin],
|
package/lib/redocly/index.d.ts
CHANGED
|
@@ -1,25 +1,31 @@
|
|
|
1
|
+
import { RegistryApi } from './registry-api';
|
|
2
|
+
import { AccessTokens, Region } from '../config/config';
|
|
1
3
|
export declare class RedoclyClient {
|
|
2
|
-
private
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
private accessTokens;
|
|
5
|
+
private region;
|
|
6
|
+
domain: string;
|
|
7
|
+
registryApi: RegistryApi;
|
|
8
|
+
constructor(region?: Region);
|
|
9
|
+
loadRegion(region?: Region): Region;
|
|
10
|
+
getRegion(): Region;
|
|
11
|
+
hasTokens(): boolean;
|
|
12
|
+
setAccessTokens(accessTokens: AccessTokens): void;
|
|
13
|
+
loadTokens(): void;
|
|
14
|
+
getValidTokens(): Promise<{
|
|
15
|
+
region: string;
|
|
16
|
+
token: string;
|
|
17
|
+
valid: boolean;
|
|
18
|
+
}[]>;
|
|
19
|
+
getTokens(): Promise<{
|
|
20
|
+
region: string;
|
|
21
|
+
token: string;
|
|
22
|
+
valid: boolean;
|
|
23
|
+
}[]>;
|
|
24
|
+
isAuthorizedWithRedoclyByRegion(): Promise<boolean>;
|
|
6
25
|
isAuthorizedWithRedocly(): Promise<boolean>;
|
|
7
|
-
|
|
8
|
-
|
|
26
|
+
readCredentialsFile(credentialsPath: string): any;
|
|
27
|
+
verifyToken(accessToken: string, region: Region, verbose?: boolean): Promise<boolean>;
|
|
9
28
|
login(accessToken: string, verbose?: boolean): Promise<void>;
|
|
10
29
|
logout(): void;
|
|
11
|
-
query(queryString: string, parameters?: {}, headers?: {}): Promise<any>;
|
|
12
|
-
static authorize(accessToken: string, options: {
|
|
13
|
-
queryName?: string;
|
|
14
|
-
verbose?: boolean;
|
|
15
|
-
}): Promise<any>;
|
|
16
|
-
updateDependencies(dependencies: string[] | undefined): Promise<void>;
|
|
17
|
-
updateDefinitionVersion(definitionId: number, versionId: number, updatePatch: object): Promise<void>;
|
|
18
|
-
getOrganizationId(organizationId: string): Promise<any>;
|
|
19
|
-
getDefinitionByName(name: string, organizationId: string): Promise<any>;
|
|
20
|
-
createDefinition(organizationId: string, name: string): Promise<any>;
|
|
21
|
-
createDefinitionVersion(definitionId: string, name: string, sourceType: string, source: any): Promise<any>;
|
|
22
|
-
getSignedUrl(organizationId: string, filesHash: string, fileName: string): Promise<any>;
|
|
23
|
-
getDefinitionVersion(organizationId: string, definitionName: string, versionName: string): Promise<any>;
|
|
24
|
-
static isRegistryURL(link: string): boolean;
|
|
25
30
|
}
|
|
31
|
+
export declare function isRedoclyRegistryURL(link: string): boolean;
|
package/lib/redocly/index.js
CHANGED
|
@@ -9,69 +9,103 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.RedoclyClient = void 0;
|
|
12
|
+
exports.isRedoclyRegistryURL = exports.RedoclyClient = void 0;
|
|
13
13
|
const fs_1 = require("fs");
|
|
14
14
|
const path_1 = require("path");
|
|
15
15
|
const os_1 = require("os");
|
|
16
16
|
const colorette_1 = require("colorette");
|
|
17
|
-
const
|
|
17
|
+
const registry_api_1 = require("./registry-api");
|
|
18
|
+
const config_1 = require("../config/config");
|
|
19
|
+
const utils_1 = require("../utils");
|
|
18
20
|
const TOKEN_FILENAME = '.redocly-config.json';
|
|
19
21
|
class RedoclyClient {
|
|
20
|
-
constructor() {
|
|
21
|
-
this.
|
|
22
|
+
constructor(region) {
|
|
23
|
+
this.accessTokens = {};
|
|
24
|
+
this.region = this.loadRegion(region);
|
|
25
|
+
this.loadTokens();
|
|
26
|
+
this.domain = region
|
|
27
|
+
? config_1.DOMAINS[region]
|
|
28
|
+
: process.env.REDOCLY_DOMAIN || config_1.DOMAINS[config_1.DEFAULT_REGION];
|
|
29
|
+
this.registryApi = new registry_api_1.RegistryApi(this.accessTokens, this.region);
|
|
30
|
+
}
|
|
31
|
+
loadRegion(region) {
|
|
32
|
+
if (region && !config_1.DOMAINS[region]) {
|
|
33
|
+
process.stdout.write(colorette_1.red(`Invalid argument: region in config file.\nGiven: ${colorette_1.green(region)}, choices: "us", "eu".\n`));
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
if (process.env.REDOCLY_DOMAIN) {
|
|
37
|
+
return (Object.keys(config_1.DOMAINS).find((region) => config_1.DOMAINS[region] === process.env.REDOCLY_DOMAIN) || config_1.DEFAULT_REGION);
|
|
38
|
+
}
|
|
39
|
+
return region || config_1.DEFAULT_REGION;
|
|
22
40
|
}
|
|
23
|
-
|
|
24
|
-
return
|
|
41
|
+
getRegion() {
|
|
42
|
+
return this.region;
|
|
25
43
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
44
|
+
hasTokens() {
|
|
45
|
+
return utils_1.isNotEmptyObject(this.accessTokens);
|
|
46
|
+
}
|
|
47
|
+
setAccessTokens(accessTokens) {
|
|
48
|
+
this.accessTokens = accessTokens;
|
|
49
|
+
}
|
|
50
|
+
loadTokens() {
|
|
31
51
|
const credentialsPath = path_1.resolve(os_1.homedir(), TOKEN_FILENAME);
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
this.
|
|
52
|
+
const credentials = this.readCredentialsFile(credentialsPath);
|
|
53
|
+
if (utils_1.isNotEmptyObject(credentials)) {
|
|
54
|
+
this.setAccessTokens(Object.assign(Object.assign({}, credentials), (credentials.token && !credentials[this.region] && {
|
|
55
|
+
[this.region]: credentials.token
|
|
56
|
+
})));
|
|
57
|
+
}
|
|
58
|
+
if (process.env.REDOCLY_AUTHORIZATION) {
|
|
59
|
+
this.setAccessTokens(Object.assign(Object.assign({}, this.accessTokens), { [this.region]: process.env.REDOCLY_AUTHORIZATION }));
|
|
35
60
|
}
|
|
36
61
|
}
|
|
37
|
-
|
|
62
|
+
getValidTokens() {
|
|
38
63
|
return __awaiter(this, void 0, void 0, function* () {
|
|
39
|
-
return this.
|
|
64
|
+
return (yield Promise.all(Object.entries(this.accessTokens).map(([key, value]) => __awaiter(this, void 0, void 0, function* () {
|
|
65
|
+
return { region: key, token: value, valid: yield this.verifyToken(value, key) };
|
|
66
|
+
})))).filter(item => Boolean(item.valid));
|
|
40
67
|
});
|
|
41
68
|
}
|
|
42
|
-
|
|
69
|
+
getTokens() {
|
|
43
70
|
return __awaiter(this, void 0, void 0, function* () {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
71
|
+
return this.hasTokens() ? yield this.getValidTokens() : [];
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
isAuthorizedWithRedoclyByRegion() {
|
|
75
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
76
|
+
if (!this.hasTokens())
|
|
48
77
|
return false;
|
|
49
|
-
|
|
78
|
+
const accessToken = this.accessTokens[this.region];
|
|
79
|
+
return !!accessToken && (yield this.verifyToken(accessToken, this.region));
|
|
50
80
|
});
|
|
51
81
|
}
|
|
52
|
-
|
|
82
|
+
isAuthorizedWithRedocly() {
|
|
53
83
|
return __awaiter(this, void 0, void 0, function* () {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
84
|
+
return this.hasTokens() && utils_1.isNotEmptyObject(yield this.getValidTokens());
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
readCredentialsFile(credentialsPath) {
|
|
88
|
+
return fs_1.existsSync(credentialsPath) ? JSON.parse(fs_1.readFileSync(credentialsPath, 'utf-8')) : {};
|
|
89
|
+
}
|
|
90
|
+
verifyToken(accessToken, region, verbose = false) {
|
|
91
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
92
|
+
if (!accessToken)
|
|
93
|
+
return false;
|
|
94
|
+
return this.registryApi.authStatus(accessToken, region, verbose);
|
|
60
95
|
});
|
|
61
96
|
}
|
|
62
97
|
login(accessToken, verbose = false) {
|
|
63
98
|
return __awaiter(this, void 0, void 0, function* () {
|
|
64
99
|
const credentialsPath = path_1.resolve(os_1.homedir(), TOKEN_FILENAME);
|
|
65
100
|
process.stdout.write(colorette_1.gray('\n Logging in...\n'));
|
|
66
|
-
const authorized = yield this.verifyToken(accessToken, verbose);
|
|
101
|
+
const authorized = yield this.verifyToken(accessToken, this.region, verbose);
|
|
67
102
|
if (!authorized) {
|
|
68
103
|
process.stdout.write(colorette_1.red('Authorization failed. Please check if you entered a valid API key.\n'));
|
|
69
104
|
process.exit(1);
|
|
70
105
|
}
|
|
71
|
-
this.accessToken
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
};
|
|
106
|
+
const credentials = Object.assign(Object.assign({}, this.readCredentialsFile(credentialsPath)), { [this.region]: accessToken, token: accessToken });
|
|
107
|
+
this.accessTokens = credentials;
|
|
108
|
+
this.registryApi.setAccessTokens(credentials);
|
|
75
109
|
fs_1.writeFileSync(credentialsPath, JSON.stringify(credentials, null, 2));
|
|
76
110
|
process.stdout.write(colorette_1.green(' Authorization confirmed. ✅\n\n'));
|
|
77
111
|
});
|
|
@@ -83,185 +117,20 @@ class RedoclyClient {
|
|
|
83
117
|
}
|
|
84
118
|
process.stdout.write('Logged out from the Redocly account. ✋\n');
|
|
85
119
|
}
|
|
86
|
-
query(queryString, parameters = {}, headers = {}) {
|
|
87
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
88
|
-
return query_1.query(queryString, parameters, Object.assign({ Authorization: this.accessToken }, headers));
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
static authorize(accessToken, options) {
|
|
92
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
93
|
-
const { queryName = '', verbose = false } = options;
|
|
94
|
-
try {
|
|
95
|
-
const queryStr = `query ${queryName}{ viewer { id } }`;
|
|
96
|
-
return yield query_1.query(queryStr, {}, { Authorization: accessToken });
|
|
97
|
-
}
|
|
98
|
-
catch (e) {
|
|
99
|
-
if (verbose)
|
|
100
|
-
console.log(e);
|
|
101
|
-
return null;
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
updateDependencies(dependencies) {
|
|
106
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
107
|
-
const definitionId = process.env.DEFINITION;
|
|
108
|
-
const versionId = process.env.DEFINITION;
|
|
109
|
-
const branchId = process.env.BRANCH;
|
|
110
|
-
if (!definitionId || !versionId || !branchId)
|
|
111
|
-
return;
|
|
112
|
-
yield this.query(`
|
|
113
|
-
mutation UpdateBranchDependenciesFromURLs(
|
|
114
|
-
$urls: [String!]!
|
|
115
|
-
$definitionId: Int!
|
|
116
|
-
$versionId: Int!
|
|
117
|
-
$branchId: Int!
|
|
118
|
-
) {
|
|
119
|
-
updateBranchDependenciesFromURLs(
|
|
120
|
-
definitionId: $definitionId
|
|
121
|
-
versionId: $versionId
|
|
122
|
-
branchId: $branchId
|
|
123
|
-
urls: $urls
|
|
124
|
-
) {
|
|
125
|
-
branchName
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
`, {
|
|
129
|
-
urls: dependencies || [],
|
|
130
|
-
definitionId: parseInt(definitionId, 10),
|
|
131
|
-
versionId: parseInt(versionId, 10),
|
|
132
|
-
branchId: parseInt(branchId, 10),
|
|
133
|
-
});
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
updateDefinitionVersion(definitionId, versionId, updatePatch) {
|
|
137
|
-
return this.query(`
|
|
138
|
-
mutation UpdateDefinitionVersion($definitionId: Int!, $versionId: Int!, $updatePatch: DefinitionVersionPatch!) {
|
|
139
|
-
updateDefinitionVersionByDefinitionIdAndId(input: {definitionId: $definitionId, id: $versionId, patch: $updatePatch}) {
|
|
140
|
-
definitionVersion {
|
|
141
|
-
...VersionDetails
|
|
142
|
-
__typename
|
|
143
|
-
}
|
|
144
|
-
__typename
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
fragment VersionDetails on DefinitionVersion {
|
|
149
|
-
id
|
|
150
|
-
nodeId
|
|
151
|
-
uuid
|
|
152
|
-
definitionId
|
|
153
|
-
name
|
|
154
|
-
description
|
|
155
|
-
sourceType
|
|
156
|
-
source
|
|
157
|
-
registryAccess
|
|
158
|
-
__typename
|
|
159
|
-
}
|
|
160
|
-
`, {
|
|
161
|
-
definitionId,
|
|
162
|
-
versionId,
|
|
163
|
-
updatePatch,
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
getOrganizationId(organizationId) {
|
|
167
|
-
return this.query(`
|
|
168
|
-
query ($organizationId: String!) {
|
|
169
|
-
organizationById(id: $organizationId) {
|
|
170
|
-
id
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
`, {
|
|
174
|
-
organizationId
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
getDefinitionByName(name, organizationId) {
|
|
178
|
-
return this.query(`
|
|
179
|
-
query ($name: String!, $organizationId: String!) {
|
|
180
|
-
definition: definitionByOrganizationIdAndName(name: $name, organizationId: $organizationId) {
|
|
181
|
-
id
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
`, {
|
|
185
|
-
name,
|
|
186
|
-
organizationId
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
createDefinition(organizationId, name) {
|
|
190
|
-
return this.query(`
|
|
191
|
-
mutation CreateDefinition($organizationId: String!, $name: String!) {
|
|
192
|
-
def: createDefinition(input: {organizationId: $organizationId, name: $name }) {
|
|
193
|
-
definition {
|
|
194
|
-
id
|
|
195
|
-
nodeId
|
|
196
|
-
name
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
`, {
|
|
201
|
-
organizationId,
|
|
202
|
-
name
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
createDefinitionVersion(definitionId, name, sourceType, source) {
|
|
206
|
-
return this.query(`
|
|
207
|
-
mutation CreateVersion($definitionId: Int!, $name: String!, $sourceType: DvSourceType!, $source: JSON) {
|
|
208
|
-
createDefinitionVersion(input: {definitionId: $definitionId, name: $name, sourceType: $sourceType, source: $source }) {
|
|
209
|
-
definitionVersion {
|
|
210
|
-
id
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
`, {
|
|
215
|
-
definitionId,
|
|
216
|
-
name,
|
|
217
|
-
sourceType,
|
|
218
|
-
source
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
getSignedUrl(organizationId, filesHash, fileName) {
|
|
222
|
-
return this.query(`
|
|
223
|
-
query ($organizationId: String!, $filesHash: String!, $fileName: String!) {
|
|
224
|
-
signFileUploadCLI(organizationId: $organizationId, filesHash: $filesHash, fileName: $fileName) {
|
|
225
|
-
signedFileUrl
|
|
226
|
-
uploadedFilePath
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
`, {
|
|
230
|
-
organizationId,
|
|
231
|
-
filesHash,
|
|
232
|
-
fileName
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
getDefinitionVersion(organizationId, definitionName, versionName) {
|
|
236
|
-
return this.query(`
|
|
237
|
-
query ($organizationId: String!, $definitionName: String!, $versionName: String!) {
|
|
238
|
-
version: definitionVersionByOrganizationDefinitionAndName(organizationId: $organizationId, definitionName: $definitionName, versionName: $versionName) {
|
|
239
|
-
id
|
|
240
|
-
definitionId
|
|
241
|
-
defaultBranch {
|
|
242
|
-
name
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
`, {
|
|
247
|
-
organizationId,
|
|
248
|
-
definitionName,
|
|
249
|
-
versionName
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
static isRegistryURL(link) {
|
|
253
|
-
const domain = process.env.REDOCLY_DOMAIN || 'redoc.ly';
|
|
254
|
-
if (!link.startsWith(`https://api.${domain}/registry/`))
|
|
255
|
-
return false;
|
|
256
|
-
const registryPath = link.replace(`https://api.${domain}/registry/`, '');
|
|
257
|
-
const pathParts = registryPath.split('/');
|
|
258
|
-
// we can be sure, that there is job UUID present
|
|
259
|
-
// (org, definition, version, bundle, branch, job, "openapi.yaml" 🤦♂️)
|
|
260
|
-
// so skip this link.
|
|
261
|
-
// FIXME
|
|
262
|
-
if (pathParts.length === 7)
|
|
263
|
-
return false;
|
|
264
|
-
return true;
|
|
265
|
-
}
|
|
266
120
|
}
|
|
267
121
|
exports.RedoclyClient = RedoclyClient;
|
|
122
|
+
function isRedoclyRegistryURL(link) {
|
|
123
|
+
const domain = process.env.REDOCLY_DOMAIN || config_1.DOMAINS[config_1.DEFAULT_REGION];
|
|
124
|
+
if (!link.startsWith(`https://api.${domain}/registry/`))
|
|
125
|
+
return false;
|
|
126
|
+
const registryPath = link.replace(`https://api.${domain}/registry/`, '');
|
|
127
|
+
const pathParts = registryPath.split('/');
|
|
128
|
+
// we can be sure, that there is job UUID present
|
|
129
|
+
// (org, definition, version, bundle, branch, job, "openapi.yaml" 🤦♂️)
|
|
130
|
+
// so skip this link.
|
|
131
|
+
// FIXME
|
|
132
|
+
if (pathParts.length === 7)
|
|
133
|
+
return false;
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
exports.isRedoclyRegistryURL = isRedoclyRegistryURL;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export declare namespace RegistryApiTypes {
|
|
2
|
+
interface VersionParams {
|
|
3
|
+
organizationId: string;
|
|
4
|
+
name: string;
|
|
5
|
+
version: string;
|
|
6
|
+
}
|
|
7
|
+
export interface PrepareFileuploadParams extends VersionParams {
|
|
8
|
+
filesHash: string;
|
|
9
|
+
filename: string;
|
|
10
|
+
isUpsert?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface PushApiParams extends VersionParams {
|
|
13
|
+
rootFilePath: string;
|
|
14
|
+
filePaths: string[];
|
|
15
|
+
branch?: string;
|
|
16
|
+
isUpsert?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface PrepareFileuploadOKResponse {
|
|
19
|
+
filePath: string;
|
|
20
|
+
signedUploadUrl: string;
|
|
21
|
+
}
|
|
22
|
+
export interface NotFoundProblemResponse {
|
|
23
|
+
status: 404;
|
|
24
|
+
title: 'Not Found';
|
|
25
|
+
code: 'ORGANIZATION_NOT_FOUND' | 'API_VERSION_NOT_FOUND';
|
|
26
|
+
}
|
|
27
|
+
export {};
|
|
28
|
+
}
|