oas-normalize 5.2.0 → 7.0.0
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/LICENSE.md +1 -1
- package/README.md +19 -12
- package/dist/index.d.ts +111 -0
- package/dist/index.js +225 -0
- package/dist/lib/utils.d.ts +21 -0
- package/dist/lib/utils.js +67 -0
- package/package.json +23 -11
- package/src/.sink.d.ts +2 -0
- package/src/index.ts +167 -0
- package/src/lib/utils.ts +63 -0
- package/tsconfig.json +14 -0
- package/index.js +0 -120
- package/lib/utils.js +0 -44
package/LICENSE.md
CHANGED
package/README.md
CHANGED
|
@@ -14,22 +14,24 @@ npm install oas-normalize --save
|
|
|
14
14
|
|
|
15
15
|
# Usage
|
|
16
16
|
|
|
17
|
-
It's pretty simple:
|
|
18
|
-
|
|
19
17
|
```javascript
|
|
20
|
-
|
|
18
|
+
import OASNormalize from 'oas-normalize';
|
|
19
|
+
// const { default: OASNormalize } = require('oas-normalize'); // If you're using CJS.
|
|
21
20
|
|
|
22
21
|
const oas = new OASNormalize(
|
|
23
22
|
// Or a string, pathname, JSON blob, whatever
|
|
24
23
|
'https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v3.0/petstore-expanded.yaml'
|
|
25
24
|
);
|
|
26
25
|
|
|
27
|
-
oas
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
})
|
|
26
|
+
oas
|
|
27
|
+
.validate()
|
|
28
|
+
.then(definition => {
|
|
29
|
+
// Definition will always be JSON, and valid.
|
|
30
|
+
console.log(definition);
|
|
31
|
+
})
|
|
32
|
+
.catch(err => {
|
|
33
|
+
console.log(err);
|
|
34
|
+
});
|
|
33
35
|
```
|
|
34
36
|
|
|
35
37
|
# Errors
|
|
@@ -59,18 +61,23 @@ For validation errors, when available, you'll get back an object:
|
|
|
59
61
|
|
|
60
62
|
If you want some more functionality, you can do anything here:
|
|
61
63
|
|
|
64
|
+
<!--
|
|
65
|
+
Prettier's table formatting sucks, hence the ignore block below.
|
|
66
|
+
-->
|
|
67
|
+
<!-- prettier-ignore-start -->
|
|
62
68
|
| Function | What it does |
|
|
63
69
|
| :--- | :--- |
|
|
64
70
|
| `.load()` | Just load the file, valid or not, as JSON |
|
|
65
71
|
| `.bundle()` | Bring together all files into one JSON blob (but retain `$ref` pointers) |
|
|
66
72
|
| `.deref()` | Resolve `$ref` pointers |
|
|
67
73
|
| `.validate([convertToLatest?])` | Validate the whole thing! |
|
|
74
|
+
<!-- prettier-ignore-end -->
|
|
68
75
|
|
|
69
76
|
# Other Little Features
|
|
70
77
|
|
|
71
78
|
### Always Return OpenAPI 3.x
|
|
72
79
|
|
|
73
|
-
If you want `.validate` to always return an OpenAPI 3.x definition, supply `true` as its argument:
|
|
80
|
+
If you want `.validate()` to always return an OpenAPI 3.x definition, supply `true` as its argument:
|
|
74
81
|
|
|
75
82
|
```js
|
|
76
83
|
OASNormalize.validate(true).then(...);
|
|
@@ -81,7 +88,7 @@ OASNormalize.validate(true).then(...);
|
|
|
81
88
|
For security reasons, you need to opt into allowing fetching by a local path. To enable it supply the `enablePaths` option to the class instance:
|
|
82
89
|
|
|
83
90
|
```js
|
|
84
|
-
const oas = new OASNormalize('./petstore.json', { enablePaths: true })
|
|
91
|
+
const oas = new OASNormalize('./petstore.json', { enablePaths: true });
|
|
85
92
|
```
|
|
86
93
|
|
|
87
94
|
### Colorized errors
|
|
@@ -91,7 +98,7 @@ If you wish errors from `.validate()` to be styled and colorized, supply `colori
|
|
|
91
98
|
```js
|
|
92
99
|
const oas = new OASNormalize('https://example.com/petstore.json', {
|
|
93
100
|
colorizeErrors: true,
|
|
94
|
-
})
|
|
101
|
+
});
|
|
95
102
|
```
|
|
96
103
|
|
|
97
104
|
Error messages will look like such:
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import type { OpenAPI } from 'openapi-types';
|
|
2
|
+
export declare type Options = {
|
|
3
|
+
colorizeErrors?: boolean;
|
|
4
|
+
enablePaths?: boolean;
|
|
5
|
+
};
|
|
6
|
+
export default class OASNormalize {
|
|
7
|
+
cache: {
|
|
8
|
+
bundle?: false | OpenAPI.Document;
|
|
9
|
+
deref?: false | OpenAPI.Document;
|
|
10
|
+
load?: false | Record<string, unknown>;
|
|
11
|
+
};
|
|
12
|
+
file: any;
|
|
13
|
+
opts: Options;
|
|
14
|
+
type: boolean | string;
|
|
15
|
+
constructor(file: any, opts?: Options);
|
|
16
|
+
load(): Promise<any>;
|
|
17
|
+
/**
|
|
18
|
+
* Bundle up the given OpenAPI or Swagger definition, resolving any external `$ref` pointers in
|
|
19
|
+
* the process.
|
|
20
|
+
*
|
|
21
|
+
*/
|
|
22
|
+
bundle(): Promise<import("openapi-types").OpenAPIV2.Document<{}> | import("openapi-types").OpenAPIV3.Document<{}> | (Omit<Omit<import("openapi-types").OpenAPIV3.Document<{}>, "paths" | "components">, "paths" | "components" | "info" | "servers" | "webhooks" | "jsonSchemaDialect"> & {
|
|
23
|
+
info: import("openapi-types").OpenAPIV3_1.InfoObject;
|
|
24
|
+
jsonSchemaDialect?: string;
|
|
25
|
+
servers?: import("openapi-types").OpenAPIV3_1.ServerObject[];
|
|
26
|
+
} & Pick<{
|
|
27
|
+
paths: import("openapi-types").OpenAPIV3_1.PathsObject<{}, {}>;
|
|
28
|
+
webhooks: Record<string, import("openapi-types").OpenAPIV3_1.ReferenceObject | import("openapi-types").OpenAPIV3_1.PathItemObject<{}>>;
|
|
29
|
+
components: import("openapi-types").OpenAPIV3_1.ComponentsObject;
|
|
30
|
+
}, "paths"> & Omit<Partial<{
|
|
31
|
+
paths: import("openapi-types").OpenAPIV3_1.PathsObject<{}, {}>;
|
|
32
|
+
webhooks: Record<string, import("openapi-types").OpenAPIV3_1.ReferenceObject | import("openapi-types").OpenAPIV3_1.PathItemObject<{}>>;
|
|
33
|
+
components: import("openapi-types").OpenAPIV3_1.ComponentsObject;
|
|
34
|
+
}>, "paths">) | (Omit<Omit<import("openapi-types").OpenAPIV3.Document<{}>, "paths" | "components">, "paths" | "components" | "info" | "servers" | "webhooks" | "jsonSchemaDialect"> & {
|
|
35
|
+
info: import("openapi-types").OpenAPIV3_1.InfoObject;
|
|
36
|
+
jsonSchemaDialect?: string;
|
|
37
|
+
servers?: import("openapi-types").OpenAPIV3_1.ServerObject[];
|
|
38
|
+
} & Pick<{
|
|
39
|
+
paths: import("openapi-types").OpenAPIV3_1.PathsObject<{}, {}>;
|
|
40
|
+
webhooks: Record<string, import("openapi-types").OpenAPIV3_1.ReferenceObject | import("openapi-types").OpenAPIV3_1.PathItemObject<{}>>;
|
|
41
|
+
components: import("openapi-types").OpenAPIV3_1.ComponentsObject;
|
|
42
|
+
}, "webhooks"> & Omit<Partial<{
|
|
43
|
+
paths: import("openapi-types").OpenAPIV3_1.PathsObject<{}, {}>;
|
|
44
|
+
webhooks: Record<string, import("openapi-types").OpenAPIV3_1.ReferenceObject | import("openapi-types").OpenAPIV3_1.PathItemObject<{}>>;
|
|
45
|
+
components: import("openapi-types").OpenAPIV3_1.ComponentsObject;
|
|
46
|
+
}>, "webhooks">) | (Omit<Omit<import("openapi-types").OpenAPIV3.Document<{}>, "paths" | "components">, "paths" | "components" | "info" | "servers" | "webhooks" | "jsonSchemaDialect"> & {
|
|
47
|
+
info: import("openapi-types").OpenAPIV3_1.InfoObject;
|
|
48
|
+
jsonSchemaDialect?: string;
|
|
49
|
+
servers?: import("openapi-types").OpenAPIV3_1.ServerObject[];
|
|
50
|
+
} & Pick<{
|
|
51
|
+
paths: import("openapi-types").OpenAPIV3_1.PathsObject<{}, {}>;
|
|
52
|
+
webhooks: Record<string, import("openapi-types").OpenAPIV3_1.ReferenceObject | import("openapi-types").OpenAPIV3_1.PathItemObject<{}>>;
|
|
53
|
+
components: import("openapi-types").OpenAPIV3_1.ComponentsObject;
|
|
54
|
+
}, "components"> & Omit<Partial<{
|
|
55
|
+
paths: import("openapi-types").OpenAPIV3_1.PathsObject<{}, {}>;
|
|
56
|
+
webhooks: Record<string, import("openapi-types").OpenAPIV3_1.ReferenceObject | import("openapi-types").OpenAPIV3_1.PathItemObject<{}>>;
|
|
57
|
+
components: import("openapi-types").OpenAPIV3_1.ComponentsObject;
|
|
58
|
+
}>, "components">)>;
|
|
59
|
+
/**
|
|
60
|
+
* Dereference the given OpenAPI or Swagger.
|
|
61
|
+
*
|
|
62
|
+
*/
|
|
63
|
+
deref(): Promise<import("openapi-types").OpenAPIV2.Document<{}> | import("openapi-types").OpenAPIV3.Document<{}> | (Omit<Omit<import("openapi-types").OpenAPIV3.Document<{}>, "paths" | "components">, "paths" | "components" | "info" | "servers" | "webhooks" | "jsonSchemaDialect"> & {
|
|
64
|
+
info: import("openapi-types").OpenAPIV3_1.InfoObject;
|
|
65
|
+
jsonSchemaDialect?: string;
|
|
66
|
+
servers?: import("openapi-types").OpenAPIV3_1.ServerObject[];
|
|
67
|
+
} & Pick<{
|
|
68
|
+
paths: import("openapi-types").OpenAPIV3_1.PathsObject<{}, {}>;
|
|
69
|
+
webhooks: Record<string, import("openapi-types").OpenAPIV3_1.ReferenceObject | import("openapi-types").OpenAPIV3_1.PathItemObject<{}>>;
|
|
70
|
+
components: import("openapi-types").OpenAPIV3_1.ComponentsObject;
|
|
71
|
+
}, "paths"> & Omit<Partial<{
|
|
72
|
+
paths: import("openapi-types").OpenAPIV3_1.PathsObject<{}, {}>;
|
|
73
|
+
webhooks: Record<string, import("openapi-types").OpenAPIV3_1.ReferenceObject | import("openapi-types").OpenAPIV3_1.PathItemObject<{}>>;
|
|
74
|
+
components: import("openapi-types").OpenAPIV3_1.ComponentsObject;
|
|
75
|
+
}>, "paths">) | (Omit<Omit<import("openapi-types").OpenAPIV3.Document<{}>, "paths" | "components">, "paths" | "components" | "info" | "servers" | "webhooks" | "jsonSchemaDialect"> & {
|
|
76
|
+
info: import("openapi-types").OpenAPIV3_1.InfoObject;
|
|
77
|
+
jsonSchemaDialect?: string;
|
|
78
|
+
servers?: import("openapi-types").OpenAPIV3_1.ServerObject[];
|
|
79
|
+
} & Pick<{
|
|
80
|
+
paths: import("openapi-types").OpenAPIV3_1.PathsObject<{}, {}>;
|
|
81
|
+
webhooks: Record<string, import("openapi-types").OpenAPIV3_1.ReferenceObject | import("openapi-types").OpenAPIV3_1.PathItemObject<{}>>;
|
|
82
|
+
components: import("openapi-types").OpenAPIV3_1.ComponentsObject;
|
|
83
|
+
}, "webhooks"> & Omit<Partial<{
|
|
84
|
+
paths: import("openapi-types").OpenAPIV3_1.PathsObject<{}, {}>;
|
|
85
|
+
webhooks: Record<string, import("openapi-types").OpenAPIV3_1.ReferenceObject | import("openapi-types").OpenAPIV3_1.PathItemObject<{}>>;
|
|
86
|
+
components: import("openapi-types").OpenAPIV3_1.ComponentsObject;
|
|
87
|
+
}>, "webhooks">) | (Omit<Omit<import("openapi-types").OpenAPIV3.Document<{}>, "paths" | "components">, "paths" | "components" | "info" | "servers" | "webhooks" | "jsonSchemaDialect"> & {
|
|
88
|
+
info: import("openapi-types").OpenAPIV3_1.InfoObject;
|
|
89
|
+
jsonSchemaDialect?: string;
|
|
90
|
+
servers?: import("openapi-types").OpenAPIV3_1.ServerObject[];
|
|
91
|
+
} & Pick<{
|
|
92
|
+
paths: import("openapi-types").OpenAPIV3_1.PathsObject<{}, {}>;
|
|
93
|
+
webhooks: Record<string, import("openapi-types").OpenAPIV3_1.ReferenceObject | import("openapi-types").OpenAPIV3_1.PathItemObject<{}>>;
|
|
94
|
+
components: import("openapi-types").OpenAPIV3_1.ComponentsObject;
|
|
95
|
+
}, "components"> & Omit<Partial<{
|
|
96
|
+
paths: import("openapi-types").OpenAPIV3_1.PathsObject<{}, {}>;
|
|
97
|
+
webhooks: Record<string, import("openapi-types").OpenAPIV3_1.ReferenceObject | import("openapi-types").OpenAPIV3_1.PathItemObject<{}>>;
|
|
98
|
+
components: import("openapi-types").OpenAPIV3_1.ComponentsObject;
|
|
99
|
+
}>, "components">)>;
|
|
100
|
+
/**
|
|
101
|
+
* Validate a given OpenAPI or Swagger definition, potentially upconverting it from Swagger to
|
|
102
|
+
* OpenAPI in the process if you wish.
|
|
103
|
+
*
|
|
104
|
+
*/
|
|
105
|
+
validate(convertToLatest?: boolean): Promise<any>;
|
|
106
|
+
/**
|
|
107
|
+
* Retrieve the OpenAPI or Swagger version of the current API definition.
|
|
108
|
+
*
|
|
109
|
+
*/
|
|
110
|
+
version(): Promise<string>;
|
|
111
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
16
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
17
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
18
|
+
}
|
|
19
|
+
Object.defineProperty(o, k2, desc);
|
|
20
|
+
}) : (function(o, m, k, k2) {
|
|
21
|
+
if (k2 === undefined) k2 = k;
|
|
22
|
+
o[k2] = m[k];
|
|
23
|
+
}));
|
|
24
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
25
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
26
|
+
}) : function(o, v) {
|
|
27
|
+
o["default"] = v;
|
|
28
|
+
});
|
|
29
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
30
|
+
if (mod && mod.__esModule) return mod;
|
|
31
|
+
var result = {};
|
|
32
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
33
|
+
__setModuleDefault(result, mod);
|
|
34
|
+
return result;
|
|
35
|
+
};
|
|
36
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
37
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
38
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
39
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
40
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
41
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
42
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
46
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
47
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
48
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
49
|
+
function step(op) {
|
|
50
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
51
|
+
while (_) try {
|
|
52
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
53
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
54
|
+
switch (op[0]) {
|
|
55
|
+
case 0: case 1: t = op; break;
|
|
56
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
57
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
58
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
59
|
+
default:
|
|
60
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
61
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
62
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
63
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
64
|
+
if (t[2]) _.ops.pop();
|
|
65
|
+
_.trys.pop(); continue;
|
|
66
|
+
}
|
|
67
|
+
op = body.call(thisArg, _);
|
|
68
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
69
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
73
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
74
|
+
};
|
|
75
|
+
exports.__esModule = true;
|
|
76
|
+
var fs_1 = __importDefault(require("fs"));
|
|
77
|
+
var openapi_parser_1 = __importDefault(require("@readme/openapi-parser"));
|
|
78
|
+
var node_fetch_1 = __importDefault(require("node-fetch"));
|
|
79
|
+
var swagger2openapi_1 = __importDefault(require("swagger2openapi"));
|
|
80
|
+
var utils = __importStar(require("./lib/utils"));
|
|
81
|
+
var OASNormalize = /** @class */ (function () {
|
|
82
|
+
function OASNormalize(file, opts) {
|
|
83
|
+
this.file = file;
|
|
84
|
+
this.opts = __assign({ colorizeErrors: false, enablePaths: false }, opts);
|
|
85
|
+
this.type = utils.getType(this.file);
|
|
86
|
+
this.cache = {
|
|
87
|
+
load: false,
|
|
88
|
+
bundle: false,
|
|
89
|
+
deref: false
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// Internal API for the most part
|
|
93
|
+
OASNormalize.prototype.load = function () {
|
|
94
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
95
|
+
var resolve, _a, resp, contents;
|
|
96
|
+
var _this = this;
|
|
97
|
+
return __generator(this, function (_b) {
|
|
98
|
+
switch (_b.label) {
|
|
99
|
+
case 0:
|
|
100
|
+
if (this.cache.load)
|
|
101
|
+
return [2 /*return*/, Promise.resolve(this.cache.load)];
|
|
102
|
+
resolve = function (obj) {
|
|
103
|
+
var ret = utils.stringToJSON(obj);
|
|
104
|
+
_this.cache.load = ret;
|
|
105
|
+
return Promise.resolve(ret);
|
|
106
|
+
};
|
|
107
|
+
_a = this.type;
|
|
108
|
+
switch (_a) {
|
|
109
|
+
case 'json': return [3 /*break*/, 1];
|
|
110
|
+
case 'string-json': return [3 /*break*/, 1];
|
|
111
|
+
case 'string-yaml': return [3 /*break*/, 1];
|
|
112
|
+
case 'buffer': return [3 /*break*/, 2];
|
|
113
|
+
case 'url': return [3 /*break*/, 3];
|
|
114
|
+
case 'path': return [3 /*break*/, 5];
|
|
115
|
+
}
|
|
116
|
+
return [3 /*break*/, 6];
|
|
117
|
+
case 1: return [2 /*return*/, resolve(this.file)];
|
|
118
|
+
case 2: return [2 /*return*/, resolve(this.file.toString())];
|
|
119
|
+
case 3: return [4 /*yield*/, (0, node_fetch_1["default"])(this.file).then(function (res) { return res.text(); })];
|
|
120
|
+
case 4:
|
|
121
|
+
resp = _b.sent();
|
|
122
|
+
return [2 /*return*/, resolve(resp)];
|
|
123
|
+
case 5:
|
|
124
|
+
// Load a local file
|
|
125
|
+
if (!this.opts.enablePaths) {
|
|
126
|
+
return [2 /*return*/, Promise.reject(new Error('Use `opts.enablePaths` to enable accessing local files.'))];
|
|
127
|
+
}
|
|
128
|
+
contents = fs_1["default"].readFileSync(this.file).toString();
|
|
129
|
+
return [2 /*return*/, resolve(contents)];
|
|
130
|
+
case 6: return [2 /*return*/, Promise.reject(new Error('Could not load this file.'))];
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Bundle up the given OpenAPI or Swagger definition, resolving any external `$ref` pointers in
|
|
137
|
+
* the process.
|
|
138
|
+
*
|
|
139
|
+
*/
|
|
140
|
+
OASNormalize.prototype.bundle = function () {
|
|
141
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
142
|
+
var _this = this;
|
|
143
|
+
return __generator(this, function (_a) {
|
|
144
|
+
if (this.cache.bundle)
|
|
145
|
+
return [2 /*return*/, Promise.resolve(this.cache.bundle)];
|
|
146
|
+
return [2 /*return*/, this.load()
|
|
147
|
+
.then(function (schema) { return openapi_parser_1["default"].bundle(schema); })
|
|
148
|
+
.then(function (bundle) {
|
|
149
|
+
_this.cache.bundle = bundle;
|
|
150
|
+
return bundle;
|
|
151
|
+
})];
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
};
|
|
155
|
+
/**
|
|
156
|
+
* Dereference the given OpenAPI or Swagger.
|
|
157
|
+
*
|
|
158
|
+
*/
|
|
159
|
+
OASNormalize.prototype.deref = function () {
|
|
160
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
161
|
+
var _this = this;
|
|
162
|
+
return __generator(this, function (_a) {
|
|
163
|
+
if (this.cache.deref)
|
|
164
|
+
return [2 /*return*/, Promise.resolve(this.cache.deref)];
|
|
165
|
+
return [2 /*return*/, this.load()
|
|
166
|
+
.then(function (schema) { return openapi_parser_1["default"].dereference(schema); })
|
|
167
|
+
.then(function (dereferenced) {
|
|
168
|
+
_this.cache.deref = dereferenced;
|
|
169
|
+
return dereferenced;
|
|
170
|
+
})];
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
};
|
|
174
|
+
/**
|
|
175
|
+
* Validate a given OpenAPI or Swagger definition, potentially upconverting it from Swagger to
|
|
176
|
+
* OpenAPI in the process if you wish.
|
|
177
|
+
*
|
|
178
|
+
*/
|
|
179
|
+
OASNormalize.prototype.validate = function (convertToLatest) {
|
|
180
|
+
if (convertToLatest === void 0) { convertToLatest = false; }
|
|
181
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
182
|
+
var colorizeErrors;
|
|
183
|
+
var _this = this;
|
|
184
|
+
return __generator(this, function (_a) {
|
|
185
|
+
colorizeErrors = this.opts.colorizeErrors;
|
|
186
|
+
return [2 /*return*/, this.load().then(function (schema) { return __awaiter(_this, void 0, void 0, function () {
|
|
187
|
+
var baseVersion, clonedSchema;
|
|
188
|
+
return __generator(this, function (_a) {
|
|
189
|
+
baseVersion = parseInt(utils.version(schema), 10);
|
|
190
|
+
if (baseVersion === 1) {
|
|
191
|
+
return [2 /*return*/, Promise.reject(new Error('Swagger v1.2 is unsupported.'))];
|
|
192
|
+
}
|
|
193
|
+
else if (baseVersion === 2 || baseVersion === 3) {
|
|
194
|
+
clonedSchema = JSON.parse(JSON.stringify(schema));
|
|
195
|
+
return [2 /*return*/, openapi_parser_1["default"]
|
|
196
|
+
.validate(clonedSchema, {
|
|
197
|
+
validate: {
|
|
198
|
+
colorizeErrors: colorizeErrors
|
|
199
|
+
}
|
|
200
|
+
})
|
|
201
|
+
.then(function () {
|
|
202
|
+
if (!convertToLatest) {
|
|
203
|
+
return schema;
|
|
204
|
+
}
|
|
205
|
+
return swagger2openapi_1["default"].convertObj(schema, { anchors: true }).then(function (options) {
|
|
206
|
+
return options.openapi;
|
|
207
|
+
});
|
|
208
|
+
})["catch"](function (err) { return Promise.reject(err); })];
|
|
209
|
+
}
|
|
210
|
+
return [2 /*return*/, Promise.reject(new Error('The supplied API definition is unsupported.'))];
|
|
211
|
+
});
|
|
212
|
+
}); })];
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
};
|
|
216
|
+
/**
|
|
217
|
+
* Retrieve the OpenAPI or Swagger version of the current API definition.
|
|
218
|
+
*
|
|
219
|
+
*/
|
|
220
|
+
OASNormalize.prototype.version = function () {
|
|
221
|
+
return this.load().then(function (schema) { return utils.version(schema); });
|
|
222
|
+
};
|
|
223
|
+
return OASNormalize;
|
|
224
|
+
}());
|
|
225
|
+
exports["default"] = OASNormalize;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { OpenAPIV2, OpenAPIV3, OpenAPIV3_1 } from 'openapi-types';
|
|
2
|
+
/**
|
|
3
|
+
* Retrieve the Swagger or OpenAPI version that a given Swagger or OpenAPI definition are targeting.
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
export declare function version(schema: OpenAPIV2.Document & OpenAPIV3.Document & OpenAPIV3_1.Document): string;
|
|
7
|
+
/**
|
|
8
|
+
* Determine if a given variable is a `Buffer`.
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
export declare function isBuffer(obj: any): any;
|
|
12
|
+
/**
|
|
13
|
+
* Convert a YAML blob or stringified JSON object into a JSON object.
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
export declare function stringToJSON(string: string | Record<string, unknown>): any;
|
|
17
|
+
/**
|
|
18
|
+
* Determine the type of a given variable. Returns `false` if unrecognized.
|
|
19
|
+
*
|
|
20
|
+
*/
|
|
21
|
+
export declare function getType(obj: any): false | "path" | "json" | "buffer" | "string-json" | "string-yaml" | "url";
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
exports.__esModule = true;
|
|
6
|
+
exports.getType = exports.stringToJSON = exports.isBuffer = exports.version = void 0;
|
|
7
|
+
var js_yaml_1 = __importDefault(require("js-yaml"));
|
|
8
|
+
/**
|
|
9
|
+
* Retrieve the Swagger or OpenAPI version that a given Swagger or OpenAPI definition are targeting.
|
|
10
|
+
*
|
|
11
|
+
*/
|
|
12
|
+
function version(schema) {
|
|
13
|
+
return schema.swagger || schema.openapi;
|
|
14
|
+
}
|
|
15
|
+
exports.version = version;
|
|
16
|
+
/**
|
|
17
|
+
* Determine if a given variable is a `Buffer`.
|
|
18
|
+
*
|
|
19
|
+
*/
|
|
20
|
+
function isBuffer(obj) {
|
|
21
|
+
return (obj != null &&
|
|
22
|
+
obj.constructor != null &&
|
|
23
|
+
typeof obj.constructor.isBuffer === 'function' &&
|
|
24
|
+
obj.constructor.isBuffer(obj));
|
|
25
|
+
}
|
|
26
|
+
exports.isBuffer = isBuffer;
|
|
27
|
+
/**
|
|
28
|
+
* Convert a YAML blob or stringified JSON object into a JSON object.
|
|
29
|
+
*
|
|
30
|
+
*/
|
|
31
|
+
function stringToJSON(string) {
|
|
32
|
+
if (typeof string === 'object') {
|
|
33
|
+
return string;
|
|
34
|
+
}
|
|
35
|
+
else if (string.match(/^\s*{/)) {
|
|
36
|
+
return JSON.parse(string);
|
|
37
|
+
}
|
|
38
|
+
return js_yaml_1["default"].load(string);
|
|
39
|
+
}
|
|
40
|
+
exports.stringToJSON = stringToJSON;
|
|
41
|
+
/**
|
|
42
|
+
* Determine the type of a given variable. Returns `false` if unrecognized.
|
|
43
|
+
*
|
|
44
|
+
*/
|
|
45
|
+
function getType(obj) {
|
|
46
|
+
if (isBuffer(obj)) {
|
|
47
|
+
return 'buffer';
|
|
48
|
+
}
|
|
49
|
+
else if (typeof obj === 'object') {
|
|
50
|
+
return 'json';
|
|
51
|
+
}
|
|
52
|
+
else if (typeof obj === 'string') {
|
|
53
|
+
if (obj.match(/\s*{/)) {
|
|
54
|
+
return 'string-json';
|
|
55
|
+
}
|
|
56
|
+
else if (obj.match(/\n/)) {
|
|
57
|
+
// Not sure about this...
|
|
58
|
+
return 'string-yaml';
|
|
59
|
+
}
|
|
60
|
+
else if (obj.substring(0, 4) === 'http') {
|
|
61
|
+
return 'url';
|
|
62
|
+
}
|
|
63
|
+
return 'path';
|
|
64
|
+
}
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
exports.getType = getType;
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oas-normalize",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.0",
|
|
4
4
|
"description": "OpenAPI 3.x or Swagger 2.0? YAML or JSON? URL, path, string or object? Who cares! It just works.",
|
|
5
|
-
"main": "index.js",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
6
7
|
"engines": {
|
|
7
|
-
"node": "
|
|
8
|
+
"node": ">=14"
|
|
8
9
|
},
|
|
9
10
|
"tags": [
|
|
10
11
|
"api",
|
|
@@ -29,25 +30,36 @@
|
|
|
29
30
|
"url": "https://github.com/readmeio/oas-normalize/issues"
|
|
30
31
|
},
|
|
31
32
|
"scripts": {
|
|
32
|
-
"
|
|
33
|
+
"build": "tsc",
|
|
34
|
+
"lint": "eslint . --ext .js,.ts && npm run prettier",
|
|
35
|
+
"prebuild": "rm -rf dist/",
|
|
36
|
+
"prepack": "npm run build",
|
|
33
37
|
"pretest": "npm run lint",
|
|
34
|
-
"prettier": "prettier --list-different
|
|
38
|
+
"prettier": "prettier --list-different \"./**/**.{md,js,ts}\"",
|
|
39
|
+
"prettier:write": "prettier --list-different --write \"./**/**.{md,js,ts}\"",
|
|
35
40
|
"test": "jest --coverage"
|
|
36
41
|
},
|
|
37
42
|
"license": "MIT",
|
|
38
43
|
"dependencies": {
|
|
39
|
-
"@readme/openapi-parser": "^2.
|
|
44
|
+
"@readme/openapi-parser": "^2.2.0",
|
|
40
45
|
"js-yaml": "^4.1.0",
|
|
41
46
|
"node-fetch": "^2.6.1",
|
|
47
|
+
"openapi-types": "^12.0.0",
|
|
42
48
|
"swagger2openapi": "^7.0.8"
|
|
43
49
|
},
|
|
44
50
|
"devDependencies": {
|
|
45
|
-
"@readme/eslint-config": "^
|
|
46
|
-
"@readme/oas-examples": "^5.
|
|
47
|
-
"
|
|
48
|
-
"
|
|
51
|
+
"@readme/eslint-config": "^10.0.0",
|
|
52
|
+
"@readme/oas-examples": "^5.1.1",
|
|
53
|
+
"@types/jest": "^28.1.6",
|
|
54
|
+
"@types/js-yaml": "^4.0.5",
|
|
55
|
+
"@types/node-fetch": "^2.6.2",
|
|
56
|
+
"eslint": "^8.21.0",
|
|
57
|
+
"jest": "^28.0.3",
|
|
58
|
+
"jet": "^0.8.1",
|
|
49
59
|
"nock": "^13.2.4",
|
|
50
|
-
"prettier": "^2.
|
|
60
|
+
"prettier": "^2.7.1",
|
|
61
|
+
"ts-jest": "^28.0.7",
|
|
62
|
+
"typescript": "^4.7.4"
|
|
51
63
|
},
|
|
52
64
|
"prettier": "@readme/eslint-config/prettier"
|
|
53
65
|
}
|
package/src/.sink.d.ts
ADDED
package/src/index.ts
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import type { OpenAPI } from 'openapi-types';
|
|
2
|
+
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
|
|
5
|
+
import openapiParser from '@readme/openapi-parser';
|
|
6
|
+
import fetch from 'node-fetch';
|
|
7
|
+
|
|
8
|
+
import converter from 'swagger2openapi';
|
|
9
|
+
|
|
10
|
+
import * as utils from './lib/utils';
|
|
11
|
+
|
|
12
|
+
export type Options = {
|
|
13
|
+
colorizeErrors?: boolean;
|
|
14
|
+
enablePaths?: boolean;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default class OASNormalize {
|
|
18
|
+
cache: {
|
|
19
|
+
bundle?: false | OpenAPI.Document;
|
|
20
|
+
deref?: false | OpenAPI.Document;
|
|
21
|
+
load?: false | Record<string, unknown>;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
file: any;
|
|
25
|
+
|
|
26
|
+
opts: Options;
|
|
27
|
+
|
|
28
|
+
type: boolean | string;
|
|
29
|
+
|
|
30
|
+
constructor(file: any, opts?: Options) {
|
|
31
|
+
this.file = file;
|
|
32
|
+
this.opts = {
|
|
33
|
+
colorizeErrors: false,
|
|
34
|
+
enablePaths: false,
|
|
35
|
+
...opts,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
this.type = utils.getType(this.file);
|
|
39
|
+
|
|
40
|
+
this.cache = {
|
|
41
|
+
load: false,
|
|
42
|
+
bundle: false,
|
|
43
|
+
deref: false,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Internal API for the most part
|
|
48
|
+
async load() {
|
|
49
|
+
if (this.cache.load) return Promise.resolve(this.cache.load);
|
|
50
|
+
|
|
51
|
+
const resolve = (obj: Parameters<typeof utils.stringToJSON>[0]) => {
|
|
52
|
+
const ret = utils.stringToJSON(obj);
|
|
53
|
+
this.cache.load = ret;
|
|
54
|
+
return Promise.resolve(ret);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
switch (this.type) {
|
|
58
|
+
case 'json':
|
|
59
|
+
case 'string-json':
|
|
60
|
+
case 'string-yaml':
|
|
61
|
+
return resolve(this.file);
|
|
62
|
+
|
|
63
|
+
case 'buffer':
|
|
64
|
+
return resolve(this.file.toString());
|
|
65
|
+
|
|
66
|
+
case 'url':
|
|
67
|
+
const resp = await fetch(this.file).then(res => res.text());
|
|
68
|
+
return resolve(resp);
|
|
69
|
+
|
|
70
|
+
case 'path':
|
|
71
|
+
// Load a local file
|
|
72
|
+
if (!this.opts.enablePaths) {
|
|
73
|
+
return Promise.reject(new Error('Use `opts.enablePaths` to enable accessing local files.'));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const contents = fs.readFileSync(this.file).toString();
|
|
77
|
+
return resolve(contents);
|
|
78
|
+
|
|
79
|
+
default:
|
|
80
|
+
return Promise.reject(new Error('Could not load this file.'));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Bundle up the given OpenAPI or Swagger definition, resolving any external `$ref` pointers in
|
|
86
|
+
* the process.
|
|
87
|
+
*
|
|
88
|
+
*/
|
|
89
|
+
async bundle() {
|
|
90
|
+
if (this.cache.bundle) return Promise.resolve(this.cache.bundle);
|
|
91
|
+
|
|
92
|
+
return this.load()
|
|
93
|
+
.then(schema => openapiParser.bundle(schema))
|
|
94
|
+
.then(bundle => {
|
|
95
|
+
this.cache.bundle = bundle;
|
|
96
|
+
return bundle;
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Dereference the given OpenAPI or Swagger.
|
|
102
|
+
*
|
|
103
|
+
*/
|
|
104
|
+
async deref() {
|
|
105
|
+
if (this.cache.deref) return Promise.resolve(this.cache.deref);
|
|
106
|
+
|
|
107
|
+
return this.load()
|
|
108
|
+
.then(schema => openapiParser.dereference(schema))
|
|
109
|
+
.then(dereferenced => {
|
|
110
|
+
this.cache.deref = dereferenced;
|
|
111
|
+
return dereferenced;
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Validate a given OpenAPI or Swagger definition, potentially upconverting it from Swagger to
|
|
117
|
+
* OpenAPI in the process if you wish.
|
|
118
|
+
*
|
|
119
|
+
*/
|
|
120
|
+
async validate(convertToLatest = false) {
|
|
121
|
+
const colorizeErrors = this.opts.colorizeErrors;
|
|
122
|
+
|
|
123
|
+
return this.load().then(async schema => {
|
|
124
|
+
const baseVersion = parseInt(utils.version(schema), 10);
|
|
125
|
+
|
|
126
|
+
if (baseVersion === 1) {
|
|
127
|
+
return Promise.reject(new Error('Swagger v1.2 is unsupported.'));
|
|
128
|
+
} else if (baseVersion === 2 || baseVersion === 3) {
|
|
129
|
+
/**
|
|
130
|
+
* `openapiParser.validate()` dereferences schemas at the same time as validation and does
|
|
131
|
+
* not give us an option to disable this. Since all we already have a dereferencing method
|
|
132
|
+
* on this library and our `validate()` method here just needs to tell us if the definition
|
|
133
|
+
* is valid or not we need to clone it before passing it over to `openapi-parser` so as to
|
|
134
|
+
* not run into pass-by-reference problems.
|
|
135
|
+
*/
|
|
136
|
+
const clonedSchema = JSON.parse(JSON.stringify(schema));
|
|
137
|
+
|
|
138
|
+
return openapiParser
|
|
139
|
+
.validate(clonedSchema, {
|
|
140
|
+
validate: {
|
|
141
|
+
colorizeErrors,
|
|
142
|
+
},
|
|
143
|
+
})
|
|
144
|
+
.then(() => {
|
|
145
|
+
if (!convertToLatest) {
|
|
146
|
+
return schema;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return converter.convertObj(schema, { anchors: true }).then((options: { openapi: OpenAPI.Document }) => {
|
|
150
|
+
return options.openapi;
|
|
151
|
+
});
|
|
152
|
+
})
|
|
153
|
+
.catch(err => Promise.reject(err));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return Promise.reject(new Error('The supplied API definition is unsupported.'));
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Retrieve the OpenAPI or Swagger version of the current API definition.
|
|
162
|
+
*
|
|
163
|
+
*/
|
|
164
|
+
version() {
|
|
165
|
+
return this.load().then(schema => utils.version(schema));
|
|
166
|
+
}
|
|
167
|
+
}
|
package/src/lib/utils.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { OpenAPIV2, OpenAPIV3, OpenAPIV3_1 } from 'openapi-types';
|
|
2
|
+
|
|
3
|
+
import YAML from 'js-yaml';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Retrieve the Swagger or OpenAPI version that a given Swagger or OpenAPI definition are targeting.
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
export function version(schema: OpenAPIV2.Document & OpenAPIV3.Document & OpenAPIV3_1.Document) {
|
|
10
|
+
return schema.swagger || schema.openapi;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Determine if a given variable is a `Buffer`.
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
export function isBuffer(obj: any) {
|
|
18
|
+
return (
|
|
19
|
+
obj != null &&
|
|
20
|
+
obj.constructor != null &&
|
|
21
|
+
typeof obj.constructor.isBuffer === 'function' &&
|
|
22
|
+
obj.constructor.isBuffer(obj)
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Convert a YAML blob or stringified JSON object into a JSON object.
|
|
28
|
+
*
|
|
29
|
+
*/
|
|
30
|
+
export function stringToJSON(string: string | Record<string, unknown>) {
|
|
31
|
+
if (typeof string === 'object') {
|
|
32
|
+
return string;
|
|
33
|
+
} else if (string.match(/^\s*{/)) {
|
|
34
|
+
return JSON.parse(string);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return YAML.load(string);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Determine the type of a given variable. Returns `false` if unrecognized.
|
|
42
|
+
*
|
|
43
|
+
*/
|
|
44
|
+
export function getType(obj: any) {
|
|
45
|
+
if (isBuffer(obj)) {
|
|
46
|
+
return 'buffer';
|
|
47
|
+
} else if (typeof obj === 'object') {
|
|
48
|
+
return 'json';
|
|
49
|
+
} else if (typeof obj === 'string') {
|
|
50
|
+
if (obj.match(/\s*{/)) {
|
|
51
|
+
return 'string-json';
|
|
52
|
+
} else if (obj.match(/\n/)) {
|
|
53
|
+
// Not sure about this...
|
|
54
|
+
return 'string-yaml';
|
|
55
|
+
} else if (obj.substring(0, 4) === 'http') {
|
|
56
|
+
return 'url';
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return 'path';
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return false;
|
|
63
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"allowJs": true,
|
|
4
|
+
"baseUrl": "./src",
|
|
5
|
+
"declaration": true,
|
|
6
|
+
"esModuleInterop": true,
|
|
7
|
+
"lib": ["dom", "es2020"],
|
|
8
|
+
"outDir": "dist/",
|
|
9
|
+
"paths": {
|
|
10
|
+
"swagger2openapi": [".sink.d.ts"]
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
"include": ["./src/**/*"]
|
|
14
|
+
}
|
package/index.js
DELETED
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
const fetch = require('node-fetch');
|
|
2
|
-
const fs = require('fs');
|
|
3
|
-
const converter = require('swagger2openapi');
|
|
4
|
-
const openapiParser = require('@readme/openapi-parser');
|
|
5
|
-
const utils = require('./lib/utils');
|
|
6
|
-
|
|
7
|
-
class oasNormalize {
|
|
8
|
-
constructor(file, opts) {
|
|
9
|
-
this.file = file;
|
|
10
|
-
this.opts = {
|
|
11
|
-
colorizeErrors: false,
|
|
12
|
-
enablePaths: false,
|
|
13
|
-
...opts,
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
this.type = utils.type(this.file);
|
|
17
|
-
|
|
18
|
-
this.cache = {
|
|
19
|
-
load: false,
|
|
20
|
-
bundle: false,
|
|
21
|
-
deref: false,
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// Internal API for the most part
|
|
26
|
-
async load() {
|
|
27
|
-
if (this.cache.load) return Promise.resolve(this.cache.load);
|
|
28
|
-
|
|
29
|
-
const resolve = obj => {
|
|
30
|
-
const ret = utils.stringToJSON(obj);
|
|
31
|
-
this.cache.load = ret;
|
|
32
|
-
return Promise.resolve(ret);
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
if (this.type === 'json' || this.type === 'string-json' || this.type === 'string-yaml') {
|
|
36
|
-
return resolve(this.file);
|
|
37
|
-
} else if (this.type === 'buffer') {
|
|
38
|
-
return resolve(this.file.toString());
|
|
39
|
-
} else if (this.type === 'url') {
|
|
40
|
-
const resp = await fetch(this.file).then(res => res.text());
|
|
41
|
-
return resolve(resp);
|
|
42
|
-
} else if (this.type === 'path') {
|
|
43
|
-
// Load a local file
|
|
44
|
-
if (!this.opts.enablePaths) {
|
|
45
|
-
return Promise.reject(new Error('Use `opts.enablePaths` to enable accessing local files.'));
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const contents = fs.readFileSync(this.file).toString();
|
|
49
|
-
return resolve(contents);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return Promise.reject(new Error('Could not load this file.'));
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
async bundle() {
|
|
56
|
-
if (this.cache.bundle) return Promise.resolve(this.cache.bundle);
|
|
57
|
-
|
|
58
|
-
return this.load()
|
|
59
|
-
.then(schema => openapiParser.bundle(schema))
|
|
60
|
-
.then(bundle => {
|
|
61
|
-
this.cache.bundle = bundle;
|
|
62
|
-
return bundle;
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
async deref() {
|
|
67
|
-
if (this.cache.deref) return Promise.resolve(this.cache.deref);
|
|
68
|
-
|
|
69
|
-
return this.load()
|
|
70
|
-
.then(schema => openapiParser.dereference(schema))
|
|
71
|
-
.then(dereferenced => {
|
|
72
|
-
this.cache.deref = dereferenced;
|
|
73
|
-
return dereferenced;
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
async validate(convertToLatest = false) {
|
|
78
|
-
const colorizeErrors = this.opts.colorizeErrors;
|
|
79
|
-
|
|
80
|
-
return this.load().then(async schema => {
|
|
81
|
-
const baseVersion = parseInt(utils.version(schema), 10);
|
|
82
|
-
|
|
83
|
-
if (baseVersion === 1) {
|
|
84
|
-
return Promise.reject(new Error('Swagger v1.2 is unsupported.'));
|
|
85
|
-
} else if (baseVersion === 2 || baseVersion === 3) {
|
|
86
|
-
// `openapiParser.validate()` dereferences schemas at the same time as validation and does
|
|
87
|
-
// not give us an option to disable this. Since all we already have a dereferencing method
|
|
88
|
-
// on this library and our `validate()` method here just needs to tell us if the definition
|
|
89
|
-
// is valid or not we need to clone it before passing it over to `openapi-parser` so as to
|
|
90
|
-
// not run into pass-by-reference problems.
|
|
91
|
-
const clonedSchema = JSON.parse(JSON.stringify(schema));
|
|
92
|
-
|
|
93
|
-
return openapiParser
|
|
94
|
-
.validate(clonedSchema, {
|
|
95
|
-
validate: {
|
|
96
|
-
colorizeErrors,
|
|
97
|
-
},
|
|
98
|
-
})
|
|
99
|
-
.then(() => {
|
|
100
|
-
if (!convertToLatest) {
|
|
101
|
-
return schema;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return converter.convertObj(schema, { anchors: true }).then(options => {
|
|
105
|
-
return options.openapi;
|
|
106
|
-
});
|
|
107
|
-
})
|
|
108
|
-
.catch(err => Promise.reject(err));
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return Promise.reject(new Error('The supplied API definition is unsupported.'));
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
version() {
|
|
116
|
-
return this.load().then(schema => utils.version(schema));
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
module.exports = oasNormalize;
|
package/lib/utils.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
const YAML = require('js-yaml');
|
|
2
|
-
|
|
3
|
-
module.exports = {
|
|
4
|
-
// YAML or JSON string to JSON Object
|
|
5
|
-
stringToJSON: string => {
|
|
6
|
-
if (typeof string === 'object') {
|
|
7
|
-
return string;
|
|
8
|
-
} else if (string.match(/^\s*{/)) {
|
|
9
|
-
return JSON.parse(string);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
return YAML.load(string);
|
|
13
|
-
},
|
|
14
|
-
|
|
15
|
-
type: obj => {
|
|
16
|
-
if (module.exports.isBuffer(obj)) {
|
|
17
|
-
return 'buffer';
|
|
18
|
-
} else if (typeof obj === 'object') {
|
|
19
|
-
return 'json';
|
|
20
|
-
} else if (typeof obj === 'string') {
|
|
21
|
-
if (obj.match(/\s*{/)) {
|
|
22
|
-
return 'string-json';
|
|
23
|
-
}
|
|
24
|
-
if (obj.match(/\n/)) {
|
|
25
|
-
// Not sure about this...
|
|
26
|
-
return 'string-yaml';
|
|
27
|
-
}
|
|
28
|
-
if (obj.substr(0, 4) === 'http') {
|
|
29
|
-
return 'url';
|
|
30
|
-
}
|
|
31
|
-
return 'path';
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return false;
|
|
35
|
-
},
|
|
36
|
-
|
|
37
|
-
version: schema => schema.swagger || schema.openapi,
|
|
38
|
-
|
|
39
|
-
isBuffer: obj =>
|
|
40
|
-
obj != null &&
|
|
41
|
-
obj.constructor != null &&
|
|
42
|
-
typeof obj.constructor.isBuffer === 'function' &&
|
|
43
|
-
obj.constructor.isBuffer(obj),
|
|
44
|
-
};
|