@svengroup/openapi-to-pdf
Version:
Create PDF API reference documentation from OpenAPI 3.0.x specification files.
157 lines (156 loc) • 7.68 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = generateSecurityMarkdown;
exports.generateApiKeysMarkdown = generateApiKeysMarkdown;
exports.generateBasicMarkdown = generateBasicMarkdown;
exports.generateBearerMarkdown = generateBearerMarkdown;
exports.generateOidcMarkdown = generateOidcMarkdown;
exports.generateOauthMarkdown = generateOauthMarkdown;
exports.generateOauthFlowsMarkdown = generateOauthFlowsMarkdown;
exports.getMatchingSecuritySchemes = getMatchingSecuritySchemes;
async function generateSecurityMarkdown(schema, config) {
const sec_schemes = schema.components?.securitySchemes;
let sec_str = "";
if (sec_schemes) {
sec_str += `# ${config?.headings?.security ?? 'Security'}`;
sec_str += "\n\n";
sec_str += "The following security schemes are used by this API for authentication and authorization. These must be taken into account in every request unless otherwise stated.";
sec_str += "\n\n";
/** @ts-expect-error we resolve all references */
sec_str += await generateApiKeysMarkdown(sec_schemes);
/** @ts-expect-error we resolve all references */
sec_str += generateBasicMarkdown(sec_schemes);
/** @ts-expect-error we resolve all references */
sec_str += generateBearerMarkdown(sec_schemes);
/** @ts-expect-error we resolve all references */
sec_str += generateOidcMarkdown(sec_schemes);
/** @ts-expect-error we resolve all references */
sec_str += await generateOauthMarkdown(sec_schemes);
}
return sec_str;
}
async function generateApiKeysMarkdown(security_schemes) {
let sec_str = "";
const match = getMatchingSecuritySchemes(security_schemes, 'apiKey');
if (Object.keys(match).length > 0) {
const changeCase = await import("change-case"); // eslint-disable-line @typescript-eslint/naming-convention
const security_scheme = Object.entries(match)[0][1];
sec_str += "## API Key Authentication";
sec_str += "\n\n";
sec_str += security_scheme.description ?? "This API is secured through API Keys which you must obtain separately.";
sec_str += "\n\n";
for (const [key, value] of Object.entries(match)) {
sec_str += `### ${changeCase.capitalCase(key)}`;
sec_str += "\n\n";
/** @ts-expect-error always ApiKeySecurityScheme */
sec_str += `To authenticate requests, include \`${value.name}\` as a request ${value.in}.${value.description ? ` ${value.description}` : ""}`;
sec_str += "\n\n";
/** @ts-expect-error always ApiKeySecurityScheme */
sec_str += `\`\`\`http\nGET /example\nHost: example.com\n${value.name}: SAMPLE-API-KEY-a29@102&3djSF9\n\`\`\``;
sec_str += "\n\n";
}
}
return sec_str;
}
function generateBasicMarkdown(security_schemes) {
let sec_str = "";
const match = getMatchingSecuritySchemes(security_schemes, 'http', 'basic');
if (Object.keys(match).length > 0) {
const security_scheme = Object.entries(match)[0][1];
sec_str += "## Basic Authentication";
sec_str += "\n\n";
sec_str += security_scheme.description ?? "This API is secured through basic authentication.";
sec_str += "\n\n";
sec_str += "To authenticate requests, Base64-encode a concatenated string of the username and password (`username:password`), prefix it with `Basic ` and include it in the request as the value of `Authorization` header.";
sec_str += "\n\n";
sec_str += "```http\nGET /example\nHost: example.com\nAuthorization: Basic dXNlcjE6cGFzc3dvcmQxMjM=\n```";
sec_str += "\n\n";
}
return sec_str;
}
function generateBearerMarkdown(security_schemes) {
let sec_str = "";
const match = getMatchingSecuritySchemes(security_schemes, 'http', 'bearer');
if (Object.keys(match).length > 0) {
const security_scheme = Object.entries(match)[0][1];
sec_str += "## Bearer Authentication";
sec_str += "\n\n";
sec_str += security_scheme.description ?? "This API is secured through bearer token authentication.";
sec_str += "\n\n";
/** @ts-expect-error always HttpSecurityScheme */
sec_str += `To authenticate requests, include the token ${security_scheme.bearerFormat ? `in ${security_scheme.bearerFormat} format ` : ''}prefixed with \`Bearer \` in the request as the value of the \`Authorization\` header.`;
sec_str += "\n\n";
sec_str += "```http\nGET /example\nHost: example.com\nAuthorization: Bearer dXNlcjE6cGFzc3dvcmQxMjM=\n```";
sec_str += "\n\n";
}
return sec_str;
}
function generateOidcMarkdown(security_schemes) {
let sec_str = "";
const match = getMatchingSecuritySchemes(security_schemes, 'openIdConnect');
if (Object.entries(match).length > 0) {
/** @ts-expect-error only for OpenIdSecurityScheme */
const security_scheme = Object.entries(match)[0][1];
sec_str += "## OpenID Connect (OIDC) Authentication";
sec_str += "\n\n";
sec_str += security_scheme.description ?? "This API is secured using the [OpenID Connect (OIDC) protocol](https://openid.net/specs/openid-connect-core-1_0-final.html).";
sec_str += "\n\n";
sec_str += `Discovery URL: [${security_scheme.openIdConnectUrl}](${security_scheme.openIdConnectUrl})`;
sec_str += "\n\n";
}
return sec_str;
}
async function generateOauthMarkdown(security_schemes) {
let sec_str = "";
const match = getMatchingSecuritySchemes(security_schemes, 'oauth2');
if (Object.entries(match).length > 0) {
/** @ts-expect-error only for OAuth2SecurityScheme */
const security_scheme = Object.entries(match)[0][1];
sec_str += "## OAuth 2.0 Authorization";
sec_str += "\n\n";
sec_str += security_scheme.description ?? "This API is secured using the [OAuth 2.0 authorization framework](https://datatracker.ietf.org/doc/html/rfc6749).";
sec_str += "\n\n";
sec_str += await generateOauthFlowsMarkdown(security_scheme);
}
return sec_str;
}
async function generateOauthFlowsMarkdown(security_scheme) {
const changeCase = await import("change-case"); // eslint-disable-line @typescript-eslint/naming-convention
let sec_str = "";
for (const [type, flow] of Object.entries(security_scheme.flows)) {
sec_str += `### ${changeCase.capitalCase(type)} Flow`;
sec_str += "\n\n";
sec_str += `This API supports the ${changeCase.noCase(type)} flow.`;
sec_str += "\n\n";
for (const [key, value] of Object.entries(flow)) {
if (key === 'scopes') {
sec_str += `- Scopes:\n`;
for (const [scope, desc] of Object.entries(value)) {
sec_str += `\t- \`${scope}\`: ${desc}\n`;
}
continue;
}
const field = changeCase.capitalCase(key).replace('Url', 'URL');
sec_str += `- ${field}: [${value}](${value})\n`;
}
sec_str += "\n\n";
}
return sec_str;
}
function getMatchingSecuritySchemes(security_schemes, type, scheme) {
const match = {};
for (const [key, value] of Object.entries(security_schemes)) {
if (value.type === type) {
if (scheme) {
/** @ts-expect-error only for HttpSecurityScheme */
if (value.scheme === scheme) {
match[key] = value;
}
}
else {
match[key] = value;
}
}
}
return match;
}