@redocly/openapi-core 1.0.0-beta.67 → 1.0.0-beta.71
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__/__snapshots__/bundle.test.ts.snap +126 -0
- package/__tests__/bundle.test.ts +53 -1
- package/__tests__/fixtures/refs/definitions.yaml +3 -0
- package/__tests__/fixtures/refs/external-request-body.yaml +13 -0
- package/__tests__/fixtures/refs/externalref.yaml +35 -0
- package/__tests__/fixtures/refs/hosted.yaml +35 -0
- package/__tests__/fixtures/refs/rename.yaml +1 -0
- package/__tests__/fixtures/refs/requestBody.yaml +9 -0
- package/__tests__/fixtures/refs/simple.yaml +1 -0
- package/__tests__/fixtures/refs/vendor.schema.yaml +20 -0
- 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 +25 -7
- 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/ref-utils.js +1 -2
- 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/oas3/no-server-trailing-slash.js +1 -1
- 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 +51 -9
- 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 +100 -227
- package/src/redocly/registry-api-types.ts +31 -0
- package/src/redocly/registry-api.ts +110 -0
- package/src/ref-utils.ts +1 -3
- 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/__tests__/no-server-trailing-slash.test.ts +19 -0
- package/src/rules/oas3/index.ts +4 -0
- package/src/rules/oas3/no-invalid-media-type-examples.ts +16 -36
- package/src/rules/oas3/no-server-trailing-slash.ts +1 -1
- 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/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.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
};
|
|
106
|
+
const credentials = Object.assign(Object.assign({}, this.readCredentialsFile(credentialsPath)), { [this.region]: 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
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { RegistryApiTypes } from './registry-api-types';
|
|
2
|
+
import { AccessTokens, Region } from '../config/config';
|
|
3
|
+
export declare class RegistryApi {
|
|
4
|
+
private accessTokens;
|
|
5
|
+
private region;
|
|
6
|
+
constructor(accessTokens: AccessTokens, region: Region);
|
|
7
|
+
get accessToken(): string | false | undefined;
|
|
8
|
+
getBaseUrl(region?: Region): string;
|
|
9
|
+
setAccessTokens(accessTokens: AccessTokens): this;
|
|
10
|
+
private request;
|
|
11
|
+
authStatus(accessToken: string, region: Region, verbose?: boolean): Promise<boolean>;
|
|
12
|
+
prepareFileUpload({ organizationId, name, version, filesHash, filename, isUpsert, }: RegistryApiTypes.PrepareFileuploadParams): Promise<RegistryApiTypes.PrepareFileuploadOKResponse>;
|
|
13
|
+
pushApi({ organizationId, name, version, rootFilePath, filePaths, branch, isUpsert, }: RegistryApiTypes.PushApiParams): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.RegistryApi = void 0;
|
|
13
|
+
const node_fetch_1 = require("node-fetch");
|
|
14
|
+
const config_1 = require("../config/config");
|
|
15
|
+
const utils_1 = require("../utils");
|
|
16
|
+
const version = require('../../package.json').version;
|
|
17
|
+
class RegistryApi {
|
|
18
|
+
constructor(accessTokens, region) {
|
|
19
|
+
this.accessTokens = accessTokens;
|
|
20
|
+
this.region = region;
|
|
21
|
+
}
|
|
22
|
+
get accessToken() {
|
|
23
|
+
return utils_1.isNotEmptyObject(this.accessTokens) && this.accessTokens[this.region];
|
|
24
|
+
}
|
|
25
|
+
getBaseUrl(region = config_1.DEFAULT_REGION) {
|
|
26
|
+
return `https://api.${config_1.DOMAINS[region]}/registry`;
|
|
27
|
+
}
|
|
28
|
+
setAccessTokens(accessTokens) {
|
|
29
|
+
this.accessTokens = accessTokens;
|
|
30
|
+
return this;
|
|
31
|
+
}
|
|
32
|
+
request(path = '', options = {}, region) {
|
|
33
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
34
|
+
const headers = Object.assign({}, options.headers || {}, { 'x-redocly-cli-version': version });
|
|
35
|
+
if (!headers.hasOwnProperty('authorization')) {
|
|
36
|
+
throw new Error('Unauthorized');
|
|
37
|
+
}
|
|
38
|
+
const response = yield node_fetch_1.default(`${this.getBaseUrl(region)}${path}`, Object.assign({}, options, { headers }));
|
|
39
|
+
if (response.status === 401) {
|
|
40
|
+
throw new Error('Unauthorized');
|
|
41
|
+
}
|
|
42
|
+
if (response.status === 404) {
|
|
43
|
+
const body = yield response.json();
|
|
44
|
+
throw new Error(body.code);
|
|
45
|
+
}
|
|
46
|
+
return response;
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
authStatus(accessToken, region, verbose = false) {
|
|
50
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
51
|
+
try {
|
|
52
|
+
const response = yield this.request('', { headers: { authorization: accessToken } }, region);
|
|
53
|
+
return response.ok;
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
if (verbose) {
|
|
57
|
+
console.log(error);
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
prepareFileUpload({ organizationId, name, version, filesHash, filename, isUpsert, }) {
|
|
64
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
65
|
+
const response = yield this.request(`/${organizationId}/${name}/${version}/prepare-file-upload`, {
|
|
66
|
+
method: 'POST',
|
|
67
|
+
headers: {
|
|
68
|
+
'content-type': 'application/json',
|
|
69
|
+
authorization: this.accessToken,
|
|
70
|
+
},
|
|
71
|
+
body: JSON.stringify({
|
|
72
|
+
filesHash,
|
|
73
|
+
filename,
|
|
74
|
+
isUpsert,
|
|
75
|
+
}),
|
|
76
|
+
}, this.region);
|
|
77
|
+
if (response.ok) {
|
|
78
|
+
return response.json();
|
|
79
|
+
}
|
|
80
|
+
throw new Error('Could not prepare file upload');
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
pushApi({ organizationId, name, version, rootFilePath, filePaths, branch, isUpsert, }) {
|
|
84
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
85
|
+
const response = yield this.request(`/${organizationId}/${name}/${version}`, {
|
|
86
|
+
method: 'PUT',
|
|
87
|
+
headers: {
|
|
88
|
+
'content-type': 'application/json',
|
|
89
|
+
authorization: this.accessToken
|
|
90
|
+
},
|
|
91
|
+
body: JSON.stringify({
|
|
92
|
+
rootFilePath,
|
|
93
|
+
filePaths,
|
|
94
|
+
branch,
|
|
95
|
+
isUpsert,
|
|
96
|
+
}),
|
|
97
|
+
}, this.region);
|
|
98
|
+
if (response.ok) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
throw new Error('Could not push api');
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
exports.RegistryApi = RegistryApi;
|
package/lib/ref-utils.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.isMappingRef = exports.isAbsoluteUrl = exports.refBaseName = exports.pointerBaseName = exports.parsePointer = exports.parseRef = exports.escapePointer = exports.unescapePointer = exports.Location = exports.isRef = exports.joinPointer = void 0;
|
|
4
|
-
const path_1 = require("path");
|
|
5
4
|
function joinPointer(base, key) {
|
|
6
5
|
if (base === '')
|
|
7
6
|
base = '#/';
|
|
@@ -56,7 +55,7 @@ function pointerBaseName(pointer) {
|
|
|
56
55
|
}
|
|
57
56
|
exports.pointerBaseName = pointerBaseName;
|
|
58
57
|
function refBaseName(ref) {
|
|
59
|
-
const parts = ref.split(
|
|
58
|
+
const parts = ref.split(/[\/\\]/); // split by '\' and '/'
|
|
60
59
|
return parts[parts.length - 1].split('.')[0];
|
|
61
60
|
}
|
|
62
61
|
exports.refBaseName = refBaseName;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const NoInvalidParameterExamples: any;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NoInvalidParameterExamples = void 0;
|
|
4
|
+
const utils_1 = require("../utils");
|
|
5
|
+
const NoInvalidParameterExamples = (opts) => {
|
|
6
|
+
var _a;
|
|
7
|
+
const disallowAdditionalProperties = (_a = opts.disallowAdditionalProperties) !== null && _a !== void 0 ? _a : true;
|
|
8
|
+
return {
|
|
9
|
+
Parameter: {
|
|
10
|
+
leave(parameter, ctx) {
|
|
11
|
+
if (parameter.example) {
|
|
12
|
+
utils_1.validateExample(parameter.example, parameter.schema, ctx.location.child('example'), ctx, disallowAdditionalProperties);
|
|
13
|
+
}
|
|
14
|
+
if (parameter.examples) {
|
|
15
|
+
for (const [key, example] of Object.entries(parameter.examples)) {
|
|
16
|
+
if ('value' in example) {
|
|
17
|
+
utils_1.validateExample(example.value, parameter.schema, ctx.location.child(['examples', key]), ctx, false);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
exports.NoInvalidParameterExamples = NoInvalidParameterExamples;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const NoInvalidSchemaExamples: any;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NoInvalidSchemaExamples = void 0;
|
|
4
|
+
const utils_1 = require("../utils");
|
|
5
|
+
const NoInvalidSchemaExamples = (opts) => {
|
|
6
|
+
var _a;
|
|
7
|
+
const disallowAdditionalProperties = (_a = opts.disallowAdditionalProperties) !== null && _a !== void 0 ? _a : true;
|
|
8
|
+
return {
|
|
9
|
+
Schema: {
|
|
10
|
+
leave(schema, ctx) {
|
|
11
|
+
if (schema.examples) {
|
|
12
|
+
for (const example of schema.examples) {
|
|
13
|
+
utils_1.validateExample(example, schema, ctx.location.child(['examples', schema.examples.indexOf(example)]), ctx, disallowAdditionalProperties);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
if (schema.example) {
|
|
17
|
+
utils_1.validateExample(schema.example, schema, ctx.location.child('example'), ctx, false);
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
exports.NoInvalidSchemaExamples = NoInvalidSchemaExamples;
|
|
@@ -4,7 +4,7 @@ exports.PathsKebabCase = void 0;
|
|
|
4
4
|
const PathsKebabCase = () => {
|
|
5
5
|
return {
|
|
6
6
|
PathItem(_path, { report, key }) {
|
|
7
|
-
const segments = key.substr(1).split('/');
|
|
7
|
+
const segments = key.substr(1).split('/').filter(s => s !== ''); // filter out empty segments
|
|
8
8
|
if (!segments.every((segment) => /^{.+}$/.test(segment) || /^[a-z0-9-.]+$/.test(segment))) {
|
|
9
9
|
report({
|
|
10
10
|
message: `\`${key}\` does not use kebab-case.`,
|
|
@@ -3,21 +3,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.RegistryDependencies = void 0;
|
|
4
4
|
const redocly_1 = require("../../redocly");
|
|
5
5
|
const RegistryDependencies = () => {
|
|
6
|
-
let redoclyClient;
|
|
7
6
|
let registryDependencies = new Set();
|
|
8
7
|
return {
|
|
9
8
|
DefinitionRoot: {
|
|
10
|
-
leave() {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
redoclyClient.updateDependencies(Array.from(registryDependencies.keys()));
|
|
14
|
-
}
|
|
9
|
+
leave(_, ctx) {
|
|
10
|
+
const data = ctx.getVisitorData();
|
|
11
|
+
data.links = Array.from(registryDependencies);
|
|
15
12
|
},
|
|
16
13
|
},
|
|
17
14
|
ref(node) {
|
|
18
15
|
if (node.$ref) {
|
|
19
16
|
const link = node.$ref.split('#/')[0];
|
|
20
|
-
if (redocly_1.
|
|
17
|
+
if (redocly_1.isRedoclyRegistryURL(link)) {
|
|
21
18
|
registryDependencies.add(link);
|
|
22
19
|
}
|
|
23
20
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Oas2Decorator, Oas2Rule } from '../../visitors';
|
|
2
2
|
export declare const rules: {
|
|
3
3
|
spec: Oas2Rule;
|
|
4
|
+
'no-invalid-schema-examples': any;
|
|
5
|
+
'no-invalid-parameter-examples': any;
|
|
4
6
|
'info-description': Oas2Rule;
|
|
5
7
|
'info-contact': Oas2Rule;
|
|
6
8
|
'info-license': Oas2Rule;
|
package/lib/rules/oas2/index.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.decorators = exports.preprocessors = exports.rules = void 0;
|
|
4
4
|
const spec_1 = require("../common/spec");
|
|
5
|
+
const no_invalid_schema_examples_1 = require("../common/no-invalid-schema-examples");
|
|
6
|
+
const no_invalid_parameter_examples_1 = require("../common/no-invalid-parameter-examples");
|
|
5
7
|
const info_description_1 = require("../common/info-description");
|
|
6
8
|
const info_contact_1 = require("../common/info-contact");
|
|
7
9
|
const info_license_url_1 = require("../common/info-license-url");
|
|
@@ -42,6 +44,8 @@ const tag_description_override_1 = require("../common/tag-description-override")
|
|
|
42
44
|
const info_description_override_1 = require("../common/info-description-override");
|
|
43
45
|
exports.rules = {
|
|
44
46
|
spec: spec_1.OasSpec,
|
|
47
|
+
'no-invalid-schema-examples': no_invalid_schema_examples_1.NoInvalidSchemaExamples,
|
|
48
|
+
'no-invalid-parameter-examples': no_invalid_parameter_examples_1.NoInvalidParameterExamples,
|
|
45
49
|
'info-description': info_description_1.InfoDescription,
|
|
46
50
|
'info-contact': info_contact_1.InfoContact,
|
|
47
51
|
'info-license': info_license_url_1.InfoLicense,
|
package/lib/rules/oas3/index.js
CHANGED
|
@@ -48,6 +48,8 @@ const operation_description_override_1 = require("../common/operation-descriptio
|
|
|
48
48
|
const tag_description_override_1 = require("../common/tag-description-override");
|
|
49
49
|
const info_description_override_1 = require("../common/info-description-override");
|
|
50
50
|
const path_excludes_patterns_1 = require("../common/path-excludes-patterns");
|
|
51
|
+
const no_invalid_schema_examples_1 = require("../common/no-invalid-schema-examples");
|
|
52
|
+
const no_invalid_parameter_examples_1 = require("../common/no-invalid-parameter-examples");
|
|
51
53
|
exports.rules = {
|
|
52
54
|
spec: spec_1.OasSpec,
|
|
53
55
|
'info-description': info_description_1.InfoDescription,
|
|
@@ -93,6 +95,8 @@ exports.rules = {
|
|
|
93
95
|
'request-mime-type': request_mime_type_1.RequestMimeType,
|
|
94
96
|
'response-mime-type': response_mime_type_1.ResponseMimeType,
|
|
95
97
|
'path-segment-plural': path_segment_plural_1.PathSegmentPlural,
|
|
98
|
+
'no-invalid-schema-examples': no_invalid_schema_examples_1.NoInvalidSchemaExamples,
|
|
99
|
+
'no-invalid-parameter-examples': no_invalid_parameter_examples_1.NoInvalidParameterExamples,
|
|
96
100
|
};
|
|
97
101
|
exports.preprocessors = {};
|
|
98
102
|
exports.decorators = {
|