@redocly/openapi-core 1.2.0 → 1.2.1
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/CHANGELOG.md +10 -0
- package/README.md +250 -7
- package/lib/bundle.d.ts +10 -4
- package/lib/bundle.js +10 -2
- package/lib/config/load.d.ts +3 -2
- package/lib/config/load.js +2 -2
- package/lib/config/types.d.ts +1 -0
- package/lib/index.d.ts +3 -2
- package/lib/index.js +5 -2
- package/lib/rules/common/assertions/asserts.js +12 -4
- package/lib/rules/oas3/no-server-example.com.js +3 -2
- package/lib/types/asyncapi.js +8 -1
- package/lib/types/oas3_1.js +8 -1
- package/package.json +3 -2
- package/src/__tests__/__snapshots__/bundle.test.ts.snap +1 -1
- package/src/__tests__/bundle.test.ts +65 -25
- package/src/__tests__/fixtures/lint/openapi.yaml +10 -0
- package/src/__tests__/fixtures/redocly.yaml +2 -0
- package/src/__tests__/lint.test.ts +31 -2
- package/src/bundle.ts +35 -7
- package/src/config/__tests__/load.test.ts +35 -2
- package/src/config/load.ts +11 -4
- package/src/config/types.ts +3 -0
- package/src/index.ts +3 -1
- package/src/rules/common/assertions/asserts.ts +16 -4
- package/src/rules/oas3/__tests__/no-server-example.com.test.ts +36 -1
- package/src/rules/oas3/__tests__/spec/spec.test.ts +1 -1
- package/src/rules/oas3/no-server-example.com.ts +3 -2
- package/src/types/asyncapi.ts +7 -1
- package/src/types/oas3_1.ts +7 -1
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @redocly/openapi-core
|
|
2
2
|
|
|
3
|
+
## 1.2.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Fixed an issue with nested refs in the `join` command.
|
|
8
|
+
- Fixed pattern for no-server-example.com rule to improve detection accuracy.
|
|
9
|
+
- Changed the report location for `pattern` and `notPattern` assertions to be more precise.
|
|
10
|
+
- Updated `unevaluatedItems` type definition to resolve either boolean or object schema per JSON Schema 2019-09 specification.
|
|
11
|
+
- Enhanced public API by small typescript typing fix and exporting new function `bundleFromString`.
|
|
12
|
+
|
|
3
13
|
## 1.2.0
|
|
4
14
|
|
|
5
15
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -2,24 +2,267 @@
|
|
|
2
2
|
|
|
3
3
|
See https://github.com/Redocly/redocly-cli
|
|
4
4
|
|
|
5
|
+
> [!IMPORTANT]
|
|
6
|
+
The `openapi-core package` is designed for our internal use; the interfaces that are considered safe to use are documented below.
|
|
7
|
+
Some of the function arguments are not documented below because they are not intended for public use.
|
|
8
|
+
Avoid using any functions or features that are not documented below.
|
|
9
|
+
If your use case is not documented below, please open an issue.
|
|
10
|
+
|
|
5
11
|
## Basic usage
|
|
6
12
|
|
|
7
|
-
### Lint
|
|
13
|
+
### Lint from file system
|
|
14
|
+
|
|
15
|
+
[Lint](https://redocly.com/docs/cli/commands/lint/) a file, optionally with a [config file](https://redocly.com/docs/cli/configuration/).
|
|
8
16
|
|
|
9
17
|
```js
|
|
10
|
-
import {
|
|
18
|
+
import { lint, loadConfig } from '@redocly/openapi-core';
|
|
11
19
|
|
|
12
20
|
const pathToApi = 'openapi.yaml';
|
|
13
|
-
const config = loadConfig({ configPath: 'optional/path/to
|
|
21
|
+
const config = await loadConfig({ configPath: 'optional/path/to/redocly.yaml' });
|
|
14
22
|
const lintResults = await lint({ ref: pathToApi, config });
|
|
15
23
|
```
|
|
16
24
|
|
|
17
|
-
|
|
25
|
+
The content of `lintResults` describes any errors or warnings found during linting; an empty array means no problems were found.
|
|
26
|
+
For each problem, the rule, severity, feedback message and a location object are provided.
|
|
27
|
+
To learn more, [check the `lint` function section](#lint).
|
|
28
|
+
|
|
29
|
+
### Bundle from file system
|
|
30
|
+
|
|
31
|
+
[Bundle](https://redocly.com/docs/cli/commands/bundle/) an API description into a single structure, optionally with a [config file](https://redocly.com/docs/cli/configuration/).
|
|
18
32
|
|
|
19
33
|
```js
|
|
20
|
-
import {
|
|
34
|
+
import { bundle, loadConfig } from '@redocly/openapi-core';
|
|
21
35
|
|
|
22
36
|
const pathToApi = 'openapi.yaml';
|
|
23
|
-
const config = loadConfig({ configPath: 'optional/path/to
|
|
24
|
-
const
|
|
37
|
+
const config = await loadConfig({ configPath: 'optional/path/to/redocly.yaml' });
|
|
38
|
+
const bundleResults = await bundle({ ref: pathToApi, config });
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
In `bundleResults`, the `bundle.parsed` field has the bundled API description.
|
|
42
|
+
For more information, [check the `bundle` function section](#bundle).
|
|
43
|
+
|
|
44
|
+
### Lint from memory with config
|
|
45
|
+
|
|
46
|
+
[Lint](https://redocly.com/docs/cli/commands/lint/) an API description, with configuration defined. This is useful if the API description you're working with isn't a file on disk.
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
import { lintFromString, createConfig, stringifyYaml } from '@redocly/openapi-core';
|
|
50
|
+
|
|
51
|
+
const config = await createConfig(
|
|
52
|
+
{
|
|
53
|
+
extends: ['minimal'],
|
|
54
|
+
rules: {
|
|
55
|
+
'operation-description': 'error',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
// optionally provide config path for resolving $refs and proper error locations
|
|
60
|
+
configPath: 'optional/path/to/redocly.yaml',
|
|
61
|
+
}
|
|
62
|
+
);
|
|
63
|
+
const source = stringifyYaml({ openapi: '3.0.1' /* ... */ }); // you can also use JSON.stringify
|
|
64
|
+
const lintResults = await lintFromString({
|
|
65
|
+
source,
|
|
66
|
+
// optionally pass path to the file for resolving $refs and proper error locations
|
|
67
|
+
absoluteRef: 'optional/path/to/openapi.yaml',
|
|
68
|
+
config,
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Lint from memory with a custom plugin
|
|
73
|
+
|
|
74
|
+
[Lint](https://redocly.com/docs/cli/commands/lint/) an API description, with configuration including a [custom plugin](https://redocly.com/docs/cli/custom-plugins/) to define a rule.
|
|
75
|
+
|
|
76
|
+
```js
|
|
77
|
+
import { lintFromString, createConfig, stringifyYaml } from '@redocly/openapi-core';
|
|
78
|
+
|
|
79
|
+
const CustomRule = (ruleOptions) => {
|
|
80
|
+
return {
|
|
81
|
+
Operation() {
|
|
82
|
+
// some rule logic
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const config = await createConfig({
|
|
88
|
+
extends: ['recommended'],
|
|
89
|
+
plugins: [
|
|
90
|
+
{
|
|
91
|
+
id: 'pluginId',
|
|
92
|
+
rules: {
|
|
93
|
+
oas3: {
|
|
94
|
+
customRule1: CustomRule,
|
|
95
|
+
},
|
|
96
|
+
oas2: {
|
|
97
|
+
customRule1: CustomRule, // if the same rule can handle both oas3 and oas2
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
decorators: {
|
|
101
|
+
// ...
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
// enable rule
|
|
106
|
+
rules: {
|
|
107
|
+
'pluginId/customRule1': 'error',
|
|
108
|
+
},
|
|
109
|
+
decorators: {
|
|
110
|
+
// ...
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
const source = stringifyYaml({ openapi: '3.0.1' /* ... */ }); // you can also use JSON.stringify
|
|
115
|
+
const lintResults = await lintFromString({
|
|
116
|
+
source,
|
|
117
|
+
// optionally pass path to the file for resolving $refs and proper error locations
|
|
118
|
+
absoluteRef: 'optional/path/to/openapi.yaml',
|
|
119
|
+
config,
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Bundle from memory
|
|
124
|
+
|
|
125
|
+
[Bundle](https://redocly.com/docs/cli/commands/bundle/) an API description into a single structure, using default configuration.
|
|
126
|
+
|
|
127
|
+
```js
|
|
128
|
+
import { bundleFromString, createConfig } from '@redocly/openapi-core';
|
|
129
|
+
|
|
130
|
+
const config = await createConfig({}); // create empty config
|
|
131
|
+
const source = stringifyYaml({ openapi: '3.0.1' /* ... */ }); // you can also use JSON.stringify
|
|
132
|
+
const bundleResults = await bundleFromString({
|
|
133
|
+
source,
|
|
134
|
+
// optionally pass path to the file for resolving $refs and proper error locations
|
|
135
|
+
absoluteRef: 'optional/path/to/openapi.yaml',
|
|
136
|
+
config,
|
|
137
|
+
});
|
|
25
138
|
```
|
|
139
|
+
|
|
140
|
+
## API
|
|
141
|
+
|
|
142
|
+
### `createConfig`
|
|
143
|
+
|
|
144
|
+
Creates a config object from a JSON or YAML string or JS object.
|
|
145
|
+
Resolves remote config from `extends` (if there are URLs or local fs paths).
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
async function createConfig(
|
|
149
|
+
// JSON or YAML string or object with Redocly config
|
|
150
|
+
config: string | RawUniversalConfig,
|
|
151
|
+
options?: {
|
|
152
|
+
// optional path to the config file for resolving $refs and proper error locations
|
|
153
|
+
configPath?: string;
|
|
154
|
+
}
|
|
155
|
+
): Promise<Config>;
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### `loadConfig`
|
|
159
|
+
|
|
160
|
+
Loads a config object from a file system. If `configPath` is not provided,
|
|
161
|
+
it tries to find `redocly.yaml` in the current working directory.
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
async function loadConfig(options?: {
|
|
165
|
+
// optional path to the config file for resolving $refs and proper error locations
|
|
166
|
+
configPath?: string;
|
|
167
|
+
// allows to add custom `extends` additionally to one from the config file
|
|
168
|
+
customExtends?: string[];
|
|
169
|
+
}): Promise<Config>;
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### `lint`
|
|
173
|
+
|
|
174
|
+
Lint an OpenAPI document from the file system.
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
async function lint(options: {
|
|
178
|
+
// path to the OpenAPI document root
|
|
179
|
+
ref: string;
|
|
180
|
+
// config object
|
|
181
|
+
config: Config;
|
|
182
|
+
}): Promise<NormalizedProblem[]>;
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### `lintFromString`
|
|
186
|
+
|
|
187
|
+
Lint an OpenAPI document from a string.
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
async function lintFromString(options: {
|
|
191
|
+
// OpenAPI document string
|
|
192
|
+
source: string;
|
|
193
|
+
// optional path to the OpenAPI document for resolving $refs and proper error locations
|
|
194
|
+
absoluteRef?: string;
|
|
195
|
+
// config object
|
|
196
|
+
config: Config;
|
|
197
|
+
}): Promise<NormalizedProblem[]>;
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### `bundle`
|
|
201
|
+
|
|
202
|
+
Bundle an OpenAPI document from the file system.
|
|
203
|
+
|
|
204
|
+
```ts
|
|
205
|
+
async function bundle(options: {
|
|
206
|
+
// path to the OpenAPI document root
|
|
207
|
+
ref: string;
|
|
208
|
+
// config object
|
|
209
|
+
config: Config;
|
|
210
|
+
// whether to fully dereference $refs, resulting document won't have any $ref
|
|
211
|
+
// warning: this can produce circular objects
|
|
212
|
+
dereference?: boolean;
|
|
213
|
+
// whether to remove unused components (schemas, parameters, responses, etc)
|
|
214
|
+
removeUnusedComponents?: boolean;
|
|
215
|
+
// whether to keep $ref pointers to the http URLs and resolve only local fs $refs
|
|
216
|
+
keepUrlRefs?: boolean;
|
|
217
|
+
}): Promise<{
|
|
218
|
+
bundle: {
|
|
219
|
+
parsed: object; // OpenAPI document object as js object
|
|
220
|
+
};
|
|
221
|
+
problems: NormalizedProblem[]
|
|
222
|
+
fileDependencies
|
|
223
|
+
rootType
|
|
224
|
+
refTypes
|
|
225
|
+
visitorsData
|
|
226
|
+
|
|
227
|
+
}>;
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### `bundleFromString`
|
|
231
|
+
|
|
232
|
+
Bundle an OpenAPI document from a string.
|
|
233
|
+
|
|
234
|
+
```ts
|
|
235
|
+
async function bundleFromString(options: {
|
|
236
|
+
// OpenAPI document string
|
|
237
|
+
source: string;
|
|
238
|
+
// optional path to the OpenAPI document for resolving $refs and proper error locations
|
|
239
|
+
absoluteRef?: string;
|
|
240
|
+
// config object
|
|
241
|
+
config: Config;
|
|
242
|
+
// whether to fully dereference $refs, resulting document won't have any $ref
|
|
243
|
+
// warning: this can produce circular objects
|
|
244
|
+
dereference?: boolean;
|
|
245
|
+
// whether to remove unused components (schemas, parameters, responses, etc)
|
|
246
|
+
removeUnusedComponents?: boolean;
|
|
247
|
+
// whether to keep $ref pointers to the http URLs and resolve only local fs $refs
|
|
248
|
+
keepUrlRefs?: boolean;
|
|
249
|
+
}): Promise<{
|
|
250
|
+
bundle: {
|
|
251
|
+
parsed: object; // OpenAPI document object as js object
|
|
252
|
+
};
|
|
253
|
+
problems: NormalizedProblem[]
|
|
254
|
+
fileDependencies
|
|
255
|
+
rootType
|
|
256
|
+
refTypes
|
|
257
|
+
visitorsData
|
|
258
|
+
|
|
259
|
+
}>;
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### `stringifyYaml`
|
|
263
|
+
|
|
264
|
+
Helper function to stringify a javascript object to YAML.
|
|
265
|
+
|
|
266
|
+
```ts
|
|
267
|
+
function stringifyYaml(obj: object): string;
|
|
268
|
+
```
|
package/lib/bundle.d.ts
CHANGED
|
@@ -10,9 +10,7 @@ export declare enum OasVersion {
|
|
|
10
10
|
Version3_0 = "oas3_0",
|
|
11
11
|
Version3_1 = "oas3_1"
|
|
12
12
|
}
|
|
13
|
-
export declare
|
|
14
|
-
ref?: string;
|
|
15
|
-
doc?: Document;
|
|
13
|
+
export declare type BundleOptions = {
|
|
16
14
|
externalRefResolver?: BaseResolver;
|
|
17
15
|
config: Config;
|
|
18
16
|
dereference?: boolean;
|
|
@@ -20,7 +18,15 @@ export declare function bundle(opts: {
|
|
|
20
18
|
skipRedoclyRegistryRefs?: boolean;
|
|
21
19
|
removeUnusedComponents?: boolean;
|
|
22
20
|
keepUrlRefs?: boolean;
|
|
23
|
-
}
|
|
21
|
+
};
|
|
22
|
+
export declare function bundle(opts: {
|
|
23
|
+
ref?: string;
|
|
24
|
+
doc?: Document;
|
|
25
|
+
} & BundleOptions): Promise<BundleResult>;
|
|
26
|
+
export declare function bundleFromString(opts: {
|
|
27
|
+
source: string;
|
|
28
|
+
absoluteRef?: string;
|
|
29
|
+
} & BundleOptions): Promise<BundleResult>;
|
|
24
30
|
export declare type BundleResult = {
|
|
25
31
|
bundle: Document;
|
|
26
32
|
problems: NormalizedProblem[];
|
package/lib/bundle.js
CHANGED
|
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.mapTypeToComponent = exports.bundleDocument = exports.bundle = exports.OasVersion = void 0;
|
|
12
|
+
exports.mapTypeToComponent = exports.bundleDocument = exports.bundleFromString = exports.bundle = exports.OasVersion = void 0;
|
|
13
13
|
const isEqual = require("lodash.isequal");
|
|
14
14
|
const resolve_1 = require("./resolve");
|
|
15
15
|
const visitors_1 = require("./visitors");
|
|
@@ -35,7 +35,7 @@ function bundle(opts) {
|
|
|
35
35
|
if (!(ref || doc)) {
|
|
36
36
|
throw new Error('Document or reference is required.\n');
|
|
37
37
|
}
|
|
38
|
-
const document = doc
|
|
38
|
+
const document = doc === undefined ? yield externalRefResolver.resolveDocument(base, ref, true) : doc;
|
|
39
39
|
if (document instanceof Error) {
|
|
40
40
|
throw document;
|
|
41
41
|
}
|
|
@@ -43,6 +43,14 @@ function bundle(opts) {
|
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
45
|
exports.bundle = bundle;
|
|
46
|
+
function bundleFromString(opts) {
|
|
47
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
48
|
+
const { source, absoluteRef, externalRefResolver = new resolve_1.BaseResolver(opts.config.resolve) } = opts;
|
|
49
|
+
const document = resolve_1.makeDocumentFromString(source, absoluteRef || '/');
|
|
50
|
+
return bundleDocument(Object.assign(Object.assign({ document }, opts), { externalRefResolver, config: opts.config.styleguide }));
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
exports.bundleFromString = bundleFromString;
|
|
46
54
|
function bundleDocument(opts) {
|
|
47
55
|
return __awaiter(this, void 0, void 0, function* () {
|
|
48
56
|
const { document, config, customTypes, externalRefResolver, dereference = false, skipRedoclyRegistryRefs = false, removeUnusedComponents = false, keepUrlRefs = false, } = opts;
|
package/lib/config/load.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Config } from './config';
|
|
2
|
-
import type { RawConfig, Region } from './types';
|
|
2
|
+
import type { RawConfig, RawUniversalConfig, Region } from './types';
|
|
3
3
|
import { RegionalTokenWithValidity } from '../redocly/redocly-client-types';
|
|
4
4
|
export declare function loadConfig(options?: {
|
|
5
5
|
configPath?: string;
|
|
@@ -14,6 +14,7 @@ export declare function getConfig(configPath?: string | undefined, processRawCon
|
|
|
14
14
|
declare type CreateConfigOptions = {
|
|
15
15
|
extends?: string[];
|
|
16
16
|
tokens?: RegionalTokenWithValidity[];
|
|
17
|
+
configPath?: string;
|
|
17
18
|
};
|
|
18
|
-
export declare function createConfig(config: string |
|
|
19
|
+
export declare function createConfig(config: string | RawUniversalConfig, options?: CreateConfigOptions): Promise<Config>;
|
|
19
20
|
export {};
|
package/lib/config/load.js
CHANGED
|
@@ -82,8 +82,8 @@ function findConfig(dir) {
|
|
|
82
82
|
const existingConfigFiles = exports.CONFIG_FILE_NAMES.map((name) => dir ? path.resolve(dir, name) : name).filter(fs.existsSync);
|
|
83
83
|
if (existingConfigFiles.length > 1) {
|
|
84
84
|
throw new Error(`
|
|
85
|
-
Multiple configuration files are not allowed.
|
|
86
|
-
Found the following files: ${existingConfigFiles.join(', ')}.
|
|
85
|
+
Multiple configuration files are not allowed.
|
|
86
|
+
Found the following files: ${existingConfigFiles.join(', ')}.
|
|
87
87
|
Please use 'redocly.yaml' instead.
|
|
88
88
|
`);
|
|
89
89
|
}
|
package/lib/config/types.d.ts
CHANGED
|
@@ -134,6 +134,7 @@ export declare type RawConfig = {
|
|
|
134
134
|
files?: string[];
|
|
135
135
|
telemetry?: Telemetry;
|
|
136
136
|
} & ThemeConfig;
|
|
137
|
+
export declare type RawUniversalConfig = Omit<RawConfig, 'styleguide'> & StyleguideRawConfig;
|
|
137
138
|
export declare type FlatApi = Omit<Api, 'styleguide'> & Omit<ApiStyleguideRawConfig, 'doNotResolveExamples'>;
|
|
138
139
|
export declare type FlatRawConfig = Omit<RawConfig, 'styleguide' | 'resolve' | 'apis'> & Omit<StyleguideRawConfig, 'doNotResolveExamples'> & {
|
|
139
140
|
resolve?: RawResolveConfig;
|
package/lib/index.d.ts
CHANGED
|
@@ -2,13 +2,14 @@ export { BundleOutputFormat, readFileFromUrl, slash, doesYamlFileExist, isTruthy
|
|
|
2
2
|
export { Oas3_1Types } from './types/oas3_1';
|
|
3
3
|
export { Oas3Types } from './types/oas3';
|
|
4
4
|
export { Oas2Types } from './types/oas2';
|
|
5
|
+
export { AsyncApi2Types } from './types/asyncapi';
|
|
5
6
|
export { ConfigTypes } from './types/redocly-yaml';
|
|
6
7
|
export type { Oas3Definition, Oas3_1Definition, Oas3Components, Oas3PathItem, Oas3Paths, Oas3ComponentName, Oas3Schema, Oas3_1Schema, Oas3Tag, Oas3_1Webhooks, Referenced, OasRef, } from './typings/openapi';
|
|
7
8
|
export type { Oas2Definition } from './typings/swagger';
|
|
8
9
|
export type { StatsAccumulator, StatsName } from './typings/common';
|
|
9
10
|
export { normalizeTypes } from './types';
|
|
10
11
|
export { Stats } from './rules/other/stats';
|
|
11
|
-
export { Config, StyleguideConfig, RawConfig, IGNORE_FILE, Region, getMergedConfig, transformConfig, loadConfig, getConfig, findConfig, CONFIG_FILE_NAMES, RuleSeverity, createConfig, ResolvedApi, } from './config';
|
|
12
|
+
export { Config, StyleguideConfig, RawConfig, RawUniversalConfig, IGNORE_FILE, Region, getMergedConfig, transformConfig, loadConfig, getConfig, findConfig, CONFIG_FILE_NAMES, RuleSeverity, createConfig, ResolvedApi, } from './config';
|
|
12
13
|
export { RedoclyClient, isRedoclyRegistryURL } from './redocly';
|
|
13
14
|
export { Source, BaseResolver, Document, resolveDocument, ResolveError, YamlParseError, makeDocumentFromString, } from './resolve';
|
|
14
15
|
export { parseYaml, stringifyYaml } from './js-yaml';
|
|
@@ -19,4 +20,4 @@ export { WalkContext, walkDocument, NormalizedProblem, ProblemSeverity, LineColL
|
|
|
19
20
|
export { getAstNodeByPointer, getLineColLocation } from './format/codeframes';
|
|
20
21
|
export { formatProblems, OutputFormat, getTotals, Totals } from './format/format';
|
|
21
22
|
export { lint, lint as validate, lintDocument, lintFromString, lintConfig } from './lint';
|
|
22
|
-
export { bundle, bundleDocument, mapTypeToComponent } from './bundle';
|
|
23
|
+
export { bundle, bundleDocument, mapTypeToComponent, bundleFromString } from './bundle';
|
package/lib/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.mapTypeToComponent = exports.bundleDocument = void 0;
|
|
3
|
+
exports.lintConfig = exports.lintFromString = exports.lintDocument = exports.validate = exports.lint = exports.getTotals = exports.formatProblems = exports.getLineColLocation = exports.getAstNodeByPointer = exports.walkDocument = exports.normalizeVisitors = exports.getTypes = exports.detectSpec = exports.SpecVersion = exports.getMajorSpecVersion = exports.SpecMajorVersion = exports.isAbsoluteUrl = exports.isRef = exports.unescapePointer = exports.stringifyYaml = exports.parseYaml = exports.makeDocumentFromString = exports.YamlParseError = exports.ResolveError = exports.resolveDocument = exports.BaseResolver = exports.Source = exports.isRedoclyRegistryURL = exports.RedoclyClient = exports.createConfig = exports.CONFIG_FILE_NAMES = exports.findConfig = exports.getConfig = exports.loadConfig = exports.transformConfig = exports.getMergedConfig = exports.IGNORE_FILE = exports.StyleguideConfig = exports.Config = exports.Stats = exports.normalizeTypes = exports.ConfigTypes = exports.AsyncApi2Types = exports.Oas2Types = exports.Oas3Types = exports.Oas3_1Types = exports.isTruthy = exports.doesYamlFileExist = exports.slash = exports.readFileFromUrl = void 0;
|
|
4
|
+
exports.bundleFromString = exports.mapTypeToComponent = exports.bundleDocument = exports.bundle = void 0;
|
|
5
5
|
var utils_1 = require("./utils");
|
|
6
6
|
Object.defineProperty(exports, "readFileFromUrl", { enumerable: true, get: function () { return utils_1.readFileFromUrl; } });
|
|
7
7
|
Object.defineProperty(exports, "slash", { enumerable: true, get: function () { return utils_1.slash; } });
|
|
@@ -13,6 +13,8 @@ var oas3_1 = require("./types/oas3");
|
|
|
13
13
|
Object.defineProperty(exports, "Oas3Types", { enumerable: true, get: function () { return oas3_1.Oas3Types; } });
|
|
14
14
|
var oas2_1 = require("./types/oas2");
|
|
15
15
|
Object.defineProperty(exports, "Oas2Types", { enumerable: true, get: function () { return oas2_1.Oas2Types; } });
|
|
16
|
+
var asyncapi_1 = require("./types/asyncapi");
|
|
17
|
+
Object.defineProperty(exports, "AsyncApi2Types", { enumerable: true, get: function () { return asyncapi_1.AsyncApi2Types; } });
|
|
16
18
|
var redocly_yaml_1 = require("./types/redocly-yaml");
|
|
17
19
|
Object.defineProperty(exports, "ConfigTypes", { enumerable: true, get: function () { return redocly_yaml_1.ConfigTypes; } });
|
|
18
20
|
var types_1 = require("./types");
|
|
@@ -73,3 +75,4 @@ var bundle_1 = require("./bundle");
|
|
|
73
75
|
Object.defineProperty(exports, "bundle", { enumerable: true, get: function () { return bundle_1.bundle; } });
|
|
74
76
|
Object.defineProperty(exports, "bundleDocument", { enumerable: true, get: function () { return bundle_1.bundleDocument; } });
|
|
75
77
|
Object.defineProperty(exports, "mapTypeToComponent", { enumerable: true, get: function () { return bundle_1.mapTypeToComponent; } });
|
|
78
|
+
Object.defineProperty(exports, "bundleFromString", { enumerable: true, get: function () { return bundle_1.bundleFromString; } });
|
|
@@ -35,7 +35,7 @@ exports.runOnValuesSet = new Set([
|
|
|
35
35
|
'const',
|
|
36
36
|
]);
|
|
37
37
|
exports.asserts = {
|
|
38
|
-
pattern: (value, condition, { baseLocation }) => {
|
|
38
|
+
pattern: (value, condition, { baseLocation, rawValue }) => {
|
|
39
39
|
if (typeof value === 'undefined' || utils_1.isPlainObject(value))
|
|
40
40
|
return []; // property doesn't exist or is an object, no need to lint it with this assert
|
|
41
41
|
const values = Array.isArray(value) ? value : [value];
|
|
@@ -43,11 +43,15 @@ exports.asserts = {
|
|
|
43
43
|
return values
|
|
44
44
|
.map((_val) => !(regex === null || regex === void 0 ? void 0 : regex.test(_val)) && {
|
|
45
45
|
message: `"${_val}" should match a regex ${condition}`,
|
|
46
|
-
location: utils_1.isString(value)
|
|
46
|
+
location: utils_1.isString(value)
|
|
47
|
+
? baseLocation
|
|
48
|
+
: utils_1.isPlainObject(rawValue)
|
|
49
|
+
? baseLocation.child(_val).key()
|
|
50
|
+
: baseLocation.key(),
|
|
47
51
|
})
|
|
48
52
|
.filter(utils_1.isTruthy);
|
|
49
53
|
},
|
|
50
|
-
notPattern: (value, condition, { baseLocation }) => {
|
|
54
|
+
notPattern: (value, condition, { baseLocation, rawValue }) => {
|
|
51
55
|
if (typeof value === 'undefined' || utils_1.isPlainObject(value))
|
|
52
56
|
return []; // property doesn't exist or is an object, no need to lint it with this assert
|
|
53
57
|
const values = Array.isArray(value) ? value : [value];
|
|
@@ -55,7 +59,11 @@ exports.asserts = {
|
|
|
55
59
|
return values
|
|
56
60
|
.map((_val) => (regex === null || regex === void 0 ? void 0 : regex.test(_val)) && {
|
|
57
61
|
message: `"${_val}" should not match a regex ${condition}`,
|
|
58
|
-
location: utils_1.isString(value)
|
|
62
|
+
location: utils_1.isString(value)
|
|
63
|
+
? baseLocation
|
|
64
|
+
: utils_1.isPlainObject(rawValue)
|
|
65
|
+
? baseLocation.child(_val).key()
|
|
66
|
+
: baseLocation.key(),
|
|
59
67
|
})
|
|
60
68
|
.filter(utils_1.isTruthy);
|
|
61
69
|
},
|
|
@@ -4,9 +4,10 @@ exports.NoServerExample = void 0;
|
|
|
4
4
|
const NoServerExample = () => {
|
|
5
5
|
return {
|
|
6
6
|
Server(server, { report, location }) {
|
|
7
|
-
|
|
7
|
+
const pattern = /^(.*[\/.])?(example\.com|localhost)([\/:?].*|$)/;
|
|
8
|
+
if (server.url && pattern.test(server.url)) {
|
|
8
9
|
report({
|
|
9
|
-
message: 'Server `url` should not point
|
|
10
|
+
message: 'Server `url` should not point to example.com or localhost.',
|
|
10
11
|
location: location.child(['url']),
|
|
11
12
|
});
|
|
12
13
|
}
|
package/lib/types/asyncapi.js
CHANGED
|
@@ -365,7 +365,14 @@ const Schema = {
|
|
|
365
365
|
maxContains: { type: 'integer', minimum: 0 },
|
|
366
366
|
patternProperties: { type: 'object' },
|
|
367
367
|
propertyNames: 'Schema',
|
|
368
|
-
unevaluatedItems:
|
|
368
|
+
unevaluatedItems: (value) => {
|
|
369
|
+
if (typeof value === 'boolean') {
|
|
370
|
+
return { type: 'boolean' };
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
return 'Schema';
|
|
374
|
+
}
|
|
375
|
+
},
|
|
369
376
|
unevaluatedProperties: (value) => {
|
|
370
377
|
if (typeof value === 'boolean') {
|
|
371
378
|
return { type: 'boolean' };
|
package/lib/types/oas3_1.js
CHANGED
|
@@ -135,7 +135,14 @@ const Schema = {
|
|
|
135
135
|
maxContains: { type: 'integer', minimum: 0 },
|
|
136
136
|
patternProperties: { type: 'object' },
|
|
137
137
|
propertyNames: 'Schema',
|
|
138
|
-
unevaluatedItems:
|
|
138
|
+
unevaluatedItems: (value) => {
|
|
139
|
+
if (typeof value === 'boolean') {
|
|
140
|
+
return { type: 'boolean' };
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
return 'Schema';
|
|
144
|
+
}
|
|
145
|
+
},
|
|
139
146
|
unevaluatedProperties: (value) => {
|
|
140
147
|
if (typeof value === 'boolean') {
|
|
141
148
|
return { type: 'boolean' };
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/openapi-core",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"engines": {
|
|
7
|
-
"node": ">=14.
|
|
7
|
+
"node": ">=14.19.0",
|
|
8
|
+
"npm": ">=7.0.0"
|
|
8
9
|
},
|
|
9
10
|
"engineStrict": true,
|
|
10
11
|
"license": "MIT",
|
|
@@ -308,7 +308,7 @@ components:
|
|
|
308
308
|
|
|
309
309
|
`;
|
|
310
310
|
|
|
311
|
-
exports[`bundle should not place
|
|
311
|
+
exports[`bundle should not place referenced schema inline when component in question is not of type "schemas" 1`] = `
|
|
312
312
|
openapi: 3.0.0
|
|
313
313
|
paths:
|
|
314
314
|
/pet:
|
|
@@ -1,11 +1,32 @@
|
|
|
1
1
|
import outdent from 'outdent';
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
|
|
4
|
-
import { bundleDocument, bundle } from '../bundle';
|
|
4
|
+
import { bundleDocument, bundle, bundleFromString } from '../bundle';
|
|
5
5
|
import { parseYamlToDocument, yamlSerializer, makeConfig } from '../../__tests__/utils';
|
|
6
|
-
import { StyleguideConfig, Config, ResolvedConfig } from '../config';
|
|
6
|
+
import { StyleguideConfig, Config, ResolvedConfig, createConfig, loadConfig } from '../config';
|
|
7
7
|
import { BaseResolver } from '../resolve';
|
|
8
8
|
|
|
9
|
+
const stringDocument = outdent`
|
|
10
|
+
openapi: 3.0.0
|
|
11
|
+
paths:
|
|
12
|
+
/pet:
|
|
13
|
+
get:
|
|
14
|
+
operationId: get
|
|
15
|
+
parameters:
|
|
16
|
+
- $ref: '#/components/parameters/shared_a'
|
|
17
|
+
- name: get_b
|
|
18
|
+
post:
|
|
19
|
+
operationId: post
|
|
20
|
+
parameters:
|
|
21
|
+
- $ref: '#/components/parameters/shared_a'
|
|
22
|
+
components:
|
|
23
|
+
parameters:
|
|
24
|
+
shared_a:
|
|
25
|
+
name: shared-a
|
|
26
|
+
`;
|
|
27
|
+
|
|
28
|
+
const testDocument = parseYamlToDocument(stringDocument, '');
|
|
29
|
+
|
|
9
30
|
describe('bundle', () => {
|
|
10
31
|
const fetchMock = jest.fn(() =>
|
|
11
32
|
Promise.resolve({
|
|
@@ -19,28 +40,6 @@ describe('bundle', () => {
|
|
|
19
40
|
|
|
20
41
|
expect.addSnapshotSerializer(yamlSerializer);
|
|
21
42
|
|
|
22
|
-
const testDocument = parseYamlToDocument(
|
|
23
|
-
outdent`
|
|
24
|
-
openapi: 3.0.0
|
|
25
|
-
paths:
|
|
26
|
-
/pet:
|
|
27
|
-
get:
|
|
28
|
-
operationId: get
|
|
29
|
-
parameters:
|
|
30
|
-
- $ref: '#/components/parameters/shared_a'
|
|
31
|
-
- name: get_b
|
|
32
|
-
post:
|
|
33
|
-
operationId: post
|
|
34
|
-
parameters:
|
|
35
|
-
- $ref: '#/components/parameters/shared_a'
|
|
36
|
-
components:
|
|
37
|
-
parameters:
|
|
38
|
-
shared_a:
|
|
39
|
-
name: shared-a
|
|
40
|
-
`,
|
|
41
|
-
''
|
|
42
|
-
);
|
|
43
|
-
|
|
44
43
|
it('change nothing with only internal refs', async () => {
|
|
45
44
|
const { bundle, problems } = await bundleDocument({
|
|
46
45
|
document: testDocument,
|
|
@@ -97,7 +96,7 @@ describe('bundle', () => {
|
|
|
97
96
|
expect(res.parsed).toMatchSnapshot();
|
|
98
97
|
});
|
|
99
98
|
|
|
100
|
-
it('should not place
|
|
99
|
+
it('should not place referenced schema inline when component in question is not of type "schemas"', async () => {
|
|
101
100
|
const { bundle: res, problems } = await bundle({
|
|
102
101
|
config: new Config({} as ResolvedConfig),
|
|
103
102
|
ref: path.join(__dirname, 'fixtures/refs/external-request-body.yaml'),
|
|
@@ -233,4 +232,45 @@ describe('bundle', () => {
|
|
|
233
232
|
|
|
234
233
|
`);
|
|
235
234
|
});
|
|
235
|
+
|
|
236
|
+
it('should throw an error when there is no document to bundle', () => {
|
|
237
|
+
const wrapper = () =>
|
|
238
|
+
bundle({
|
|
239
|
+
config: new Config({} as ResolvedConfig),
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
expect(wrapper()).rejects.toThrowError('Document or reference is required.\n');
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it('should bundle with a doc provided', async () => {
|
|
246
|
+
const {
|
|
247
|
+
bundle: { parsed },
|
|
248
|
+
problems,
|
|
249
|
+
} = await bundle({
|
|
250
|
+
config: await loadConfig({ configPath: path.join(__dirname, 'fixtures/redocly.yaml') }),
|
|
251
|
+
doc: testDocument,
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
const origCopy = JSON.parse(JSON.stringify(testDocument.parsed));
|
|
255
|
+
|
|
256
|
+
expect(problems).toHaveLength(0);
|
|
257
|
+
expect(parsed).toEqual(origCopy);
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
describe('bundleFromString', () => {
|
|
262
|
+
it('should bundle from string using bundleFromString', async () => {
|
|
263
|
+
const {
|
|
264
|
+
bundle: { parsed, ...rest },
|
|
265
|
+
problems,
|
|
266
|
+
} = await bundleFromString({
|
|
267
|
+
config: await createConfig(`
|
|
268
|
+
extends:
|
|
269
|
+
- recommended
|
|
270
|
+
`),
|
|
271
|
+
source: testDocument.source.body,
|
|
272
|
+
});
|
|
273
|
+
expect(problems).toHaveLength(0);
|
|
274
|
+
expect(rest.source.body).toEqual(stringDocument);
|
|
275
|
+
});
|
|
236
276
|
});
|