UNPKG

@x82-softworks/aws-api

Version:

An OpenAPI compatible api system intended for use with AWS Lambda and API Gateway

962 lines (931 loc) 33.1 kB
/******/ (() => { // webpackBootstrap /******/ "use strict"; /******/ // The require scope /******/ var __webpack_require__ = {}; /******/ /************************************************************************/ /******/ /* webpack/runtime/compat get default export */ /******/ (() => { /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = (module) => { /******/ var getter = module && module.__esModule ? /******/ () => (module['default']) : /******/ () => (module); /******/ __webpack_require__.d(getter, { a: getter }); /******/ return getter; /******/ }; /******/ })(); /******/ /******/ /* webpack/runtime/define property getters */ /******/ (() => { /******/ // define getter functions for harmony exports /******/ __webpack_require__.d = (exports, definition) => { /******/ for(var key in definition) { /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); /******/ } /******/ } /******/ }; /******/ })(); /******/ /******/ /* webpack/runtime/hasOwnProperty shorthand */ /******/ (() => { /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) /******/ })(); /******/ /******/ /* webpack/runtime/make namespace object */ /******/ (() => { /******/ // define __esModule on exports /******/ __webpack_require__.r = (exports) => { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ })(); /******/ /************************************************************************/ var __webpack_exports__ = {}; // ESM COMPAT FLAG __webpack_require__.r(__webpack_exports__); // EXPORTS __webpack_require__.d(__webpack_exports__, { "APIKEY": () => (/* reexport */ APIKEY), "ARRAY": () => (/* reexport */ ARRAY), "BINARY": () => (/* reexport */ BINARY), "BOOLEAN": () => (/* reexport */ BOOLEAN), "BYTE": () => (/* reexport */ BYTE), "DATE": () => (/* reexport */ DATE), "DATETIME": () => (/* reexport */ DATETIME), "DEFAULT_CORS": () => (/* binding */ DEFAULT_CORS), "DOUBLE": () => (/* reexport */ DOUBLE), "EMAIL": () => (/* reexport */ EMAIL), "FLOAT": () => (/* reexport */ FLOAT), "FORM_ENCODED": () => (/* binding */ FORM_ENCODED), "GENERIC_ERROR": () => (/* reexport */ GENERIC_ERROR), "HEADER": () => (/* reexport */ HEADER), "INT32": () => (/* reexport */ INT32), "INT64": () => (/* reexport */ INT64), "INTEGER": () => (/* reexport */ INTEGER), "NUMBER": () => (/* reexport */ NUMBER), "OBJECT": () => (/* reexport */ OBJECT), "PASSWORD": () => (/* reexport */ PASSWORD), "STRING": () => (/* reexport */ STRING), "create": () => (/* binding */ create), "default": () => (/* binding */ src), "jsonResponseContent": () => (/* binding */ jsonResponseContent), "requiredJsonRequest": () => (/* binding */ requiredJsonRequest) }); ;// CONCATENATED MODULE: ./src/types.ts var Method; (function (Method) { Method["GET"] = "get"; Method["POST"] = "post"; Method["PUT"] = "put"; Method["DELETE"] = "delete"; Method["PATCH"] = "patch"; Method["OPTIONS"] = "options"; })(Method || (Method = {})); ;// CONCATENATED MODULE: ./src/constants.ts const NUMBER = "number"; const BOOLEAN = "boolean"; const INTEGER = "integer"; const INT32 = "int32"; const INT64 = "int64"; const STRING = "string"; const FLOAT = "float"; const DOUBLE = "double"; const OBJECT = "object"; const BYTE = "byte"; const BINARY = "binary"; const DATE = "date"; const DATETIME = "dateTime"; const ARRAY = "array"; const HEADER = "header"; const PASSWORD = "password"; const APIKEY = "apikey"; const EMAIL = "email"; ;// CONCATENATED MODULE: ./src/urlPattern.ts const keyPattern = /({[^}]*})/g; class URLPattern { constructor(pattern) { const keys = []; let key; while ((key = keyPattern.exec(pattern))) { key = key[0].slice(1, -1); keys.push(key); } //We need the inorder value of the keys this.keys = keys; pattern = pattern.replace(/({[^}]*})/g, "([a-zA-Z0-9-\\._~ %]+)"); this.regex = new RegExp(pattern); } match(test) { let ret = null, match; if ((match = this.regex.exec(test))) { ret = {}; for (let i = 0; i < this.keys.length; i++) { ret[this.keys[i]] = match[i + 1]; } //We need to check for the param keys and return it as an object } return ret; } } ;// CONCATENATED MODULE: ./src/utils.ts var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; /** * The default generic error code * @public */ const GENERIC_ERROR = "GenericError"; const isError = (err) => { return typeof err === "object" && err.name && err.stack && err.message; }; /** * Performs the final toStringing of data in the res body * @internal * @param res - The response * @returns The same response with the stringified version of its body */ const returnFinal = (res) => { if (res.body && typeof res.body !== "string") { res.body = JSON.stringify(res.body); } return res; }; /** * Checks to see if the object contains a reference to another in the api doc * @param obj */ const isRef = (obj) => { return typeof obj === "object" && typeof (obj === null || obj === void 0 ? void 0 : obj.$ref) === "string"; }; const coerce = (schema, val) => { switch (schema.type) { case OBJECT: if (typeof val === "string") { val = JSON.parse(val); } break; case INTEGER: case NUMBER: val = Number(val); break; case BOOLEAN: val = Boolean(val); break; default: break; } return val; }; const returnNotFound = function (res) { return __awaiter(this, void 0, void 0, function* () { return returnFinal(Object.assign(Object.assign({}, res), { statusCode: 404 })); }); }; /** * Convert a string like /{test}/{param} to a url pattern matching object * @internal * @param path * @returns A URLPattern matcher */ const convertToRegex = (path) => { return new URLPattern(path); }; const returnInvalid = function (res, reason) { return __awaiter(this, void 0, void 0, function* () { if (typeof reason === "string") { reason = { code: GENERIC_ERROR, message: reason, }; } if (isError(reason)) { reason = { code: reason.code || GENERIC_ERROR, message: reason.message, }; } return returnFinal(Object.assign(Object.assign({}, res), { statusCode: 400, body: reason })); }); }; ;// CONCATENATED MODULE: external "serialize-error" const external_serialize_error_namespaceObject = require("serialize-error"); ;// CONCATENATED MODULE: external "@x82-softworks/clone-merge" const clone_merge_namespaceObject = require("@x82-softworks/clone-merge"); var clone_merge_default = /*#__PURE__*/__webpack_require__.n(clone_merge_namespaceObject); ;// CONCATENATED MODULE: external "cookie" const external_cookie_namespaceObject = require("cookie"); var external_cookie_default = /*#__PURE__*/__webpack_require__.n(external_cookie_namespaceObject); ;// CONCATENATED MODULE: external "ajv" const external_ajv_namespaceObject = require("ajv"); var external_ajv_default = /*#__PURE__*/__webpack_require__.n(external_ajv_namespaceObject); ;// CONCATENATED MODULE: external "is-integer" const external_is_integer_namespaceObject = require("is-integer"); var external_is_integer_default = /*#__PURE__*/__webpack_require__.n(external_is_integer_namespaceObject); ;// CONCATENATED MODULE: ./src/jsonSchemaValidator.ts const MAX_INT_32 = 2147483647; const ajv = new (external_ajv_default())({ useDefaults: true, coerceTypes: true, }); ajv.addFormat(INT32, { validate: function (a) { return external_is_integer_default()(a) && a <= MAX_INT_32 && a >= -MAX_INT_32; }, type: NUMBER, }); ajv.addFormat(INT64, { validate: function (a) { return external_is_integer_default()(a); }, type: NUMBER, }); /** * Checks to see if the value matches to the given schema * @method exports * @param schema * @param val * @internal * @throws {Error} */ /* harmony default export */ const jsonSchemaValidator = ((schema, val) => { let validate = ajv.compile(schema), err; if (!validate(val)) { err = new Error("Validation error"); err.additional = validate.errors; throw err; } }); ;// CONCATENATED MODULE: ./src/params.ts var params_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; /* harmony default export */ const params = ((req, controller, api) => params_awaiter(void 0, void 0, void 0, function* () { (controller.parameters || []).forEach(param => { let val; switch (param.in) { case 'query': val = (req.queryStringParameters || {})[param.name]; break; case 'header': val = req.headers[param.name]; break; case 'path': val = decodeURIComponent(req.pathParams[param.name]); break; case 'cookie': val = req.headers.cookie[param.name]; break; default: throw new Error('Unknown param type : ' + param.in); } if (val === undefined) { if (param.required) { throw new Error(`Required parameter "${param.name}" not found`); } } else if (param.schema) { let schema = param.schema; if (isRef(schema)) { schema = api.getRef(schema); } val = coerce(schema, val); jsonSchemaValidator(schema, val); } req.params[param.name] = val; }); })); ;// CONCATENATED MODULE: external "@x82-softworks/aws-api-multipart" const aws_api_multipart_namespaceObject = require("@x82-softworks/aws-api-multipart"); ;// CONCATENATED MODULE: external "query-string" const external_query_string_namespaceObject = require("query-string"); var external_query_string_default = /*#__PURE__*/__webpack_require__.n(external_query_string_namespaceObject); ;// CONCATENATED MODULE: ./src/requestBody.ts var requestBody_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; /* eslint-disable no-case-declarations */ function validateSchema(req, schema, api) { if (!schema) { return; } if (isRef(schema)) { schema = api.getRef(schema); } const val = (req.body = coerce(schema, req.body)); jsonSchemaValidator(schema, val); } /** * Handles the request body portion of a request * @param {Object} req * @param {?Object} controllerRequestBody * @param {Object} api */ /* harmony default export */ function requestBody(req, controllerRequestBody, api) { return requestBody_awaiter(this, void 0, void 0, function* () { let contentSelector, hasNoBody = req.body === null || req.body === undefined, schema, contentType; if (!controllerRequestBody) { return; } //Check if its a request body reference if (isRef(controllerRequestBody)) { controllerRequestBody = api.getRef(controllerRequestBody); } //Check to see if required if (controllerRequestBody.required && hasNoBody) { throw new Error("Request body must be supplied"); } //If there is no body to parse and its not required then we're done if (hasNoBody) { return; } contentType = req.headers["content-type"]; if (!contentType) { return; // throw new Error('Request headers do not contain "content-type"'); } //In the case of multipart/form-data having a boundary contentType = contentType.split(";")[0]; //Check to see if that controller accepts the content type if (!(contentSelector = controllerRequestBody.content[contentType])) { throw new Error(`Content Type "${contentType}" is not supported`); } schema = contentSelector.schema; switch (contentType) { case "application/json": try { req.body = JSON.parse(req.body); } catch (err) { throw new Error("Cannot parse request body"); } break; case "application/x-www-form-urlencoded": req.body = external_query_string_default().parse(req.body); break; case "multipart/form-data": const ret = yield (0,aws_api_multipart_namespaceObject.parse)(req); const { val, multiparts } = ret.files.reduce((acc, file) => { acc.val[file.fieldName] = file.data.toString("utf-8"); acc.multiparts[file.fieldName] = file; return acc; }, { val: {}, multiparts: {}, }); //The coercion from the validate schea should handle converting application json,etc for us req.body = val; req.multiparts = multiparts; break; //Passthrough default: break; } validateSchema(req, schema, api); }); } ;// CONCATENATED MODULE: ./src/index.ts var src_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; const FORM_ENCODED = 'application/x-www-form-urlencoded'; const DEFAULT_CORS = { 'Access-Control-Allow-Methods': 'GET,OPTIONS,HEAD', 'Access-Control-Allow-headers': 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token' }; const APP_JSON = 'application/json', REQUEST_BODY = 'requestBodies', SCHEMA = 'schemas', CALLBACK = 'callbacks', src_HEADER = 'headers', SECURITY = 'securitySchemes', PARAMETER = 'parameters', RESPONSE = 'responses', EXAMPLE = 'examples', LINK = 'links', src_OBJECT = 'object', CONTENT_TYPE = 'content-type'; const paramRegex = /\{([^}]*)\}/; /** * Generates a reference object * @public * @param type * @param name * @returns A reference object */ function ref(type, name) { return { $ref: '#/components/' + type + '/' + name }; } class API { constructor(opts, devMode) { this.devMode = !!devMode; this.rootDef = clone_merge_default()({ openapi: '3.0.0', info: { version: '0.0.0', description: 'Default API', termsOfService: 'http://swagger.io/terms/', title: '', contact: { email: 'no-reply@example.com' }, license: { name: 'Proprietary' // url: 'http://www.apache.org/licenses/LICENSE-2.0.html' } }, host: 'localhost', basePath: '/', paths: {} }, opts); this.corsConfig = function (req, res) { const origin = req.headers.Origin ? req.headers.Origin : '*'; res.headers = clone_merge_default()(res.headers, { 'Access-Control-Allow-Origin': origin }, DEFAULT_CORS); }; this.paths = []; this.defSchema('genericError', { type: src_OBJECT, properties: { code: { description: 'Error code', type: STRING }, message: { description: 'Human readable message', type: STRING } }, required: ['code', 'message'] }); this.defResponse('genericError', { description: 'An unexpected error occurred', content: { 'application/json': { schema: this.refSchema('genericError') } } }); this._suppressValidationErrors = false; } /** * Sets the validation error suppression * @param val */ suppressValidationErrors(val) { this._suppressValidationErrors = val; } /** * @public * @returns The Root API defintion */ getRoot() { return clone_merge_default()(true, this.rootDef); } defRoot(def) { this.rootDef = clone_merge_default()(true, this.rootDef, def); } /** * Define the Cors function */ cors(configFunc) { this.corsConfig = configFunc; } defComponent(type, name, val) { if (!this.rootDef.components) { this.rootDef.components = {}; } if (!this.rootDef.components[type]) { this.rootDef.components[type] = {}; } if (this.rootDef.components[type][name]) { throw new Error('Component of type : "' + type + '" and name : "' + name + '" is already defined'); } this.rootDef.components[type][name] = val; return this; } defSecurity(name, props) { return this.defComponent(SECURITY, name, props); } defResponse(name, props) { return this.defComponent(RESPONSE, name, props); } ref(type, name) { return ref(type, name); } defSchema(name, props) { if (!props.title) { props.title = name; } return this.defComponent(SCHEMA, name, props); } getHost() { return this.rootDef.host; } /** * Gets the value from the reference object * @public * @param refObj * @returns The referenced object */ getRef(refObj) { if (!isRef(refObj)) { throw new Error('Not a valid reference object'); } //"$ref": "#/components/schemas/Pet" return refObj.$ref .split('/') .slice(1) .reduce(function (acc, piece) { return acc[piece]; }, this.rootDef); } /** * Ref requests */ refResponse(name) { return ref(RESPONSE, name); } refSchema(name) { return ref(SCHEMA, name); } refRequestBody(name) { return ref(REQUEST_BODY, name); } refSecurity(name) { return ref(SECURITY, name); } refExample(name) { return ref(EXAMPLE, name); } refParameter(name) { return ref(PARAMETER, name); } refHeader(name) { return ref(src_HEADER, name); } refCallback(name) { return ref(CALLBACK, name); } refLink(name) { return ref(LINK, name); } /** * Adds a route to the router * @public * @param path * @param method * @param [def] * @param handler */ path(path, method, def, handler) { if (!handler) { handler = def; def = null; } def = clone_merge_default()(true, { summary: '', description: '', tags: [], parameters: [], requestBody: null, responses: { 200: { description: 'Success' // schema: null }, default: this.refResponse('genericError') } }, def); if (!def.requestBody) { delete def.requestBody; } const methodString = method.toLowerCase(); def.handler = handler; if (!this.rootDef.paths) { this.rootDef.paths = {}; } if (!this.rootDef.paths[path]) { this.rootDef.paths[path] = {}; } if (this.rootDef.paths[path][methodString]) { throw new Error('Redefinition of path : ' + path + ' method : ' + methodString); } this.rootDef.paths[path][methodString] = def; //If it has path params if (paramRegex.test(path)) { this.paths.push({ regex: convertToRegex(path), original: path }); } return this; } /** * Adds a GET route * @public * @param path * @param [def] * @param handler */ get(path, def, handler) { return this.path(path, Method.GET, def, handler); } /** * Adds a POST route * @public * @param path * @param [def] * @param handler */ post(path, def, handler) { return this.path(path, Method.POST, def, handler); } /** * Adds a PUT route * @public * @param path * @param [def] * @param handler */ put(path, def, handler) { return this.path(path, Method.PUT, def, handler); } /** * Adds a PATCH route * @public * @param path * @param [def] * @param handler */ patch(path, def, handler) { return this.path(path, Method.PATCH, def, handler); } /** * Adds a DELETE route * @public * @param path * @param [def] * @param handler */ delete(path, def, handler) { return this.path(path, Method.DELETE, def, handler); } defParameter(name, props) { return this.defComponent(PARAMETER, name, props); } defExample(name, props) { return this.defComponent(EXAMPLE, name, props); } defRequestBody(name, props) { return this.defComponent(REQUEST_BODY, name, props); } defHeader(name, props) { return this.defComponent(src_HEADER, name, props); } defLink(name, props) { return this.defComponent(LINK, name, props); } defCallback(name, props) { return this.defComponent(CALLBACK, name, props); } lambda() { const self = this; return function (event) { return src_awaiter(this, void 0, void 0, function* () { //Automatically set the correct host if (event.headers && event.headers.Host) { let more = ''; if (event.requestContext) { if (event.requestContext.path.indexOf('/' + event.requestContext.stage) === 0) { //Then we have some kind of basepath added on more = '/' + event.requestContext.stage; } } self.defRoot({ host: 'https://' + event.headers.Host + more }); } return yield self.dispatch(event); }); }; } /** * @public * @param event */ dispatch(event) { var _a; return src_awaiter(this, void 0, void 0, function* () { const req = Object.assign({ path: '/', rawPath: '/', httpMethod: Method.GET, headers: { //Incoming request headers }, rawHeaders: {}, queryStringParameters: { //query string parameters }, params: { //Will be added by the dispatcher }, stageVariables: { //Applicable stage variables }, requestContext: { //Request context,including authorizer - returned key - value pairs }, pathParams: {}, body: null, isBase64Encoded: false, rawBody: null }, event); const self = this; req.rawPath = req.path; req.httpMethod = req.httpMethod.toLowerCase(); //Make sure all headers are lower case as according to RFCs it doesn't matter but it does simplify lookup req.headers = Object.keys(req.headers || {}).reduce((acc, key) => { acc[key.toLowerCase()] = req.headers[key]; return acc; }, {}); //In case middleware attempts to overwrite it req.rawBody = req.body; req.rawHeaders = req.headers; if ((_a = req.headers) === null || _a === void 0 ? void 0 : _a.cookie) { req.headers.cookie = external_cookie_default().parse(req.headers.cookie); } if (req.path[0] !== '/') { //Normalise req.path = '/' + req.path; } if (!req.httpMethod || !req.path) { throw new Error('Event is not wellformed'); } const res = { body: undefined, headers: {}, statusCode: 200 }; //check this against the base path if (req.path.indexOf(self.rootDef.basePath) !== 0) { return returnNotFound(res); } self.corsConfig(req, res); req.path = req.path.slice(self.rootDef.basePath.length); if (req.path[0] !== '/') { req.path = '/' + req.path; } //Lookup the path directly if possible otherwise use pattern matching let methods = self.rootDef.paths[req.path], pathParams = null, controller; if (!methods) { //Try lookup via path matching for (let i = 0, c = self.paths.length; i < c; i++) { if ((pathParams = self.paths[i].regex.match(req.path))) { methods = self.rootDef.paths[self.paths[i].original]; break; } } } req.pathParams = pathParams; if (!methods || !(controller = methods[req.httpMethod])) { //This allows added options to override the base support if (req.httpMethod === 'options') { //Automagic option support return res; } return returnNotFound(res); } return (requestBody(req, controller.requestBody, self) .catch(err => { //Assume user fuckup res.statusCode = 400; throw err; }) .then(() => src_awaiter(this, void 0, void 0, function* () { yield params(req, controller, self); return new Promise((resolve, reject) => { try { resolve(controller.handler(req, res)); } catch (err) { reject(err); } }).catch(err => { if (!res.body) { if (self.devMode) { res.body = err; } else { // eslint-disable-next-line no-console console.error(err); res.body = new Error('An internal server error has occurred'); } res.statusCode = res.body.statusCode ? res.body.statusCode : 500; } }); })) //Errors from params and requestbody should fall through to here .catch(err => { res.body = err; }) .then(() => { var _a, _b; //Check if the body is an error in which case we extract only the message to prevent leaking the specifics of the server if (res.body instanceof Error) { if (self.devMode) { res.body = (0,external_serialize_error_namespaceObject.serializeError)(res.body); } else { res.body = { code: ((_a = res.body) === null || _a === void 0 ? void 0 : _a.code) || GENERIC_ERROR, message: res.body.message, additional: self._suppressValidationErrors ? null : (_b = res.body) === null || _b === void 0 ? void 0 : _b.additional }; } if (!res.statusCode) { res.statusCode = res.body.statusCode || 500; } } if (typeof res.body === 'object' && !res.headers[CONTENT_TYPE]) { //All other types must be res.headers[CONTENT_TYPE] = APP_JSON; } //Convert the body to a string return returnFinal(res); })); }); } } /* harmony default export */ const src = (API); //Auto generate all the ref functions // [ // SECURITY, // EXAMPLE, // PARAMETER, // RESPONSE, // HEADER, // CALLBACK, // LINK, // SCHEMA, // REQUEST_BODY // ].forEach(type => { // let name = type; // if (name === REQUEST_BODY) { // //Tiny hack because request body does not have a simple pluralization // name = 'RequestBodys'; // } // //We use the -1 to remove the pluralization // API.prototype['ref' + capitalize(name).slice(0, -1)] = (name) => ref(type, name); // }); /** * Factory function to create an API * @public * @param init * @param debug * @returns The created api */ const create = function (init, debug) { return new API(init, debug); }; /** * An easy shorthand to create a required JSON requestBody with provided inner schema * @public * @param schema */ const requiredJsonRequest = (schema) => ({ required: true, content: { 'application/json': { schema: schema } } }); /** * An easy shorhand to create a json response with the provided schema * @param schema * @public * @returns */ const jsonResponseContent = (schema) => ({ 'application/json': { schema: schema } }); module.exports = __webpack_exports__; /******/ })() ; //# sourceMappingURL=commonjs.cjs.map