diff options
author | Puyodead1 <puyodead@proton.me> | 2023-03-24 18:14:47 -0400 |
---|---|---|
committer | Puyodead1 <puyodead@proton.me> | 2023-04-13 15:20:10 -0400 |
commit | 6b3a3b750f3e29b491c51f8199efd64c05176a65 (patch) | |
tree | 2f15670152c3fb99630c648a86dd63e0a0b86b74 /scripts | |
parent | AAA (diff) | |
download | server-6b3a3b750f3e29b491c51f8199efd64c05176a65.tar.xz |
fixing lots of openapi crap
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/openapi.js | 124 | ||||
-rw-r--r-- | scripts/schema.js | 2 |
2 files changed, 69 insertions, 57 deletions
diff --git a/scripts/openapi.js b/scripts/openapi.js index 86527ada..35654eea 100644 --- a/scripts/openapi.js +++ b/scripts/openapi.js @@ -27,34 +27,46 @@ require("missing-native-js-functions"); const openapiPath = path.join(__dirname, "..", "assets", "openapi.json"); const SchemaPath = path.join(__dirname, "..", "assets", "schemas.json"); -let schemas = JSON.parse(fs.readFileSync(SchemaPath, { encoding: "utf8" })); - -for (var schema in schemas) { - const part = schemas[schema]; - for (var key in part.properties) { - if (part.properties[key].anyOf) { - const nullIndex = part.properties[key].anyOf.findIndex( - (x) => x.type == "null", - ); - if (nullIndex != -1) { - part.properties[key].nullable = true; - part.properties[key].anyOf.splice(nullIndex, 1); - - if (part.properties[key].anyOf.length == 1) { - Object.assign( - part.properties[key], - part.properties[key].anyOf[0], - ); - delete part.properties[key].anyOf; - } - } - } - } -} - -const specification = JSON.parse( - fs.readFileSync(openapiPath, { encoding: "utf8" }), -); +const schemas = JSON.parse(fs.readFileSync(SchemaPath, { encoding: "utf8" })); +// const specification = JSON.parse( +// fs.readFileSync(openapiPath, { encoding: "utf8" }), +// ); +let specification = { + openapi: "3.1.0", + info: { + title: "Fosscord Server", + description: + "Fosscord is a free open source selfhostable discord compatible chat, voice and video platform", + license: { + name: "AGPLV3", + url: "https://www.gnu.org/licenses/agpl-3.0.en.html", + }, + version: "1.0.0", + }, + externalDocs: { + description: "Fosscord Docs", + url: "https://docs.fosscord.com", + }, + servers: [ + { + url: "https://staging.fosscord.com/api/", + description: "Official Fosscord Instance", + }, + ], + components: { + securitySchemes: { + bearer: { + type: "http", + scheme: "bearer", + description: "Bearer/Bot prefixes are not required.", + bearerFormat: "JWT", + in: "header", + }, + }, + }, + tags: [], + paths: {}, +}; function combineSchemas(schemas) { var definitions = {}; @@ -72,6 +84,11 @@ function combineSchemas(schemas) { } for (const key in definitions) { + const reg = new RegExp(/^[a-zA-Z0-9\.\-_]+$/, "gm"); + if (!reg.test(key)) { + console.error(`Invalid schema name: ${key} (${reg.test(key)})`); + continue; + } specification.components = specification.components || {}; specification.components.schemas = specification.components.schemas || {}; @@ -102,30 +119,20 @@ function getTag(key) { function apiRoutes() { const routes = getRouteDescriptions(); - const tags = Array.from(routes.keys()).map((x) => getTag(x)); - specification.tags = specification.tags || []; - specification.tags = [...specification.tags.map((x) => x.name), ...tags] - .unique() - .map((x) => ({ name: x })); - - specification.components = specification.components || {}; - specification.components.securitySchemes = { - bearer: { - type: "http", - scheme: "bearer", - description: "Bearer/Bot prefixes are not required.", - }, - }; + // populate tags + const tags = Array.from(routes.keys()) + .map((x) => getTag(x)) + .sort((a, b) => a.localeCompare(b)); + specification.tags = tags.unique().map((x) => ({ name: x })); routes.forEach((route, pathAndMethod) => { const [p, method] = pathAndMethod.split("|"); const path = p.replace(/:(\w+)/g, "{$1}"); - specification.paths = specification.paths || {}; let obj = specification.paths[path]?.[method] || {}; obj["x-right-required"] = route.right; obj["x-permission-required"] = route.permission; - obj["x-fires-event"] = route.test?.event; + obj["x-fires-event"] = route.event; if ( !NO_AUTHORIZATION_ROUTES.some((x) => { @@ -136,12 +143,17 @@ function apiRoutes() { obj.security = [{ bearer: [] }]; } - if (route.body) { + if (route.description) obj.description = route.description; + if (route.summary) obj.summary = route.summary; + + if (route.requestBody) { obj.requestBody = { required: true, content: { "application/json": { - schema: { $ref: `#/components/schemas/${route.body}` }, + schema: { + $ref: `#/components/schemas/${route.requestBody}`, + }, }, }, }.merge(obj.requestBody); @@ -150,16 +162,9 @@ function apiRoutes() { if (route.responses) { for (const [k, v] of Object.entries(route.responses)) { let schema = { - allOf: [ - { - $ref: `#/components/schemas/${v.body}`, - }, - { - example: v.body, - }, - ], + $ref: `#/components/schemas/${v.body}`, }; - if (!v.body) schema = schema.allOf[0]; + // if (!v.body) schema = schema.allOf[0]; obj.responses = { [k]: { @@ -173,12 +178,16 @@ function apiRoutes() { }, }, } - : {}), + : { + description: "No description available", + }), }, }.merge(obj.responses); delete obj.responses.default; } } + + // handles path parameters if (p.includes(":")) { obj.parameters = p.match(/:\w+/g)?.map((x) => ({ name: x.replace(":", ""), @@ -188,16 +197,17 @@ function apiRoutes() { description: x.replace(":", ""), })); } + obj.tags = [...(obj.tags || []), getTag(p)].unique(); specification.paths[path] = { - ...specification.paths[path], [method]: obj, }; }); } function main() { + console.log("Generating OpenAPI Specification..."); combineSchemas(schemas); apiRoutes(); diff --git a/scripts/schema.js b/scripts/schema.js index c29d5bab..bb3e9ddc 100644 --- a/scripts/schema.js +++ b/scripts/schema.js @@ -57,6 +57,8 @@ const Excluded = [ "PropertiesSchema", "AsyncSchema", "AnySchema", + "SMTPConnection.CustomAuthenticationResponse", + "TransportMakeRequestResponse", ]; function modify(obj) { |