oas-normalize
Version:
Tooling for converting, validating, and parsing OpenAPI, Swagger, and Postman API definitions
250 lines (233 loc) • 9.37 kB
JavaScript
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
var _chunkAKXTCPGMcjs = require('./chunk-AKXTCPGM.cjs');
var _chunkHIUYACR6cjs = require('./chunk-HIUYACR6.cjs');
// src/index.ts
var _fs = require('fs'); var _fs2 = _interopRequireDefault(_fs);
var _openapiparser = require('@readme/openapi-parser');
var _postmantoopenapi = require('@readme/postman-to-openapi'); var _postmantoopenapi2 = _interopRequireDefault(_postmantoopenapi);
var _swagger2openapi = require('swagger2openapi'); var _swagger2openapi2 = _interopRequireDefault(_swagger2openapi);
var OASNormalize = class _OASNormalize {
// biome-ignore lint/suspicious/noExplicitAny: Intentionally loose because this library supports a wide variety of inputs.
// biome-ignore lint/suspicious/noExplicitAny: Intentionally loose because this library supports a wide variety of inputs.
constructor(file, opts) {
this.file = file;
this.opts = {
colorizeErrors: false,
enablePaths: false,
parser: {},
...opts
};
if (!this.opts.enablePaths) {
if (!this.opts.parser) this.opts.parser = {};
if (!this.opts.parser.resolve) this.opts.parser.resolve = {};
this.opts.parser.resolve = { file: false };
}
this.type = _chunkHIUYACR6cjs.getType.call(void 0, this.file);
this.cache = {
load: false,
bundle: false,
deref: false
};
}
/**
* Load and return the API definition that `oas-normalize` was initialized with.
*
*/
async load() {
if (this.cache.load) return this.cache.load;
const resolve = (obj) => {
const ret = _chunkHIUYACR6cjs.stringToJSON.call(void 0, obj);
this.cache.load = ret;
return ret;
};
switch (this.type) {
case "json":
case "string-json":
case "string-yaml":
return resolve(this.file);
case "buffer":
return resolve(this.file.toString());
case "url": {
const { url, options } = _chunkHIUYACR6cjs.prepareURL.call(void 0, this.file);
const resp = await fetch(url, options).then((res) => res.text());
return resolve(resp);
}
case "path": {
if (!this.opts.enablePaths) {
throw new Error("Use `opts.enablePaths` to enable accessing local files.");
}
const contents = _fs2.default.readFileSync(this.file).toString();
if (!contents.trim()) {
throw new Error("No file contents found.");
}
return resolve(contents);
}
default:
throw new Error("Could not load this file.");
}
}
static async convertPostmanToOpenAPI(schema) {
return _postmantoopenapi2.default.call(void 0, JSON.stringify(schema), void 0, {
outputFormat: "json",
replaceVars: true
}).then(JSON.parse);
}
/**
* Bundle up the given API definition, resolving any external `$ref` pointers in the process.
*
*/
async bundle() {
if (this.cache.bundle) return this.cache.bundle;
const parserOptions = this.opts.parser || {};
return this.load().then((schema) => {
if (_chunkHIUYACR6cjs.isPostman.call(void 0, schema)) {
return _OASNormalize.convertPostmanToOpenAPI(schema);
}
return schema;
}).then((schema) => _openapiparser.bundle.call(void 0, schema, parserOptions)).then((bundled) => {
this.cache.bundle = bundled;
return bundled;
});
}
/**
* Dereference the given API definition.
*
*/
async dereference() {
if (this.cache.deref) return this.cache.deref;
const parserOptions = this.opts.parser || {};
return this.load().then((schema) => {
if (_chunkHIUYACR6cjs.isPostman.call(void 0, schema)) {
return _OASNormalize.convertPostmanToOpenAPI(schema);
}
return schema;
}).then((schema) => _openapiparser.dereference.call(void 0, schema, parserOptions)).then((dereferenced) => {
this.cache.deref = dereferenced;
return dereferenced;
});
}
/**
* Dereference the given API definition.
*
* This method is deprecated in favor of `dereference`. It will be removed in a future release.
*
* @deprecated
*/
async deref() {
return this.dereference();
}
/**
* Convert a given API definition to OpenAPI if it is not already.
*
*/
async convert() {
if (this.cache.convert) return this.cache.convert;
return this.load().then(async (schema) => {
return _chunkHIUYACR6cjs.isPostman.call(void 0, schema) ? _OASNormalize.convertPostmanToOpenAPI(schema) : schema;
}).then(async (schema) => {
if (!_chunkHIUYACR6cjs.isSwagger.call(void 0, schema) && !_chunkHIUYACR6cjs.isOpenAPI.call(void 0, schema)) {
throw new Error("The supplied API definition is unsupported.");
} else if (_chunkHIUYACR6cjs.isOpenAPI.call(void 0, schema)) {
return schema;
}
const baseVersion = parseInt(schema.swagger, 10);
if (baseVersion === 1) {
throw new Error("Swagger v1.2 is unsupported.");
}
return _swagger2openapi2.default.convertObj(schema, { anchors: true }).then((options) => options.openapi);
});
}
/**
* Validate a given API definition.
*
* If supplied a Postman collection it will be converted to OpenAPI first and then run through
* standard OpenAPI validation.
*
*/
async validate(opts = {}) {
const shouldThrowIfInvalid = _nullishCoalesce(opts.shouldThrowIfInvalid, () => ( true));
const parserOptions = opts.parser || this.opts.parser || {};
if (!parserOptions.validate) parserOptions.validate = {};
if (!parserOptions.validate.errors) parserOptions.validate.errors = {};
parserOptions.validate.errors.colorize = this.opts.colorizeErrors;
return this.load().then(async (schema) => {
return _chunkHIUYACR6cjs.isPostman.call(void 0, schema) ? _OASNormalize.convertPostmanToOpenAPI(schema) : schema;
}).then(async (schema) => {
if (!_chunkHIUYACR6cjs.isSwagger.call(void 0, schema) && !_chunkHIUYACR6cjs.isOpenAPI.call(void 0, schema)) {
if (shouldThrowIfInvalid) {
throw new (0, _chunkAKXTCPGMcjs.ValidationError)("The supplied API definition is unsupported.");
}
return {
valid: false,
errors: [{ message: "The supplied API definition is unsupported." }],
warnings: [],
additionalErrors: 0,
specification: null
};
} else if (_chunkHIUYACR6cjs.isSwagger.call(void 0, schema)) {
const baseVersion = parseInt(schema.swagger, 10);
if (baseVersion === 1) {
if (shouldThrowIfInvalid) {
throw new (0, _chunkAKXTCPGMcjs.ValidationError)("Swagger v1.2 is unsupported.");
}
return {
valid: false,
errors: [{ message: "Swagger v1.2 is unsupported." }],
warnings: [],
additionalErrors: 0,
specification: "Swagger"
};
}
}
const clonedSchema = JSON.parse(JSON.stringify(schema));
const result = await _openapiparser.validate.call(void 0, clonedSchema, parserOptions);
if (!result.valid && shouldThrowIfInvalid) {
throw new (0, _chunkAKXTCPGMcjs.ValidationError)(_openapiparser.compileErrors.call(void 0, result), {
errors: result.errors,
warnings: result.warnings
});
}
return result;
});
}
/**
* Retrieve OpenAPI, Swagger, or Postman version information about the supplied API definition.
*
*/
async version() {
return this.load().then((schema) => {
switch (_chunkHIUYACR6cjs.getAPIDefinitionType.call(void 0, schema)) {
case "openapi":
return {
specification: "openapi",
version: schema.openapi
};
case "postman": {
let version = "unknown";
if (_optionalChain([schema, 'optionalAccess', _ => _.info, 'optionalAccess', _2 => _2.schema])) {
const match = (_optionalChain([schema, 'optionalAccess', _3 => _3.info])).schema.match(
/http(s?):\/\/schema.getpostman.com\/json\/collection\/v([0-9.]+)\//
);
if (match) {
version = match[2];
}
}
return {
specification: "postman",
version
};
}
case "swagger":
return {
specification: "swagger",
version: schema.swagger
};
default:
throw new Error("Unknown file detected.");
}
});
}
};
exports.default = OASNormalize;
module.exports = exports.default;
//# sourceMappingURL=index.cjs.map