UNPKG

oas

Version:

Comprehensive tooling for working with OpenAPI definitions

1 lines 52.4 kB
{"version":3,"sources":["/Users/erunion/code/readme/oas/packages/oas/dist/chunk-7XLR2GY5.cjs","../src/index.ts","../src/lib/get-auth.ts","../src/lib/get-user-variable.ts"],"names":[],"mappings":"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","file":"/Users/erunion/code/readme/oas/packages/oas/dist/chunk-7XLR2GY5.cjs","sourcesContent":[null,"import type { Extensions } from './extensions.js';\nimport type * as RMOAS from './types.js';\nimport type { OpenAPIV3_1 } from 'openapi-types';\nimport type { Match, ParamData } from 'path-to-regexp';\n\nimport { dereference } from '@readme/openapi-parser';\nimport { pathToRegexp, match } from 'path-to-regexp';\n\nimport {\n CODE_SAMPLES,\n HEADERS,\n OAUTH_OPTIONS,\n PARAMETER_ORDERING,\n SAMPLES_LANGUAGES,\n extensionDefaults,\n getExtension,\n hasRootExtension,\n validateParameterOrdering,\n} from './extensions.js';\nimport { getAuth } from './lib/get-auth.js';\nimport getUserVariable from './lib/get-user-variable.js';\nimport { isPrimitive } from './lib/helpers.js';\nimport { Operation, Webhook } from './operation/index.js';\nimport { findSchemaDefinition, supportedMethods } from './utils.js';\n\ninterface PathMatch {\n match?: Match<ParamData>;\n operation: RMOAS.PathsObject;\n url: {\n method?: RMOAS.HttpMethods;\n nonNormalizedPath: string;\n origin: string;\n path: string;\n slugs: Record<string, string>;\n };\n}\ntype PathMatches = PathMatch[];\n\nconst SERVER_VARIABLE_REGEX = /{([-_a-zA-Z0-9:.[\\]]+)}/g;\n\nfunction ensureProtocol(url: string) {\n // Add protocol to urls starting with // e.g. //example.com\n // This is because httpsnippet throws a HARError when it doesnt have a protocol\n if (url.match(/^\\/\\//)) {\n return `https:${url}`;\n }\n\n // Add protocol to urls with no // within them\n // This is because httpsnippet throws a HARError when it doesnt have a protocol\n if (!url.match(/\\/\\//)) {\n return `https://${url}`;\n }\n\n return url;\n}\n\nfunction stripTrailingSlash(url: string) {\n if (url[url.length - 1] === '/') {\n return url.slice(0, -1);\n }\n\n return url;\n}\n\n/**\n * Normalize a OpenAPI server URL by ensuring that it has a proper HTTP protocol and doesn't have a\n * trailing slash.\n *\n * @param api The API definition that we're processing.\n * @param selected The index of the `servers` array in the API definition that we want to normalize.\n */\nfunction normalizedUrl(api: RMOAS.OASDocument, selected: number) {\n const exampleDotCom = 'https://example.com';\n let url;\n try {\n url = api.servers[selected].url;\n // This is to catch the case where servers = [{}]\n if (!url) throw new Error('no url');\n\n // Stripping the '/' off the end\n url = stripTrailingSlash(url);\n\n // Check if the URL is just a path a missing an origin, for example `/api/v3`. If so, then make\n // `example.com` the origin to avoid it becoming something invalid like `https:///api/v3`.\n // RM-1044\n if (url.startsWith('/') && !url.startsWith('//')) {\n const urlWithOrigin = new URL(exampleDotCom);\n urlWithOrigin.pathname = url;\n url = urlWithOrigin.href;\n }\n } catch (e) {\n url = exampleDotCom;\n }\n\n return ensureProtocol(url);\n}\n\n/**\n * With a URL that may contain server variables, transform those server variables into regex that\n * we can query against.\n *\n * For example, when given `https://{region}.node.example.com/v14` this will return back:\n *\n * https://([-_a-zA-Z0-9:.[\\\\]]+).node.example.com/v14\n *\n * @param url URL to transform\n */\nfunction transformUrlIntoRegex(url: string) {\n return stripTrailingSlash(url.replace(SERVER_VARIABLE_REGEX, '([-_a-zA-Z0-9:.[\\\\]]+)'));\n}\n\n/**\n * Normalize a path so that we can use it with `path-to-regexp` to do operation lookups.\n *\n * @param path Path to normalize.\n */\nfunction normalizePath(path: string) {\n return (\n path\n // This regex transforms `{pathParam}` into `:pathParam` so we can regex against it. We're\n // also handling quirks here like if there's an optional proceeding or trailing curly bracket\n // (`{{pathParam}` or `{pathParam}}`) as any unescaped curlys, which would be present in\n // `:pathParam}`, will throw a regex exception.\n .replace(/({?){(.*?)}(}?)/g, (str, ...args) => {\n // If a path contains a path parameter with hyphens, like `:dlc-release`, when it's regexd\n // with `path-to-regexp` it match against the `:dlc` portion of the parameter, breaking all\n // matching against the full path.\n //\n // For example on `/games/:game/dlc/:dlc-release` the regex that's actually used to search\n // against a path like `/games/destiny-2/dlc/witch-queen` is the following:\n // /^\\/games(?:\\/([^\\/#\\?]+?))\\/dlc(?:\\/([^\\/#\\?]+?))-release[\\/#\\?]?$/i\n //\n // However if `:dlc-release` is rewritten to `:dlcrelease` we end up with a functional\n // regex: /^\\/games(?:\\/([^\\/#\\?]+?))\\/dlc(?:\\/([^\\/#\\?]+?))[\\/#\\?]?$/i.\n return `:${args[1].replace('-', '')}`;\n })\n\n // In addition to transforming `{pathParam}` into `:pathParam` we also need to escape cases\n // where a non-variabled colon is next to a variabled-colon because if we don't then\n // `path-to-regexp` won't be able to correct identify where the variable starts.\n //\n // For example if the URL is `/post/:param1::param2` we'll be escaping it to\n // `/post/:param1\\::param2`.\n .replace(/::/, '\\\\::')\n\n // We also need to escape question marks too because they're treated as regex modifiers.\n .split('?')[0]\n );\n}\n\n/**\n * Generate path matches for a given path and origin on a set of OpenAPI path objects.\n *\n * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#paths-object}\n * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#paths-object}\n * @param paths The OpenAPI Paths Object to process.\n * @param pathName Path to look for a match.\n * @param origin The origin that we're matching against.\n */\nfunction generatePathMatches(paths: RMOAS.PathsObject, pathName: string, origin: string) {\n const prunedPathName = pathName.split('?')[0];\n return Object.keys(paths)\n .map(path => {\n const cleanedPath = normalizePath(path);\n\n let matchResult: PathMatch['match'];\n try {\n const matchStatement = match(cleanedPath, { decode: decodeURIComponent });\n matchResult = matchStatement(prunedPathName);\n } catch (err) {\n // If path matching fails for whatever reason (maybe they have a malformed path parameter)\n // then we shouldn't also fail.\n return;\n }\n\n const slugs: Record<string, string> = {};\n\n if (matchResult && Object.keys(matchResult.params).length) {\n Object.keys(matchResult.params).forEach(param => {\n slugs[`:${param}`] = (matchResult.params as Record<string, string>)[param];\n });\n }\n\n // eslint-disable-next-line consistent-return\n return {\n url: {\n origin,\n path: cleanedPath.replace(/\\\\::/, '::'),\n nonNormalizedPath: path,\n slugs,\n },\n operation: paths[path],\n match: matchResult,\n };\n })\n .filter(Boolean)\n .filter(p => p.match) as PathMatches;\n}\n\n/**\n * @param pathMatches Array of path matches to filter down.\n * @param targetMethod HTTP method to look for.\n * @returns Filtered down path matches.\n */\nfunction filterPathMethods(pathMatches: PathMatches, targetMethod: RMOAS.HttpMethods) {\n const regExp = pathToRegexp(targetMethod);\n return pathMatches\n .map(p => {\n const captures = Object.keys(p.operation).filter(r => regExp.regexp.exec(r));\n\n if (captures.length) {\n const method = captures[0];\n p.url.method = method.toUpperCase() as RMOAS.HttpMethods;\n\n return {\n url: p.url,\n operation: p.operation[method],\n };\n }\n\n return false;\n })\n .filter(Boolean) as { operation: RMOAS.OperationObject; url: PathMatch['url'] }[];\n}\n\n/**\n * @param pathMatches URL and PathsObject matches to narrow down to find a target path.\n * @returns An object containing matches that were discovered in the API definition.\n */\nfunction findTargetPath(pathMatches: { operation: RMOAS.PathsObject; url: PathMatch['url'] }[]) {\n let minCount = Object.keys(pathMatches[0].url.slugs).length;\n let operation;\n\n for (let m = 0; m < pathMatches.length; m += 1) {\n const selection = pathMatches[m];\n const paramCount = Object.keys(selection.url.slugs).length;\n if (paramCount <= minCount) {\n minCount = paramCount;\n operation = selection;\n }\n }\n\n return operation;\n}\n\nexport default class Oas {\n /**\n * An OpenAPI API Definition.\n */\n api: RMOAS.OASDocument;\n\n /**\n * The current user that we should use when pulling auth tokens from security schemes.\n */\n user: RMOAS.User;\n\n /**\n * Internal storage array that the library utilizes to keep track of the times the\n * {@see Oas.dereference} has been called so that if you initiate multiple promises they'll all\n * end up returning the same data set once the initial dereference call completed.\n */\n protected promises: {\n reject: any;\n resolve: any;\n }[];\n\n /**\n * Internal storage array that the library utilizes to keep track of its `dereferencing` state so\n * it doesn't initiate multiple dereferencing processes.\n */\n protected dereferencing: {\n circularRefs: string[];\n complete: boolean;\n processing: boolean;\n };\n\n /**\n * @param oas An OpenAPI definition.\n * @param user The information about a user that we should use when pulling auth tokens from\n * security schemes.\n */\n constructor(oas: RMOAS.OASDocument | string, user?: RMOAS.User) {\n if (typeof oas === 'string') {\n // eslint-disable-next-line try-catch-failsafe/json-parse\n oas = JSON.parse(oas) as RMOAS.OASDocument;\n }\n\n this.api = oas || ({} as RMOAS.OASDocument);\n this.user = user || {};\n\n this.promises = [];\n this.dereferencing = {\n processing: false,\n complete: false,\n circularRefs: [],\n };\n }\n\n /**\n * This will initialize a new instance of the `Oas` class. This method is useful if you're using\n * Typescript and are attempting to supply an untyped JSON object into `Oas` as it will force-type\n * that object to an `OASDocument` for you.\n *\n * @param oas An OpenAPI definition.\n * @param user The information about a user that we should use when pulling auth tokens from\n * security schemes.\n */\n static init(oas: Record<string, unknown> | RMOAS.OASDocument, user?: RMOAS.User): Oas {\n return new Oas(oas as RMOAS.OASDocument, user);\n }\n\n /**\n * Retrieve the OpenAPI version that this API definition is targeted for.\n */\n getVersion(): string {\n if (this.api.openapi) {\n return this.api.openapi;\n }\n\n throw new Error('Unable to recognize what specification version this API definition conforms to.');\n }\n\n /**\n * Retrieve the current OpenAPI API Definition.\n *\n */\n getDefinition(): RMOAS.OASDocument {\n return this.api;\n }\n\n url(selected = 0, variables?: RMOAS.ServerVariable): string {\n const url = normalizedUrl(this.api, selected);\n return this.replaceUrl(url, variables || this.defaultVariables(selected)).trim();\n }\n\n variables(selected = 0): RMOAS.ServerVariablesObject {\n let variables: RMOAS.ServerVariablesObject;\n try {\n variables = this.api.servers[selected].variables;\n if (!variables) throw new Error('no variables');\n } catch (e) {\n variables = {};\n }\n\n return variables;\n }\n\n defaultVariables(selected = 0): RMOAS.ServerVariable {\n const variables = this.variables(selected);\n const defaults: RMOAS.ServerVariable = {};\n\n Object.keys(variables).forEach(key => {\n defaults[key] = getUserVariable(this.user, key) || variables[key].default || '';\n });\n\n return defaults;\n }\n\n splitUrl(selected = 0): (\n | {\n /**\n * A unique key, where the `value` is concatenated to its index\n */\n key: string;\n type: 'text';\n value: string;\n }\n | {\n /**\n * An optional description for the server variable.\n *\n * @see {@link https://spec.openapis.org/oas/v3.1.0#fixed-fields-4}\n */\n description?: string;\n\n /**\n * An enumeration of string values to be used if the substitution options are from a limited set.\n *\n * @see {@link https://spec.openapis.org/oas/v3.1.0#fixed-fields-4}\n */\n enum?: string[];\n\n /**\n * A unique key, where the `value` is concatenated to its index\n */\n key: string;\n type: 'variable';\n value: string;\n }\n )[] {\n const url = normalizedUrl(this.api, selected);\n const variables = this.variables(selected);\n\n return url\n .split(/({.+?})/)\n .filter(Boolean)\n .map((part, i) => {\n const isVariable = part.match(/[{}]/);\n const value = part.replace(/[{}]/g, '');\n // To ensure unique keys, we're going to create a key\n // with the value concatenated to its index.\n const key = `${value}-${i}`;\n\n if (!isVariable) {\n return {\n type: 'text',\n value,\n key,\n };\n }\n\n const variable = variables?.[value];\n\n return {\n type: 'variable',\n value,\n key,\n description: variable?.description,\n enum: variable?.enum,\n };\n });\n }\n\n /**\n * With a fully composed server URL, run through our list of known OAS servers and return back\n * which server URL was selected along with any contained server variables split out.\n *\n * For example, if you have an OAS server URL of `https://{name}.example.com:{port}/{basePath}`,\n * and pass in `https://buster.example.com:3000/pet` to this function, you'll get back the\n * following:\n *\n * { selected: 0, variables: { name: 'buster', port: 3000, basePath: 'pet' } }\n *\n * Re-supplying this data to `oas.url()` should return the same URL you passed into this method.\n *\n * @param baseUrl A given URL to extract server variables out of.\n */\n splitVariables(baseUrl: string): RMOAS.Servers | false {\n const matchedServer = (this.api.servers || [])\n .map((server, i) => {\n const rgx = transformUrlIntoRegex(server.url);\n const found = new RegExp(rgx).exec(baseUrl);\n if (!found) {\n return false;\n }\n\n // While it'd be nice to use named regex groups to extract path parameters from the URL and\n // match them up with the variables that we have present in it, JS unfortunately doesn't\n // support having the groups duplicated. So instead of doing that we need to re-regex the\n // server URL, this time splitting on the path parameters -- this way we'll be able to\n // extract the parameter names and match them up with the matched server that we obtained\n // above.\n const variables: Record<string, number | string> = {};\n Array.from(server.url.matchAll(SERVER_VARIABLE_REGEX)).forEach((variable, y) => {\n variables[variable[1]] = found[y + 1];\n });\n\n return {\n selected: i,\n variables,\n };\n })\n .filter(Boolean);\n\n return matchedServer.length ? matchedServer[0] : false;\n }\n\n /**\n * Replace templated variables with supplied data in a given URL.\n *\n * There are a couple ways that this will utilize variable data:\n *\n * - Supplying a `variables` object. If this is supplied, this data will always take priority.\n * This incoming `variables` object can be two formats:\n * `{ variableName: { default: 'value' } }` and `{ variableName: 'value' }`. If the former is\n * present, that will take precedence over the latter.\n * - If the supplied `variables` object is empty or does not match the current template name,\n * we fallback to the data stored in `this.user` and attempt to match against that.\n * See `getUserVariable` for some more information on how this data is pulled from `this.user`.\n *\n * If no variables supplied match up with the template name, the template name will instead be\n * used as the variable data.\n *\n * @param url A URL to swap variables into.\n * @param variables An object containing variables to swap into the URL.\n */\n replaceUrl(url: string, variables: RMOAS.ServerVariable = {}): string {\n // When we're constructing URLs, server URLs with trailing slashes cause problems with doing\n // lookups, so if we have one here on, slice it off.\n return stripTrailingSlash(\n url.replace(SERVER_VARIABLE_REGEX, (original: string, key: string) => {\n if (key in variables) {\n const data = variables[key];\n if (typeof data === 'object') {\n if (!Array.isArray(data) && data !== null && 'default' in data) {\n return data.default as string;\n }\n } else {\n return data as string;\n }\n }\n\n const userVariable = getUserVariable(this.user, key);\n if (userVariable) {\n return userVariable as string;\n }\n\n return original;\n }),\n );\n }\n\n /**\n * Retrieve an Operation of Webhook class instance for a given path and method.\n *\n * @param path Path to lookup and retrieve.\n * @param method HTTP Method to retrieve on the path.\n */\n operation(\n path: string,\n method: RMOAS.HttpMethods,\n opts: {\n /**\n * If you prefer to first look for a webhook with this path and method.\n */\n isWebhook?: boolean;\n } = {},\n ): Operation {\n // If we're unable to locate an operation for this path+method combination within the API\n // definition, we should still set an empty schema on the operation in the `Operation` class\n // because if we don't trying to use any of the accessors on that class are going to fail as\n // `schema` will be `undefined`.\n let operation: RMOAS.OperationObject = {\n parameters: [],\n };\n\n if (opts.isWebhook) {\n const api = this.api as OpenAPIV3_1.Document;\n // Typecasting this to a `PathsObject` because we don't have `$ref` pointers here.\n if ((api?.webhooks[path] as RMOAS.PathsObject)?.[method]) {\n operation = (api.webhooks[path] as RMOAS.PathsObject)[method] as RMOAS.OperationObject;\n return new Webhook(api, path, method, operation);\n }\n }\n\n if (this?.api?.paths?.[path]?.[method]) {\n operation = this.api.paths[path][method];\n }\n\n return new Operation(this.api, path, method, operation);\n }\n\n findOperationMatches(url: string): PathMatches {\n const { origin, hostname } = new URL(url);\n const originRegExp = new RegExp(origin, 'i');\n const { servers, paths } = this.api;\n\n let pathName;\n let targetServer;\n let matchedServer;\n\n if (!servers || !servers.length) {\n // If this API definition doesn't have any servers set up let's treat it as if it were\n // https://example.com because that's the default origin we add in `normalizedUrl` under the\n // same circumstances. Without this we won't be able to match paths within what is otherwise\n // a valid OpenAPI definition.\n matchedServer = {\n url: 'https://example.com',\n };\n } else {\n matchedServer = servers.find(s => originRegExp.exec(this.replaceUrl(s.url, s.variables || {})));\n if (!matchedServer) {\n const hostnameRegExp = new RegExp(hostname);\n matchedServer = servers.find(s => hostnameRegExp.exec(this.replaceUrl(s.url, s.variables || {})));\n }\n }\n\n // If we **still** haven't found a matching server, then the OAS server URL might have server\n // variables and we should loosen it up with regex to try to discover a matching path.\n //\n // For example if an OAS has `https://{region}.node.example.com/v14` set as its server URL, and\n // the `this.user` object has a `region` value of `us`, if we're trying to locate an operation\n // for https://eu.node.example.com/v14/api/esm we won't be able to because normally the users\n // `region` of `us` will be transposed in and we'll be trying to locate `eu.node.example.com`\n // in `us.node.example.com` -- which won't work.\n //\n // So what this does is transform `https://{region}.node.example.com/v14` into\n // `https://([-_a-zA-Z0-9[\\\\]]+).node.example.com/v14`, and from there we'll be able to match\n // https://eu.node.example.com/v14/api/esm and ultimately find the operation matches for\n // `/api/esm`.\n if (!matchedServer) {\n const matchedServerAndPath = servers\n .map(server => {\n const rgx = transformUrlIntoRegex(server.url);\n const found = new RegExp(rgx).exec(url);\n if (!found) {\n return undefined;\n }\n\n return {\n matchedServer: server,\n pathName: url.split(new RegExp(rgx)).slice(-1).pop(),\n };\n })\n .filter(Boolean);\n\n if (!matchedServerAndPath.length) {\n return undefined;\n }\n\n pathName = matchedServerAndPath[0].pathName;\n targetServer = {\n ...matchedServerAndPath[0].matchedServer,\n };\n } else {\n // Instead of setting `url` directly against `matchedServer` we need to set it to an\n // intermediary object as directly modifying `matchedServer.url` will in turn update\n // `this.servers[idx].url` which we absolutely do not want to happen.\n targetServer = {\n ...matchedServer,\n url: this.replaceUrl(matchedServer.url, matchedServer.variables || {}),\n };\n\n [, pathName] = url.split(new RegExp(targetServer.url, 'i'));\n }\n\n if (pathName === undefined) return undefined;\n if (pathName === '') pathName = '/';\n const annotatedPaths = generatePathMatches(paths, pathName, targetServer.url);\n if (!annotatedPaths.length) return undefined;\n\n return annotatedPaths;\n }\n\n /**\n * Discover an operation in an OAS from a fully-formed URL and HTTP method. Will return an object\n * containing a `url` object and another one for `operation`. This differs from `getOperation()`\n * in that it does not return an instance of the `Operation` class.\n *\n * @param url A full URL to look up.\n * @param method The cooresponding HTTP method to look up.\n */\n findOperation(url: string, method: RMOAS.HttpMethods): PathMatch {\n const annotatedPaths = this.findOperationMatches(url);\n if (!annotatedPaths) {\n return undefined;\n }\n\n const matches = filterPathMethods(annotatedPaths, method) as {\n operation: RMOAS.PathsObject;\n url: PathMatch['url']; // @fixme this should actually be an `OperationObject`.\n }[];\n if (!matches.length) return undefined;\n return findTargetPath(matches);\n }\n\n /**\n * Discover an operation in an OAS from a fully-formed URL without an HTTP method. Will return an\n * object containing a `url` object and another one for `operation`.\n *\n * @param url A full URL to look up.\n */\n findOperationWithoutMethod(url: string): PathMatch {\n const annotatedPaths = this.findOperationMatches(url);\n if (!annotatedPaths) {\n return undefined;\n }\n return findTargetPath(annotatedPaths);\n }\n\n /**\n * Retrieve an operation in an OAS from a fully-formed URL and HTTP method. Differs from\n * `findOperation` in that while this method will return an `Operation` instance,\n * `findOperation()` does not.\n *\n * @param url A full URL to look up.\n * @param method The cooresponding HTTP method to look up.\n */\n getOperation(url: string, method: RMOAS.HttpMethods): Operation {\n const op = this.findOperation(url, method);\n if (op === undefined) {\n return undefined;\n }\n\n return this.operation(op.url.nonNormalizedPath, method);\n }\n\n /**\n * Retrieve an operation in an OAS by an `operationId`.\n *\n * If an operation does not have an `operationId` one will be generated in place, using the\n * default behavior of `Operation.getOperationId()`, and then asserted against your query.\n *\n * Note that because `operationId`s are unique that uniqueness does include casing so the ID\n * you are looking for will be asserted as an exact match.\n *\n * @see {Operation.getOperationId()}\n * @param id The `operationId` to look up.\n */\n getOperationById(id: string): Operation | Webhook {\n let found: Operation | Webhook;\n\n Object.values(this.getPaths()).forEach(operations => {\n if (found) return;\n found = Object.values(operations).find(operation => operation.getOperationId() === id);\n });\n\n if (found) {\n return found;\n }\n\n Object.entries(this.getWebhooks()).forEach(([, webhooks]) => {\n if (found) return;\n found = Object.values(webhooks).find(webhook => webhook.getOperationId() === id);\n });\n\n return found;\n }\n\n /**\n * With an object of user information, retrieve the appropriate API auth keys from the current\n * OAS definition.\n *\n * @see {@link https://docs.readme.com/docs/passing-data-to-jwt}\n * @param user User\n * @param selectedApp The user app to retrieve an auth key for.\n */\n getAuth(user: RMOAS.User, selectedApp?: number | string): RMOAS.AuthForHAR {\n if (!this.api?.components?.securitySchemes) {\n return {};\n }\n\n return getAuth(this.api, user, selectedApp);\n }\n\n /**\n * Returns the `paths` object that exists in this API definition but with every `method` mapped\n * to an instance of the `Operation` class.\n *\n * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.0.md#openapi-object}\n * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#openapi-object}\n */\n getPaths(): Record<string, Record<RMOAS.HttpMethods, Operation | Webhook>> {\n /**\n * Because a path doesn't need to contain a keyed-object of HTTP methods, we should exclude\n * anything from within the paths object that isn't a known HTTP method.\n *\n * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.0.md#fixed-fields-7}\n * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#fixed-fields-7}\n */\n const paths: Record<string, Record<RMOAS.HttpMethods, Operation | Webhook>> = {};\n\n Object.keys(this.api.paths ? this.api.paths : []).forEach(path => {\n // If this is a specification extension then we should ignore it.\n if (path.startsWith('x-')) {\n return;\n }\n\n paths[path] = {} as Record<RMOAS.HttpMethods, Operation | Webhook>;\n\n // Though this library is generally unaware of `$ref` pointers we're making a singular\n // exception with this accessor out of convenience.\n if ('$ref' in this.api.paths[path]) {\n this.api.paths[path] = findSchemaDefinition(this.api.paths[path].$ref, this.api);\n }\n\n Object.keys(this.api.paths[path]).forEach((method: RMOAS.HttpMethods) => {\n if (!supportedMethods.includes(method)) return;\n\n paths[path][method] = this.operation(path, method);\n });\n });\n\n return paths;\n }\n\n /**\n * Returns the `webhooks` object that exists in this API definition but with every `method`\n * mapped to an instance of the `Webhook` class.\n *\n * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.0.md#openapi-object}\n * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#openapi-object}\n */\n getWebhooks(): Record<string, Record<RMOAS.HttpMethods, Webhook>> {\n const webhooks: Record<string, Record<RMOAS.HttpMethods, Webhook>> = {};\n const api = this.api as OpenAPIV3_1.Document;\n\n Object.keys(api.webhooks ? api.webhooks : []).forEach(id => {\n webhooks[id] = {} as Record<RMOAS.HttpMethods, Webhook>;\n Object.keys(api.webhooks[id]).forEach((method: RMOAS.HttpMethods) => {\n webhooks[id][method] = this.operation(id, method, { isWebhook: true }) as Webhook;\n });\n });\n\n return webhooks;\n }\n\n /**\n * Return an array of all tag names that exist on this API definition.\n *\n * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.0.md#openapi-object}\n * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#openapi-object}\n * @param setIfMissing If a tag is not present on an operation that operations path will be added\n * into the list of tags returned.\n */\n getTags(setIfMissing = false): string[] {\n const allTags = new Set<string>();\n\n const oasTags =\n this.api.tags?.map(tag => {\n return tag.name;\n }) || [];\n\n const disableTagSorting = getExtension('disable-tag-sorting', this.api);\n\n Object.entries(this.getPaths()).forEach(([path, operations]) => {\n Object.values(operations).forEach(operation => {\n const tags = operation.getTags();\n if (setIfMissing && !tags.length) {\n allTags.add(path);\n return;\n }\n\n tags.forEach(tag => {\n allTags.add(tag.name);\n });\n });\n });\n\n Object.entries(this.getWebhooks()).forEach(([path, webhooks]) => {\n Object.values(webhooks).forEach(webhook => {\n const tags = webhook.getTags();\n if (setIfMissing && !tags.length) {\n allTags.add(path);\n return;\n }\n\n tags.forEach(tag => {\n allTags.add(tag.name);\n });\n });\n });\n\n // Tags that exist only on the endpoint\n const endpointTags: string[] = [];\n // Tags that the user has defined in the `tags` array\n const tagsArray: string[] = [];\n\n // Distinguish between which tags exist in the `tags` array and which tags\n // exist only at the endpoint level. For tags that exist only at the\n // endpoint level, we'll just tack that on to the end of the sorted tags.\n if (disableTagSorting) {\n return Array.from(allTags);\n }\n\n Array.from(allTags).forEach(tag => {\n if (oasTags.includes(tag)) {\n tagsArray.push(tag);\n } else {\n endpointTags.push(tag);\n }\n });\n\n let sortedTags = tagsArray.sort((a, b) => {\n return oasTags.indexOf(a) - oasTags.indexOf(b);\n });\n\n sortedTags = sortedTags.concat(endpointTags);\n\n return sortedTags;\n }\n\n /**\n * Determine if a given a custom specification extension exists within the API definition.\n *\n * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specification-extensions}\n * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#specification-extensions}\n * @param extension Specification extension to lookup.\n */\n hasExtension(extension: string): boolean {\n return hasRootExtension(extension, this.api);\n }\n\n /**\n * Retrieve a custom specification extension off of the API definition.\n *\n * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specification-extensions}\n * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#specification-extensions}\n * @param extension Specification extension to lookup.\n */\n getExtension(extension: string | keyof Extensions, operation?: Operation): any {\n return getExtension(extension, this.api, operation);\n }\n\n /**\n * Determine if a given OpenAPI custom extension is valid or not.\n *\n * @see {@link https://docs.readme.com/docs/openapi-extensions}\n * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specification-extensions}\n * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#specification-extensions}\n * @param extension Specification extension to validate.\n * @throws\n */\n validateExtension(extension: keyof Extensions): void {\n if (this.hasExtension('x-readme')) {\n const data = this.getExtension('x-readme') as Extensions;\n if (typeof data !== 'object' || Array.isArray(data) || data === null) {\n throw new TypeError('\"x-readme\" must be of type \"Object\"');\n }\n\n if (extension in data) {\n if ([CODE_SAMPLES, HEADERS, PARAMETER_ORDERING, SAMPLES_LANGUAGES].includes(extension)) {\n if (!Array.isArray(data[extension])) {\n throw new TypeError(`\"x-readme.${extension}\" must be of type \"Array\"`);\n }\n\n if (extension === PARAMETER_ORDERING) {\n validateParameterOrdering(data[extension], `x-readme.${extension}`);\n }\n } else if (extension === OAUTH_OPTIONS) {\n if (typeof data[extension] !== 'object') {\n throw new TypeError(`\"x-readme.${extension}\" must be of type \"Object\"`);\n }\n } else if (typeof data[extension] !== 'boolean') {\n throw new TypeError(`\"x-readme.${extension}\" must be of type \"Boolean\"`);\n }\n }\n }\n\n // If the extension isn't grouped under `x-readme`, we need to look for them with `x-` prefixes.\n if (this.hasExtension(`x-${extension}`)) {\n const data = this.getExtension(`x-${extension}`);\n if ([CODE_SAMPLES, HEADERS, PARAMETER_ORDERING, SAMPLES_LANGUAGES].includes(extension)) {\n if (!Array.isArray(data)) {\n throw new TypeError(`\"x-${extension}\" must be of type \"Array\"`);\n }\n\n if (extension === PARAMETER_ORDERING) {\n validateParameterOrdering(data, `x-${extension}`);\n }\n } else if (extension === OAUTH_OPTIONS) {\n if (typeof data !== 'object') {\n throw new TypeError(`\"x-${extension}\" must be of type \"Object\"`);\n }\n } else if (typeof data !== 'boolean') {\n throw new TypeError(`\"x-${extension}\" must be of type \"Boolean\"`);\n }\n }\n }\n\n /**\n * Validate all of our custom or known OpenAPI extensions, throwing exceptions when necessary.\n *\n * @see {@link https://docs.readme.com/docs/openapi-extensions}\n * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specification-extensions}\n * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#specification-extensions}\n */\n validateExtensions(): void {\n Object.keys(extensionDefaults).forEach((extension: keyof Extensions) => {\n this.validateExtension(extension);\n });\n }\n\n /**\n * Retrieve any circular `$ref` pointers that maybe present within the API definition.\n *\n * This method requires that you first dereference the definition.\n *\n * @see Oas.dereference\n */\n getCircularReferences(): string[] {\n if (!this.dereferencing.complete) {\n throw new Error('#dereference() must be called first in order for this method to obtain circular references.');\n }\n\n return this.dereferencing.circularRefs;\n }\n\n /**\n * Dereference the current OAS definition so it can be parsed free of worries of `$ref` schemas\n * and circular structures.\n *\n */\n async dereference(\n opts: {\n /**\n * A callback method can be supplied to be called when dereferencing is complete. Used for\n * debugging that the multi-promise handling within this method works.\n *\n * @private\n */\n cb?: () => void;\n\n /**\n * Preserve component schema names within themselves as a `title`.\n */\n preserveRefAsJSONSchemaTitle?: boolean;\n } = { preserveRefAsJSONSchemaTitle: false },\n ): Promise<(typeof this.promises)[] | boolean> {\n if (this.dereferencing.complete) {\n return new Promise(resolve => {\n resolve(true);\n });\n }\n\n if (this.dereferencing.processing) {\n return new Promise((resolve, reject) => {\n this.promises.push({ resolve, reject });\n });\n }\n\n this.dereferencing.processing = true;\n\n const { api, promises } = this;\n\n // Because referencing will eliminate any lineage back to the original `$ref`, information that\n // we might need at some point, we should run through all available component schemas and denote\n // what their name is so that when dereferencing happens below those names will be preserved.\n if (api.components && api.components.schemas && typeof api.components.schemas === 'object') {\n Object.keys(api.components.schemas).forEach(schemaName => {\n // As of OpenAPI 3.1 component schemas can be primitives or arrays. If this happens then we\n // shouldn't try to add `title` or `x-readme-ref-name` properties because we can't. We'll\n // have some data loss on these schemas but as they aren't objects they likely won't be used\n // in ways that would require needing a `title` or `x-readme-ref-name` anyways.\n if (\n isPrimitive(api.components.schemas[schemaName]) ||\n Array.isArray(api.components.schemas[schemaName]) ||\n api.components.schemas[schemaName] === null\n ) {\n return;\n }\n\n if (opts.preserveRefAsJSONSchemaTitle) {\n // This may result in some data loss if there's already a `title` present, but in the case\n // where we want to generate code for the API definition (see http://npm.im/api), we'd\n // prefer to retain original reference name as a title for any generated types.\n (api.components.schemas[schemaName] as RMOAS.SchemaObject).title = schemaName;\n }\n\n (api.components.schemas[schemaName] as RMOAS.SchemaObject)['x-readme-ref-name'] = schemaName;\n });\n }\n\n const circularRefs: Set<string> = new Set();\n\n return dereference<RMOAS.OASDocument>(api, {\n resolve: {\n // We shouldn't be resolving external pointers at this point so just ignore them.\n external: false,\n },\n dereference: {\n // If circular `$refs` are ignored they'll remain in the OAS as `$ref: String`, otherwise\n // `$ref‘ just won't exist. This allows us to do easy circular reference detection.\n circular: 'ignore',\n\n onCircular: (path: string) => {\n // The circular references that are coming out of `json-schema-ref-parser` are prefixed\n // with the schema path (file path, URL, whatever) that the schema exists in. Because\n // we don't care about this information for this reporting mechanism, and only the\n // `$ref` pointer, we're removing it.\n circularRefs.add(`#${path.split('#')[1]}`);\n },\n },\n })\n .then((dereferenced: RMOAS.OASDocument) => {\n this.api = dereferenced;\n\n this.promises = promises;\n this.dereferencing = {\n processing: false,\n complete: true,\n // We need to convert our `Set` to an array in order to match the typings.\n circularRefs: [...circularRefs],\n };\n\n // Used for debugging that dereferencing promise awaiting works.\n if (opts.cb) {\n opts.cb();\n }\n })\n .then(() => {\n return this.promises.map(deferred => deferred.resolve());\n });\n }\n}\n","import type * as RMOAS from '../types.js';\nimport type { OpenAPIV3, OpenAPIV3_1 } from 'openapi-types';\n\ntype authKey = unknown | { password: number | string; user: number | string } | null;\n\n/**\n * @param user User to retrieve retrieve an auth key for.\n * @param scheme The type of security scheme that we want a key for.\n */\nfunction getKey(user: RMOAS.User, scheme: RMOAS.KeyedSecuritySchemeObject): authKey {\n switch (scheme.type) {\n case 'oauth2':\n case 'apiKey':\n return user[scheme._key] || user.apiKey || scheme['x-default'] || null;\n\n case 'http':\n if (scheme.scheme === 'basic') {\n return user[scheme._key] || { user: user.user || null, pass: user.pass || null };\n }\n\n if (scheme.scheme === 'bearer') {\n return user[scheme._key] || user.apiKey || scheme['x-default'] || null;\n }\n return null;\n\n default:\n return null;\n }\n}\n\n/**\n * Retrieve auth keys for a specific security scheme for a given user for a specific \"app\" that\n * they have configured.\n *\n * For `scheme` we're typing it to a union of `SecurityScheme` and `any` because we have handling\n * and tests for an unknown or unrecognized `type` and though it's not possible with the\n * `SecurityScheme.type` to be unrecognized it may still be possible to get an unrecognized scheme\n * with this me